1

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();
            frequency = 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);
Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
kikito
  • 51,734
  • 32
  • 149
  • 189

3 Answers3

3

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.

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • good point about the frequency. You have a sharp eye. ... unfortunately your example doesn't seem to work anyway (I'm on firefox 3.6) – kikito Mar 04 '11 at 12:39
  • I used `console.log` which crashes your firefox if you don't have [firebug](http://getfirebug.com/). Try the updated example which doesn't break. – Raynos Mar 04 '11 at 13:12
  • Ah yes, good catch. :) I hadn't even registered that that line was just multiplying itself by 1000. I always try to use different variables so didn't twig that it was doing that. :) Good job. :) – Chris Mar 04 '11 at 16:45
  • I finally got some time to test this and indeed moving the frequency upwards fixed the issue. Changes are committed on my plugin. Thanks! – kikito Mar 05 '11 at 17:14
1

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. :)

Chris
  • 27,210
  • 6
  • 71
  • 92
  • Thanks for your comment. I agree with you, they are not playing nicely with each other. But it is quite strange anyway. – kikito Mar 04 '11 at 12:06
  • yes it is the closures & scoping. Namely the `frequency` argument. There's actaully nothing wrong with the `ti` – Raynos Mar 04 '11 at 12:25
  • @Raynos: You are totally right, I was barking up the wrong tree. Still, I'll leave my comment there and hope that people don't mark it down for not actually being right since somebody obviously liked it. :) – Chris Mar 04 '11 at 16:49
-2

@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

Community
  • 1
  • 1
xkeshav
  • 53,360
  • 44
  • 177
  • 245
  • I... don't understand what you're trying to say here. Sure you can define and bind your event handlers like that; no reason to always use anonymous functions – Yi Jiang Mar 04 '11 at 11:49
  • Hi diEcho, I don't understand your answer, especially the first sentence. Can you re-write it? – kikito Mar 04 '11 at 11:50
  • I understand one part - "define your function beforehand". That doesn't answer my question. I know I can do that. But that doesn't answer my question. I want to know why some selectors work while others don't. That is my main goal. – kikito Mar 04 '11 at 11:54
  • @egarcia...please see my reference Question link.. u must get the answer. u cant do the way u r doing – xkeshav Mar 04 '11 at 11:55
  • I'm sorry but that doesn't make sense. I do an `each` on the result of the multiple selector. If I put a watch on firebug, I see bind being called once per element. That ought to be equivalent to invoking the same function several times. But somehow it is not. – kikito Mar 04 '11 at 12:01
  • @diEcho You **can** define your function like that; the very answer you linked to states so. – Yi Jiang Mar 04 '11 at 12:01
  • 2
    @diEcho, Please, please, please try to avoid txtspk if you want people to take you seriously. – Benjol Mar 04 '11 at 12:05