Question

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);
    });
});
Was it helpful?

Solution

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.

OTHER TIPS

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){

  }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top