3

Here's a <select> element:

<select>
    <option>Hello</option>
    <option>Banana</option>
    <option>Balloon</option>
    <option>Something</option>
    <option>Potato</option>
    <option>Cleveland</option>
</select>

Here's a little bit of JavaScript (a jQuery "ready" handler):

$(function() {

    function foo() {
        var s = $('select').find(':selected');
    }

    setInterval(foo, 200);
});

Here is the jsfiddle for this question..

The handler sets up an interval timer which, every 200 milliseconds, finds the currently-selected <option> of the <select>, and does nothing at all with it. When I run the fiddle in Chrome (13.0.782.112), and I click on the <select> element, and then try to select an entry, the selection highlight keeps jumping back to the first selected element. I can click on any of the <option> elements shown and that works, of course, and then it does the same thing the next time.

Now, if I change the timer handler so that it doesn't use jQuery to find the currently-selected <option> element, as follows:

$(function() {

    function foo() {
        var select = $('select')[0];
        var s = $(select.options[select.selectedIndex]);
    }

    setInterval(foo, 200);
});

then I no longer see the effect.

Firefox does not do this. I haven't tried Safari yet.

Personally I think that something's doing something wrong here. Is it Chrome? jQuery?

edit — one more detail - I'm running Chrome on Linux. I'll try Windows in a sec. (edit same in Windows.)

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Chrome+Safari on Windows 7 are both broken in the same way. – thirtydot Aug 24 '11 at 23:32
  • @thirtydot -- thanks! I added "webkit" to the tags – Pointy Aug 24 '11 at 23:36
  • I can duplicate this issue as well (Chrome 13/Win7), but may I ask why you can't just use `$('select').change()` to capture the change event in a callback, rather than use an interval? – Jimmy Sawczuk Aug 24 '11 at 23:37
  • Also, I like your random ` – Jimmy Sawczuk Aug 24 '11 at 23:38
  • @Jimmy Sawczuk -- I could clearly do that here, and I could *probably* do that in my real situation. The thing is, I'm sort-of "watching" an entire form for changes. I *could* bind to "change" on all my elements, but I was trying to avoid some of the idiotic "change" bugs that IE has by simply polling. Usually, that doesn't cause any problems. – Pointy Aug 24 '11 at 23:39
  • @Pointy My guess is you'll run into more problems trying to poll than if you just bind to event handlers. And particularly with jQuery, this sort of thing is pretty foolproof these days - I can't think of any gotchas I've had recently with capturing events off of a ` – Jimmy Sawczuk Aug 24 '11 at 23:43
  • It's not ` – Pointy Aug 24 '11 at 23:46

1 Answers1

3

Change the code to:

function foo() {
    var s = $('select option:selected');
}

setInterval(foo, 200);

Not sure why exactly it does this, but my guess would be that it's related to the way pseudoselectors work in jQuery. They're implemented as functions which are paired with the name of the selector (In this case "selected"). Consequently they are run against every possible element in the context (not just those which could potentially be selected).

Maybe there some sort of weird ghost element against which the "selected" pseudoselector is being executed when it shouldn't. The solution here is that I restrict the context to options before doing the pseudoselector. Always a good thing to do.

Wyatt
  • 1,366
  • 9
  • 14
  • This works for me, nice! ([I put that in a jsFiddle to test](http://jsfiddle.net/LNHVp/)) – Jimmy Sawczuk Aug 24 '11 at 23:44
  • Yes, that definitely makes the weirdness stop. I'm still curious to see whether some genius figures out exactly what the deal is :-) – Pointy Aug 24 '11 at 23:45
  • This does work, but `$('select').find('option:selected')` still breaks and (blabla newline) `$('select :selected')` works. What I'm saying is that it doesn't appear to be related to adding `option` in the selector. `.find()` seems to be the problem. – thirtydot Aug 24 '11 at 23:49