Problem
If you have a spinner and interrupt the spin process with a dialog box e.g. on blur from the previous field, or on focus of the spinner, when the dialog is closed the spinner continues the spin process as if the mouse was held down on the spin button, like an infinite loop.
I have created a jsfiddle that illustrates the point, consisting of 2 spinners and a confirm dialog in the change event.
In order to see the infinite spinning:
- Trigger the confirm dialog as described on the example page.
- Clear the dialog (this can be with the “OK” or the “Cancel” button).
- Hover over the spinner control’s button with the mouse.
- See the spinner go!
\Edit – There is mouseleave code that is not firing, I think that’s the problem. Going to look into whether I can manually make this happen
Workarounds tried
- I have tried disabling the other spinners before the confirm is displayed, then re-enabling them after, in the hope it would clear the state, but that doesn’t work.
- In my situation I am using spinners on an ordering form. I use the confirm for a maximum quantity check: if the user confirms then the value is allowed, otherwise it’s set back to the previous value. I tried putting the confirm into the spin event, but this doesn’t fire when the user updates the input field usign the keyboard.
- I also tried it in the stop event, which fires after every mouse/key press. However this didn’t work well as the maximum quantity of my spinners is 999 and the confirm is displayed at varying values that are all quite low e.g. 12. So, if the user wants to enter 130 they would get the confirm dialog when they enter the 3, which would not be expected behaviour. Note that this may end up being my workaround, as this scenario is the least likely to occur.
- I also tried setting a flag to check in the spin event, so that the second spinner’s spin can be cancelled. This does work and prevents it spinning, but as soon as the flag is unset the problem occurs. Applying focus and blus to the second spinner (or any other for that matter) doesn’t help, neither does applying blur to the actual spinner buttons.
I think I’ve identified a bug in the jQuery UI 1.9 spinner, affecting all browsers and is present in milestone 8. I’m hoping someone with a bit more knowledge can give me a workaround for this (please!), until a fix is issued…
As I believe this is a bug in the jQuery UI library, I’ve asked this question at the jQuery forum, so I’ll keep this question updated if I hear anything there.
Explanation
This is a ui.spinner bug (most likely) and it is probably worth notifying the jQuery UI developers.
Note: If you do not want to file the ticket w/ the jQuery UI team, please let me know and I will file it. I might even provide a patch if I get the time.
The issue is that the spinner is starting on
mousedown(in this case, it also starts onmousewheeelandkeydown) and unfortunately it isn’t being fired until after the confirm().The
confirm()in FireFox also has the cool side-effect of stopping all document events while theconfirm()is open. The spinner stops onmouseupandmouseout(andkeyup) on the spinner/spinner buttons, but those events are never fired. Thus, the spinner running continuously till you move back to the spinner and cause one of the stop events to fire.Workarounds
I have two work arounds for you until the jQuery UI team fixes this issue. It depends on what processing you need to do. One is to put the
confirm()on a timeout the other is to trigger amouseupevent on all spinner buttons on a timeout.Which one is useful (if any) are dependent on what you are trying to do with the result of your
confirm().Neither are pretty, but these are the best workarounds I could come up with.
Workaround 1 – Timeout on fake event
Workaround 2 – Timeout on confirm()
Other Hacks
It is possible to obtain the spinner’s internal private instance in order to access the
spinniningproperty, mark it true, and then call the_stop()member function. However, that is a very intrusive fix. Another route is to just clear the timeout that stop uses, but again intrusive and none of that is future proof. As such, I will not provide examples of those hacks.