Text inputs on forms can be used to submit numbers. A common use would be a “quantity” input on an eCommerce site. Changing the quantity value, from the user’s perspective entails tabbing or clicking to the input, deleting it’s current content, and typing in a new value. Expected behavior that nobody is going to yell at you for, but these number inputs could be a little friendlier. Through use of JavaScript (yes, jQuery), let’s do just that.
Clean HTML
Here the form markup. Nothing extra added, just clean HTML. Without JavaScript, this form will function perfectly well and not have anything extraneous.
<form method="post" action="">
<div>
<label for="name">French Hens</label>
<input type="text" name="french-hens" id="french-hens" value="3">
</div>
<div>
<label for="name">Turtle Doves</label>
<input type="text" name="turtle-doves" id="turtle-doves" value="2">
</div>
<div>
<label for="name">Partridges</label>
<input type="text" name="partridge" id="partridge" value="1">
</div>
<input type="submit" value="Submit" id="submit">
</form>
The CSS…
… isn’t very interesting. Maybe a few things to note. Everything is floated left and the DIV’s have overflow hidden to clear the floats. The labels are display block and text-align right to get the grid thing going. Pixel adjustments are made here and there to get things lining up right. I didn’t spend much time on this, so you may see some cross-browser differences.
Make Some Buttons
Photoshop up a couple of buttons. Might as well use a sprite eh? I’ll include the PSD in the download just in case you want to use these.
Appending Increment Buttons
We need to append these buttons to each input. You’ll notice in the markup that each label/input pair is wrapped in a DIV. This is good practice so that label inputs get broken onto their own line (better readability) for when CSS is turned off. It’s also required for validation with some DOCTYPES. AND, it’s the perfect little hook we can target for appending these buttons.
$(function() {
$("form div").append('<div class="inc button">+</div><div class="dec button">-</div>');
});
Two classes each, one generic “button” class which will be 90% of the styling and the class we’ll use to bind the click event. The other unique class to adjust the background position and utilize the sprite.
Make Them Work
The “plain English”:
- Cache the selector
- Save the “old” value of the input (value at time of clicking)
- If the “plus” button is clicked…
- …increment value up one
- Else if the “minus” button is clicked…
- …decrement the value down one
- Drop the new value into the input
$(".button").on("click", function() {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find("input").val(newVal);
});
The above code does everything we described, with a little extra logic. Before it decrements the value, it makes sure the number is at least a value of 1 or higher. This prevents the value from ever going negative (at least through using these buttons). This is a no-brainer for “quanity” style inputs, but if your use doesn’t need this just remove that “if” wrapper.
There are also a couple of commented lines about AJAX saving. If your application is all dynamic-cool-like that, you might wish to save the value automatically after a button is pressed, making it feel a little more desktop-application-y.
If you were to do that, you could put some code like this (perhaps):
var id = $button.attr("id");
$.ajax({
type: "POST",
url: "dosomething.php?id=" + id + "&newvalue=" + newVal,
success: function() {
$button.parent().find("input").val(newVal);
}
});
You’d probably remove the bottom line of the click function where it updates the value and leave that in the “success” sub function above. That way the number doesn’t get visually updated unless the AJAX save was successful.
Check it
MooTools
And as always, David Walsh with a port to MooTools.
One thing you could try and add is if the user holds the mouse button down it continues adding to the total.
Thx Chris!
Nice tut. I disagree about the “easier than typing” bit though; at least it’s not always so. I think typing anything larger than 10 (20, 30…..1000) is easier than using buttons.
cheers/k
Definitely. Even 10 is too many, I agree. You’d have to balance this technique with the application.
For example, an inventory application where you need to reduce the inventory when sales come in. The average sale is 1-5 things. Having to do the math in your head every single time and manually type in the new number would kinda suck, not to mention be more error prone. Far easier to just look at the number sold and click the button that many times.
Not to forget that the user doesn’t *have to* use the buttons. The input field is still an fully working operational input field !
A good walk-through, thanks. I’d rather not see this too often, though, like kongondo says, typing in a number is my preference too.
Maybe useful for mobile apps, though, and for cases where typing in the number isn’t the point as much as “more” and “less” on a scale, but then why not just click along the range ( ie with star ratings ).
ohw this is very nice !,
i don’t agree with David S. you are not obligated to use these buttons and can decide to type in the number.
As we all know, users do not read they just “look”, i think adding this kind of functionality gives the user a bit more information about the data they should enter here.
Once again I visit this page and like clock-work Chris you always have something I’m either looking for or could use on my current designs.
Thanks a ton for doing what you do!
And use parseInt escape when some fool types in only letters. Currently you’ll get NaN error.
Great tut… but it would be nice to teach us how to use “mouse scrool”.
nice one again chris :) !
very nice technique and as heldopslippers said, it’s up to the users if they prefer to type in the number or if they want a really high value.
A neat addition to this, I think, would be to be able to change the value by using the scroll wheel while hovering the input. That, and hitting the up and down arrow keys.
A nice addition to that would be to detect mouse down (for a long time that is) and increase accordingly.
A little feedback for the user would be to make a small onclick picture change (like hover state sprites), (and it shouldn’t be too much of a problem too).
Might be a little Safari bug (or intended, I don’t know).
When you click on the + or – buttons, it highlights the image and some of the background…..
Not sure what the easiest way around it though!
Sorry…Just figured out what it is. Its if you click too fast, Safari sees it as a double click and instead of going forward, it highlights the image.
Any ideas?
What probably helps in all browsers and in my opinion is already a lot better to use is instead of adding the buttons in a div, create them as input type=”image”.
And you keep tabbing functionality(tho in this case users who use their keyboard can just fill in the numbers)
Hey Chris, don’t get me wrong I love the mini tutorials you put in, but I think you are losing focus on ‘css-tricks’ ;)
This site hasn’t been about only CSS Tricks in a long long time. The new slogan is more like “all things web design.”
Time to change the domain name to web-tricks.com ? :-))
And yes… your tutorials and site is amazing… always the first to browse every morning… took me around 2 weeks to watched almost all the screencasts you did…
Great work Chris !
Keep it Up !
Interesting. I’ll try it out. Thanks.
Cool, thanks Chris. Love this site man it rocks!
Keep it up.
jQuery UI has this already. It also supports auto-incrementing while holding your mouse button down, and optional mousewheel support.
http://docs.jquery.com/UI/Spinner
Nice. I think a good addition to this would be to make it so that you can use the mosue wheel to change the value while hovering over it.
Would be better if you can restrict the input boxes only accept numbers.
Just realized the nod at the Twelve Days of Christmas lol.
It’s the little things in life. Keep it up Chris!
I’ve made this into a plugin for myself, but I want to publish it to the plugins.jquery.com website. I just wanted to know if that was OK? I also wanted to know if it was OK to use the images you made for the buttons in it and to add some extra things to it?
Thanks
Go for it.
Nice! Thank you, now I will use.
Very handy, thanks for this!
Nice article.
btw cant it go lower than 0 i.e. in negative lolz ?
I definitely like the idea and with the feature Baylor Rae’ mentioned this would really be awesome.
I was wondering if this is doable… adding it so that you can hold the button down on click, which will continually increase the integer and then speeding the quantity up?
Wow! This looks awesome and we definitely will use this in our next design. So handy!
Cheers,
i’m a big fan of the blog, thanks again.
Not sure it matters at this pint or anything for this particular article, but I just finished up some research on the name used for the spinner widget. Take a look when you get a chance. Other users might find this info helpful if they are researching the best way to implement this functionality…
Is “Numeric Spinner” the best name for this?
http://uxfindings.blogspot.com/2014/06/is-numeric-spinner-best-name-for-this.html
Wow Chris, I checked out the demo and saw the update that we should use type=”number” instead. Saved me a good bit of time. Thanks!