<commit_before>// Define a local copy of jQuery
var jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return arguments.length === 0 ?
			rootjQuery :
			new jQuery.fn.init( selector, context );
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// Use the correct document accordingly with window argument (sandbox)
	document = window.document,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// (both of which we optimize for)
	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,

	// Is it a simple selector
	isSimple = /^.[^:#\[\.,]*$/,

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent.toLowerCase(),

	// Save a reference to the core toString method
	toString = Object.prototype.toString;

// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
		var match, elem, ret;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) {
			this.length = 0;
			return this;
		}

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this[0] = selector;
			this.length = 1;
			this.context = selector;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			match = quickExpr.exec( selector );

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					selector = jQuery.clean( [ match[1] ], context );

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[3] );

					// Handle the case where IE and Opera return items
					// by name instead of ID
					if ( elem && elem.id !== match[3] ) {
						return rootjQuery.find( selector );
					}

					// Otherwise, we inject the element directly into the jQuery object
					this.length = elem ? 1 : 0;
					if ( elem ) {
						this[0] = elem;
					}
					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return (context || rootjQuery).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return jQuery( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		// Make sure that old selector state is passed along
		if ( selector.selector && selector.context ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return this.setArray(jQuery.isArray( selector ) ?
			selector :
			jQuery.makeArray(selector));
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "@VERSION",

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},

	toArray: Array.prototype.slice,

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this.toArray.call(this, num)[0] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = jQuery( elems || null );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" ) {
			ret.selector = this.selector + (this.selector ? " " : "") + selector;
		} else if ( name ) {
			ret.selector = this.selector + "." + name + "(" + selector + ")";
		}

		// Return the newly-formed element set
		return ret;
	},

	// Force the current matched set of elements to become
	// the specified array of elements (destroying the stack in the process)
	// You should use pushStack() in order to do this, but maintain the stack
	setArray: function( elems ) {
		// Resetting the length to 0, then using the native Array push
		// is a super-fast way to populate an object with array-like properties
		this.length = 0;
		Array.prototype.push.apply( this, elems );

		return this;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {
		if ( !elem || typeof elem === "string" ) {
			return jQuery.inArray( this[0],
				// If it receives a string, the selector is used
				// If it receives nothing, the siblings are used
				elem ? jQuery( elem ) : this.parent().children() );
		}
		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[0] : elem, this );
	},

	is: function( selector ) {
		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: [].push,
	sort: [].sort,
	splice: [].splice
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

jQuery.extend = jQuery.fn.extend = function() {
	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( length === i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging object values
				if ( deep && copy && typeof copy === "object" && !copy.nodeType ) {
					var clone;

					if( src ) clone = src;
					else if( jQuery.isArray(copy) ) clone = [ ];
					else if( jQuery.isObject(copy) ) clone = { };
					else clone = copy;

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend({
	noConflict: function( deep ) {
		window.$ = _$;

		if ( deep ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return toString.call(obj) === "[object Function]";
	},

	isArray: function( obj ) {
		return toString.call(obj) === "[object Array]";
	},

	isObject: function( obj ) {
		return this.constructor.call(obj) === Object;
	},

	isEmptyObject: function( obj ) {
		for(var name in obj)
			return false;
		return true;
	},

	// check if an element is in a (or is an) XML document
	isXMLDoc: function( elem ) {
		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
			!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
	},

	// Evalulates a script in a global context
	globalEval: function( data ) {
		if ( data && /\S/.test(data) ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";
			if ( jQuery.support.scriptEval ) {
				script.appendChild( document.createTextNode( data ) );
			} else {
				script.text = data;
			}

			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
			// This arises when a base node is used (#2709).
			head.insertBefore( script, head.firstChild );
			head.removeChild( script );
		}
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0,
			length = object.length,
			isObj = length === undefined || jQuery.isFunction(object);

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}
			} else {
				for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
			}
		}

		return object;
	},

	trim: function( text ) {
		return (text || "").replace( /^\s+|\s+$/g, "" );
	},

	makeArray: function( array ) {
		var ret = [], i;

		if ( array != null ) {
			i = array.length;

			// The window, strings (and functions) also have 'length'
			if ( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval ) {
				ret[0] = array;
			} else {
				while ( i ) {
					ret[--i] = array[i];
				}
			}
		}

		return ret;
	},

	inArray: function( elem, array ) {
		for ( var i = 0, length = array.length; i < length; i++ ) {
			if ( array[ i ] === elem ) {
				return i;
			}
		}

		return -1;
	},

	merge: function( first, second ) {
		// We have to loop this way because IE & Opera overwrite the length
		// expando of getElementsByTagName
		var i = 0, elem, pos = first.length;

		// Also, we need to make sure that the correct elements are being returned
		// (IE returns comment nodes in a '*' query)
		if ( !jQuery.support.getAll ) {
			while ( (elem = second[ i++ ]) != null ) {
				if ( elem.nodeType !== 8 ) {
					first[ pos++ ] = elem;
				}
			}

		} else {
			while ( (elem = second[ i++ ]) != null ) {
				first[ pos++ ] = elem;
			}
		}

		return first;
	},

	unique: function( array ) {
		var ret = [], done = {}, id;

		try {
			for ( var i = 0, length = array.length; i < length; i++ ) {
				id = jQuery.data( array[ i ] );

				if ( !done[ id ] ) {
					done[ id ] = true;
					ret.push( array[ i ] );
				}
			}
		} catch( e ) {
			ret = array;
		}

		return ret;
	},

	grep: function( elems, callback, inv ) {
		var ret = [];

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			if ( !inv !== !callback( elems[ i ], i ) ) {
				ret.push( elems[ i ] );
			}
		}

		return ret;
	},

	map: function( elems, callback ) {
		var ret = [], value;

		// Go through the array, translating each of the items to their
		// new value (or values).
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			value = callback( elems[ i ], i );

			if ( value != null ) {
				ret[ ret.length ] = value;
			}
		}

		return ret.concat.apply( [], ret );
	},

	// Use of jQuery.browser is deprecated.
	// It's included for backwards compatibility and plugins,
	// although they should work to migrate away.
	browser: {
		version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
		safari: /webkit/.test( userAgent ),
		opera: /opera/.test( userAgent ),
		msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
		mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
	}
});

// All jQuery objects should point back to these
rootjQuery = jQuery(document);

function evalScript( i, elem ) {
	if ( elem.src ) {
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});
	} else {
		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
	}

	if ( elem.parentNode ) {
		elem.parentNode.removeChild( elem );
	}
}

