Timing_JQuery_Util

try to take over the world!

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyfork.org/scripts/404470/812557/Timing_JQuery_Util.js

/**
 * code from http: //creativecouple.github.io/jquery-timing/jquery-timing.js
 * timing.jquery.js
 * 
 * JavaScript functions for waiting / repeating / stopping jQuery actions.
 * 
 * This code is published under the MIT License (MIT).
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * For examples, reference, and other information see
 * http://creativecouple.github.com/jquery-timing/
 * 
 * @author CreativeCouple
 * @author Peter Liske
 * @copyright (c) 2011 by CreativeCouple
 * @see http://creativecouple.github.com/jquery-timing/
 */

(function(jQuery, window){
	/**
	 * object to store statically invoked threads
	 */
	var THREAD_GROUPS = {},
	
	/**
	 * unique timing identifier for different purposes
	 */
	tuid = 1,

	/**
	 * remember original core function $.each()
	 */
	originalEach = jQuery.fn.each,

	/**
	 * remember original core function $.on() (or $.bind())
	 */
	originalOn = jQuery.fn.on || jQuery.fn.bind,
	
	/**
	 * remember original core function $.off() (or $.unbind())
	 */
	originalOff = jQuery.fn.off || jQuery.fn.unbind,
	
	/**
	 * .until() and .all() have special meanings
	 */
	loopEndMethods = {};
	
	function sameOrNextJQuery(before, after) {
		after = jQuery(after);
		after.prevObject = before;
		var i = before.length;
		if (i !== after.length) {
			return after;
		}
		while (i--) {
			if (before[i] !== after[i]) {
				return after;
			}
		}
		return before;
	}
	
	function loopCounts(loops) {
		var ret = [], i = loops.length;
		while (i--) {
			ret[i] = loops[i]._count;
		}
		return ret;
	}
	
	/**
	 * Initialize a new timed invocation chain.
	 * 
	 * @author CreativeCouple
	 * @author Peter Liske
	 * 
	 * @param context initial context
	 * @param methodStack linked list of methods that has been or will be filled by someone else 
	 * @param ongoingLoops optional arguments for callback parameters
	 * @param onStepCallback function to call on each step
	 * @returns the timed invocation chain method
	 */
	function createTimedInvocationChain(context, methodStack, ongoingLoops, onStepCallback) {
		ongoingLoops = ongoingLoops || [];
		var executionState = {
				_context: context,
				_method: methodStack
		},
		preventRecursion = false,
		method, otherExecutionState, deferred;
		
		function hookupToProxy(state, mockup){
			state._canContinue = false;
			function fire(){
				state._next = sameOrNextJQuery(state._context, state._next);
				state._canContinue = true;
				timedInvocationChain();
			}
			return typeof mockup.promise == "function" ? mockup.promise().then(fire) : mockup.then(fire, true);
		}
		
		/**
		 * Invoke all the methods currently in the timed invocation chain.
		 * 
		 * @author CreativeCouple
		 * @author Peter Liske
		 */
		function timedInvocationChain(deferredReturnValue) {
			while (!preventRecursion) try {
				// keep recursive calls away
				preventRecursion = !preventRecursion;
				// save current context state
				if (typeof onStepCallback == "function") {
					onStepCallback(jQuery.makeArray(executionState._next || executionState._context));
				}
				// leave the chain when waiting for a trigger
				if (executionState._canContinue == false) {
					break;
				}
				// check end of chain
				if (!executionState._method._name) {
					if (deferred && (!ongoingLoops.length || ongoingLoops[0]._allowPromise)) {
						// resolve any waiting promise 
						if (executionState._context && typeof executionState._context.promise == "function") {
							executionState._context.promise().then(deferred.resolve);
						} else {
							deferred.resolveWith(executionState._context);
						}
						deferred = null;
					}
					if (!ongoingLoops.length) {
						/*
						 * We've reached the end of our TIC
						 * and there is nothing left to wait for.
						 * So we can safely return the original jQuery object
						 * hence enabling instant invocation.
						 */
						return executionState._context; 
					}
					/*
					 * Now we have ongoing loops but reached the chain's end.
					 */
					otherExecutionState = ongoingLoops[0]._openEndAction && ongoingLoops[0]._openEndAction(timedInvocationChain, executionState, ongoingLoops);
					if (!otherExecutionState) {
						// if innermost loop can't help us, just leave the chain
						break;
					}
					executionState = otherExecutionState;
					continue;
				}
				// check if user tries to use a non-existing function call
				method = executionState._context && executionState._context[executionState._method._name] || loopEndMethods[executionState._method._name];
				if (!method) {					
					throw 'no such method "'+executionState._method._name+'" on object ('+executionState._context+')';
				}
				// check whether we came here triggered or not
				if (method.timing && !executionState._canContinue) {
					// prevent automatic re-trigger in case of loops
					executionState._canContinue = false;
					// handle timing method
					executionState = method.timing(timedInvocationChain, executionState, ongoingLoops, onStepCallback) || executionState;
				} else {
					if (!method.timing && !executionState._canContinue) {
						// prevent automatic re-trigger in case of loops
						executionState._next = executionState._context[executionState._method._name].apply(executionState._context, executionState._method._arguments);
						if (ongoingLoops.length && executionState._next && executionState._next instanceof PredictingProxy) {
							hookupToProxy(executionState, executionState._next);
							continue;
						}
					}
					// go to next step
					otherExecutionState = {
							_context: executionState._next,
							_method: executionState._method._next
					};
					// prevent automatic re-trigger in case of loops
					executionState._canContinue = false;
					// invoke callback method with given arguments
					if (typeof executionState._callback == "function") {
						executionState._callback.apply(executionState._context, loopCounts(ongoingLoops));
					}
					executionState = otherExecutionState;
				}
			} catch(e) {
				/*
				 * We had a runtime exception.
				 * In plain JavaScript live the chain would break now.
				 * So we do, too.
				 */
				preventRecursion = !preventRecursion;
				throw e;
			} finally {
				preventRecursion = !preventRecursion;				
			}
			return deferredReturnValue;
		};
		if (jQuery.Deferred) {
			// add .promise() method to tic
			timedInvocationChain.promise = function(type, target){
				var ret = (deferred = deferred || jQuery.Deferred()).promise(target);
				timedInvocationChain();
				return ret;
			};
		}
		return timedInvocationChain;
	}
	
	/**
	 * Create a placeholder object to collect chained method calls.
	 * 
	 * @author CreativeCouple
	 * @author Peter Liske
	 *
	 * @param context initial context
	 * @param methodStack a linked list that this placeholder will fill with call parameters 
	 * @return the placeholder object
	 */
	function PredictingProxy(context, methodStack, onStepCallback) {
		this['.methods'] = methodStack;
		this['.callback'] = onStepCallback;
		this.length = 0;
		Array.prototype.push.apply(this, jQuery.makeArray(this._ = context._ = context));
		
		for (var key in context) {
			if (!(key in PredictingProxy.prototype) && typeof context[key] == "function") {
				this[key] = extendMockupPrototype(key);
			}
		}
	}
	
	// enabling jQuery.when(tic);
	if (jQuery.Deferred) {
		PredictingProxy.prototype.promise = function(type, target) {
			if (typeof type == "object") {
				target = type;
				type = null;
			}
			return (this['.callback'] && typeof this['.callback'].promise == "function") ? this['.callback'].promise(type, target) : jQuery.Deferred().resolveWith(this).promise(target);
		};
	}
	
	/**
	 * Create and return a new placeholder function on the prototype of PredictingProxy. 
	 */
	function extendMockupPrototype(name){
		return PredictingProxy.prototype[name] = function(){
			this['.methods']._name = name;
			this['.methods']._arguments = arguments;
			this['.methods'] = this['.methods']._next = {};
			return this['.callback'] ? this['.callback'](this, name, arguments) : this;
		};
	}
	
	
	/**
	 * Create replacement methods for .bind(), .on(), .one(), .live(), and .delegate()
	 * that support chaining instead of giving a callback function.
	 */
	jQuery.each(['bind','on','one','live','delegate'], function(index, name){
		if (jQuery.fn[name]) {
			var original = jQuery.fn[name];
			jQuery.fn[name] = function(){
				var i, methodStack, placeholder, timedInvocationChain, deferred, context = this;
				for(i=0; i<arguments.length; i++) {
					if (typeof arguments[i] == "function" || (arguments[i] && typeof arguments[i] == "object") || arguments[i] === false) {
						if (arguments[i] !== jQuery) {
							// fix for jQuery 1.6 .one() + .unbind()
							if (typeof arguments[i] == "function" && jQuery.guid) {
								arguments[i].guid = arguments[i].guid || jQuery.guid++;
							}
							return original.apply(context, arguments);
						}
						break;
					}
				}
				Array.prototype.splice.call(arguments, i, 1, function(){
					timedInvocationChain = createTimedInvocationChain(context.$(this), methodStack, [{
							_count: jQuery.extend(Array.prototype.shift.apply(arguments), arguments),
							_allowPromise: true
						}], function(elements){
						placeholder.length = 0;
						Array.prototype.push.apply(placeholder, elements);
					});
					if (deferred) {
						timedInvocationChain.promise().then(deferred.resolve);
						deferred = null;
					}
					return timedInvocationChain();
				});
				function fire(){
					return timedInvocationChain ? timedInvocationChain(placeholder) : placeholder;
				}
				if (jQuery.Deferred) {					
					fire.promise = function(type, target){
						if (typeof type == "object") {
							target = type;
							type = null;
						}
						return (timedInvocationChain && !type) ? timedInvocationChain.promise(type, target) : (deferred = deferred || jQuery.Deferred()).promise(target);
					};
				}
				return placeholder = new PredictingProxy(original.apply(context, arguments), methodStack = {}, fire);
			};
		}
	});
	
	/**
	 * Create replacement method for .animate() and .load()
	 * that support chaining if $ is given as callback function.
	 */
	jQuery.each(['animate','load'], function(index, name){
		if (jQuery.fn[name]) {
			var original = jQuery.fn[name];
			jQuery.fn[name] = function(){
				while (arguments.length && arguments[arguments.length-1] == null) {
					Array.prototype.pop.apply(arguments);
				}
				if (this.length && arguments.length > 1 && arguments[arguments.length-1] === jQuery) {
					var event = '_timing'+tuid++;
					arguments[arguments.length-1] = function(){
						jQuery(this).trigger(event);
					};
					return this.each().one(event).all(original.apply(this, arguments));
				}
				return original.apply(this, arguments);
			};
		}
	});
		
	/**
	 * Define new methods .wait(), .repeat(), .join(), .then()
	 * which will always start a new TIC if invoked outside of a TIC.  
	 */
	jQuery.each(['wait','repeat','join','then'], function(index, name){
		jQuery.fn[name] = function(){
			var methodStack = {},
			placeholder = new PredictingProxy(this, methodStack, createTimedInvocationChain(this, methodStack, [], function(elements){
					placeholder.length = 0;
					Array.prototype.push.apply(placeholder, elements);
				}));
			return placeholder[name].apply(placeholder, arguments);
		};
	});
	
	/**
	 * Define to wait for joining all animation queues.
	 * 
	 * @param timedInvocationChain
	 * @param executionState
	 */
	jQuery.fn.join.timing = function(timedInvocationChain, executionState) {
		var queueName,
		promising,
		waitingElements = executionState._context.length;
		
		if (typeof executionState._method._arguments[0] == "string") {
			queueName = executionState._method._arguments[0];
			if (typeof executionState._method._arguments[1] == "function") {
				executionState._callback = executionState._method._arguments[1];
			} else {
				promising = executionState._method._arguments[1];
				executionState._callback = executionState._method._arguments[2];
			}
		} else {
			if (typeof executionState._method._arguments[0] == "function") {
				executionState._callback = executionState._method._arguments[0];
			} else {
				promising = executionState._method._arguments[0];
				executionState._callback = executionState._method._arguments[1];
			}
		}
		
		executionState._next = executionState._context;
		executionState._canContinue = !waitingElements;

		// wait for each element to reach the current end of its queue
		if (promising) {
			executionState._context.promise(queueName == null ? 'fx' : queueName).then(function(){
				executionState._canContinue = true;
				timedInvocationChain();
			});
		} else {
			executionState._context.queue(queueName == null ? 'fx' : queueName, function(next){
				executionState._canContinue = !--waitingElements;
				timedInvocationChain();
				next();
			});
		}
	};

	/**
	 * Define to simply run callback method for .then()
	 * 
	 * @param timedInvocationChain
	 * @param executionState
	 */
	jQuery.fn.then.timing = function(timedInvocationChain, executionState){
		executionState._callback = executionState._method._arguments[0];
		executionState._next = executionState._context;
		executionState._canContinue = true;
		if (executionState._method._arguments[1]) {
			Array.prototype.shift.apply(executionState._method._arguments);
		}
	};
	
	/**
	 * Define timeout or binding to wait for.
	 * 
	 * @param timedInvocationChain
	 * @param executionState
	 */
	jQuery.fn.wait.timing = function(timedInvocationChain, executionState, ongoingLoops) {
		var trigger, event, timeout, context = executionState._context;
		
		trigger = executionState._method._arguments[0];
		executionState._callback = executionState._method._arguments[1];

		function triggerAction() {
			originalOff.call(event ? originalOff.call(context, event, triggerAction) : context, 'unwait', unwaitAction);
			executionState._canContinue = true;
			executionState._next = sameOrNextJQuery(executionState._context, executionState._next);
			timedInvocationChain();
		}
		
		function unwaitAction(evt, skipWait){
			originalOff.call(event ? originalOff.call(jQuery(this), event, triggerAction) : jQuery(this), 'unwait', unwaitAction);
			context = context.not(this);
			if (!skipWait) {
				executionState._next = executionState._next.not(this);
			}
			if (!context.length) {
				executionState._canContinue = executionState._next.length;
				executionState._next = sameOrNextJQuery(executionState._context, executionState._next);
				window.clearTimeout(timeout);
				executionState = { _context: context };
			}
			// just update the snapshot info
			timedInvocationChain();
		}

		originalOn.call(context, 'unwait', unwaitAction);
		executionState._next = context;

		if (trigger == null || trigger == jQuery) {
			trigger = context;
		}	
		if (typeof trigger == "function") {
			trigger = trigger.apply(context, loopCounts(ongoingLoops));
		}
		if (typeof trigger == "string") {

			originalOn.call(context, event = trigger, triggerAction);

		} else if (trigger && typeof trigger.promise == "function") {
			
			trigger.promise().then(triggerAction);
			
		} else if (trigger && typeof trigger.then == "function") {
			
			trigger.then(triggerAction, true);
			
		} else {

			timeout = window.setTimeout(triggerAction, Math.max(0,trigger));

		}
	};

	/**
	 * Define to simply run callback method for .then()
	 * 
	 * @param timedInvocationChain
	 * @param executionState
	 */
	jQuery.fn.each = function(callback){
		if (!callback || callback === jQuery) {
			var methodStack = {},
			placeholder = new PredictingProxy(this, methodStack, createTimedInvocationChain(this, methodStack, [], function(elements){
					placeholder.length = 0;
					Array.prototype.push.apply(placeholder, elements);
				}));
			return placeholder.each(callback);
		}
		return originalEach.apply(this, arguments);
	};
	
	/**
	 * Define interval or binding to repeat.
	 * 
	 * @param timedInvocationChain
	 * @param executionState
	 */
	jQuery.fn.each.timing = function(timedInvocationChain, executionState, ongoingLoops, onStepCallback) {
		if (executionState._method._arguments[0] && executionState._method._arguments[0] !== jQuery) {
			executionState._canContinue = true;
			executionState._next = originalEach.apply(executionState._context, executionState._method._arguments);
			return;
		}
		
		var size = Math.max(executionState._context.length, 1),
		finished = 0,
		key, methodToGoOn, openLoopTimeout,
		innerTICs = [],
		innerElements = [],
		proxyPlaceholder = jQuery.extend({}, executionState._context),
		stepByStep = executionState._method._arguments[0] === jQuery;

		if (stepByStep) {
			window.setTimeout(function(){
				openLoopTimeout = true;
				timedInvocationChain();
			},0);
		}
		
		function spreadAction(){
			if (stepByStep) {
				if (finished < size) {
					(innerTICs[finished])();
				}
			} else {
				for (var i=0; i<size; i++) {
					(innerTICs[i])();
				}
			}
			return proxyPlaceholder;
		}
		
		for (key in PredictingProxy.prototype) {
			proxyPlaceholder[key] = spreadAction;
		}
		proxyPlaceholder.length = size;
		for(key=0; key<size; key++) (function(index){
			var innerLoops = ongoingLoops.slice(),
			context = executionState._context.eq(index);
			innerElements[index] = context.get();
			innerLoops.unshift({
				_count: index,
				_allAction: function(state){
					finished++;
					if (finished == size) {
						methodToGoOn = state._method._next;
					}
					timedInvocationChain();
				},
				_fixOpenLoop: loopEndMethods.all,
				_openEndAction: function(tic, state){
					if (openLoopTimeout) {
						finished++;
						if (finished == size) {
							methodToGoOn = state._method;
						}
						timedInvocationChain();
					}
				}
			});
			innerTICs[index] = createTimedInvocationChain(context, executionState._method._next, innerLoops, function(elements){
				innerElements[index] = elements;
				proxyPlaceholder.length = 0;
				for (var i=0; i<size; i++) {
					Array.prototype.push.apply(proxyPlaceholder, innerElements[i]);
				}
				if (onStepCallback)
					onStepCallback(jQuery.makeArray(proxyPlaceholder));
			});
		})(key);

		executionState._next = proxyPlaceholder;
		executionState._canContinue = true;
		executionState._openEndAction = function(tic, state){			
			if (finished == size) {
				ongoingLoops.shift();
				return {
					_context: sameOrNextJQuery(executionState._context, proxyPlaceholder),
					_method: methodToGoOn
				};
			}
			var finishedBefore = finished;
			spreadAction();
			if (finished != finishedBefore) {
				return state;
			}
		};
		executionState._count = size;
		
		ongoingLoops.unshift(executionState);
	};

	loopEndMethods.all = function(executionState){
		jQuery.extend(executionState._method, {
			_next: jQuery.extend({}, executionState._method),
			_name: 'all',
			_arguments: []
		});
		executionState._canContinue = null;
	};
	loopEndMethods.all.timing = function(timedInvocationChain, executionState, ongoingLoops) {
		if (!ongoingLoops.length || !ongoingLoops[0]._fixOpenLoop) {
			throw '.all() method must be used after .each() only';
		}
		if (!ongoingLoops[0]._allAction) {
			ongoingLoops[0]._fixOpenLoop(executionState);
			return;
		}
		
		ongoingLoops[0]._allAction(executionState);
	};
	
	/**
	 * Define interval or binding to repeat.
	 * 
	 * @param timedInvocationChain
	 * @param executionState
	 */
	jQuery.fn.repeat.timing = function(timedInvocationChain, executionState, ongoingLoops) {
		var trigger,
		firstRunNow,
		openLoopTimeout,
		event,
		interval;

		if (typeof executionState._method._arguments[0] == "function") {
			executionState._callback = executionState._method._arguments[0];
		} else if (typeof executionState._method._arguments[1] == "function") {
			trigger = executionState._method._arguments[0];
			executionState._callback = executionState._method._arguments[1];
		} else {
			trigger = executionState._method._arguments[0];
			firstRunNow = executionState._method._arguments[1];
			executionState._callback = executionState._method._arguments[2];
		}
		
		function triggerAction() {
			executionState._next = executionState._next || executionState._context;
			executionState._canContinue = true;
			timedInvocationChain();
		}
		
		function unrepeatAction(){
			originalOff.call(event ? originalOff.call(jQuery(this), event, triggerAction) : jQuery(this), 'unrepeat', unrepeatAction);
			var context = executionState._context.not(this);
			executionState._next = (executionState._next == executionState._context) ? context : executionState._next;
			executionState._context = context;
			executionState._canContinue = executionState._context.length && executionState._canContinue;
			trigger = executionState._context.length && trigger;
			window.clearInterval(!executionState._context.length && interval);
			// just update the snapshot info
			timedInvocationChain();
		}
		
		executionState._openEndAction = function(tic, state){
			if (executionState._canContinue || openLoopTimeout) {
				executionState._count++;
				executionState._next = executionState._next || executionState._context;
				executionState._canContinue = executionState._canContinue || (trigger && state._context && state._context.length);
				return executionState;
			}
		};

		if (trigger == null) {
			
			firstRunNow = trigger = true;
			window.setTimeout(function(){
				openLoopTimeout = true;
				timedInvocationChain();
			},0);
			
		} else {
			if (typeof trigger == "string") {
				originalOn.call(executionState._context, event = trigger, triggerAction);
			} else {
				interval = window.setInterval(triggerAction, Math.max(0, trigger));				
			}
			trigger = false;
		}

		originalOn.call(executionState._context, 'unrepeat', unrepeatAction);
		
		executionState._next = executionState._context;
		executionState._count = 0;
		executionState._untilAction = function(end){
			if (end) {
				unrepeatAction.apply(executionState._context);
			}
			if (trigger) {
				triggerAction();
			}
		};
		executionState._fixOpenLoop = loopEndMethods.until;

		if (firstRunNow) {
			triggerAction();
		}
		
		ongoingLoops.unshift(executionState);
	};

	/**
	 * Defined to evaluate condition when calling .until()
	 */
	loopEndMethods.until = function(executionState){
		jQuery.extend(executionState._method, {
			_next: jQuery.extend({}, executionState._method),
			_name: 'until',
			_arguments: []
		});
		executionState._canContinue = null;
	};
	loopEndMethods.until.timing = function(timedInvocationChain, executionState, ongoingLoops) {
		if (!ongoingLoops.length || !ongoingLoops[0]._fixOpenLoop) {
			throw '.until() method must be used after .repeat() only';
		}
		if (!ongoingLoops[0]._untilAction) {
			ongoingLoops[0]._fixOpenLoop(executionState);
			return;
		}

		var condition = executionState._method._arguments[0],
		loopContext = executionState._method._arguments[1];
		if (condition === jQuery) {
			condition = null;
			loopContext = executionState._method._arguments.length <= 1 || loopContext;
		}
		if (typeof condition == "function") {
			condition = condition.apply(executionState._context, loopCounts(ongoingLoops));
		}
		if (condition == null) {
			condition = !executionState._context.size();
		}
		if (typeof condition == "object") {
			condition = condition.toString();
		}
		if (typeof condition == "number") {
			condition = ongoingLoops[0]._count >= condition-1;
		}
		if (condition) {
			executionState._canContinue = true;
			executionState._next = executionState._context;
			ongoingLoops.shift()._untilAction(condition);
		} else {
			if (loopContext) {
				ongoingLoops[0]._next = executionState._context;
			}
			executionState = ongoingLoops[0];
			executionState._count++;
			executionState._untilAction(condition);
			return executionState;
		}
	};
	
	// support .until() and .all()
	new PredictingProxy(loopEndMethods);
	
	/**
	 * Define unwait and unrepeat methods.
	 */
	jQuery.each(['unwait','unrepeat'], function(index, name){
		jQuery.fn[name] = function(){
			return this.trigger(name, arguments);
		};
	});
	
	/**
	 * define all static timing methods:
	 *  $.wait, $.repeat ,$.join, $.then, $.unwait, $.unrepeat
	 */
	jQuery.each(['wait','repeat','join','then','unwait','unrepeat'], function(index, name){
		jQuery[name] = function(){
			var group = typeof arguments[0] == "string" ? Array.prototype.shift.apply(arguments) : '';
			return jQuery.fn[name].apply(THREAD_GROUPS[group] = (THREAD_GROUPS[group] || jQuery('<div>').text(group)), arguments);
		};
	});

	/**
	 * X defines deferred variables that can be used in timed invocation chains 
	 * 
	 * @author CreativeCouple
	 * @author Peter Liske
	 */
	function X(compute, Var, calculation){
		if (typeof compute == "string") {
			calculation = new Function('x','return ['+compute+'\n,x]');
			compute = function(x, result){
				result = calculation(x);
				callbackVariable.x = result[1];
				return result[0];
			};
		}
		var hasRelatedVariable = typeof Var == "function",
		hasComputation = typeof compute == "function",
		
		callbackVariable = function(value) {
			if (arguments.length == 1) {
				callbackVariable.x = value;
				if (hasRelatedVariable) {
					Var(value);
				}
			} else {
				return evaluate();
			}
		};
		function evaluate(value){
			value = hasRelatedVariable ? Var() : callbackVariable.x;
			return hasComputation ? compute(value) : value;				
		}
		
		callbackVariable.x = 0;
		callbackVariable._ = { toString: callbackVariable.$ = callbackVariable.toString = evaluate.toString = evaluate };
		callbackVariable.mod = function(val){
			return X(function(x){
				return x % val;
			}, callbackVariable);
		};
		callbackVariable.add = function(val){
			return X(function(x){
				return x + val;
			}, callbackVariable);
		};
		callbackVariable.neg = function(){
			return X('-x', callbackVariable);
		};
		// $$ only for backward compatibility
		callbackVariable.$$ = callbackVariable.X = function(compute){
			return X(compute, callbackVariable);
		};
		jQuery.each(['a','b','c','d','e','f','g','h','i','j'], function(index, character){
			callbackVariable[index] = callbackVariable[character] = function(){
				callbackVariable(arguments[index]);
			};
		});
		
		return callbackVariable;
	};
	
	// $$ only for backward compatibility
	window.$$ = jQuery.$$ = jQuery.X = X;
	
	/**
	 * Define chained version of $().
	 * This allows to use .end() to come back to previous jQuery selection.
	 */
	jQuery.fn.$ = function(){
		var ret = jQuery.apply(window, arguments);
		ret.prevObject = this;
		return ret;
	};
	
})(jQuery, window);