/* ** jquery.schedule.js -- jQuery plugin for scheduled/deferred actions ** Copyright (c) 2007 Ralf S. Engelschall ** Licensed under GPL ** ** $LastChangedDate$ ** $LastChangedRevision$ */ /* *
TEST BUTTON
*
* * */ (function($) { /* object constructor */ $.scheduler = function () { this.bucket = {}; return; }; /* object methods */ $.scheduler.prototype = { /* schedule a task */ schedule: function () { /* schedule context with default parameters */ var ctx = { "id": null, /* unique identifier of high-level schedule */ "time": 1000, /* time in milliseconds after which the task is run */ "repeat": false, /* whether schedule should be automatically repeated */ "protect": false, /* whether schedule should be protected from double scheduling */ "obj": null, /* function context object ("this") */ "func": function(){}, /* function to call */ "args": [] /* function arguments to pass */ }; /* helper function: portable checking whether something is a function */ function _isfn (fn) { return ( !!fn && typeof fn != "string" && typeof fn[0] == "undefined" && RegExp("function", "i").test(fn + "") ); }; /* parse arguments into context parameters (part 1/4): detect an override object (special case to support jQuery method) */ var i = 0; var override = false; if (typeof arguments[i] == "object" && arguments.length > 1) { override = true; i++; } /* parse arguments into context parameters (part 2/4): support the flexible way of an associated array */ if (typeof arguments[i] == "object") { for (var option in arguments[i]) if (typeof ctx[option] != "undefined") ctx[option] = arguments[i][option]; i++; } /* parse arguments into context parameters (part 3/4): support: schedule([time [, repeat], ]{{obj, methodname} | func}[, arg, ...]); */ if ( typeof arguments[i] == "number" || ( typeof arguments[i] == "string" && arguments[i].match(RegExp("^[0-9]+[smhdw]$")))) ctx["time"] = arguments[i++]; if (typeof arguments[i] == "boolean") ctx["repeat"] = arguments[i++]; if (typeof arguments[i] == "boolean") ctx["protect"] = arguments[i++]; if ( typeof arguments[i] == "object" && typeof arguments[i+1] == "string" && _isfn(arguments[i][arguments[i+1]])) { ctx["obj"] = arguments[i++]; ctx["func"] = arguments[i++]; } else if ( typeof arguments[i] != "undefined" && ( _isfn(arguments[i]) || typeof arguments[i] == "string")) ctx["func"] = arguments[i++]; while (typeof arguments[i] != "undefined") ctx["args"].push(arguments[i++]); /* parse arguments into context parameters (part 4/4): apply parameters from override object */ if (override) { if (typeof arguments[1] == "object") { for (var option in arguments[0]) if ( typeof ctx[option] != "undefined" && typeof arguments[1][option] == "undefined") ctx[option] = arguments[0][option]; } else { for (var option in arguments[0]) if (typeof ctx[option] != "undefined") ctx[option] = arguments[0][option]; } i++; } /* annotate context with internals */ ctx["_scheduler"] = this; /* internal: back-reference to scheduler object */ ctx["_handle"] = null; /* internal: unique handle of low-level task */ /* determine time value in milliseconds */ var match = String(ctx["time"]).match(RegExp("^([0-9]+)([smhdw])$")); if (match && match[0] != "undefined" && match[1] != "undefined") ctx["time"] = String(parseInt(match[1]) * { s: 1000, m: 1000*60, h: 1000*60*60, d: 1000*60*60*24, w: 1000*60*60*24*7 }[match[2]]); /* determine unique identifier of task */ if (ctx["id"] == null) ctx["id"] = ( String(ctx["repeat"]) + ":" + String(ctx["protect"]) + ":" + String(ctx["time"]) + ":" + String(ctx["obj"]) + ":" + String(ctx["func"]) + ":" + String(ctx["args"]) ); /* optionally protect from duplicate calls */ if (ctx["protect"]) if (typeof this.bucket[ctx["id"]] != "undefined") return this.bucket[ctx["id"]]; /* support execution of methods by name and arbitrary scripts */ if (!_isfn(ctx["func"])) { if ( ctx["obj"] != null && typeof ctx["obj"] == "object" && typeof ctx["func"] == "string" && _isfn(ctx["obj"][ctx["func"]])) /* method by name */ ctx["func"] = ctx["obj"][ctx["func"]]; else /* arbitrary script */ ctx["func"] = eval("function () { " + ctx["func"] + " }"); } /* pass-through to internal scheduling operation */ ctx["_handle"] = this._schedule(ctx); /* store context into bucket of scheduler object */ this.bucket[ctx["id"]] = ctx; /* return context */ return ctx; }, /* re-schedule a task */ reschedule: function (ctx) { if (typeof ctx == "string") ctx = this.bucket[ctx]; /* pass-through to internal scheduling operation */ ctx["_handle"] = this._schedule(ctx); /* return context */ return ctx; }, /* internal scheduling operation */ _schedule: function (ctx) { /* closure to act as the call trampoline function */ var trampoline = function () { /* jump into function */ var obj = (ctx["obj"] != null ? ctx["obj"] : ctx); (ctx["func"]).apply(obj, ctx["args"]); /* either repeat scheduling and keep in bucket or just stop scheduling and delete from scheduler bucket */ if ( /* not cancelled from inside... */ typeof (ctx["_scheduler"]).bucket[ctx["id"]] != "undefined" && /* ...and repeating requested */ ctx["repeat"]) (ctx["_scheduler"])._schedule(ctx); else delete (ctx["_scheduler"]).bucket[ctx["id"]]; }; /* schedule task and return handle */ return setTimeout(trampoline, ctx["time"]); }, /* cancel a scheduled task */ cancel: function (ctx) { if (typeof ctx == "string") ctx = this.bucket[ctx]; /* cancel scheduled task */ if (typeof ctx == "object") { clearTimeout(ctx["_handle"]); delete this.bucket[ctx["id"]]; } } }; /* integrate a global instance of the scheduler into the global jQuery object */ $.extend({ scheduler$: new $.scheduler(), schedule: function () { return $.scheduler$.schedule.apply ($.scheduler$, arguments) }, reschedule: function () { return $.scheduler$.reschedule.apply($.scheduler$, arguments) }, cancel: function () { return $.scheduler$.cancel.apply ($.scheduler$, arguments) } }); /* integrate scheduling convinience method into all jQuery objects */ $.fn.extend({ schedule: function () { var a = [ {} ]; for (var i = 0; i < arguments.length; i++) a.push(arguments[i]); return this.each(function () { a[0] = { "id": this, "obj": this }; return $.schedule.apply($, a); }); } }); })(jQuery);