function now() {
	return (new Date).getTime();
}
<commit_msg>jQuery objects have a default length of 0. Simplifies $() some.<commit_after>// Define a local copy of jQuery
var jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return arguments.length === 0 ?
			rootjQuery :
			new jQuery.fn.init( selector, context );
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// Use the correct document accordingly with window argument (sandbox)
	document = window.document,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// (both of which we optimize for)
	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,

	// Is it a simple selector
	isSimple = /^.[^:#\[\.,]*$/,

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent.toLowerCase(),

	// Save a reference to the core toString method
	toString = Object.prototype.toString;

// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
		var match, elem, ret;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) return this;

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this[0] = selector;
			this.length++;
			this.context = selector;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			match = quickExpr.exec( selector );

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					selector = jQuery.clean( [ match[1] ], context );

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[3] );

					if ( elem ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						if ( elem.id !== match[3] ) return rootjQuery.find( selector );

						// Otherwise, we inject the element directly into the jQuery object
						this.length++;
						this[0] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return (context || rootjQuery).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return jQuery( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		// Make sure that old selector state is passed along
		if ( selector.selector && selector.context ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return this.setArray(jQuery.isArray( selector ) ?
			selector :
			jQuery.makeArray(selector));
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "@VERSION",

	// The default length of a jQuery object is 0
	length: 0,

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},

	toArray: Array.prototype.slice,

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this.toArray.call(this, num)[0] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = jQuery( elems || null );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" ) {
			ret.selector = this.selector + (this.selector ? " " : "") + selector;
		} else if ( name ) {
			ret.selector = this.selector + "." + name + "(" + selector + ")";
		}

		// Return the newly-formed element set
		return ret;
	},

	// Force the current matched set of elements to become
	// the specified array of elements (destroying the stack in the process)
	// You should use pushStack() in order to do this, but maintain the stack
	setArray: function( elems ) {
		// Resetting the length to 0, then using the native Array push
		// is a super-fast way to populate an object with array-like properties
		this.length = 0;
		Array.prototype.push.apply( this, elems );

		return this;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {
		if ( !elem || typeof elem === "string" ) {
			return jQuery.inArray( this[0],
				// If it receives a string, the selector is used
				// If it receives nothing, the siblings are used
				elem ? jQuery( elem ) : this.parent().children() );
		}
		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[0] : elem, this );
	},

	is: function( selector ) {
		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: [].push,
	sort: [].sort,
	splice: [].splice
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

jQuery.extend = jQuery.fn.extend = function() {
	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( length === i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging object values
				if ( deep && copy && typeof copy === "object" && !copy.nodeType ) {
					var clone;

					if( src ) clone = src;
					else if( jQuery.isArray(copy) ) clone = [ ];
					else if( jQuery.isObject(copy) ) clone = { };
					else clone = copy;

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend({
	noConflict: function( deep ) {
		window.$ = _$;

		if ( deep ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return toString.call(obj) === "[object Function]";
	},

	isArray: function( obj ) {
		return toString.call(obj) === "[object Array]";
	},

	isObject: function( obj ) {
		return this.constructor.call(obj) === Object;
	},

	isEmptyObject: function( obj ) {
		for(var name in obj)
			return false;
		return true;
	},

	// check if an element is in a (or is an) XML document
	isXMLDoc: function( elem ) {
		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
			!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
	},

	// Evalulates a script in a global context
	globalEval: function( data ) {
		if ( data && /\S/.test(data) ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";
			if ( jQuery.support.scriptEval ) {
				script.appendChild( document.createTextNode( data ) );
			} else {
				script.text = data;
			}

			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
			// This arises when a base node is used (#2709).
			head.insertBefore( script, head.firstChild );
			head.removeChild( script );
		}
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0,
			length = object.length,
			isObj = length === undefined || jQuery.isFunction(object);

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}
			} else {
				for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
			}
		}

		return object;
	},

	trim: function( text ) {
		return (text || "").replace( /^\s+|\s+$/g, "" );
	},

	makeArray: function( array ) {
		var ret = [], i;

		if ( array != null ) {
			i = array.length;

			// The window, strings (and functions) also have 'length'
			if ( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval ) {
				ret[0] = array;
			} else {
				while ( i ) {
					ret[--i] = array[i];
				}
			}
		}

		return ret;
	},

	inArray: function( elem, array ) {
		for ( var i = 0, length = array.length; i < length; i++ ) {
			if ( array[ i ] === elem ) {
				return i;
			}
		}

		return -1;
	},

	merge: function( first, second ) {
		// We have to loop this way because IE & Opera overwrite the length
		// expando of getElementsByTagName
		var i = 0, elem, pos = first.length;

		// Also, we need to make sure that the correct elements are being returned
		// (IE returns comment nodes in a '*' query)
		if ( !jQuery.support.getAll ) {
			while ( (elem = second[ i++ ]) != null ) {
				if ( elem.nodeType !== 8 ) {
					first[ pos++ ] = elem;
				}
			}

		} else {
			while ( (elem = second[ i++ ]) != null ) {
				first[ pos++ ] = elem;
			}
		}

		return first;
	},

	unique: function( array ) {
		var ret = [], done = {}, id;

		try {
			for ( var i = 0, length = array.length; i < length; i++ ) {
				id = jQuery.data( array[ i ] );

				if ( !done[ id ] ) {
					done[ id ] = true;
					ret.push( array[ i ] );
				}
			}
		} catch( e ) {
			ret = array;
		}

		return ret;
	},

	grep: function( elems, callback, inv ) {
		var ret = [];

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			if ( !inv !== !callback( elems[ i ], i ) ) {
				ret.push( elems[ i ] );
			}
		}

		return ret;
	},

	map: function( elems, callback ) {
		var ret = [], value;

		// Go through the array, translating each of the items to their
		// new value (or values).
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			value = callback( elems[ i ], i );

			if ( value != null ) {
				ret[ ret.length ] = value;
			}
		}

		return ret.concat.apply( [], ret );
	},

	// Use of jQuery.browser is deprecated.
	// It's included for backwards compatibility and plugins,
	// although they should work to migrate away.
	browser: {
		version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
		safari: /webkit/.test( userAgent ),
		opera: /opera/.test( userAgent ),
		msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
		mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
	}
});

// All jQuery objects should point back to these
rootjQuery = jQuery(document);

function evalScript( i, elem ) {
	if ( elem.src ) {
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});
	} else {
		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
	}

	if ( elem.parentNode ) {
		elem.parentNode.removeChild( elem );
	}
}

function now() {
	return (new Date).getTime();
}
<|endoftext|>


<commit_before>import React from 'react'
import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

import { Message } from 'semantic-ui-react'

const CheckboxTypesExamples = () => (
  <ExampleSection title='Types'>
    <Message info>
      All checkbox types use an input with type checkbox, except for type radio.
      {' '}Use inputType if you'd like to mix and match style and behavior.
      {' '}For instance, type slider with inputType radio for exclusive sliders.
    </Message>

    <ComponentExample
      title='Checkbox'
      description='A box for checking.'
      examplePath='modules/Checkbox/Types/CheckboxExampleCheckbox'
    />
    <ComponentExample
      description='You can define a label with a props object.'
      examplePath='modules/Checkbox/Types/CheckboxExampleShorthandObject'
    />
    <ComponentExample
      description='You can define a label by passing your own element.'
      examplePath='modules/Checkbox/Types/CheckboxExampleShorthandElement'
    />

    <ComponentExample
      title='Toggle'
      description='A checkbox can toggle.'
      examplePath='modules/Checkbox/Types/CheckboxExampleToggle'
    />

    <ComponentExample
      title='Slider'
      description='A checkbox can look like a slider.'
      examplePath='modules/Checkbox/Types/CheckboxExampleSlider'
    />

    <ComponentExample
      title='Radio'
      description='A checkbox can be formatted as a radio element. This means it is an exclusive option.'
      examplePath='modules/Checkbox/Types/CheckboxExampleRadio'
    />

    <ComponentExample
      title='Radio Group'
      examplePath='modules/Checkbox/Types/CheckboxExampleRadioGroup'
    >
      <Message warning>
        Radios in a group must be

           controlled components.

      </Message>
    </ComponentExample>
  </ExampleSection>
)

