DA.
DA.

Reputation: 40671

Can I use a custom jQuery function not dependent on a selector for chaining?

I think I'm probably doing a jQuery faux pas here. Or a JavaScript one for that matter. So stop me if I am! :)

The scenario:

I want to create a function that takes in a string and perhaps some other parameters and then wraps them in a settimeout. Simple thing, but it's a lot cleaner than sticking settimeouts all over my code.

It'd look something like this:

function myFunction(text,interval) {
    setTimeout(function(){
        // do a bunch of stuff with the text var
    },interval)
}

Easy enough. Then I realized I might want to change this together multiple times and to do so, I'd then have to wrap my calls in a nested setTimeouts of their own, and I'm back to messy looking code.

So I was wondering if I could leverage jQuery to make this look better and more usable throughout my code.

I tried this, first making my own custom jQuery function:

$.fn.myFunction = function(text,interval) {
    setTimeout(function(){
        // do a bunch of stuff with the text var
    },interval)
}

Thinking I could then call it with something like this:

$('body')
    .myFunction('string1',1000).delay(500)
    .myFunction('string2',1000).delay(500)
    .myFunction('string3',1000)

This looks so much nicer and makes repetitive use a whole lot leaner. BUT...this doesn't work at all. My questions:

update

Thanks to cookie monster's answer, I now have an updated example:

  $.fn.myFunction = function(text,interval) {
    return this.queue(function(next) {
         setTimeout(function(){
            console.log(text);
        },interval)
    })
  };

I'm then attempting it to calling it as such:

$.myFunction('msg1',500).delay(500).myFunction('msg2',500).delay(500).myFunction('msg3',500)

Doing that gives me this error:

TypeError: 'undefined' is not a function (evaluating '$.myFunction()')

So I thought maybe it still needs a selector:

$('body').myFunction('msg1',500).delay(500).myFunction('msg2',500).delay(500).myFunction('msg3',500)

That works!...but just once. It executes the function once, but not again for the other 2 times in the chain. So, a step closer but I still think I'm missing some important concept or syntax.

update 2

JSBin of my almost working code: http://jsbin.com/exAyuCUp/1/

Upvotes: 0

Views: 147

Answers (2)

Mattias Buelens
Mattias Buelens

Reputation: 20159

I don't see why you'd bother with doing the setTimeout when you can just use $.fn.delay.

I would just use a function without any delay:

$.fn.myFunction = function(text) {
    return this.queue(function(next) {
        // do a bunch of stuff with the text var
        console.log(text);
        next();
    });
}

and add .delay where needed:

$('body')
      .delay(500).myFunction('msg1')
      .delay(500).myFunction('msg2')
      .delay(500).myFunction('msg3');

If you don't need to select any element, you can still construct a jQuery object around something else such as a dummy object:

$({}).delay(500).myFunction('msg1');

(You cannot just use $.delay(500).myFunction('msg1') since the $ object is not a jQuery object inheriting the $.fn prototype.)

Here's a fiddle.

Upvotes: 1

cookie monster
cookie monster

Reputation: 10972

Use .queue() to make your code work with a .delay().

start = Date.now()
$.fn.myFunction = function(text,interval) {
    return this.queue(function(next) {
        setTimeout(function(){
            console.log(text, start - Date.now())
            next() // This is mandatory!
        },interval)
    })
}

http://jsfiddle.net/FkR2D/

  • am I even on the right path in thinking this is a viable use of jQuery and custom functions?

Yes, as long as there's a facility to manage an ordered execution of time delayed code, which jQuery does have.

  • if it is where am I messing up my logic?

Only thing missing was queuing your code, and retuning a jQuery object

  • and finally, does one need to always choose a selector before calling chained jQuery functions? (I selected 'body' just to make the jQuery chain typical, but I'm obviously not doing anything in particular with that jQuery object)

No, a selector simply performs a DOM selection. If you already have a set of elements in your jQuery object, there's no DOM selection needed.

Upvotes: 3

Related Questions