views:

304

answers:

2

Hello,

I am still trying to understand plugin procedure so I can write my own or adapt another.

I try to learn from this plugin It sets methods with fn.extend and then passes itself(with this) to some function made in jquery.extend.

jQuery.fn.extend({
    everyTime: function(interval, label, fn, times) {
        return this.each(function() {
            jQuery.timer.add(this, interval, label, fn, times);
        });
    },

I also see other plugins that don't do that.

Why is that?? or what's the idea behind it.

(I read some other explanations, saying one is used for functions and the other for methods, but that's to vague for me.)

thanks, Richard

EDIT

complete plugin code wich uses two different extends

jQuery.fn.extend({
    everyTime: function(interval, label, fn, times) {
        return this.each(function() {
            jQuery.timer.add(this, interval, label, fn, times);
        });
    },
    oneTime: function(interval, label, fn) {
        return this.each(function() {
            jQuery.timer.add(this, interval, label, fn, 1);
        });
    },
    stopTime: function(label, fn) {
        return this.each(function() {
            jQuery.timer.remove(this, label, fn);
        });
    }
});

jQuery.extend({
    timer: {
        global: [],
        guid: 1,
        dataKey: "jQuery.timer",
        regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
        powers: {
            // Yeah this is major overkill...
            'ms': 1,
            'cs': 10,
            'ds': 100,
            's': 1000,
            'das': 10000,
            'hs': 100000,
            'ks': 1000000
        },
        timeParse: function(value) {
            if (value == undefined || value == null)
                return null;
            var result = this.regex.exec(jQuery.trim(value.toString()));
            if (result[2]) {
                var num = parseFloat(result[1]);
                var mult = this.powers[result[2]] || 1;
                return num * mult;
            } else {
                return value;
            }
        },
        add: function(element, interval, label, fn, times) {
            var counter = 0;

            if (jQuery.isFunction(label)) {
                if (!times) 
                    times = fn;
                fn = label;
                label = interval;
            }

            interval = jQuery.timer.timeParse(interval);

            if (typeof interval != 'number' || isNaN(interval) || interval < 0)
                return;

            if (typeof times != 'number' || isNaN(times) || times < 0) 
                times = 0;

            times = times || 0;

            var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});

            if (!timers[label])
                timers[label] = {};

            fn.timerID = fn.timerID || this.guid++;

            var handler = function() {
                if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
                    jQuery.timer.remove(element, label, fn);
            };

            handler.timerID = fn.timerID;

            if (!timers[label][fn.timerID])
                timers[label][fn.timerID] = window.setInterval(handler,interval);

            this.global.push( element );

        },
        remove: function(element, label, fn) {
            var timers = jQuery.data(element, this.dataKey), ret;

            if ( timers ) {

                if (!label) {
                    for ( label in timers )
                        this.remove(element, label, fn);
                } else if ( timers[label] ) {
                    if ( fn ) {
                        if ( fn.timerID ) {
                            window.clearInterval(timers[label][fn.timerID]);
                            delete timers[label][fn.timerID];
                        }
                    } else {
                        for ( var fn in timers[label] ) {
                            window.clearInterval(timers[label][fn]);
                            delete timers[label][fn];
                        }
                    }

                    for ( ret in timers[label] ) break;
                    if ( !ret ) {
                        ret = null;
                        delete timers[label];
                    }
                }

                for ( ret in timers ) break;
                if ( !ret ) 
                    jQuery.removeData(element, this.dataKey);
            }
        }
    }
});

jQuery(window).bind("unload", function() {
    jQuery.each(jQuery.timer.global, function(index, item) {
        jQuery.timer.remove(item);
    });
});
A: 

There are a couple of ways you can define plugins

$.fn.myFunc=function(opt){

};

$.fn.myOtherFunc=function(opt){

};

Is the same as

$.fn.extend({
  myFunc:function(opt){

  },
  myOtherFunc:function(opt){

  }
});
czarchaic
Thanks, but this was not really my question. What I wanted to know is why something from fn is returned to the jquery object. Because these are two separate things. –
Richard
What you showed was actually sort off an answer to my previous question. The syntax for adding multiple methods at once.
Richard
Point taken, I was unclear about your question as well. The code you added made things more clear. Good luck.
czarchaic
+1  A: 

It's just how the plugin mechanism works. You create jQuery plugins by extending the jQuery.fn object with your own functions. Either by directly adding functions to the jQuery.fn object, or by calling jQuery.fn.extend()

These plugin functions are always passed the jQuery object (i.e. the selection of DOM elements it was invoked on) as the this variable.

For example, let's say you want to create a jQuery plugin that shows the number of items in a DOM set using an alert:

$.fn.showCount = function() { 
   alert("Count = " + this.length); // "this" is a refernce to the jQuery object
}

or (which is exactly the same):

// $.fn.extend is just a convenience method for extending the jQuery.fn object
// It's also the same as calling $.extend($.fn, { ... })

$.fn.extend( {
                showCount: function() { 
                        alert("Count = " + this.length);
                }
             });

So when you call:

$("a").showCount();

It will pop up an alert telling you the number of <a> tags in your document.

EDIT:

After seeing your code, I think I know what you're getting at.

When using jQuery.extend() (not jQuery.fn.extend), you're not creating a REAL plugin. You're merely creating a global function or object, unrelated to jQuery itself.

In fact, the timer plugin could have been written like this, and it would have done exactly the same thing:

var timerPlugin = {
       global: [],
        guid: 1,
        dataKey: "jQuery.timer",
        regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
        powers: {
            // Yeah this is major overkill...
            'ms': 1,
            'cs': 10,
            'ds': 100,
            's': 1000,
            'das': 10000,
            'hs': 100000,
            'ks': 1000000
        },
        timeParse: function(value) {
           //...
        }
        // ...
  };

Then (for example) you call timerPlugin.remove() instead of jQuery.timer.remove().

Extending the jQuery.fn object is done to allow calling your own functions on jQuery objects. For example: $("a").myPlugin()

The thing to remember is that jQuery.extend() has nothing to do with jQuery or jQuery plugins. It's simply a utility function provided by the jQuery library.

Philippe Leybaert
thanks, for following my questionsI have this idea that I am not making my question very clear. I will paste the whole code in a minute. It's just that to my understanding that the jqueryobject and jquery.fn are two separate entity's. If they start mixing things up. I get confused. Just a sec, I wil paste it.
Richard
Could all the code also have been stored within the fn.extend or would that conflict with something?
Richard