export default CheckboxTypesExamples
<commit_msg>fix(docs) - fix checkbox inputType docs to use correct props (#1263)<commit_after>import React from 'react'
import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

import { Message } from 'semantic-ui-react'

const CheckboxTypesExamples = () => (
  <ExampleSection title='Types'>
    <Message info>
      All checkbox types use an input with type checkbox unless type is provided.
      {' '}Use type if you'd like to mix and match style and behavior.
      {' '}For instance, slider with type radio for exclusive sliders.
    </Message>

    <ComponentExample
      title='Checkbox'
      description='A box for checking.'
      examplePath='modules/Checkbox/Types/CheckboxExampleCheckbox'
    />
    <ComponentExample
      description='You can define a label with a props object.'
      examplePath='modules/Checkbox/Types/CheckboxExampleShorthandObject'
    />
    <ComponentExample
      description='You can define a label by passing your own element.'
      examplePath='modules/Checkbox/Types/CheckboxExampleShorthandElement'
    />

    <ComponentExample
      title='Toggle'
      description='A checkbox can toggle.'
      examplePath='modules/Checkbox/Types/CheckboxExampleToggle'
    />

    <ComponentExample
      title='Slider'
      description='A checkbox can look like a slider.'
      examplePath='modules/Checkbox/Types/CheckboxExampleSlider'
    />

    <ComponentExample
      title='Radio'
      description='A checkbox can be formatted as a radio element. This means it is an exclusive option.'
      examplePath='modules/Checkbox/Types/CheckboxExampleRadio'
    />

    <ComponentExample
      title='Radio Group'
      examplePath='modules/Checkbox/Types/CheckboxExampleRadioGroup'
    >
      <Message warning>
        Radios in a group must be

           controlled components.

      </Message>
    </ComponentExample>
  </ExampleSection>
)

export default CheckboxTypesExamples
<|endoftext|>


<commit_before>define(
  'ephox.snooker.selection.Rectangular',

  [
    'ephox.peanut.Fun',
    'ephox.perhaps.Option',
    'ephox.snooker.api.Structs',
    'ephox.snooker.model.DetailsList',
    'ephox.snooker.model.Warehouse',
    'ephox.snooker.selection.SpanningCells',
    'ephox.sugar.api.Compare',
    'global!Math'
  ],

  function (Fun, Option, Structs, DetailsList, Warehouse, SpanningCells, Compare, Math) {
    var getBox = function (table, startCell, finishCell) {
      var list = DetailsList.fromTable(table);
      var warehouse = Warehouse.generate(list);

      var startCoords = Warehouse.findItem(warehouse, startCell, Compare.eq);
      var finishCoords = Warehouse.findItem(warehouse, finishCell, Compare.eq);
      return startCoords.bind(function (sc) {
        return finishCoords.map(function (fc) {

          var leftCol = Math.min(sc.column(), fc.column());
          var rightCol = Math.max(sc.column() + sc.colspan() - 1, fc.column() + fc.colspan() - 1);

          var topRow = Math.min(sc.row(), fc.row());
          var bottomRow = Math.max(sc.row() + sc.rowspan() - 1 , fc.row() + fc.rowspan() - 1);

          return {
            startCol: Fun.constant(leftCol),
            finishCol: Fun.constant(rightCol),

            startRow: Fun.constant(topRow),
            finishRow: Fun.constant(bottomRow),
            // This will need to be a fun constant.
            warehouse: warehouse
          };
        });
      });
    };

    var isRectangular = function (table, startCell, finishCell) {
      return getBox(table, startCell, finishCell).bind(function (info) {

        var boundingBox = Structs.bounds({
          startRow: info.startRow(),
          startCol : info.startCol(),
          finishRow : info.finishRow(),
          finishCol : info.finishCol()
        });

        var isRect = true;
        for (var i = info.startRow(); i<=info.finishRow(); i++) {
          for (var j = info.startCol(); j<=info.finishCol(); j++ ) {
            var cell = Structs.cell({
              row : i,
              col : j
            });
            isRect = isRect && SpanningCells.isSpanning(info.warehouse.access(), cell, boundingBox);
          }
        }

        return isRect ? Option.some(info) : Option.none();
      });
    };

    return {
      getBox: getBox,
      isRectangular: isRectangular
    };
  }
);<commit_msg>TBIO-405: for merging in polish<commit_after>define(
  'ephox.snooker.selection.Rectangular',

  [
    'ephox.peanut.Fun',
    'ephox.perhaps.Option',
    'ephox.snooker.api.Structs',
    'ephox.snooker.model.DetailsList',
    'ephox.snooker.model.Warehouse',
    'ephox.snooker.selection.SpanningCells',
    'ephox.sugar.api.Compare',
    'global!Math'
  ],

  function (Fun, Option, Structs, DetailsList, Warehouse, SpanningCells, Compare, Math) {
    var getBox = function (table, startCell, finishCell) {
      var list = DetailsList.fromTable(table);
      var warehouse = Warehouse.generate(list);

      var startCoords = Warehouse.findItem(warehouse, startCell, Compare.eq);
      var finishCoords = Warehouse.findItem(warehouse, finishCell, Compare.eq);
      return startCoords.bind(function (sc) {
        return finishCoords.map(function (fc) {

          var leftCol = Math.min(sc.column(), fc.column());
          var rightCol = Math.max(sc.column() + sc.colspan() - 1, fc.column() + fc.colspan() - 1);

          var topRow = Math.min(sc.row(), fc.row());
          var bottomRow = Math.max(sc.row() + sc.rowspan() - 1 , fc.row() + fc.rowspan() - 1);

          console.log('leftCol', leftCol, 'rightCol', rightCol);

          return {
            startCol: Fun.constant(leftCol),
            finishCol: Fun.constant(rightCol),

            startRow: Fun.constant(topRow),
            finishRow: Fun.constant(bottomRow),
            // This will need to be a fun constant.
            warehouse: warehouse
          };
        });
      });
    };

    var isRectangular = function (table, startCell, finishCell) {
      return getBox(table, startCell, finishCell).bind(function (info) {

        var boundingBox = Structs.bounds({
          startRow: info.startRow(),
          startCol : info.startCol(),
          finishRow : info.finishRow(),
          finishCol : info.finishCol()
        });

        var isRect = true;
        for (var i = info.startRow(); i<=info.finishRow(); i++) {
          for (var j = info.startCol(); j<=info.finishCol(); j++ ) {
            var cell = Structs.cell({
              row : i,
              col : j
            });
            isRect = isRect && SpanningCells.isSpanning(info.warehouse.access(), cell, boundingBox);
          }
        }

        return isRect ? Option.some(info) : Option.none();
      });
    };

    return {
      getBox: getBox,
      isRectangular: isRectangular
    };
  }
);<|endoftext|>


<commit_before>/**
 * PowerTip Core
 *
 * @fileoverview  Core variables, plugin object, and API.
 * @link          http://stevenbenner.github.com/jquery-powertip/
 * @author        Steven Benner (http://stevenbenner.com/)
 * @requires      jQuery 1.7+
 */

// useful private variables
var $document = $(document),
	$window = $(window),
	$body = $('body');

// constants
var DATA_DISPLAYCONTROLLER = 'displayController',
	DATA_HASACTIVEHOVER = 'hasActiveHover',
	DATA_HASMOUSEENTER = 'hasMouseEnter',
	DATA_FORCEDOPEN = 'forcedOpen',
	DATA_HASMOUSEMOVE = 'hasMouseMove',
	DATA_MOUSEONTOTIP = 'mouseOnToPopup',
	DATA_ORIGINALTITLE = 'originalTitle',
	DATA_POWERTIP = 'powertip',
	DATA_POWERTIPJQ = 'powertipjq',
	DATA_POWERTIPTARGET = 'powertiptarget',
	EVENT_NAMESPACE = '.powertip',
	RAD2DEG = 180 / Math.PI;

/**
 * Session data
 * Private properties global to all powerTip instances
 */
var session = {
	elements: null,
	tooltips: null,
	isTipOpen: false,
	isFixedTipOpen: false,
	isClosing: false,
	tipOpenImminent: false,
	activeHover: null,
	currentX: 0,
	currentY: 0,
	previousX: 0,
	previousY: 0,
	desyncTimeout: null,
	closeDelayTimeout: null,
	mouseTrackingActive: false,
	delayInProgress: false,
	windowWidth: 0,
	windowHeight: 0,
	scrollTop: 0,
	scrollLeft: 0
};

/**
 * Collision enumeration
 * @enum {number}
 */
var Collision = {
	none: 0,
	top: 1,
	bottom: 2,
	left: 4,
	right: 8
};

/**
 * Display hover tooltips on the matched elements.
 * @param {(Object|string)} opts The options object to use for the plugin, or
 *     the name of a method to invoke on the first matched element.
 * @param {*=} [arg] Argument for an invoked method (optional).
 * @return {jQuery} jQuery object for the matched selectors.
 */
$.fn.powerTip = function(opts, arg) {
	var targetElements = this,
		options,
		tipController;

	// don't do any work if there were no matched elements
	if (!targetElements.length) {
		return targetElements;
	}

	// handle api method calls on the plugin, e.g. powerTip('hide')
	if ($.type(opts) === 'string' && $.powerTip[opts]) {
		return $.powerTip[opts].call(targetElements, targetElements, arg);
	}

	// extend options and instantiate TooltipController
	options = $.extend({}, $.fn.powerTip.defaults, opts);
	tipController = new TooltipController(options);

	// hook mouse and viewport dimension tracking
	initTracking();

	// setup the elements
	targetElements.each(function elementSetup() {
		var $this = $(this),
			dataPowertip = $this.data(DATA_POWERTIP),
			dataElem = $this.data(DATA_POWERTIPJQ),
			dataTarget = $this.data(DATA_POWERTIPTARGET),
			title;

		// handle repeated powerTip calls on the same element by destroying the
		// original instance hooked to it and replacing it with this call
		if ($this.data(DATA_DISPLAYCONTROLLER)) {
			$.powerTip.destroy($this);
		}

		// attempt to use title attribute text if there is no data-powertip,
		// data-powertipjq or data-powertiptarget. If we do use the title
		// attribute, delete the attribute so the browser will not show it
		title = $this.attr('title');
		if (!dataPowertip && !dataTarget && !dataElem && title) {
			$this.data(DATA_POWERTIP, title);
			$this.data(DATA_ORIGINALTITLE, title);
			$this.removeAttr('title');
		}

		// create hover controllers for each element
		$this.data(
			DATA_DISPLAYCONTROLLER,
			new DisplayController($this, options, tipController)
		);
	});

	// attach events to matched elements if the manual option is not enabled
	if (!options.manual) {
		// attach open events
		$.each(options.openEvents, function(idx, evt) {
			if ($.inArray(evt, options.closeEvents) > -1) {
				// event is in both openEvents and closeEvents arrays, so attach show/hide helper
				targetElements.on(evt + EVENT_NAMESPACE, function elementOpenCloseEvent(event) {
					$.fn.powerTip.showHide(this, event);
				});
			} else {
				targetElements.on(evt + EVENT_NAMESPACE, function elementOpenEvent(event) {
					$.fn.powerTip.show(this, event);
				});
			}
		});

		// attach close events
		$.each(options.closeEvents, function(idx, evt) {
			if ($.inArray(evt, options.openEvents) < 0) {
				targetElements.on(evt + EVENT_NAMESPACE, function elementCloseEvent(event) {
					$.fn.powerTip.hide(this, event);
				});
			}
		});

		// attach escape key close event
		targetElements.on('keydown' + EVENT_NAMESPACE, function elementKeyDown(event) {
			// always close tooltip when the escape key is pressed
			if (event.keyCode === 27) {
				$.powerTip.hide(this, true);
			}
		});
	}

	// remember elements that the plugin is attached to
	session.elements = session.elements ? session.elements.add(targetElements) : targetElements;

	return targetElements;
};

/**
 * Default options for the powerTip plugin.
 */
$.fn.powerTip.defaults = {
	fadeInTime: 200,
	fadeOutTime: 100,
	followMouse: false,
	popupId: 'powerTip',
	intentSensitivity: 7,
	intentPollInterval: 100,
	closeDelay: 100,
	placement: 'n',
	smartPlacement: false,
	offset: 10,
	mouseOnToPopup: false,
	manual: false,
	openEvents: [ 'mouseenter', 'focus' ],
	closeEvents: [ 'mouseleave', 'blur' ]
};

/**
 * Default smart placement priority lists.
 * The first item in the array is the highest priority, the last is the lowest.
 * The last item is also the default, which will be used if all previous options
 * do not fit.
 */
$.fn.powerTip.smartPlacementLists = {
	n: ['n', 'ne', 'nw', 's'],
	e: ['e', 'ne', 'se', 'w', 'nw', 'sw', 'n', 's', 'e'],
	s: ['s', 'se', 'sw', 'n'],
	w: ['w', 'nw', 'sw', 'e', 'ne', 'se', 'n', 's', 'w'],
	nw: ['nw', 'w', 'sw', 'n', 's', 'se', 'nw'],
	ne: ['ne', 'e', 'se', 'n', 's', 'sw', 'ne'],
	sw: ['sw', 'w', 'nw', 's', 'n', 'ne', 'sw'],
	se: ['se', 'e', 'ne', 's', 'n', 'nw', 'se'],
	'nw-alt': ['nw-alt', 'n', 'ne-alt', 'sw-alt', 's', 'se-alt', 'w', 'e'],
	'ne-alt': ['ne-alt', 'n', 'nw-alt', 'se-alt', 's', 'sw-alt', 'e', 'w'],
	'sw-alt': ['sw-alt', 's', 'se-alt', 'nw-alt', 'n', 'ne-alt', 'w', 'e'],
	'se-alt': ['se-alt', 's', 'sw-alt', 'ne-alt', 'n', 'nw-alt', 'e', 'w']
};

/**
 * Determines whether to open or close tooltip for specified event. (Only
 * fires for events that appear in both the openEvents and closeEvents
 * options for specified element's powerTip instance.)
 * @param {jQuery|Element} element The element to open or close the tooltip for.
 * @param {jQuery.Event=} event jQuery event.
 */
$.fn.powerTip.showHide = function(element, event) {
	if (session.activeHover && element[0] === session.activeHover[0]) {
		// tooltip for element is active, so close it
		$.fn.powerTip.hide(element, event);
	} else {
		// tooltip for element is not active, so open it
		$.fn.powerTip.show(element, event);
	}
};

/**
 * Dispatches $.powerTip.show with specified element after determining
 * whether or not to pass the fired event on to show function.
 * @param {jQuery|Element} element The element to open the tooltip for.
 * @param {jQuery.Event=} event jQuery event.
 */
$.fn.powerTip.show = function(element, event) {
	if (event.pageX) {
		// for mouse events, pass event to show (for hover intent and mouse tracking)
		$.powerTip.show(element, event);
	} else {
		$.powerTip.show(element);
	}
};

/**
 * Dispatches $.powerTip.hide with specified element after determining
 * whether or not to immediately hide the tooltip.
 * @param {jQuery|Element} element The element to close the tooltip for.
 * @param {jQuery.Event=} event jQuery event.
 */
$.fn.powerTip.hide = function(element, event) {
	if (event.type === 'blur') {
		$.powerTip.hide(element, true);
	} else {
		$.powerTip.hide(element);
	}
};

/**
 * Public API
 */
$.powerTip = {
	/**
	 * Attempts to show the tooltip for the specified element.
	 * @param {jQuery|Element} element The element to open the tooltip for.
	 * @param {jQuery.Event=} event jQuery event for hover intent and mouse
	 *     tracking (optional).
	 */
	show: function apiShowTip(element, event) {
		if (event) {
			trackMouse(event);
			session.previousX = event.pageX;
			session.previousY = event.pageY;
			$(element).data(DATA_DISPLAYCONTROLLER).show();
		} else {
			$(element).first().data(DATA_DISPLAYCONTROLLER).show(true, true);
		}
		return element;
	},

	/**
	 * Repositions the tooltip on the element.
	 * @param {jQuery|Element} element The element the tooltip is shown for.
	 */
	reposition: function apiResetPosition(element) {
		$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();
		return element;
	},

	/**
	 * Attempts to close any open tooltips.
	 * @param {(jQuery|Element)=} element The element with the tooltip that
	 *     should be closed (optional).
	 * @param {boolean=} immediate Disable close delay (optional).
	 */
	hide: function apiCloseTip(element, immediate) {
		if (element) {
			$(element).first().data(DATA_DISPLAYCONTROLLER).hide(immediate);
		} else {
			if (session.activeHover) {
				session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true);
			}
		}
		return element;
	},

	/**
	 * Destroy and roll back any powerTip() instance on the specified elements.
	 * If no elements are specified then all elements that the plugin is
	 * currently attached to will be rolled back.
	 * @param {(jQuery|Element)=} element The element with the powerTip instance.
	 */
	destroy: function apiDestroy(element) {
		var $element = element ? $(element) : session.elements;

		// unhook events and destroy plugin changes to each element
		$element.off(EVENT_NAMESPACE).each(function destroy() {
			var $this = $(this),
				dataAttributes = [
					DATA_ORIGINALTITLE,
					DATA_DISPLAYCONTROLLER,
					DATA_HASACTIVEHOVER,
					DATA_FORCEDOPEN
				];

			// revert title attribute
			if ($this.data(DATA_ORIGINALTITLE)) {
				$this.attr('title', $this.data(DATA_ORIGINALTITLE));
				dataAttributes.push(DATA_POWERTIP);
			}

			// remove data attributes
			$this.removeData(dataAttributes);
		});

		// remove destroyed element from active elements collection
		session.elements = session.elements.not($element);

		// if there are no active elements left then we will unhook all of the
		// events that we've bound code to
		if (session.elements.length === 0) {
			$window.off(EVENT_NAMESPACE);
			$document.off(EVENT_NAMESPACE);
			session.mouseTrackingActive = false;
		}

		return element;
	}
};

