Ian Stanway
Ian Stanway

Reputation: 610

jQuery UI 1.9 Spinner Dialog Interrupting Spin Causes Infinite Loop

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:

  1. Trigger the confirm dialog as described on the example page.
  2. Clear the dialog (this can be with the "OK" or the "Cancel" button).
  3. Hover over the spinner control's button with the mouse.
  4. 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 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.

Upvotes: 3

Views: 2181

Answers (1)

Andrew Martinez
Andrew Martinez

Reputation: 3754

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 on mousewheeel and keydown) 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 the confirm() is open. The spinner stops on mouseup and mouseout (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 a mouseup event 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

var spinner = $( ".mySpinner" ).spinner({
    max: 100,
    min: -100,
    change: function( event, ui ) {
        confirm("Pressing cancel breaks the other spinner");
        setTimeout(function(){
            $('.ui-spinner-button').trigger('mouseup');
        },1);
    }
});

Workaround 2 - Timeout on confirm()

var spinner = $( ".mySpinner" ).spinner({
    max: 100,
    min: -100,
    change: function( event, ui ) {
        setTimeout(function(){confirm("Pressing cancel breaks the other spinner");},1);
    }
});

Other Hacks

It is possible to obtain the spinner's internal private instance in order to access the spinnining property, 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.

Upvotes: 1

Related Questions