/**

 * jQuery.timers - Timer abstractions for jQuery

 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)

 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).

 * Date: 2009/10/16

 *

 * @author Blair Mitchelmore

 * @version 1.2

 *

 **/



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

    });

});