// API aliasing
$.powerTip.showTip = $.powerTip.show;
$.powerTip.closeTip = $.powerTip.hide;
<commit_msg>Changed destroy() API method to remove tip elements.<commit_after>/**
 * PowerTip Core
 *
 * @fileoverview  Core variables, plugin object, and API.
 * @link          http://stevenbenner.github.com/jquery-powertip/
 * @author        Steven Benner (http://stevenbenner.com/)
 * @requires      jQuery 1.7+
 */

// useful private variables
var $document = $(document),
	$window = $(window),
	$body = $('body');

// constants
var DATA_DISPLAYCONTROLLER = 'displayController',
	DATA_HASACTIVEHOVER = 'hasActiveHover',
	DATA_HASMOUSEENTER = 'hasMouseEnter',
	DATA_FORCEDOPEN = 'forcedOpen',
	DATA_HASMOUSEMOVE = 'hasMouseMove',
	DATA_MOUSEONTOTIP = 'mouseOnToPopup',
	DATA_ORIGINALTITLE = 'originalTitle',
	DATA_POWERTIP = 'powertip',
	DATA_POWERTIPJQ = 'powertipjq',
	DATA_POWERTIPTARGET = 'powertiptarget',
	EVENT_NAMESPACE = '.powertip',
	RAD2DEG = 180 / Math.PI;

