开发者

Why does my jQuery plugin fail on multiple selectors?

I've created a jQuery selector called jquery.observe_field. It mimics Prototype's observe_field. My plugin works ok with "single" selectors, like an ID selector:

$('#foo').observe_field(1, function() { alert(this.value); });

But it doesn't seem to work (I don't get any errors, but alerts are just never shown) when a multiple selector is used:

$('#foo,#bar,#baz').observe_field(1, function() { alert(this.value); });

Why is that?

EDIT: I've created an example in jsFiddle (notice that in the JavaScript part, the initialization code is right after the plugin code): http://jsfiddle.net/X2Bzk/

(function($) {
    jQuery.fn.observe_field = function(frequency, callback) {
        return this.each(function() {
            var $this = $(this);
            var prev = $this.val();

            var check = function() {
                var val = $this.val();
                if (prev != val) {
                    prev = val;
                    $this.map(callback); // invokes the callback on $this
                }
            };

            var reset = function() {
                if (ti) {
                    clearInterval(ti);
                    ti = setInterval(check, frequency);
                }
            };

            check();
            fr开发者_运维技巧equency = frequency * 1000; // translate to milliseconds
            var ti = setInterval(check, frequency); // invoke check periodically
            // reset counter after user interaction
            $this.bind('keyup mousemove', reset); //mousemove is for selects
        });
    };
})(jQuery);


The problem is this line

frequency = frequency * 1000;

For the first item the frequency is set to 1s.

For the second item the frequency is set to 1000s.

For the third ...

You want the frequency to be set properly once not for every item. So do it outside the .each function. Of course when the interval is removed and added back it's added back with the 1000s interval which breaks your code completely. Imagine doing this for 20 items.

Fixed.


Note: I am aware that this is not the right answer now but will leave it here for later reference for those interested. Please see Raynos's answer for the correct solution.

Having had a look at your code if you comment out the line witht he clear interval then it starts working for the first field... I'm thinking that when you have more than one setinterval that they are not playing nicely with others. Its probably all to do with closures and scoping and such like but I often get lost in these areas so can't give you an exact solution. hopefully it puts you on the right path though or if not puts another user on the path to give you a more full answer. :)

Edit to add: It occurs to me that a solution might be to store the timer reference on the element itself. Something like $this.data('timer',ti) or similar. You might have to play around a bit but this should ensure that each timer is kept safe and sound on its own and when you retrieve it ($this.data('timer') you can be sure there is no chance of getting the wrong one. :)


@egarcia i m saying that why u want to put together when it is working by writing separate.

AFAIK You can't Define your function beforehand:

function eventHandler(event) {}

and assign it separately:

$('select').mouseover(eventHandler);
$('input').bind('keyup', eventHandler);

With .bind you can at least bind one event handler to multiple events.

Reference Question

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