/**
 * Session data
 * Private properties global to all powerTip instances
 */
var session = {
	elements: null,
	tooltips: null,
	isTipOpen: false,
	isFixedTipOpen: false,
	isClosing: false,
	tipOpenImminent: false,
	activeHover: null,
	currentX: 0,
	currentY: 0,
	previousX: 0,
	previousY: 0,
	desyncTimeout: null,
	closeDelayTimeout: null,
	mouseTrackingActive: false,
	delayInProgress: false,
	windowWidth: 0,
	windowHeight: 0,
	scrollTop: 0,
	scrollLeft: 0
};

/**
 * Collision enumeration
 * @enum {number}
 */
var Collision = {
	none: 0,
	top: 1,
	bottom: 2,
	left: 4,
	right: 8
};

/**
 * Display hover tooltips on the matched elements.
 * @param {(Object|string)} opts The options object to use for the plugin, or
 *     the name of a method to invoke on the first matched element.
 * @param {*=} [arg] Argument for an invoked method (optional).
 * @return {jQuery} jQuery object for the matched selectors.
 */
$.fn.powerTip = function(opts, arg) {
	var targetElements = this,
		options,
		tipController;

	// don't do any work if there were no matched elements
	if (!targetElements.length) {
		return targetElements;
	}

	// handle api method calls on the plugin, e.g. powerTip('hide')
	if ($.type(opts) === 'string' && $.powerTip[opts]) {
		return $.powerTip[opts].call(targetElements, targetElements, arg);
	}

	// extend options and instantiate TooltipController
	options = $.extend({}, $.fn.powerTip.defaults, opts);
	tipController = new TooltipController(options);

	// hook mouse and viewport dimension tracking
	initTracking();

	// setup the elements
	targetElements.each(function elementSetup() {
		var $this = $(this),
			dataPowertip = $this.data(DATA_POWERTIP),
			dataElem = $this.data(DATA_POWERTIPJQ),
			dataTarget = $this.data(DATA_POWERTIPTARGET),
			title;

		// handle repeated powerTip calls on the same element by destroying the
		// original instance hooked to it and replacing it with this call
		if ($this.data(DATA_DISPLAYCONTROLLER)) {
			$.powerTip.destroy($this);
		}

		// attempt to use title attribute text if there is no data-powertip,
		// data-powertipjq or data-powertiptarget. If we do use the title
		// attribute, delete the attribute so the browser will not show it
		title = $this.attr('title');
		if (!dataPowertip && !dataTarget && !dataElem && title) {
			$this.data(DATA_POWERTIP, title);
			$this.data(DATA_ORIGINALTITLE, title);
			$this.removeAttr('title');
		}

		// create hover controllers for each element
		$this.data(
			DATA_DISPLAYCONTROLLER,
			new DisplayController($this, options, tipController)
		);
	});

	// attach events to matched elements if the manual option is not enabled
	if (!options.manual) {
		// attach open events
		$.each(options.openEvents, function(idx, evt) {
			if ($.inArray(evt, options.closeEvents) > -1) {
				// event is in both openEvents and closeEvents arrays, so attach show/hide helper
				targetElements.on(evt + EVENT_NAMESPACE, function elementOpenCloseEvent(event) {
					$.fn.powerTip.showHide(this, event);
				});
			} else {
				targetElements.on(evt + EVENT_NAMESPACE, function elementOpenEvent(event) {
					$.fn.powerTip.show(this, event);
				});
			}
		});

		// attach close events
		$.each(options.closeEvents, function(idx, evt) {
			if ($.inArray(evt, options.openEvents) < 0) {
				targetElements.on(evt + EVENT_NAMESPACE, function elementCloseEvent(event) {
					$.fn.powerTip.hide(this, event);
				});
			}
		});

		// attach escape key close event
		targetElements.on('keydown' + EVENT_NAMESPACE, function elementKeyDown(event) {
			// always close tooltip when the escape key is pressed
			if (event.keyCode === 27) {
				$.powerTip.hide(this, true);
			}
		});
	}

	// remember elements that the plugin is attached to
	session.elements = session.elements ? session.elements.add(targetElements) : targetElements;

	return targetElements;
};

/**
 * Default options for the powerTip plugin.
 */
$.fn.powerTip.defaults = {
	fadeInTime: 200,
	fadeOutTime: 100,
	followMouse: false,
	popupId: 'powerTip',
	intentSensitivity: 7,
	intentPollInterval: 100,
	closeDelay: 100,
	placement: 'n',
	smartPlacement: false,
	offset: 10,
	mouseOnToPopup: false,
	manual: false,
	openEvents: [ 'mouseenter', 'focus' ],
	closeEvents: [ 'mouseleave', 'blur' ]
};

/**
 * Default smart placement priority lists.
 * The first item in the array is the highest priority, the last is the lowest.
 * The last item is also the default, which will be used if all previous options
 * do not fit.
 */
$.fn.powerTip.smartPlacementLists = {
	n: ['n', 'ne', 'nw', 's'],
	e: ['e', 'ne', 'se', 'w', 'nw', 'sw', 'n', 's', 'e'],
	s: ['s', 'se', 'sw', 'n'],
	w: ['w', 'nw', 'sw', 'e', 'ne', 'se', 'n', 's', 'w'],
	nw: ['nw', 'w', 'sw', 'n', 's', 'se', 'nw'],
	ne: ['ne', 'e', 'se', 'n', 's', 'sw', 'ne'],
	sw: ['sw', 'w', 'nw', 's', 'n', 'ne', 'sw'],
	se: ['se', 'e', 'ne', 's', 'n', 'nw', 'se'],
	'nw-alt': ['nw-alt', 'n', 'ne-alt', 'sw-alt', 's', 'se-alt', 'w', 'e'],
	'ne-alt': ['ne-alt', 'n', 'nw-alt', 'se-alt', 's', 'sw-alt', 'e', 'w'],
	'sw-alt': ['sw-alt', 's', 'se-alt', 'nw-alt', 'n', 'ne-alt', 'w', 'e'],
	'se-alt': ['se-alt', 's', 'sw-alt', 'ne-alt', 'n', 'nw-alt', 'e', 'w']
};

/**
 * Determines whether to open or close tooltip for specified event. (Only
 * fires for events that appear in both the openEvents and closeEvents
 * options for specified element's powerTip instance.)
 * @param {jQuery|Element} element The element to open or close the tooltip for.
 * @param {jQuery.Event=} event jQuery event.
 */
$.fn.powerTip.showHide = function(element, event) {
	if (session.activeHover && element[0] === session.activeHover[0]) {
		// tooltip for element is active, so close it
		$.fn.powerTip.hide(element, event);
	} else {
		// tooltip for element is not active, so open it
		$.fn.powerTip.show(element, event);
	}
};

/**
 * Dispatches $.powerTip.show with specified element after determining
 * whether or not to pass the fired event on to show function.
 * @param {jQuery|Element} element The element to open the tooltip for.
 * @param {jQuery.Event=} event jQuery event.
 */
$.fn.powerTip.show = function(element, event) {
	if (event.pageX) {
		// for mouse events, pass event to show (for hover intent and mouse tracking)
		$.powerTip.show(element, event);
	} else {
		$.powerTip.show(element);
	}
};

/**
 * Dispatches $.powerTip.hide with specified element after determining
 * whether or not to immediately hide the tooltip.
 * @param {jQuery|Element} element The element to close the tooltip for.
 * @param {jQuery.Event=} event jQuery event.
 */
$.fn.powerTip.hide = function(element, event) {
	if (event.type === 'blur') {
		$.powerTip.hide(element, true);
	} else {
		$.powerTip.hide(element);
	}
};

/**
 * Public API
 */
$.powerTip = {
	/**
	 * Attempts to show the tooltip for the specified element.
	 * @param {jQuery|Element} element The element to open the tooltip for.
	 * @param {jQuery.Event=} event jQuery event for hover intent and mouse
	 *     tracking (optional).
	 */
	show: function apiShowTip(element, event) {
		if (event) {
			trackMouse(event);
			session.previousX = event.pageX;
			session.previousY = event.pageY;
			$(element).data(DATA_DISPLAYCONTROLLER).show();
		} else {
			$(element).first().data(DATA_DISPLAYCONTROLLER).show(true, true);
		}
		return element;
	},

	/**
	 * Repositions the tooltip on the element.
	 * @param {jQuery|Element} element The element the tooltip is shown for.
	 */
	reposition: function apiResetPosition(element) {
		$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();
		return element;
	},

	/**
	 * Attempts to close any open tooltips.
	 * @param {(jQuery|Element)=} element The element with the tooltip that
	 *     should be closed (optional).
	 * @param {boolean=} immediate Disable close delay (optional).
	 */
	hide: function apiCloseTip(element, immediate) {
		if (element) {
			$(element).first().data(DATA_DISPLAYCONTROLLER).hide(immediate);
		} else {
			if (session.activeHover) {
				session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true);
			}
		}
		return element;
	},

	/**
	 * Destroy and roll back any powerTip() instance on the specified elements.
	 * If no elements are specified then all elements that the plugin is
	 * currently attached to will be rolled back.
	 * @param {(jQuery|Element)=} element The element with the powerTip instance.
	 */
	destroy: function apiDestroy(element) {
		var $element = element ? $(element) : session.elements;

		// unhook events and destroy plugin changes to each element
		$element.off(EVENT_NAMESPACE).each(function destroy() {
			var $this = $(this),
				dataAttributes = [
					DATA_ORIGINALTITLE,
					DATA_DISPLAYCONTROLLER,
					DATA_HASACTIVEHOVER,
					DATA_FORCEDOPEN
				];

			// revert title attribute
			if ($this.data(DATA_ORIGINALTITLE)) {
				$this.attr('title', $this.data(DATA_ORIGINALTITLE));
				dataAttributes.push(DATA_POWERTIP);
			}

			// remove data attributes
			$this.removeData(dataAttributes);
		});

		// remove destroyed element from active elements collection
		session.elements = session.elements.not($element);

		// if there are no active elements left then we will unhook all of the
		// events that we've bound code to and remove the tooltip elements
		if (session.elements.length === 0) {
			$window.off(EVENT_NAMESPACE);
			$document.off(EVENT_NAMESPACE);
			session.mouseTrackingActive = false;
			session.tooltips.remove();
			session.tooltips = null;
		}

		return element;
	}
};

// API aliasing
$.powerTip.showTip = $.powerTip.show;
$.powerTip.closeTip = $.powerTip.hide;
<|endoftext|>


<commit_before>'use strict';

import rp from 'request-promise';

// TODO add an auditState function to audit whether there are already enough maintenance windows to not run this

// Function to get future maintenance windows
// TODO handle pagination
export function getFutureWindows(services, apiKey) {
  const options = {
    url: 'https://api.pagerduty.com/maintenance_windows?filter=future&service_ids%5B%5D=' + encodeURIComponent(services.toString()),
    method: 'GET',
    headers: {
      'Accept': 'application/vnd.pagerduty+json;version=2',
      'Authorization': 'Token token=' + apiKey
    }
  };

  return rp(options)
    .then((response) => {
      return JSON.parse(response).maintenance_windows;
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Function to queue 20 maintenance windows
// TODO make this a configurable number of queues or base it on the interval/duration
export function queueWindows(services, startTime, interval, duration, description) {
  let queue = [];
  for(let i=0; i<20; i++) {
    startTime = new Date(Date.parse(startTime));
    if(isNaN(startTime)) {
      throw new Error('Invalid START_TIME date format. Please use ISO 8601 format.');
    }
    let endTime = new Date(startTime.getTime() + duration * 1000);
    queue[i] = {
      maintenance_window: {
        start_time: startTime.toISOString(),
        end_time: endTime.toISOString(),
        description: description,
        services: services,
        type: 'maintenance_window'
      }
    }
    startTime = new Date(Date.parse(startTime) + interval * 1000).toISOString();
  }
  return queue;
}

// Function to de-dupe between the current windows in PagerDuty and the 20 queued windows
// TODO improve efficiency by dropping the older maintenance windows from currentWindows after each loop of queuedWindows
// TODO add error handling for partially-overlapping windows
export function dedupeWindows(currentWindows, queuedWindows) {
  for(let qw of queuedWindows) {
    for(let cw of currentWindows) {
      if(qw.maintenance_window.start_time == cw.start_time && qw.maintenance_window.end_time == cw.end_time) {
        queuedWindows.splice(queuedWindows.indexOf(qw), 1);
      }
    }
  }
  return queuedWindows;
}

// Function to create maintenance windows
export function createWindows(windows, apiKey, email) {
  for(let mw of windows) {
    const options = {
      url: 'https://api.pagerduty.com/maintenance_windows',
      method: 'POST',
      headers: {
        'Accept': 'application/vnd.pagerduty+json;version=2',
        'Authorization': 'Token token=' + apiKey,
        'From': email
      },
      body: mw,
      json: true
    };

    return rp(options)
      .then((response) => {
        return response['maintenance_windows'];
      })
      .catch((error) => {
        throw new Error(error);
      });
  }
}

// Function to delete one maintenance window
function deleteWindow(windowId, apiKey) {
  const options = {
    url: 'https://api.pagerduty.com/maintenance_windows/' + windowId,
    method: 'DELETE',
    headers: {
      'Accept': 'application/vnd.pagerduty+json;version=2',
      'Authorization': 'Token token=' + apiKey
    }
  };

  return rp(options)
    .then((response) => {
      return response;
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Function to remove all maintenance windows in the future from given services
// TODO handle pagination
// TODO add better error handling
export function removeAllFutureWindows(services, apiKey) {
  let counter = 0;
  return getFutureWindows(services, apiKey)
    .then((result) => {
      function loop(services, apiKey, counter) {
        if(counter >= services.length) {
          return 204;
        }
        else {
        return deleteWindow(services[counter].id, apiKey)
          .then((response) => {
            counter++;
            return loop(services, apiKey, counter);
          })
          .catch((error) => {
            throw new Error(error);
          })
        }
      }
      return loop(result, apiKey, counter);
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Default function to run everything and create the proper windows
export default function initialize() {
  let services = process.env.SERVICES.split(",");
  return getFutureWindows(services, process.env.ACCESS_TOKEN)
    .then((result) => {
      for(let i=0; i<services.length; i++) {
        services[i] = {
          "id": services[i],
          "type": "service_reference"
        }
      }
      const queuedWindows = queueWindows(services, process.env.START_TIME, process.env.INTERVAL, process.env.DURATION, process.env.DESCRIPTION);
      const windows = dedupeWindows(result, queuedWindows);
      return createWindows(windows, process.env.ACCESS_TOKEN, process.env.EMAIL)
        .then((result) => {
          process.env.START_TIME = windows[windows.length-1].maintenance_window.start_time;
          return 200;
        })
        .catch((error) => {
          throw new Error(error);
        });
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Immediately invoke initialize
// FIXME do this without breaking tests
initialize();
<commit_msg>Sanity checks<commit_after>'use strict';

import rp from 'request-promise';

console.log(process.env.ACCESS_TOKEN);
console.log(process.env.DESCRIPTION);
console.log(process.env.DURATION);
console.log(process.env.INTERVAL);
console.log(process.env.REQUESTER_EMAIL);
console.log(process.env.SERVICES);
console.log(process.env.START_TIME);

// TODO add an auditState function to audit whether there are already enough maintenance windows to not run this

// Function to get future maintenance windows
// TODO handle pagination
export function getFutureWindows(services, apiKey) {
  const options = {
    url: 'https://api.pagerduty.com/maintenance_windows?filter=future&service_ids%5B%5D=' + encodeURIComponent(services.toString()),
    method: 'GET',
    headers: {
      'Accept': 'application/vnd.pagerduty+json;version=2',
      'Authorization': 'Token token=' + apiKey
    }
  };

  return rp(options)
    .then((response) => {
      return JSON.parse(response).maintenance_windows;
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Function to queue 20 maintenance windows
// TODO make this a configurable number of queues or base it on the interval/duration
export function queueWindows(services, startTime, interval, duration, description) {
  let queue = [];
  for(let i=0; i<20; i++) {
    startTime = new Date(Date.parse(startTime));
    if(isNaN(startTime)) {
      throw new Error('Invalid START_TIME date format. Please use ISO 8601 format.');
    }
    let endTime = new Date(startTime.getTime() + duration * 1000);
    queue[i] = {
      maintenance_window: {
        start_time: startTime.toISOString(),
        end_time: endTime.toISOString(),
        description: description,
        services: services,
        type: 'maintenance_window'
      }
    }
    startTime = new Date(Date.parse(startTime) + interval * 1000).toISOString();
  }
  return queue;
}

// Function to de-dupe between the current windows in PagerDuty and the 20 queued windows
// TODO improve efficiency by dropping the older maintenance windows from currentWindows after each loop of queuedWindows
// TODO add error handling for partially-overlapping windows
export function dedupeWindows(currentWindows, queuedWindows) {
  for(let qw of queuedWindows) {
    for(let cw of currentWindows) {
      if(qw.maintenance_window.start_time == cw.start_time && qw.maintenance_window.end_time == cw.end_time) {
        queuedWindows.splice(queuedWindows.indexOf(qw), 1);
      }
    }
  }
  return queuedWindows;
}

// Function to create maintenance windows
export function createWindows(windows, apiKey, email) {
  for(let mw of windows) {
    const options = {
      url: 'https://api.pagerduty.com/maintenance_windows',
      method: 'POST',
      headers: {
        'Accept': 'application/vnd.pagerduty+json;version=2',
        'Authorization': 'Token token=' + apiKey,
        'From': email
      },
      body: mw,
      json: true
    };

    return rp(options)
      .then((response) => {
        return response['maintenance_windows'];
      })
      .catch((error) => {
        throw new Error(error);
      });
  }
}

// Function to delete one maintenance window
function deleteWindow(windowId, apiKey) {
  const options = {
    url: 'https://api.pagerduty.com/maintenance_windows/' + windowId,
    method: 'DELETE',
    headers: {
      'Accept': 'application/vnd.pagerduty+json;version=2',
      'Authorization': 'Token token=' + apiKey
    }
  };

  return rp(options)
    .then((response) => {
      return response;
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Function to remove all maintenance windows in the future from given services
// TODO handle pagination
// TODO add better error handling
export function removeAllFutureWindows(services, apiKey) {
  let counter = 0;
  return getFutureWindows(services, apiKey)
    .then((result) => {
      function loop(services, apiKey, counter) {
        if(counter >= services.length) {
          return 204;
        }
        else {
        return deleteWindow(services[counter].id, apiKey)
          .then((response) => {
            counter++;
            return loop(services, apiKey, counter);
          })
          .catch((error) => {
            throw new Error(error);
          })
        }
      }
      return loop(result, apiKey, counter);
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Default function to run everything and create the proper windows
export default function initialize() {
  let services = process.env.SERVICES.split(",");
  return getFutureWindows(services, process.env.ACCESS_TOKEN)
    .then((result) => {
      for(let i=0; i<services.length; i++) {
        services[i] = {
          "id": services[i],
          "type": "service_reference"
        }
      }
      const queuedWindows = queueWindows(services, process.env.START_TIME, process.env.INTERVAL, process.env.DURATION, process.env.DESCRIPTION);
      const windows = dedupeWindows(result, queuedWindows);
      return createWindows(windows, process.env.ACCESS_TOKEN, process.env.EMAIL)
        .then((result) => {
          process.env.START_TIME = windows[windows.length-1].maintenance_window.start_time;
          return 200;
        })
        .catch((error) => {
          throw new Error(error);
        });
    })
    .catch((error) => {
      throw new Error(error);
    });
}

// Immediately invoke initialize
// FIXME do this without breaking tests
initialize();
<|endoftext|>


<commit_before>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        this.el = document.getElementById(_el);
        this.html = this.el.innerHTML;
        this.dom = {type: this.el.nodeName, children: [], node: this.el};

        Object.defineProperty(this, 'data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        this.build = function(children) {
          var tempData = this.data;
          for(var i = 0; i < children.length; i++) {
            var el = children[i];
            if(el.type === "#text") {
              el.val.replace(/{{(\w+)}}/gi, function(match, p1) {
                var dataToAdd = tempData[p1];
                el.node.textContent = el.val.replace(new RegExp(match, "gi"), dataToAdd);
              });
            } else {
               this.build(el.children);
            }
          }
        }

        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, child));
          }
          return recursiveChildrenArr;
        }

        this.createElement = function(type, children, val, node) {
          return {type: type, children: children, val: val, node: node};
        }

        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, node);
          this.dom = vdom;
        }

        this.seed = function() {
          this.createVirtualDOM(this.el);
        }

        this.set = function(key, val) {
          this.data[key] = val;
          this.build(this.dom.children);
        }

        this.get = function(key) {
          return this.data[key];
        }

        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        this.method = function(method) {
          _methods[method]();
        }
        this.seed();
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<commit_msg> not el<commit_after>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        this.$el = document.getElementById(_el);
        this.html = this.$el.innerHTML;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        Object.defineProperty(this, 'data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        this.build = function(children) {
          var tempData = this.data;
          for(var i = 0; i < children.length; i++) {
            var el = children[i];
            if(el.type === "#text") {
              el.val.replace(/{{(\w+)}}/gi, function(match, p1) {
                var dataToAdd = tempData[p1];
                el.node.textContent = el.val.replace(new RegExp(match, "gi"), dataToAdd);
              });
            } else {
               this.build(el.children);
            }
          }
        }

        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, child));
          }
          return recursiveChildrenArr;
        }

        this.createElement = function(type, children, val, node) {
          return {type: type, children: children, val: val, node: node};
        }

        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, node);
          this.dom = vdom;
        }

        this.seed = function() {
          this.createVirtualDOM(this.$el);
        }

        this.set = function(key, val) {
          this.data[key] = val;
          this.build(this.dom.children);
        }

        this.get = function(key) {
          return this.data[key];
        }

        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        this.method = function(method) {
          _methods[method]();
        }
        this.seed();
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<|endoftext|>


<commit_before>/**
 * Faiash Core
 *
 * @author Rakume Hayashi<i@fake.moe>
 */

// Define the Faiash
var Faiash = function(selector, context) {
    return new Faiash.ise.init(selector, context);
};

Faiash.ise = Faiash.prototype = {
    // Version of Faiash
    version: 0.1,
    constructor: Faiash,

    toArr: function(r) {
        return Array.prototype.slice.apply(r);
    },

    // Behaves like array
    push: [].push,
	sort: [].sort,
	splice: [].splice
};

var init = Faiash.ise.init = function(selector, context) {
    // Return self when selector is "", void, undefined, false
    if (!selector) {
        return this;
    }

    // When selector is an objcet
    if (typeof selector === 'object') {
        return selector;
    }

    // When context is string
    if (typeof context === 'string') {
        context = document.querySelector(context);
    }

    selector = (context || document).querySelectorAll(selector);

    for (i = 0; i < +selector.length; i++) {
        this[i] = selector[i];
    }

    this.length = i;
    return this;
}

init.prototype = Faiash.ise;

Faiash.extend = Faiash.ise.extend = function() {
    var copy;

    // No arguments
    if (arguments.length < 1) {
        return;
    }

    // There are an array outside the object
    for (var i = 0; i < arguments.length; i++) {
        for (var name in arguments[i]) {
            copy = arguments[i][name];

            // Prevent never-ending loop
            if (this === copy) {
                continue;
            }

            // Don't bring in undefined values
            if (copy !== undefined) {
                this[name] = copy;
            }
        }
    }

    return this;
}

Faiash.extend({
    each: function(arr, func) {
        var forEach = Function.prototype.call.bind(Array.prototype.forEach);
        return forEach(arr, func);
    }
});

Faiash.ise.extend({
    each: function(func) {
        return Faiash.each(this, func);
    }
});
<commit_msg>Let toArr be a extend<commit_after>/**
 * Faiash Core
 *
 * @author Rakume Hayashi<i@fake.moe>
 */

// Define the Faiash
var Faiash = function(selector, context) {
    return new Faiash.ise.init(selector, context);
};

Faiash.ise = Faiash.prototype = {
    // Version of Faiash
    version: 0.1,
    constructor: Faiash,

    // Behaves like array
    push: [].push,
	sort: [].sort,
	splice: [].splice
};

var init = Faiash.ise.init = function(selector, context) {
    // Return self when selector is "", void, undefined, false
    if (!selector) {
        return this;
    }

    // When selector is an objcet
    if (typeof selector === 'object') {
        return selector;
    }

    // When context is string
    if (typeof context === 'string') {
        context = document.querySelector(context);
    }

    selector = (context || document).querySelectorAll(selector);

    for (i = 0; i < +selector.length; i++) {
        this[i] = selector[i];
    }

    this.length = i;
    return this;
}

init.prototype = Faiash.ise;

Faiash.extend = Faiash.ise.extend = function() {
    var copy;

    // No arguments
    if (arguments.length < 1) {
        return;
    }

    // There are an array outside the object
    for (var i = 0; i < arguments.length; i++) {
        for (var name in arguments[i]) {
            copy = arguments[i][name];

            // Prevent never-ending loop
            if (this === copy) {
                continue;
            }

            // Don't bring in undefined values
            if (copy !== undefined) {
                this[name] = copy;
            }
        }
    }

    return this;
}

Faiash.extend({
    toArr: function(r) {
        return Array.prototype.slice.apply(r);
    },

    each: function(arr, func) {
        var forEach = Function.prototype.call.bind(Array.prototype.forEach);
        return forEach(arr, func);
    }
});

Faiash.ise.extend({
    each: function(func) {
        return Faiash.each(this, func);
    }
});
<|endoftext|>