diff options
| -rwxr-xr-x | vendors/jquery/init.js | 131 | ||||
| -rwxr-xr-x | vendors/jquery/jquery-1.2.4a.js | 3436 | ||||
| -rwxr-xr-x | vendors/jquery/ui.base.js | 204 | ||||
| -rwxr-xr-x | vendors/jquery/ui.draggable.js | 572 | ||||
| -rwxr-xr-x | vendors/jquery/ui.droppable.js | 312 | ||||
| -rwxr-xr-x | vendors/jquery/ui.sortable.js | 676 | 
6 files changed, 5331 insertions, 0 deletions
diff --git a/vendors/jquery/init.js b/vendors/jquery/init.js new file mode 100755 index 000000000..b60d268f0 --- /dev/null +++ b/vendors/jquery/init.js @@ -0,0 +1,131 @@ +(function($){ +	var updateUpDown = function(sortable){ +		$('div:not(.ui-sortable-helper)', sortable) +			.removeClass('first').removeClass('last') +			.find('.up, .down').removeClass('disabled').end() +			.filter(':first').addClass('first').find('.up').addClass('disabled').end().end() +			.filter(':last').addClass('last').find('.down').addClass('disabled').end().end(); +	}; +	 +	var moveUpDown = function(){ +		var link = $(this), +			dl = link.parents('div'), +			prev = dl.prev('div'), +			next = dl.next('div'); +	 +		if(link.is('.up') && prev.length > 0) +			dl.insertBefore(prev); +	 +		if(link.is('.down') && next.length > 0) +			dl.insertAfter(next); +	 +		updateUpDown(dl.parent()); +	}; +	 +	var addItem = function(){ +		var sortable = $(this).parents('.ui-sortable'); +		var options = '<span class="options"><a class="up">up</a><a class="down">down</a></span>'; +		var tpl = '<dl class="sort"><dt>{name}' + options + '</dt><dd>{desc}</dd></dl>'; +		var html = tpl.replace(/{name}/g, 'Dynamic name :D').replace(/{desc}/g, 'Description'); +	 +		sortable.append(html).sortable('refresh').find('a.up, a.down').bind('click', moveUpDown); +		updateUpDown(sortable); +	}; +	 +	//var emptyTrashCan = function(item){ +	//	item.remove(); +	//}; +	 +	var sortableChange = function(e, ui){ +		if(ui.sender){ +			var w = ui.element.width(); +			ui.placeholder.width(w); +			ui.helper.css("width",ui.element.children().width()); +		} +	}; +	 +	var sortableUpdate = function(e, ui){ +		//if(ui.element[0].id == 'trashcan'){ +		//	emptyTrashCan(ui.item); +		//} else { +			updateUpDown(ui.element[0]); +			if(ui.sender) +				updateUpDown(ui.sender[0]); +		//} +	}; +	 +	// toggle content panel +	var togglePanel = function(e) { +		var targetContent = $('div.panelcontent', this.parentNode.parentNode); +			if (targetContent.css('display') == 'none') { +				targetContent.slideDown(400); +				$(this).html('[-]'); +				$(this).css("color","#cccccc"); +			} else { +				targetContent.slideUp(400); +				$(this).html('[+]'); +				$(this).css("color","#666666"); +			} +		return false; +	}; +	 +	// toggle edit panel +	var editpanel = function(e) { +		var targetEditPanel = $('div.editpanel', this.parentNode.parentNode); +			if (targetEditPanel.css('display') == 'none') { +				targetEditPanel.slideDown(400); +			} else { +				targetEditPanel.slideUp(400); +			} +			$(this).toggleClass("active"); return false; +		return false; +	}; +	 +	$(document).ready(function(){ +				 +		// toggle edit panel  +		$('a.button_editpanel').bind('click', editpanel); +		 +		// toggle content panel +		$('a.togglepanel').bind('click', togglePanel); + +		var els = ['#mainContent', '#sidebar_right']; +		var $els = $(els.toString()); +		 +		//$('h2', $els.slice(0,-1)).append('<span class="options"><a class="add">add</a></span>'); +		//$('dt', $els).append('<span class="options"><a class="up">up</a><a class="down">down</a></span>'); +		 +		//$('a.add').bind('click', addItem); +		//$('a.up, a.down').bind('click', moveUpDown); +		 +		//$els.each(function(){ +		//	updateUpDown(this); +		//}); +		 +		$els.sortable({ +			items: '> div', +			handle: 'h1', +			cursor: 'move', +			//revert: true, +			cursorAt: { top: 10, left: 100 }, +			//opacity: 0.8, +			containment: 'parent', +			appendTo: 'body', +			placeholder: 'placeholder', +			connectWith: els, +			start: function(e,ui) { +				ui.helper.css("width", ui.item.width()); +			}, +			change: sortableChange, +			update: sortableUpdate +		}); +	}); +	 +	$(window).bind('load',function(){ +		setTimeout(function(){ +			$('#overlay').fadeOut(function(){ +				$('body').css('overflow', 'auto'); +			}); +		}, 450); +	}); +})(jQuery);
\ No newline at end of file diff --git a/vendors/jquery/jquery-1.2.4a.js b/vendors/jquery/jquery-1.2.4a.js new file mode 100755 index 000000000..ea640733f --- /dev/null +++ b/vendors/jquery/jquery-1.2.4a.js @@ -0,0 +1,3436 @@ +(function(){ +/* + * jQuery 1.2.4a - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-04-08 13:40:03 -0300 (ter, 08 abr 2008) $ + * $Rev: 5214 $ + */ + +// Map over jQuery in case of overwrite +if ( window.jQuery ) +	var _jQuery = window.jQuery; + +var jQuery = window.jQuery = function( selector, context ) { +	// The jQuery object is actually just the init constructor 'enhanced' +	return new jQuery.prototype.init( selector, context ); +}; + +// Map over the $ in case of overwrite +if ( window.$ ) +	var _$ = window.$; +	 +// Map the jQuery namespace to the '$' one +window.$ = jQuery; + +// A simple way to check for HTML strings or ID strings +// (both of which we optimize for) +var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; + +// Is it a simple selector +var isSimple = /^.[^:#\[\.]*$/; + +jQuery.fn = jQuery.prototype = { +	init: function( selector, context ) { +		// Make sure that a selection was provided +		selector = selector || document; + +		// Handle $(DOMElement) +		if ( selector.nodeType ) { +			this[0] = selector; +			this.length = 1; +			return this; + +		// Handle HTML strings +		} else if ( typeof selector == "string" ) { +			// Are we dealing with HTML string or an ID? +			var 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 { +					var elem = document.getElementById( match[3] ); + +					// Make sure an element was located +					if ( elem ) +						// Handle the case where IE and Opera return items +						// by name instead of ID +						if ( elem.id != match[3] ) +							return jQuery().find( selector ); + +						// Otherwise, we inject the element directly into the jQuery object +						else { +							this[0] = elem; +							this.length = 1; +							return this; +						} + +					else +						selector = []; +				} + +			// HANDLE: $(expr, [context]) +			// (which is just equivalent to: $(content).find(expr) +			} else +				return new jQuery( context ).find( selector ); + +		// HANDLE: $(function) +		// Shortcut for document ready +		} else if ( jQuery.isFunction( selector ) ) +			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); + +		return this.setArray( +			// HANDLE: $(array) +			selector.constructor == Array && selector || + +			// HANDLE: $(arraylike) +			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector +			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) || + +			// HANDLE: $(*) +			[ selector ] ); +	}, +	 +	// The current version of jQuery being used +	jquery: "1.2.4a", + +	// The number of elements contained in the matched element set +	size: function() { +		return this.length; +	}, +	 +	// The number of elements contained in the matched element set +	length: 0, + +	// 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 == undefined ? + +			// Return a 'clean' array +			jQuery.makeArray( this ) : + +			// Return just the object +			this[ num ]; +	}, +	 +	// Take an array of elements and push it onto the stack +	// (returning the new matched element set) +	pushStack: function( elems ) { +		// Build a new jQuery matched element set +		var ret = jQuery( elems ); + +		// Add the old object onto the stack (as a reference) +		ret.prevObject = this; + +		// 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 ) { +		var ret = -1; + +		// Locate the position of the desired element +		this.each(function(i){ +			if ( this == elem ) +				ret = i; +		}); + +		return ret; +	}, + +	attr: function( name, value, type ) { +		var options = name; +		 +		// Look for the case where we're accessing a style value +		if ( name.constructor == String ) +			if ( value == undefined ) +				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined; + +			else { +				options = {}; +				options[ name ] = value; +			} +		 +		// Check to see if we're setting style values +		return this.each(function(i){ +			// Set all the styles +			for ( name in options ) +				jQuery.attr( +					type ? +						this.style : +						this, +					name, jQuery.prop( this, options[ name ], type, i, name ) +				); +		}); +	}, + +	css: function( key, value ) { +		// ignore negative width and height values +		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) +			value = undefined; +		return this.attr( key, value, "curCSS" ); +	}, + +	text: function( text ) { +		if ( typeof text != "object" && text != null ) +			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + +		var ret = ""; + +		jQuery.each( text || this, function(){ +			jQuery.each( this.childNodes, function(){ +				if ( this.nodeType != 8 ) +					ret += this.nodeType != 1 ? +						this.nodeValue : +						jQuery.fn.text( [ this ] ); +			}); +		}); + +		return ret; +	}, + +	wrapAll: function( html ) { +		if ( this[0] ) +			// The elements to wrap the target around +			jQuery( html, this[0].ownerDocument ) +				.clone() +				.insertBefore( this[0] ) +				.map(function(){ +					var elem = this; + +					while ( elem.firstChild ) +						elem = elem.firstChild; + +					return elem; +				}) +				.append(this); + +		return this; +	}, + +	wrapInner: function( html ) { +		return this.each(function(){ +			jQuery( this ).contents().wrapAll( html ); +		}); +	}, + +	wrap: function( html ) { +		return this.each(function(){ +			jQuery( this ).wrapAll( html ); +		}); +	}, + +	append: function() { +		return this.domManip(arguments, true, false, function(elem){ +			if (this.nodeType == 1) +				this.appendChild( elem ); +		}); +	}, + +	prepend: function() { +		return this.domManip(arguments, true, true, function(elem){ +			if (this.nodeType == 1) +				this.insertBefore( elem, this.firstChild ); +		}); +	}, +	 +	before: function() { +		return this.domManip(arguments, false, false, function(elem){ +			this.parentNode.insertBefore( elem, this ); +		}); +	}, + +	after: function() { +		return this.domManip(arguments, false, true, function(elem){ +			this.parentNode.insertBefore( elem, this.nextSibling ); +		}); +	}, + +	end: function() { +		return this.prevObject || jQuery( [] ); +	}, + +	find: function( selector ) { +		var elems = jQuery.map(this, function(elem){ +			return jQuery.find( selector, elem ); +		}); + +		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? +			jQuery.unique( elems ) : +			elems ); +	}, + +	clone: function( events ) { +		// Do the clone +		var ret = this.map(function(){ +			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { +				// IE copies events bound via attachEvent when +				// using cloneNode. Calling detachEvent on the +				// clone will also remove the events from the orignal +				// In order to get around this, we use innerHTML. +				// Unfortunately, this means some modifications to  +				// attributes in IE that are actually only stored  +				// as properties will not be copied (such as the +				// the name attribute on an input). +				var clone = this.cloneNode(true), +					container = document.createElement("div"); +				container.appendChild(clone); +				return jQuery.clean([container.innerHTML])[0]; +			} else +				return this.cloneNode(true); +		}); + +		// Need to set the expando to null on the cloned set if it exists +		// removeData doesn't work here, IE removes it from the original as well +		// this is primarily for IE but the data expando shouldn't be copied over in any browser +		var clone = ret.find("*").andSelf().each(function(){ +			if ( this[ expando ] != undefined ) +				this[ expando ] = null; +		}); +		 +		// Copy the events from the original to the clone +		if ( events === true ) +			this.find("*").andSelf().each(function(i){ +				if (this.nodeType == 3) +					return; +				var events = jQuery.data( this, "events" ); + +				for ( var type in events ) +					for ( var handler in events[ type ] ) +						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); +			}); + +		// Return the cloned set +		return ret; +	}, + +	filter: function( selector ) { +		return this.pushStack( +			jQuery.isFunction( selector ) && +			jQuery.grep(this, function(elem, i){ +				return selector.call( elem, i ); +			}) || + +			jQuery.multiFilter( selector, this ) ); +	}, + +	not: function( selector ) { +		if ( selector.constructor == String ) +			// test special case where just one selector is passed in +			if ( isSimple.test( selector ) ) +				return this.pushStack( jQuery.multiFilter( selector, this, true ) ); +			else +				selector = jQuery.multiFilter( selector, this ); + +		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; +		return this.filter(function() { +			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; +		}); +	}, + +	add: function( selector ) { +		return !selector ? this : this.pushStack( jQuery.merge(  +			this.get(), +			selector.constructor == String ?  +				jQuery( selector ).get() : +				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ? +					selector : [selector] ) ); +	}, + +	is: function( selector ) { +		return selector ? +			jQuery.multiFilter( selector, this ).length > 0 : +			false; +	}, + +	hasClass: function( selector ) { +		return this.is( "." + selector ); +	}, +	 +	val: function( value ) { +		if ( value == undefined ) { + +			if ( this.length ) { +				var elem = this[0]; + +				// We need to handle select boxes special +				if ( jQuery.nodeName( elem, "select" ) ) { +					var index = elem.selectedIndex, +						values = [], +						options = elem.options, +						one = elem.type == "select-one"; +					 +					// Nothing was selected +					if ( index < 0 ) +						return null; + +					// Loop through all the selected options +					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { +						var option = options[ i ]; + +						if ( option.selected ) { +							// Get the specifc value for the option +							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; +							 +							// We don't need an array for one selects +							if ( one ) +								return value; +							 +							// Multi-Selects return an array +							values.push( value ); +						} +					} +					 +					return values; +					 +				// Everything else, we just grab the value +				} else +					return (this[0].value || "").replace(/\r/g, ""); + +			} + +			return undefined; +		} + +		return this.each(function(){ +			if ( this.nodeType != 1 ) +				return; + +			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) ) +				this.checked = (jQuery.inArray(this.value, value) >= 0 || +					jQuery.inArray(this.name, value) >= 0); + +			else if ( jQuery.nodeName( this, "select" ) ) { +				var values = value.constructor == Array ? +					value : +					[ value ]; + +				jQuery( "option", this ).each(function(){ +					this.selected = (jQuery.inArray( this.value, values ) >= 0 || +						jQuery.inArray( this.text, values ) >= 0); +				}); + +				if ( !values.length ) +					this.selectedIndex = -1; + +			} else +				this.value = value; +		}); +	}, +	 +	html: function( value ) { +		return value == undefined ? +			(this.length ? +				this[0].innerHTML : +				null) : +			this.empty().append( value ); +	}, + +	replaceWith: function( value ) { +		return this.after( value ).remove(); +	}, + +	eq: function( i ) { +		return this.slice( i, i + 1 ); +	}, + +	slice: function() { +		return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); +	}, + +	map: function( callback ) { +		return this.pushStack( jQuery.map(this, function(elem, i){ +			return callback.call( elem, i, elem ); +		})); +	}, + +	andSelf: function() { +		return this.add( this.prevObject ); +	}, + +	data: function( key, value ){ +		var parts = key.split("."); +		parts[1] = parts[1] ? "." + parts[1] : ""; + +		if ( value == null ) { +			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); +			 +			if ( data == undefined && this.length ) +				data = jQuery.data( this[0], key ); + +			return data == null && parts[1] ? +				this.data( parts[0] ) : +				data; +		} else +			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ +				jQuery.data( this, key, value ); +			}); +	}, + +	removeData: function( key ){ +		return this.each(function(){ +			jQuery.removeData( this, key ); +		}); +	}, +	 +	domManip: function( args, table, reverse, callback ) { +		var clone = this.length > 1, elems;  + +		return this.each(function(){ +			if ( !elems ) { +				elems = jQuery.clean( args, this.ownerDocument ); + +				if ( reverse ) +					elems.reverse(); +			} + +			var obj = this; + +			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) ) +				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") ); + +			var scripts = jQuery( [] ); + +			jQuery.each(elems, function(){ +				var elem = clone ? +					jQuery( this ).clone( true )[0] : +					this; + +				// execute all scripts after the elements have been injected +				if ( jQuery.nodeName( elem, "script" ) ) { +					scripts = scripts.add( elem ); +				} else { +					// Remove any inner scripts for later evaluation +					if ( elem.nodeType == 1 ) +						scripts = scripts.add( jQuery( "script", elem ).remove() ); + +					// Inject the elements into the document +					callback.call( obj, elem ); +				} +			}); + +			scripts.each( evalScript ); +		}); +	} +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.prototype.init.prototype = jQuery.prototype; + +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 ); +} + +jQuery.extend = jQuery.fn.extend = function() { +	// copy reference to target object +	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + +	// Handle a deep copy situation +	if ( target.constructor == 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" && typeof target != "function" ) +		target = {}; + +	// extend jQuery itself if only one argument is passed +	if ( length == 1 ) { +		target = this; +		i = 0; +	} + +	for ( ; i < length; i++ ) +		// Only deal with non-null/undefined values +		if ( (options = arguments[ i ]) != null ) +			// Extend the base object +			for ( var name in options ) { +				// Prevent never-ending loop +				if ( target === options[ name ] ) +					continue; + +				// Recurse if we're merging object values +				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType ) +					target[ name ] = jQuery.extend( deep, target[ name ], options[ name ] ); + +				// Don't bring in undefined values +				else if ( options[ name ] != undefined ) +					target[ name ] = options[ name ]; + +			} + +	// Return the modified object +	return target; +}; + +var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {}; + +// exclude the following css properties to add px +var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; + +jQuery.extend({ +	noConflict: function( deep ) { +		window.$ = _$; + +		if ( deep ) +			window.jQuery = _jQuery; + +		return jQuery; +	}, + +	// See test/unit/core.js for details concerning this function. +	isFunction: function( fn ) { +		return !!fn && typeof fn != "string" && !fn.nodeName &&  +			fn.constructor != Array && /function/i.test( fn + "" ); +	}, +	 +	// check if an element is in a (or is an) XML document +	isXMLDoc: function( elem ) { +		return elem.documentElement && !elem.body || +			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; +	}, + +	// Evalulates a script in a global context +	globalEval: function( data ) { +		data = jQuery.trim( data ); + +		if ( 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.browser.msie ) +				script.text = data; +			else +				script.appendChild( document.createTextNode( data ) ); + +			head.appendChild( script ); +			head.removeChild( script ); +		} +	}, + +	nodeName: function( elem, name ) { +		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); +	}, +	 +	cache: {}, +	 +	data: function( elem, name, data ) { +		elem = elem == window ? +			windowData : +			elem; + +		var id = elem[ expando ]; + +		// Compute a unique ID for the element +		if ( !id )  +			id = elem[ expando ] = ++uuid; + +		// Only generate the data cache if we're +		// trying to access or manipulate it +		if ( name && !jQuery.cache[ id ] ) +			jQuery.cache[ id ] = {}; +		 +		// Prevent overriding the named cache with undefined values +		if ( data != undefined ) +			jQuery.cache[ id ][ name ] = data; +		 +		// Return the named cache data, or the ID for the element	 +		return name ? +			jQuery.cache[ id ][ name ] : +			id; +	}, +	 +	removeData: function( elem, name ) { +		elem = elem == window ? +			windowData : +			elem; + +		var id = elem[ expando ]; + +		// If we want to remove a specific section of the element's data +		if ( name ) { +			if ( jQuery.cache[ id ] ) { +				// Remove the section of cache data +				delete jQuery.cache[ id ][ name ]; + +				// If we've removed all the data, remove the element's cache +				name = ""; + +				for ( name in jQuery.cache[ id ] ) +					break; + +				if ( !name ) +					jQuery.removeData( elem ); +			} + +		// Otherwise, we want to remove all of the element's data +		} else { +			// Clean up the element expando +			try { +				delete elem[ expando ]; +			} catch(e){ +				// IE has trouble directly removing the expando +				// but it's ok with using removeAttribute +				if ( elem.removeAttribute ) +					elem.removeAttribute( expando ); +			} + +			// Completely remove the data cache +			delete jQuery.cache[ id ]; +		} +	}, + +	// args is for internal usage only +	each: function( object, callback, args ) { +		if ( args ) { +			if ( object.length == undefined ) { +				for ( var name in object ) +					if ( callback.apply( object[ name ], args ) === false ) +						break; +			} else +				for ( var i = 0, length = object.length; i < length; i++ ) +					if ( callback.apply( object[ i ], args ) === false ) +						break; + +		// A special, fast, case for the most common use of each +		} else { +			if ( object.length == undefined ) { +				for ( var name in object ) +					if ( callback.call( object[ name ], name, object[ name ] ) === false ) +						break; +			} else +				for ( var i = 0, length = object.length, value = object[0];  +					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} +		} + +		return object; +	}, +	 +	prop: function( elem, value, type, i, name ) { +			// Handle executable functions +			if ( jQuery.isFunction( value ) ) +				value = value.call( elem, i ); +				 +			// Handle passing in a number to a CSS property +			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? +				value + "px" : +				value; +	}, + +	className: { +		// internal only, use addClass("class") +		add: function( elem, classNames ) { +			jQuery.each((classNames || "").split(/\s+/), function(i, className){ +				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) +					elem.className += (elem.className ? " " : "") + className; +			}); +		}, + +		// internal only, use removeClass("class") +		remove: function( elem, classNames ) { +			if (elem.nodeType == 1) +				elem.className = classNames != undefined ? +					jQuery.grep(elem.className.split(/\s+/), function(className){ +						return !jQuery.className.has( classNames, className );	 +					}).join(" ") : +					""; +		}, + +		// internal only, use is(".class") +		has: function( elem, className ) { +			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; +		} +	}, + +	// A method for quickly swapping in/out CSS properties to get correct calculations +	swap: function( elem, options, callback ) { +		var old = {}; +		// Remember the old values, and insert the new ones +		for ( var name in options ) { +			old[ name ] = elem.style[ name ]; +			elem.style[ name ] = options[ name ]; +		} + +		callback.call( elem ); + +		// Revert the old values +		for ( var name in options ) +			elem.style[ name ] = old[ name ]; +	}, + +	css: function( elem, name, force ) { +		if ( name == "width" || name == "height" ) { +			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; +		 +			function getWH() { +				val = name == "width" ? elem.offsetWidth : elem.offsetHeight; +				var padding = 0, border = 0; +				jQuery.each( which, function() { +					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; +					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; +				}); +				val -= Math.round(padding + border); +			} +		 +			if ( jQuery(elem).is(":visible") ) +				getWH(); +			else +				jQuery.swap( elem, props, getWH ); +			 +			return Math.max(0, val); +		} +		 +		return jQuery.curCSS( elem, name, force ); +	}, + +	curCSS: function( elem, name, force ) { +		var ret; + +		// A helper method for determining if an element's values are broken +		function color( elem ) { +			if ( !jQuery.browser.safari ) +				return false; + +			var ret = document.defaultView.getComputedStyle( elem, null ); +			return !ret || ret.getPropertyValue("color") == ""; +		} + +		// We need to handle opacity special in IE +		if ( name == "opacity" && jQuery.browser.msie ) { +			ret = jQuery.attr( elem.style, "opacity" ); + +			return ret == "" ? +				"1" : +				ret; +		} +		// Opera sometimes will give the wrong display answer, this fixes it, see #2037 +		if ( jQuery.browser.opera && name == "display" ) { +			var save = elem.style.outline; +			elem.style.outline = "0 solid black"; +			elem.style.outline = save; +		} +		 +		// Make sure we're using the right name for getting the float value +		if ( name.match( /float/i ) ) +			name = styleFloat; + +		if ( !force && elem.style && elem.style[ name ] ) +			ret = elem.style[ name ]; + +		else if ( document.defaultView && document.defaultView.getComputedStyle ) { + +			// Only "float" is needed here +			if ( name.match( /float/i ) ) +				name = "float"; + +			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); + +			var getComputedStyle = document.defaultView.getComputedStyle( elem, null ); + +			if ( getComputedStyle && !color( elem ) ) +				ret = getComputedStyle.getPropertyValue( name ); + +			// If the element isn't reporting its values properly in Safari +			// then some display: none elements are involved +			else { +				var swap = [], stack = []; + +				// Locate all of the parent display: none elements +				for ( var a = elem; a && color(a); a = a.parentNode ) +					stack.unshift(a); + +				// Go through and make them visible, but in reverse +				// (It would be better if we knew the exact display type that they had) +				for ( var i = 0; i < stack.length; i++ ) +					if ( color( stack[ i ] ) ) { +						swap[ i ] = stack[ i ].style.display; +						stack[ i ].style.display = "block"; +					} + +				// Since we flip the display style, we have to handle that +				// one special, otherwise get the value +				ret = name == "display" && swap[ stack.length - 1 ] != null ? +					"none" : +					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || ""; + +				// Finally, revert the display styles back +				for ( var i = 0; i < swap.length; i++ ) +					if ( swap[ i ] != null ) +						stack[ i ].style.display = swap[ i ]; +			} + +			// We should always get a number back from opacity +			if ( name == "opacity" && ret == "" ) +				ret = "1"; + +		} else if ( elem.currentStyle ) { +			var camelCase = name.replace(/\-(\w)/g, function(all, letter){ +				return letter.toUpperCase(); +			}); + +			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; + +			// From the awesome hack by Dean Edwards +			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + +			// If we're not dealing with a regular pixel number +			// but a number that has a weird ending, we need to convert it to pixels +			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { +				// Remember the original values +				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left; + +				// Put in the new values to get a computed value out +				elem.runtimeStyle.left = elem.currentStyle.left; +				elem.style.left = ret || 0; +				ret = elem.style.pixelLeft + "px"; + +				// Revert the changed values +				elem.style.left = style; +				elem.runtimeStyle.left = runtimeStyle; +			} +		} + +		return ret; +	}, +	 +	clean: function( elems, context ) { +		var ret = []; +		context = context || document; +		// !context.createElement fails in IE with an error but returns typeof 'object' +		if (typeof context.createElement == 'undefined')  +			context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + +		jQuery.each(elems, function(i, elem){ +			if ( !elem ) +				return; + +			if ( elem.constructor == Number ) +				elem = elem.toString(); +			 +			// Convert html string into DOM nodes +			if ( typeof elem == "string" ) { +				// Fix "XHTML"-style tags in all browsers +				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ +					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? +						all : +						front + "></" + tag + ">"; +				}); + +				// Trim whitespace, otherwise indexOf won't work as expected +				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); + +				var wrap = +					// option or optgroup +					!tags.indexOf("<opt") && +					[ 1, "<select multiple='multiple'>", "</select>" ] || +					 +					!tags.indexOf("<leg") && +					[ 1, "<fieldset>", "</fieldset>" ] || +					 +					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && +					[ 1, "<table>", "</table>" ] || +					 +					!tags.indexOf("<tr") && +					[ 2, "<table><tbody>", "</tbody></table>" ] || +					 +				 	// <thead> matched above +					(!tags.indexOf("<td") || !tags.indexOf("<th")) && +					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] || +					 +					!tags.indexOf("<col") && +					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] || + +					// IE can't serialize <link> and <script> tags normally +					jQuery.browser.msie && +					[ 1, "div<div>", "</div>" ] || +					 +					[ 0, "", "" ]; + +				// Go to html and back, then peel off extra wrappers +				div.innerHTML = wrap[1] + elem + wrap[2]; +				 +				// Move to the right depth +				while ( wrap[0]-- ) +					div = div.lastChild; +				 +				// Remove IE's autoinserted <tbody> from table fragments +				if ( jQuery.browser.msie ) { +					 +					// String was a <table>, *may* have spurious <tbody> +					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ? +						div.firstChild && div.firstChild.childNodes : +						 +						// String was a bare <thead> or <tfoot> +						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ? +							div.childNodes : +							[]; +				 +					for ( var j = tbody.length - 1; j >= 0 ; --j ) +						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) +							tbody[ j ].parentNode.removeChild( tbody[ j ] ); +					 +					// IE completely kills leading whitespace when innerHTML is used	 +					if ( /^\s/.test( elem ) )	 +						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild ); +				 +				} +				 +				elem = jQuery.makeArray( div.childNodes ); +			} + +			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) ) +				return; + +			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options ) +				ret.push( elem ); + +			else +				ret = jQuery.merge( ret, elem ); + +		}); + +		return ret; +	}, +	 +	attr: function( elem, name, value ) { +		// don't set attributes on text and comment nodes +		if (!elem || elem.nodeType == 3 || elem.nodeType == 8) +			return undefined; + +		var fix = jQuery.isXMLDoc( elem ) ? +			{} : +			jQuery.props; + +		// Safari mis-reports the default selected property of a hidden option +		// Accessing the parent's selectedIndex property fixes it +		if ( name == "selected" && jQuery.browser.safari ) +			elem.parentNode.selectedIndex; +		 +		// Certain attributes only work when accessed via the old DOM 0 way +		if ( fix[ name ] ) { +			if ( value != undefined ) +				elem[ fix[ name ] ] = value; + +			return elem[ fix[ name ] ]; + +		} else if ( jQuery.browser.msie && name == "style" ) +			return jQuery.attr( elem.style, "cssText", value ); + +		else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") ) +			return elem.getAttributeNode( name ).nodeValue; + +		// IE elem.getAttribute passes even for style +		else if ( elem.tagName ) { + +			if ( value != undefined ) { +				// We can't allow the type property to be changed (since it causes problems in IE) +				if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode ) +					throw "type property can't be changed"; + +				// convert the value to a string (all browsers do this but IE) see #1070 +				elem.setAttribute( name, "" + value ); +			} + +			if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) )  +				return elem.getAttribute( name, 2 ); + +			return elem.getAttribute( name ); + +		// elem is actually elem.style ... set the style +		} else { +			// IE actually uses filters for opacity +			if ( name == "opacity" && jQuery.browser.msie ) { +				if ( value != undefined ) { +					// IE has trouble with opacity if it does not have layout +					// Force it by setting the zoom level +					elem.zoom = 1;  +	 +					// Set the alpha filter to set the opacity +					elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) + +						(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")"); +				} +	 +				return elem.filter && elem.filter.indexOf("opacity=") >= 0 ? +					(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() : +					""; +			} + +			name = name.replace(/-([a-z])/ig, function(all, letter){ +				return letter.toUpperCase(); +			}); + +			if ( value != undefined ) +				elem[ name ] = value; + +			return elem[ name ]; +		} +	}, +	 +	trim: function( text ) { +		return (text || "").replace( /^\s+|\s+$/g, "" ); +	}, + +	makeArray: function( array ) { +		var ret = []; + +		// Need to use typeof to fight Safari childNodes crashes +		if ( array.constructor != Array ) +			for ( var i = 0, length = array.length; i < length; i++ ) +				ret.push( array[ i ] ); +		else +			ret = array.slice( 0 ); + +		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 + +		// Also, we need to make sure that the correct elements are being returned +		// (IE returns comment nodes in a '*' query) +		if ( jQuery.browser.msie ) { +			for ( var i = 0; second[ i ]; i++ ) +				if ( second[ i ].nodeType != 8 ) +					first.push( second[ i ] ); + +		} else +			for ( var i = 0; second[ i ]; i++ ) +				first.push( second[ i ] ); + +		return first; +	}, + +	unique: function( array ) { +		var ret = [], done = {}; + +		try { + +			for ( var i = 0, length = array.length; i < length; i++ ) { +				var 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 ) || inv && !callback( elems[ i ], i ) ) +				ret.push( elems[ i ] ); + +		return ret; +	}, + +	map: function( elems, callback ) { +		var ret = []; + +		// 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++ ) { +			var value = callback( elems[ i ], i ); + +			if ( value !== null && value != undefined ) { +				if ( value.constructor != Array ) +					value = [ value ]; + +				ret = ret.concat( value ); +			} +		} + +		return ret; +	} +}); + +var userAgent = navigator.userAgent.toLowerCase(); + +// Figure out what browser is being used +jQuery.browser = { +	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1], +	safari: /webkit/.test( userAgent ), +	opera: /opera/.test( userAgent ), +	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), +	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) +}; + +var styleFloat = jQuery.browser.msie ? +	"styleFloat" : +	"cssFloat"; +	 +jQuery.extend({ +	// Check to see if the W3C box model is being used +	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat", +	 +	props: { +		"for": "htmlFor", +		"class": "className", +		"float": styleFloat, +		cssFloat: styleFloat, +		styleFloat: styleFloat, +		innerHTML: "innerHTML", +		className: "className", +		value: "value", +		disabled: "disabled", +		checked: "checked", +		readonly: "readOnly", +		selected: "selected", +		maxlength: "maxLength", +		selectedIndex: "selectedIndex", +		defaultValue: "defaultValue", +		tagName: "tagName", +		nodeName: "nodeName" +	} +}); + +jQuery.each({ +	parent: function(elem){return elem.parentNode;}, +	parents: function(elem){return jQuery.dir(elem,"parentNode");}, +	next: function(elem){return jQuery.nth(elem,2,"nextSibling");}, +	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");}, +	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");}, +	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");}, +	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);}, +	children: function(elem){return jQuery.sibling(elem.firstChild);}, +	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);} +}, function(name, fn){ +	jQuery.fn[ name ] = function( selector ) { +		var ret = jQuery.map( this, fn ); + +		if ( selector && typeof selector == "string" ) +			ret = jQuery.multiFilter( selector, ret ); + +		return this.pushStack( jQuery.unique( ret ) ); +	}; +}); + +jQuery.each({ +	appendTo: "append", +	prependTo: "prepend", +	insertBefore: "before", +	insertAfter: "after", +	replaceAll: "replaceWith" +}, function(name, original){ +	jQuery.fn[ name ] = function() { +		var args = arguments; + +		return this.each(function(){ +			for ( var i = 0, length = args.length; i < length; i++ ) +				jQuery( args[ i ] )[ original ]( this ); +		}); +	}; +}); + +jQuery.each({ +	removeAttr: function( name ) { +		jQuery.attr( this, name, "" ); +		if (this.nodeType == 1)  +			this.removeAttribute( name ); +	}, + +	addClass: function( classNames ) { +		jQuery.className.add( this, classNames ); +	}, + +	removeClass: function( classNames ) { +		jQuery.className.remove( this, classNames ); +	}, + +	toggleClass: function( classNames ) { +		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames ); +	}, + +	remove: function( selector ) { +		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) { +			// Prevent memory leaks +			jQuery( "*", this ).add(this).each(function(){ +				jQuery.event.remove(this); +				jQuery.removeData(this); +			}); +			if (this.parentNode) +				this.parentNode.removeChild( this ); +		} +	}, + +	empty: function() { +		// Remove element nodes and prevent memory leaks +		jQuery( ">*", this ).remove(); +		 +		// Remove any remaining nodes +		while ( this.firstChild ) +			this.removeChild( this.firstChild ); +	} +}, function(name, fn){ +	jQuery.fn[ name ] = function(){ +		return this.each( fn, arguments ); +	}; +}); + +jQuery.each([ "Height", "Width" ], function(i, name){ +	var type = name.toLowerCase(); +	 +	jQuery.fn[ type ] = function( size ) { +		// Get window width or height +		return this[0] == window ? +			// Opera reports document.body.client[Width/Height] properly in both quirks and standards +			jQuery.browser.opera && document.body[ "client" + name ] ||  +			 +			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths) +			jQuery.browser.safari && window[ "inner" + name ] || +			 +			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode +			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] : +		 +			// Get document width or height +			this[0] == document ? +				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater +				Math.max(  +					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),  +					Math.max(document.body["offset" + name], document.documentElement["offset" + name])  +				) : + +				// Get or set width or height on the element +				size == undefined ? +					// Get width or height on the element +					(this.length ? jQuery.css( this[0], type ) : null) : + +					// Set the width or height on the element (default to pixels if value is unitless) +					this.css( type, size.constructor == String ? size : size + "px" ); +	}; +}); + +var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ? +		"(?:[\\w*_-]|\\\\.)" : +		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)", +	quickChild = new RegExp("^>\\s*(" + chars + "+)"), +	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"), +	quickClass = new RegExp("^([#.]?)(" + chars + "*)"); + +jQuery.extend({ +	expr: { +		"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);}, +		"#": function(a,i,m){return a.getAttribute("id")==m[2];}, +		":": { +			// Position Checks +			lt: function(a,i,m){return i<m[3]-0;}, +			gt: function(a,i,m){return i>m[3]-0;}, +			nth: function(a,i,m){return m[3]-0==i;}, +			eq: function(a,i,m){return m[3]-0==i;}, +			first: function(a,i){return i==0;}, +			last: function(a,i,m,r){return i==r.length-1;}, +			even: function(a,i){return i%2==0;}, +			odd: function(a,i){return i%2;}, + +			// Child Checks +			"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;}, +			"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;}, +			"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");}, + +			// Parent Checks +			parent: function(a){return a.firstChild;}, +			empty: function(a){return !a.firstChild;}, + +			// Text Check +			contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;}, + +			// Visibility +			visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";}, +			hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";}, + +			// Form attributes +			enabled: function(a){return !a.disabled;}, +			disabled: function(a){return a.disabled;}, +			checked: function(a){return a.checked;}, +			selected: function(a){return a.selected||jQuery.attr(a,"selected");}, + +			// Form elements +			text: function(a){return "text"==a.type;}, +			radio: function(a){return "radio"==a.type;}, +			checkbox: function(a){return "checkbox"==a.type;}, +			file: function(a){return "file"==a.type;}, +			password: function(a){return "password"==a.type;}, +			submit: function(a){return "submit"==a.type;}, +			image: function(a){return "image"==a.type;}, +			reset: function(a){return "reset"==a.type;}, +			button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");}, +			input: function(a){return /input|select|textarea|button/i.test(a.nodeName);}, + +			// :has() +			has: function(a,i,m){return jQuery.find(m[3],a).length;}, + +			// :header +			header: function(a){return /h\d/i.test(a.nodeName);}, + +			// :animated +			animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;} +		} +	}, +	 +	// The regular expressions that power the parsing engine +	parse: [ +		// Match: [@value='test'], [@foo] +		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/, + +		// Match: :contains('foo') +		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/, + +		// Match: :even, :last-chlid, #id, .class +		new RegExp("^([:.#]*)(" + chars + "+)") +	], + +	multiFilter: function( expr, elems, not ) { +		var old, cur = []; + +		while ( expr && expr != old ) { +			old = expr; +			var f = jQuery.filter( expr, elems, not ); +			expr = f.t.replace(/^\s*,\s*/, "" ); +			cur = not ? elems = f.r : jQuery.merge( cur, f.r ); +		} + +		return cur; +	}, + +	find: function( t, context ) { +		// Quickly handle non-string expressions +		if ( typeof t != "string" ) +			return [ t ]; + +		// check to make sure context is a DOM element or a document +		if ( context && context.nodeType != 1 && context.nodeType != 9) +			return [ ]; + +		// Set the correct context (if none is provided) +		context = context || document; + +		// Initialize the search +		var ret = [context], done = [], last, nodeName; + +		// Continue while a selector expression exists, and while +		// we're no longer looping upon ourselves +		while ( t && last != t ) { +			var r = []; +			last = t; + +			t = jQuery.trim(t); + +			var foundToken = false; + +			// An attempt at speeding up child selectors that +			// point to a specific element tag +			var re = quickChild; +			var m = re.exec(t); + +			if ( m ) { +				nodeName = m[1].toUpperCase(); + +				// Perform our own iteration and filter +				for ( var i = 0; ret[i]; i++ ) +					for ( var c = ret[i].firstChild; c; c = c.nextSibling ) +						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) ) +							r.push( c ); + +				ret = r; +				t = t.replace( re, "" ); +				if ( t.indexOf(" ") == 0 ) continue; +				foundToken = true; +			} else { +				re = /^([>+~])\s*(\w*)/i; + +				if ( (m = re.exec(t)) != null ) { +					r = []; + +					var merge = {}; +					nodeName = m[2].toUpperCase(); +					m = m[1]; + +					for ( var j = 0, rl = ret.length; j < rl; j++ ) { +						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild; +						for ( ; n; n = n.nextSibling ) +							if ( n.nodeType == 1 ) { +								var id = jQuery.data(n); + +								if ( m == "~" && merge[id] ) break; +								 +								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) { +									if ( m == "~" ) merge[id] = true; +									r.push( n ); +								} +								 +								if ( m == "+" ) break; +							} +					} + +					ret = r; + +					// And remove the token +					t = jQuery.trim( t.replace( re, "" ) ); +					foundToken = true; +				} +			} + +			// See if there's still an expression, and that we haven't already +			// matched a token +			if ( t && !foundToken ) { +				// Handle multiple expressions +				if ( !t.indexOf(",") ) { +					// Clean the result set +					if ( context == ret[0] ) ret.shift(); + +					// Merge the result sets +					done = jQuery.merge( done, ret ); + +					// Reset the context +					r = ret = [context]; + +					// Touch up the selector string +					t = " " + t.substr(1,t.length); + +				} else { +					// Optimize for the case nodeName#idName +					var re2 = quickID; +					var m = re2.exec(t); +					 +					// Re-organize the results, so that they're consistent +					if ( m ) { +						m = [ 0, m[2], m[3], m[1] ]; + +					} else { +						// Otherwise, do a traditional filter check for +						// ID, class, and element selectors +						re2 = quickClass; +						m = re2.exec(t); +					} + +					m[2] = m[2].replace(/\\/g, ""); + +					var elem = ret[ret.length-1]; + +					// Try to do a global search by ID, where we can +					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) { +						// Optimization for HTML document case +						var oid = elem.getElementById(m[2]); +						 +						// Do a quick check for the existence of the actual ID attribute +						// to avoid selecting by the name attribute in IE +						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form +						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] ) +							oid = jQuery('[@id="'+m[2]+'"]', elem)[0]; + +						// Do a quick check for node name (where applicable) so +						// that div#foo searches will be really fast +						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : []; +					} else { +						// We need to find all descendant elements +						for ( var i = 0; ret[i]; i++ ) { +							// Grab the tag name being searched for +							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2]; + +							// Handle IE7 being really dumb about <object>s +							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" ) +								tag = "param"; + +							r = jQuery.merge( r, ret[i].getElementsByTagName( tag )); +						} + +						// It's faster to filter by class and be done with it +						if ( m[1] == "." ) +							r = jQuery.classFilter( r, m[2] ); + +						// Same with ID filtering +						if ( m[1] == "#" ) { +							var tmp = []; + +							// Try to find the element with the ID +							for ( var i = 0; r[i]; i++ ) +								if ( r[i].getAttribute("id") == m[2] ) { +									tmp = [ r[i] ]; +									break; +								} + +							r = tmp; +						} + +						ret = r; +					} + +					t = t.replace( re2, "" ); +				} + +			} + +			// If a selector string still exists +			if ( t ) { +				// Attempt to filter it +				var val = jQuery.filter(t,r); +				ret = r = val.r; +				t = jQuery.trim(val.t); +			} +		} + +		// An error occurred with the selector; +		// just return an empty set instead +		if ( t ) +			ret = []; + +		// Remove the root context +		if ( ret && context == ret[0] ) +			ret.shift(); + +		// And combine the results +		done = jQuery.merge( done, ret ); + +		return done; +	}, + +	classFilter: function(r,m,not){ +		m = " " + m + " "; +		var tmp = []; +		for ( var i = 0; r[i]; i++ ) { +			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0; +			if ( !not && pass || not && !pass ) +				tmp.push( r[i] ); +		} +		return tmp; +	}, + +	filter: function(t,r,not) { +		var last; + +		// Look for common filter expressions +		while ( t && t != last ) { +			last = t; + +			var p = jQuery.parse, m; + +			for ( var i = 0; p[i]; i++ ) { +				m = p[i].exec( t ); + +				if ( m ) { +					// Remove what we just matched +					t = t.substring( m[0].length ); + +					m[2] = m[2].replace(/\\/g, ""); +					break; +				} +			} + +			if ( !m ) +				break; + +			// :not() is a special case that can be optimized by +			// keeping it out of the expression list +			if ( m[1] == ":" && m[2] == "not" ) +				// optimize if only one selector found (most common case) +				r = isSimple.test( m[3] ) ? +					jQuery.filter(m[3], r, true).r : +					jQuery( r ).not( m[3] ); + +			// We can get a big speed boost by filtering by class here +			else if ( m[1] == "." ) +				r = jQuery.classFilter(r, m[2], not); + +			else if ( m[1] == "[" ) { +				var tmp = [], type = m[3]; +				 +				for ( var i = 0, rl = r.length; i < rl; i++ ) { +					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ]; +					 +					if ( z == null || /href|src|selected/.test(m[2]) ) +						z = jQuery.attr(a,m[2]) || ''; + +					if ( (type == "" && !!z || +						 type == "=" && z == m[5] || +						 type == "!=" && z != m[5] || +						 type == "^=" && z && !z.indexOf(m[5]) || +						 type == "$=" && z.substr(z.length - m[5].length) == m[5] || +						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not ) +							tmp.push( a ); +				} +				 +				r = tmp; + +			// We can get a speed boost by handling nth-child here +			} else if ( m[1] == ":" && m[2] == "nth-child" ) { +				var merge = {}, tmp = [], +					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' +					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( +						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" || +						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]), +					// calculate the numbers (first)n+(last) including if they are negative +					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0; +  +				// loop through all the elements left in the jQuery object +				for ( var i = 0, rl = r.length; i < rl; i++ ) { +					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode); + +					if ( !merge[id] ) { +						var c = 1; + +						for ( var n = parentNode.firstChild; n; n = n.nextSibling ) +							if ( n.nodeType == 1 ) +								n.nodeIndex = c++; + +						merge[id] = true; +					} + +					var add = false; + +					if ( first == 0 ) { +						if ( node.nodeIndex == last ) +							add = true; +					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 ) +						add = true; + +					if ( add ^ not ) +						tmp.push( node ); +				} + +				r = tmp; + +			// Otherwise, find the expression to execute +			} else { +				var fn = jQuery.expr[ m[1] ]; +				if ( typeof fn == "object" ) +					fn = fn[ m[2] ]; + +				if ( typeof fn == "string" ) +					fn = eval("false||function(a,i){return " + fn + ";}"); + +				// Execute it against the current filter +				r = jQuery.grep( r, function(elem, i){ +					return fn(elem, i, m, r); +				}, not ); +			} +		} + +		// Return an array of filtered elements (r) +		// and the modified expression string (t) +		return { r: r, t: t }; +	}, + +	dir: function( elem, dir ){ +		var matched = []; +		var cur = elem[dir]; +		while ( cur && cur != document ) { +			if ( cur.nodeType == 1 ) +				matched.push( cur ); +			cur = cur[dir]; +		} +		return matched; +	}, +	 +	nth: function(cur,result,dir,elem){ +		result = result || 1; +		var num = 0; + +		for ( ; cur; cur = cur[dir] ) +			if ( cur.nodeType == 1 && ++num == result ) +				break; + +		return cur; +	}, +	 +	sibling: function( n, elem ) { +		var r = []; + +		for ( ; n; n = n.nextSibling ) { +			if ( n.nodeType == 1 && (!elem || n != elem) ) +				r.push( n ); +		} + +		return r; +	} +}); + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code orignated from  + * Dean Edwards' addEvent library. + */ +jQuery.event = { + +	// Bind an event to an element +	// Original by Dean Edwards +	add: function(elem, types, handler, data) { +		if ( elem.nodeType == 3 || elem.nodeType == 8 ) +			return; + +		// For whatever reason, IE has trouble passing the window object +		// around, causing it to be cloned in the process +		if ( jQuery.browser.msie && elem.setInterval != undefined ) +			elem = window; + +		// Make sure that the function being executed has a unique ID +		if ( !handler.guid ) +			handler.guid = this.guid++; +			 +		// if data is passed, bind to handler  +		if( data != undefined ) {  +			// Create temporary function pointer to original handler  +			var fn = handler;  + +			// Create unique handler function, wrapped around original handler  +			handler = function() {  +				// Pass arguments and context to original handler  +				return fn.apply(this, arguments);  +			}; + +			// Store data in unique handler  +			handler.data = data; + +			// Set the guid of unique handler to the same of original handler, so it can be removed  +			handler.guid = fn.guid; +		} + +		// Init the element's event structure +		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}), +			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){ +				// returned undefined or false +				var val; + +				// Handle the second event of a trigger and when +				// an event is called after a page has unloaded +				if ( typeof jQuery == "undefined" || jQuery.event.triggered ) +					return val; +		 +				val = jQuery.event.handle.apply(arguments.callee.elem, arguments); +		 +				return val; +			}); +		// Add elem as a property of the handle function +		// This is to prevent a memory leak with non-native +		// event in IE. +		handle.elem = elem; +			 +			// Handle multiple events seperated by a space +			// jQuery(...).bind("mouseover mouseout", fn); +			jQuery.each(types.split(/\s+/), function(index, type) { +				// Namespaced event handlers +				var parts = type.split("."); +				type = parts[0]; +				handler.type = parts[1]; + +				// Get the current list of functions bound to this event +				var handlers = events[type]; + +				// Init the event handler queue +				if (!handlers) { +					handlers = events[type] = {}; +		 +					// Check for a special event handler +					// Only use addEventListener/attachEvent if the special +					// events handler returns false +					if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) { +						// Bind the global event handler to the element +						if (elem.addEventListener) +							elem.addEventListener(type, handle, false); +						else if (elem.attachEvent) +							elem.attachEvent("on" + type, handle); +					} +				} + +				// Add the function to the element's handler list +				handlers[handler.guid] = handler; + +				// Keep track of which events have been used, for global triggering +				jQuery.event.global[type] = true; +			}); +		 +		// Nullify elem to prevent memory leaks in IE +		elem = null; +	}, + +	guid: 1, +	global: {}, + +	// Detach an event or set of events from an element +	remove: function(elem, types, handler) { +		// don't do events on text and comment nodes +		if ( elem.nodeType == 3 || elem.nodeType == 8 ) +			return; + +		var events = jQuery.data(elem, "events"), ret, index; + +		if ( events ) { +			// Unbind all events for the element +			if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") ) +				for ( var type in events ) +					this.remove( elem, type + (types || "") ); +			else { +				// types is actually an event object here +				if ( types.type ) { +					handler = types.handler; +					types = types.type; +				} +				 +				// Handle multiple events seperated by a space +				// jQuery(...).unbind("mouseover mouseout", fn); +				jQuery.each(types.split(/\s+/), function(index, type){ +					// Namespaced event handlers +					var parts = type.split("."); +					type = parts[0]; +					 +					if ( events[type] ) { +						// remove the given handler for the given type +						if ( handler ) +							delete events[type][handler.guid]; +			 +						// remove all handlers for the given type +						else +							for ( handler in events[type] ) +								// Handle the removal of namespaced events +								if ( !parts[1] || events[type][handler].type == parts[1] ) +									delete events[type][handler]; + +						// remove generic event handler if no more handlers exist +						for ( ret in events[type] ) break; +						if ( !ret ) { +							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) { +								if (elem.removeEventListener) +									elem.removeEventListener(type, jQuery.data(elem, "handle"), false); +								else if (elem.detachEvent) +									elem.detachEvent("on" + type, jQuery.data(elem, "handle")); +							} +							ret = null; +							delete events[type]; +						} +					} +				}); +			} + +			// Remove the expando if it's no longer used +			for ( ret in events ) break; +			if ( !ret ) { +				var handle = jQuery.data( elem, "handle" ); +				if ( handle ) handle.elem = null; +				jQuery.removeData( elem, "events" ); +				jQuery.removeData( elem, "handle" ); +			} +		} +	}, + +	trigger: function(type, data, elem, donative, extra) { +		// Clone the incoming data, if any +		data = jQuery.makeArray(data || []); + +		if ( type.indexOf("!") >= 0 ) { +			type = type.slice(0, -1); +			var exclusive = true; +		} + +		// Handle a global trigger +		if ( !elem ) { +			// Only trigger if we've ever bound an event for it +			if ( this.global[type] ) +				jQuery("*").add([window, document]).trigger(type, data); + +		// Handle triggering a single element +		} else { +			// don't do events on text and comment nodes +			if ( elem.nodeType == 3 || elem.nodeType == 8 ) +				return undefined; + +			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ), +				// Check to see if we need to provide a fake event, or not +				event = !data[0] || !data[0].preventDefault; +			 +			// Pass along a fake event +			if ( event ) +				data.unshift( this.fix({ type: type, target: elem }) ); + +			// Enforce the right trigger type +			data[0].type = type; +			if ( exclusive ) +				data[0].exclusive = true; + +			// Trigger the event +			if ( jQuery.isFunction( jQuery.data(elem, "handle") ) ) +				val = jQuery.data(elem, "handle").apply( elem, data ); + +			// Handle triggering native .onfoo handlers +			if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false ) +				val = false; + +			// Extra functions don't get the custom event object +			if ( event ) +				data.shift(); + +			// Handle triggering of extra function +			if ( extra && jQuery.isFunction( extra ) ) { +				// call the extra function and tack the current return value on the end for possible inspection +				ret = extra.apply( elem, val == null ? data : data.concat( val ) ); +				// if anything is returned, give it precedence and have it overwrite the previous value +				if (ret !== undefined) +					val = ret; +			} + +			// Trigger the native events (except for clicks on links) +			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) { +				this.triggered = true; +				try { +					elem[ type ](); +				// prevent IE from throwing an error for some hidden elements +				} catch (e) {} +			} + +			this.triggered = false; +		} + +		return val; +	}, + +	handle: function(event) { +		// returned undefined or false +		var val; + +		// Empty object is for triggered events with no data +		event = jQuery.event.fix( event || window.event || {} );  + +		// Namespaced event handlers +		var parts = event.type.split("."); +		event.type = parts[0]; + +		var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 ); +		args.unshift( event ); + +		for ( var j in handlers ) { +			var handler = handlers[j]; +			// Pass in a reference to the handler function itself +			// So that we can later remove it +			args[0].handler = handler; +			args[0].data = handler.data; + +			// Filter the functions by class +			if ( !parts[1] && !event.exclusive || handler.type == parts[1] ) { +				var ret = handler.apply( this, args ); + +				if ( val !== false ) +					val = ret; + +				if ( ret === false ) { +					event.preventDefault(); +					event.stopPropagation(); +				} +			} +		} + +		// Clean up added properties in IE to prevent memory leak +		if (jQuery.browser.msie) +			event.target = event.preventDefault = event.stopPropagation = +				event.handler = event.data = null; + +		return val; +	}, + +	fix: function(event) { +		// store a copy of the original event object  +		// and clone to set read-only properties +		var originalEvent = event; +		event = jQuery.extend({}, originalEvent); +		 +		// add preventDefault and stopPropagation since  +		// they will not work on the clone +		event.preventDefault = function() { +			// if preventDefault exists run it on the original event +			if (originalEvent.preventDefault) +				originalEvent.preventDefault(); +			// otherwise set the returnValue property of the original event to false (IE) +			originalEvent.returnValue = false; +		}; +		event.stopPropagation = function() { +			// if stopPropagation exists run it on the original event +			if (originalEvent.stopPropagation) +				originalEvent.stopPropagation(); +			// otherwise set the cancelBubble property of the original event to true (IE) +			originalEvent.cancelBubble = true; +		}; +		 +		// Fix target property, if necessary +		if ( !event.target ) +			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either +				 +		// check if target is a textnode (safari) +		if ( event.target.nodeType == 3 ) +			event.target = originalEvent.target.parentNode; + +		// Add relatedTarget, if necessary +		if ( !event.relatedTarget && event.fromElement ) +			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement; + +		// Calculate pageX/Y if missing and clientX/Y available +		if ( event.pageX == null && event.clientX != null ) { +			var doc = document.documentElement, body = document.body; +			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0); +			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0); +		} +			 +		// Add which for key events +		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) +			event.which = event.charCode || event.keyCode; +		 +		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) +		if ( !event.metaKey && event.ctrlKey ) +			event.metaKey = event.ctrlKey; + +		// Add which for click: 1 == left; 2 == middle; 3 == right +		// Note: button is not normalized, so don't use it +		if ( !event.which && event.button ) +			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); +			 +		return event; +	}, +	 +	special: { +		ready: { +			setup: function() { +				// Make sure the ready event is setup +				bindReady(); +				return; +			}, +			 +			teardown: function() { return; } +		}, +		 +		mouseenter: { +			setup: function() { +				if ( jQuery.browser.msie ) return false; +				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler); +				return true; +			}, +		 +			teardown: function() { +				if ( jQuery.browser.msie ) return false; +				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler); +				return true; +			}, +			 +			handler: function(event) { +				// If we actually just moused on to a sub-element, ignore it +				if ( withinElement(event, this) ) return true; +				// Execute the right handlers by setting the event type to mouseenter +				arguments[0].type = "mouseenter"; +				return jQuery.event.handle.apply(this, arguments); +			} +		}, +	 +		mouseleave: { +			setup: function() { +				if ( jQuery.browser.msie ) return false; +				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler); +				return true; +			}, +		 +			teardown: function() { +				if ( jQuery.browser.msie ) return false; +				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler); +				return true; +			}, +			 +			handler: function(event) { +				// If we actually just moused on to a sub-element, ignore it +				if ( withinElement(event, this) ) return true; +				// Execute the right handlers by setting the event type to mouseleave +				arguments[0].type = "mouseleave"; +				return jQuery.event.handle.apply(this, arguments); +			} +		} +	} +}; + +jQuery.fn.extend({ +	bind: function( type, data, fn ) { +		return type == "unload" ? this.one(type, data, fn) : this.each(function(){ +			jQuery.event.add( this, type, fn || data, fn && data ); +		}); +	}, +	 +	one: function( type, data, fn ) { +		return this.each(function(){ +			jQuery.event.add( this, type, function(event) { +				jQuery(this).unbind(event); +				return (fn || data).apply( this, arguments); +			}, fn && data); +		}); +	}, + +	unbind: function( type, fn ) { +		return this.each(function(){ +			jQuery.event.remove( this, type, fn ); +		}); +	}, + +	trigger: function( type, data, fn ) { +		return this.each(function(){ +			jQuery.event.trigger( type, data, this, true, fn ); +		}); +	}, + +	triggerHandler: function( type, data, fn ) { +		if ( this[0] ) +			return jQuery.event.trigger( type, data, this[0], false, fn ); +		return undefined; +	}, + +	toggle: function() { +		// Save reference to arguments for access in closure +		var args = arguments; + +		return this.click(function(event) { +			// Figure out which function to execute +			this.lastToggle = 0 == this.lastToggle ? 1 : 0; +			 +			// Make sure that clicks stop +			event.preventDefault(); +			 +			// and execute the function +			return args[this.lastToggle].apply( this, arguments ) || false; +		}); +	}, + +	hover: function(fnOver, fnOut) { +		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut); +	}, +	 +	ready: function(fn) { +		// Attach the listeners +		bindReady(); + +		// If the DOM is already ready +		if ( jQuery.isReady ) +			// Execute the function immediately +			fn.call( document, jQuery ); +			 +		// Otherwise, remember the function for later +		else +			// Add the function to the wait list +			jQuery.readyList.push( function() { return fn.call(this, jQuery); } ); +	 +		return this; +	} +}); + +jQuery.extend({ +	isReady: false, +	readyList: [], +	// Handle when the DOM is ready +	ready: function() { +		// Make sure that the DOM is not already loaded +		if ( !jQuery.isReady ) { +			// Remember that the DOM is ready +			jQuery.isReady = true; +			 +			// If there are functions bound, to execute +			if ( jQuery.readyList ) { +				// Execute all of them +				jQuery.each( jQuery.readyList, function(){ +					this.apply( document ); +				}); +				 +				// Reset the list of functions +				jQuery.readyList = null; +			} +		 +			// Trigger any bound ready events +			jQuery(document).triggerHandler("ready"); +		} +	} +}); + +var readyBound = false; + +function bindReady(){ +	if ( readyBound ) return; +	readyBound = true; + +	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event +	if ( document.addEventListener && !jQuery.browser.opera) +		// Use the handy event callback +		document.addEventListener( "DOMContentLoaded", jQuery.ready, false ); +	 +	// If IE is used and is not in a frame +	// Continually check to see if the document is ready +	if ( jQuery.browser.msie && window == top ) (function(){ +		if (jQuery.isReady) return; +		try { +			// If IE is used, use the trick by Diego Perini +			// http://javascript.nwbox.com/IEContentLoaded/ +			document.documentElement.doScroll("left"); +		} catch( error ) { +			setTimeout( arguments.callee, 0 ); +			return; +		} +		// and execute any waiting functions +		jQuery.ready(); +	})(); + +	if ( jQuery.browser.opera ) +		document.addEventListener( "DOMContentLoaded", function () { +			if (jQuery.isReady) return; +			for (var i = 0; i < document.styleSheets.length; i++) +				if (document.styleSheets[i].disabled) { +					setTimeout( arguments.callee, 0 ); +					return; +				} +			// and execute any waiting functions +			jQuery.ready(); +		}, false); + +	if ( jQuery.browser.safari ) { +		var numStyles; +		(function(){ +			if (jQuery.isReady) return; +			if ( document.readyState != "loaded" && document.readyState != "complete" ) { +				setTimeout( arguments.callee, 0 ); +				return; +			} +			if ( numStyles === undefined ) +				numStyles = jQuery("style, link[rel=stylesheet]").length; +			if ( document.styleSheets.length != numStyles ) { +				setTimeout( arguments.callee, 0 ); +				return; +			} +			// and execute any waiting functions +			jQuery.ready(); +		})(); +	} + +	// A fallback to window.onload, that will always work +	jQuery.event.add( window, "load", jQuery.ready ); +} + +jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + +	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +  +	"submit,keydown,keypress,keyup,error").split(","), function(i, name){ +	 +	// Handle event binding +	jQuery.fn[name] = function(fn){ +		return fn ? this.bind(name, fn) : this.trigger(name); +	}; +}); + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function(event, elem) { +	// Check if mouse(over|out) are still within the same parent element +	var parent = event.relatedTarget; +	// Traverse up the tree +	while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; } +	// Return true if we actually just moused on to a sub-element +	return parent == elem; +}; + +// Prevent memory leaks in IE +// And prevent errors on refresh with events like mouseover in other browsers +// Window isn't included so as not to unbind existing unload events +jQuery(window).bind("unload", function() { +	jQuery("*").add(document).unbind(); +}); +jQuery.fn.extend({ +	load: function( url, params, callback ) { +		if ( jQuery.isFunction( url ) ) +			return this.bind("load", url); + +		var off = url.indexOf(" "); +		if ( off >= 0 ) { +			var selector = url.slice(off, url.length); +			url = url.slice(0, off); +		} + +		callback = callback || function(){}; + +		// Default to a GET request +		var type = "GET"; + +		// If the second parameter was provided +		if ( params ) +			// If it's a function +			if ( jQuery.isFunction( params ) ) { +				// We assume that it's the callback +				callback = params; +				params = null; + +			// Otherwise, build a param string +			} else { +				params = jQuery.param( params ); +				type = "POST"; +			} + +		var self = this; + +		// Request the remote document +		jQuery.ajax({ +			url: url, +			type: type, +			dataType: "html", +			data: params, +			complete: function(res, status){ +				// If successful, inject the HTML into all the matched elements +				if ( status == "success" || status == "notmodified" ) +					// See if a selector was specified +					self.html( selector ? +						// Create a dummy div to hold the results +						jQuery("<div/>") +							// inject the contents of the document in, removing the scripts +							// to avoid any 'Permission Denied' errors in IE +							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, "")) + +							// Locate the specified elements +							.find(selector) : + +						// If not, just inject the full result +						res.responseText ); + +				self.each( callback, [res.responseText, status, res] ); +			} +		}); +		return this; +	}, + +	serialize: function() { +		return jQuery.param(this.serializeArray()); +	}, +	serializeArray: function() { +		return this.map(function(){ +			return jQuery.nodeName(this, "form") ? +				jQuery.makeArray(this.elements) : this; +		}) +		.filter(function(){ +			return this.name && !this.disabled &&  +				(this.checked || /select|textarea/i.test(this.nodeName) ||  +					/text|hidden|password/i.test(this.type)); +		}) +		.map(function(i, elem){ +			var val = jQuery(this).val(); +			return val == null ? null : +				val.constructor == Array ? +					jQuery.map( val, function(val, i){ +						return {name: elem.name, value: val}; +					}) : +					{name: elem.name, value: val}; +		}).get(); +	} +}); + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){ +	jQuery.fn[o] = function(f){ +		return this.bind(o, f); +	}; +}); + +var jsc = (new Date).getTime(); + +jQuery.extend({ +	get: function( url, data, callback, type ) { +		// shift arguments if data argument was ommited +		if ( jQuery.isFunction( data ) ) { +			callback = data; +			data = null; +		} +		 +		return jQuery.ajax({ +			type: "GET", +			url: url, +			data: data, +			success: callback, +			dataType: type +		}); +	}, + +	getScript: function( url, callback ) { +		return jQuery.get(url, null, callback, "script"); +	}, + +	getJSON: function( url, data, callback ) { +		return jQuery.get(url, data, callback, "json"); +	}, + +	post: function( url, data, callback, type ) { +		if ( jQuery.isFunction( data ) ) { +			callback = data; +			data = {}; +		} + +		return jQuery.ajax({ +			type: "POST", +			url: url, +			data: data, +			success: callback, +			dataType: type +		}); +	}, + +	ajaxSetup: function( settings ) { +		jQuery.extend( jQuery.ajaxSettings, settings ); +	}, + +	ajaxSettings: { +		global: true, +		type: "GET", +		timeout: 0, +		contentType: "application/x-www-form-urlencoded", +		processData: true, +		async: true, +		data: null, +		username: null, +		password: null, +		accepts: { +			xml: "application/xml, text/xml", +			html: "text/html", +			script: "text/javascript, application/javascript", +			json: "application/json, text/javascript", +			text: "text/plain", +			_default: "*/*" +		} +	}, +	 +	// Last-Modified header cache for next request +	lastModified: {}, + +	ajax: function( s ) { +		var jsonp, jsre = /=\?(&|$)/g, status, data; + +		// Extend the settings, but re-extend 's' so that it can be +		// checked again later (in the test suite, specifically) +		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); + +		// convert data if not already a string +		if ( s.data && s.processData && typeof s.data != "string" ) +			s.data = jQuery.param(s.data); + +		// Handle JSONP Parameter Callbacks +		if ( s.dataType == "jsonp" ) { +			if ( s.type.toLowerCase() == "get" ) { +				if ( !s.url.match(jsre) ) +					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?"; +			} else if ( !s.data || !s.data.match(jsre) ) +				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; +			s.dataType = "json"; +		} + +		// Build temporary JSONP function +		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) { +			jsonp = "jsonp" + jsc++; + +			// Replace the =? sequence both in the query string and the data +			if ( s.data ) +				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); +			s.url = s.url.replace(jsre, "=" + jsonp + "$1"); + +			// We need to make sure +			// that a JSONP style response is executed properly +			s.dataType = "script"; + +			// Handle JSONP-style loading +			window[ jsonp ] = function(tmp){ +				data = tmp; +				success(); +				complete(); +				// Garbage collect +				window[ jsonp ] = undefined; +				try{ delete window[ jsonp ]; } catch(e){} +				if ( head ) +					head.removeChild( script ); +			}; +		} + +		if ( s.dataType == "script" && s.cache == null ) +			s.cache = false; + +		if ( s.cache === false && s.type.toLowerCase() == "get" ) { +			var ts = (new Date()).getTime(); +			// try replacing _= if it is there +			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); +			// if nothing was replaced, add timestamp to the end +			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : ""); +		} + +		// If data is available, append data to url for get requests +		if ( s.data && s.type.toLowerCase() == "get" ) { +			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data; + +			// IE likes to send both get and post data, prevent this +			s.data = null; +		} + +		// Watch for a new set of requests +		if ( s.global && ! jQuery.active++ ) +			jQuery.event.trigger( "ajaxStart" ); + +		// If we're requesting a remote document +		// and trying to load JSON or Script with a GET +		if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get" ) { +			var head = document.getElementsByTagName("head")[0]; +			var script = document.createElement("script"); +			script.src = s.url; +			if (s.scriptCharset) +				script.charset = s.scriptCharset; + +			// Handle Script loading +			if ( !jsonp ) { +				var done = false; + +				// Attach handlers for all browsers +				script.onload = script.onreadystatechange = function(){ +					if ( !done && (!this.readyState ||  +							this.readyState == "loaded" || this.readyState == "complete") ) { +						done = true; +						success(); +						complete(); +						head.removeChild( script ); +					} +				}; +			} + +			head.appendChild(script); + +			// We handle everything using the script element injection +			return undefined; +		} + +		var requestDone = false; + +		// Create the request object; Microsoft failed to properly +		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available +		var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); + +		// Open the socket +		xml.open(s.type, s.url, s.async, s.username, s.password); + +		// Need an extra try/catch for cross domain requests in Firefox 3 +		try { +			// Set the correct header, if data is being sent +			if ( s.data ) +				xml.setRequestHeader("Content-Type", s.contentType); + +			// Set the If-Modified-Since header, if ifModified mode. +			if ( s.ifModified ) +				xml.setRequestHeader("If-Modified-Since", +					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" ); + +			// Set header so the called script knows that it's an XMLHttpRequest +			xml.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + +			// Set the Accepts header for the server, depending on the dataType +			xml.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? +				s.accepts[ s.dataType ] + ", */*" : +				s.accepts._default ); +		} catch(e){} + +		// Allow custom headers/mimetypes +		if ( s.beforeSend ) +			s.beforeSend(xml); +			 +		if ( s.global ) +			jQuery.event.trigger("ajaxSend", [xml, s]); + +		// Wait for a response to come back +		var onreadystatechange = function(isTimeout){ +			// The transfer is complete and the data is available, or the request timed out +			if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) { +				requestDone = true; +				 +				// clear poll interval +				if (ival) { +					clearInterval(ival); +					ival = null; +				} +				 +				status = isTimeout == "timeout" && "timeout" || +					!jQuery.httpSuccess( xml ) && "error" || +					s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" || +					"success"; + +				if ( status == "success" ) { +					// Watch for, and catch, XML document parse errors +					try { +						// process the data (runs the xml through httpData regardless of callback) +						data = jQuery.httpData( xml, s.dataType ); +					} catch(e) { +						status = "parsererror"; +					} +				} + +				// Make sure that the request was successful or notmodified +				if ( status == "success" ) { +					// Cache Last-Modified header, if ifModified mode. +					var modRes; +					try { +						modRes = xml.getResponseHeader("Last-Modified"); +					} catch(e) {} // swallow exception thrown by FF if header is not available +	 +					if ( s.ifModified && modRes ) +						jQuery.lastModified[s.url] = modRes; + +					// JSONP handles its own success callback +					if ( !jsonp ) +						success();	 +				} else +					jQuery.handleError(s, xml, status); + +				// Fire the complete handlers +				complete(); + +				// Stop memory leaks +				if ( s.async ) +					xml = null; +			} +		}; +		 +		if ( s.async ) { +			// don't attach the handler to the request, just poll it instead +			var ival = setInterval(onreadystatechange, 13);  + +			// Timeout checker +			if ( s.timeout > 0 ) +				setTimeout(function(){ +					// Check to see if the request is still happening +					if ( xml ) { +						// Cancel the request +						xml.abort(); +	 +						if( !requestDone ) +							onreadystatechange( "timeout" ); +					} +				}, s.timeout); +		} +			 +		// Send the data +		try { +			xml.send(s.data); +		} catch(e) { +			jQuery.handleError(s, xml, null, e); +		} +		 +		// firefox 1.5 doesn't fire statechange for sync requests +		if ( !s.async ) +			onreadystatechange(); + +		function success(){ +			// If a local callback was specified, fire it and pass it the data +			if ( s.success ) +				s.success( data, status ); + +			// Fire the global callback +			if ( s.global ) +				jQuery.event.trigger( "ajaxSuccess", [xml, s] ); +		} + +		function complete(){ +			// Process result +			if ( s.complete ) +				s.complete(xml, status); + +			// The request was completed +			if ( s.global ) +				jQuery.event.trigger( "ajaxComplete", [xml, s] ); + +			// Handle the global AJAX counter +			if ( s.global && ! --jQuery.active ) +				jQuery.event.trigger( "ajaxStop" ); +		} +		 +		// return XMLHttpRequest to allow aborting the request etc. +		return xml; +	}, + +	handleError: function( s, xml, status, e ) { +		// If a local callback was specified, fire it +		if ( s.error ) s.error( xml, status, e ); + +		// Fire the global callback +		if ( s.global ) +			jQuery.event.trigger( "ajaxError", [xml, s, e] ); +	}, + +	// Counter for holding the number of active queries +	active: 0, + +	// Determines if an XMLHttpRequest was successful or not +	httpSuccess: function( r ) { +		try { +			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 +			return !r.status && location.protocol == "file:" || +				( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 || +				jQuery.browser.safari && r.status == undefined; +		} catch(e){} +		return false; +	}, + +	// Determines if an XMLHttpRequest returns NotModified +	httpNotModified: function( xml, url ) { +		try { +			var xmlRes = xml.getResponseHeader("Last-Modified"); + +			// Firefox always returns 200. check Last-Modified date +			return xml.status == 304 || xmlRes == jQuery.lastModified[url] || +				jQuery.browser.safari && xml.status == undefined; +		} catch(e){} +		return false; +	}, + +	httpData: function( r, type ) { +		var ct = r.getResponseHeader("content-type"); +		var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0; +		var data = xml ? r.responseXML : r.responseText; + +		if ( xml && data.documentElement.tagName == "parsererror" ) +			throw "parsererror"; + +		// If the type is "script", eval it in global context +		if ( type == "script" ) +			jQuery.globalEval( data ); + +		// Get the JavaScript object, if JSON is used. +		if ( type == "json" ) +			data = eval("(" + data + ")"); + +		return data; +	}, + +	// Serialize an array of form elements or a set of +	// key/values into a query string +	param: function( a ) { +		var s = []; + +		// If an array was passed in, assume that it is an array +		// of form elements +		if ( a.constructor == Array || a.jquery ) +			// Serialize the form elements +			jQuery.each( a, function(){ +				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) ); +			}); + +		// Otherwise, assume that it's an object of key/value pairs +		else +			// Serialize the key/values +			for ( var j in a ) +				// If the value is an array then the key names need to be repeated +				if ( a[j] && a[j].constructor == Array ) +					jQuery.each( a[j], function(){ +						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) ); +					}); +				else +					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) ); + +		// Return the resulting serialization +		return s.join("&").replace(/%20/g, "+"); +	} + +}); +jQuery.fn.extend({ +	show: function(speed,callback){ +		return speed ? +			this.animate({ +				height: "show", width: "show", opacity: "show" +			}, speed, callback) : +			 +			this.filter(":hidden").each(function(){ +				this.style.display = this.oldblock || ""; +				if ( jQuery.css(this,"display") == "none" ) { +					var elem = jQuery("<" + this.tagName + " />").appendTo("body"); +					this.style.display = elem.css("display"); +					// handle an edge condition where css is - div { display:none; } or similar +					if (this.style.display == "none") +						this.style.display = "block"; +					elem.remove(); +				} +			}).end(); +	}, +	 +	hide: function(speed,callback){ +		return speed ? +			this.animate({ +				height: "hide", width: "hide", opacity: "hide" +			}, speed, callback) : +			 +			this.filter(":visible").each(function(){ +				this.oldblock = this.oldblock || jQuery.css(this,"display"); +				this.style.display = "none"; +			}).end(); +	}, + +	// Save the old toggle function +	_toggle: jQuery.fn.toggle, +	 +	toggle: function( fn, fn2 ){ +		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ? +			this._toggle( fn, fn2 ) : +			fn ? +				this.animate({ +					height: "toggle", width: "toggle", opacity: "toggle" +				}, fn, fn2) : +				this.each(function(){ +					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ](); +				}); +	}, +	 +	slideDown: function(speed,callback){ +		return this.animate({height: "show"}, speed, callback); +	}, +	 +	slideUp: function(speed,callback){ +		return this.animate({height: "hide"}, speed, callback); +	}, + +	slideToggle: function(speed, callback){ +		return this.animate({height: "toggle"}, speed, callback); +	}, +	 +	fadeIn: function(speed, callback){ +		return this.animate({opacity: "show"}, speed, callback); +	}, +	 +	fadeOut: function(speed, callback){ +		return this.animate({opacity: "hide"}, speed, callback); +	}, +	 +	fadeTo: function(speed,to,callback){ +		return this.animate({opacity: to}, speed, callback); +	}, +	 +	animate: function( prop, speed, easing, callback ) { +		var optall = jQuery.speed(speed, easing, callback); + +		return this[ optall.queue === false ? "each" : "queue" ](function(){ +			if ( this.nodeType != 1) +				return false; + +			var opt = jQuery.extend({}, optall); +			var hidden = jQuery(this).is(":hidden"), self = this; +			 +			for ( var p in prop ) { +				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden ) +					return jQuery.isFunction(opt.complete) && opt.complete.apply(this); + +				if ( p == "height" || p == "width" ) { +					// Store display property +					opt.display = jQuery.css(this, "display"); + +					// Make sure that nothing sneaks out +					opt.overflow = this.style.overflow; +				} +			} + +			if ( opt.overflow != null ) +				this.style.overflow = "hidden"; + +			opt.curAnim = jQuery.extend({}, prop); +			 +			jQuery.each( prop, function(name, val){ +				var e = new jQuery.fx( self, opt, name ); + +				if ( /toggle|show|hide/.test(val) ) +					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop ); +				else { +					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/), +						start = e.cur(true) || 0; + +					if ( parts ) { +						var end = parseFloat(parts[2]), +							unit = parts[3] || "px"; + +						// We need to compute starting value +						if ( unit != "px" ) { +							self.style[ name ] = (end || 1) + unit; +							start = ((end || 1) / e.cur(true)) * start; +							self.style[ name ] = start + unit; +						} + +						// If a +=/-= token was provided, we're doing a relative animation +						if ( parts[1] ) +							end = ((parts[1] == "-=" ? -1 : 1) * end) + start; + +						e.custom( start, end, unit ); +					} else +						e.custom( start, val, "" ); +				} +			}); + +			// For JS strict compliance +			return true; +		}); +	}, +	 +	queue: function(type, fn){ +		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) { +			fn = type; +			type = "fx"; +		} + +		if ( !type || (typeof type == "string" && !fn) ) +			return queue( this[0], type ); + +		return this.each(function(){ +			if ( fn.constructor == Array ) +				queue(this, type, fn); +			else { +				queue(this, type).push( fn ); +			 +				if ( queue(this, type).length == 1 ) +					fn.apply(this); +			} +		}); +	}, + +	stop: function(clearQueue, gotoEnd){ +		var timers = jQuery.timers; + +		if (clearQueue) +			this.queue([]); + +		this.each(function(){ +			// go in reverse order so anything added to the queue during the loop is ignored +			for ( var i = timers.length - 1; i >= 0; i-- ) +				if ( timers[i].elem == this ) { +					if (gotoEnd) +						// force the next step to be the last +						timers[i](true); +					timers.splice(i, 1); +				} +		}); + +		// start the next in the queue if the last step wasn't forced +		if (!gotoEnd) +			this.dequeue(); + +		return this; +	} + +}); + +var queue = function( elem, type, array ) { +	if ( !elem ) +		return undefined; + +	type = type || "fx"; + +	var q = jQuery.data( elem, type + "queue" ); + +	if ( !q || array ) +		q = jQuery.data( elem, type + "queue",  +			array ? jQuery.makeArray(array) : [] ); + +	return q; +}; + +jQuery.fn.dequeue = function(type){ +	type = type || "fx"; + +	return this.each(function(){ +		var q = queue(this, type); + +		q.shift(); + +		if ( q.length ) +			q[0].apply( this ); +	}); +}; + +jQuery.extend({ +	 +	speed: function(speed, easing, fn) { +		var opt = speed && speed.constructor == Object ? speed : { +			complete: fn || !fn && easing ||  +				jQuery.isFunction( speed ) && speed, +			duration: speed, +			easing: fn && easing || easing && easing.constructor != Function && easing +		}; + +		opt.duration = (opt.duration && opt.duration.constructor == Number ?  +			opt.duration :  +			{ slow: 600, fast: 200 }[opt.duration]) || 400; +	 +		// Queueing +		opt.old = opt.complete; +		opt.complete = function(){ +			if ( opt.queue !== false ) +				jQuery(this).dequeue(); +			if ( jQuery.isFunction( opt.old ) ) +				opt.old.apply( this ); +		}; +	 +		return opt; +	}, +	 +	easing: { +		linear: function( p, n, firstNum, diff ) { +			return firstNum + diff * p; +		}, +		swing: function( p, n, firstNum, diff ) { +			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; +		} +	}, +	 +	timers: [], +	timerId: null, + +	fx: function( elem, options, prop ){ +		this.options = options; +		this.elem = elem; +		this.prop = prop; + +		if ( !options.orig ) +			options.orig = {}; +	} + +}); + +jQuery.fx.prototype = { + +	// Simple function for setting a style value +	update: function(){ +		if ( this.options.step ) +			this.options.step.apply( this.elem, [ this.now, this ] ); + +		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); + +		// Set display property to block for height/width animations +		if ( this.prop == "height" || this.prop == "width" ) +			this.elem.style.display = "block"; +	}, + +	// Get the current size +	cur: function(force){ +		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null ) +			return this.elem[ this.prop ]; + +		var r = parseFloat(jQuery.css(this.elem, this.prop, force)); +		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0; +	}, + +	// Start an animation from one number to another +	custom: function(from, to, unit){ +		this.startTime = (new Date()).getTime(); +		this.start = from; +		this.end = to; +		this.unit = unit || this.unit || "px"; +		this.now = this.start; +		this.pos = this.state = 0; +		this.update(); + +		var self = this; +		function t(gotoEnd){ +			return self.step(gotoEnd); +		} + +		t.elem = this.elem; + +		jQuery.timers.push(t); + +		if ( jQuery.timerId == null ) { +			jQuery.timerId = setInterval(function(){ +				var timers = jQuery.timers; +				 +				for ( var i = 0; i < timers.length; i++ ) +					if ( !timers[i]() ) +						timers.splice(i--, 1); + +				if ( !timers.length ) { +					clearInterval( jQuery.timerId ); +					jQuery.timerId = null; +				} +			}, 13); +		} +	}, + +	// Simple 'show' function +	show: function(){ +		// Remember where we started, so that we can go back to it later +		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); +		this.options.show = true; + +		// Begin the animation +		this.custom(0, this.cur()); + +		// Make sure that we start at a small width/height to avoid any +		// flash of content +		if ( this.prop == "width" || this.prop == "height" ) +			this.elem.style[this.prop] = "1px"; +		 +		// Start by showing the element +		jQuery(this.elem).show(); +	}, + +	// Simple 'hide' function +	hide: function(){ +		// Remember where we started, so that we can go back to it later +		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); +		this.options.hide = true; + +		// Begin the animation +		this.custom(this.cur(), 0); +	}, + +	// Each step of an animation +	step: function(gotoEnd){ +		var t = (new Date()).getTime(); + +		if ( gotoEnd || t > this.options.duration + this.startTime ) { +			this.now = this.end; +			this.pos = this.state = 1; +			this.update(); + +			this.options.curAnim[ this.prop ] = true; + +			var done = true; +			for ( var i in this.options.curAnim ) +				if ( this.options.curAnim[i] !== true ) +					done = false; + +			if ( done ) { +				if ( this.options.display != null ) { +					// Reset the overflow +					this.elem.style.overflow = this.options.overflow; +				 +					// Reset the display +					this.elem.style.display = this.options.display; +					if ( jQuery.css(this.elem, "display") == "none" ) +						this.elem.style.display = "block"; +				} + +				// Hide the element if the "hide" operation was done +				if ( this.options.hide ) +					this.elem.style.display = "none"; + +				// Reset the properties, if the item has been hidden or shown +				if ( this.options.hide || this.options.show ) +					for ( var p in this.options.curAnim ) +						jQuery.attr(this.elem.style, p, this.options.orig[p]); +			} + +			// If a callback was provided, execute it +			if ( done && jQuery.isFunction( this.options.complete ) ) +				// Execute the complete function +				this.options.complete.apply( this.elem ); + +			return false; +		} else { +			var n = t - this.startTime; +			this.state = n / this.options.duration; + +			// Perform the easing function, defaults to swing +			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration); +			this.now = this.start + ((this.end - this.start) * this.pos); + +			// Perform the next step of the animation +			this.update(); +		} + +		return true; +	} + +}; + +jQuery.fx.step = { +	scrollLeft: function(fx){ +		fx.elem.scrollLeft = fx.now; +	}, + +	scrollTop: function(fx){ +		fx.elem.scrollTop = fx.now; +	}, + +	opacity: function(fx){ +		jQuery.attr(fx.elem.style, "opacity", fx.now); +	}, + +	_default: function(fx){ +		fx.elem.style[ fx.prop ] = fx.now + fx.unit; +	} +}; +// The Offset Method +// Originally By Brandon Aaron, part of the Dimension Plugin +// http://jquery.com/plugins/project/dimensions +jQuery.fn.offset = function() { +	var left = 0, top = 0, elem = this[0], results; +	 +	if ( elem ) with ( jQuery.browser ) { +		var parent       = elem.parentNode,  +		    offsetChild  = elem, +		    offsetParent = elem.offsetParent,  +		    doc          = elem.ownerDocument, +		    safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent), +		    fixed        = jQuery.css(elem, "position") == "fixed"; +	 +		// Use getBoundingClientRect if available +		if ( elem.getBoundingClientRect ) { +			var box = elem.getBoundingClientRect(); +		 +			// Add the document scroll offsets +			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), +				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop)); +		 +			// IE adds the HTML element's border, by default it is medium which is 2px +			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; } +			// IE 7 standards mode, the border is always 2px +			// This border/offset is typically represented by the clientLeft and clientTop properties +			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS +			// Therefore this method will be off by 2px in IE while in quirksmode +			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop ); +	 +		// Otherwise loop through the offsetParents and parentNodes +		} else { +		 +			// Initial element offsets +			add( elem.offsetLeft, elem.offsetTop ); +			 +			// Get parent offsets +			while ( offsetParent ) { +				// Add offsetParent offsets +				add( offsetParent.offsetLeft, offsetParent.offsetTop ); +			 +				// Mozilla and Safari > 2 does not include the border on offset parents +				// However Mozilla adds the border for table or table cells +				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 ) +					border( offsetParent ); +					 +				// Add the document scroll offsets if position is fixed on any offsetParent +				if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" ) +					fixed = true; +			 +				// Set offsetChild to previous offsetParent unless it is the body element +				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent; +				// Get next offsetParent +				offsetParent = offsetParent.offsetParent; +			} +		 +			// Get parent scroll offsets +			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) { +				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug +				if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) ) +					// Subtract parent scroll offsets +					add( -parent.scrollLeft, -parent.scrollTop ); +			 +				// Mozilla does not add the border for a parent that has overflow != visible +				if ( mozilla && jQuery.css(parent, "overflow") != "visible" ) +					border( parent ); +			 +				// Get next parent +				parent = parent.parentNode; +			} +		 +			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild +			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild +			if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) ||  +				(mozilla && jQuery.css(offsetChild, "position") != "absolute") ) +					add( -doc.body.offsetLeft, -doc.body.offsetTop ); +			 +			// Add the document scroll offsets if position is fixed +			if ( fixed ) +				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), +					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop)); +		} + +		// Return an object with top and left properties +		results = { top: top, left: left }; +	} + +	function border(elem) { +		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) ); +	} + +	function add(l, t) { +		left += parseInt(l) || 0; +		top += parseInt(t) || 0; +	} + +	return results; +}; + +// Create innerHeight, innerWidth, outerHeight and outerWidth methods +jQuery.each(["Height", "Width"], function(i, name){ + +	var tl = name == "Height" ? "Top"    : "Left",  // top or left +		br = name == "Height" ? "Bottom" : "Right"; // bottom or right +	 +	// innerHeight and innerWidth +	jQuery.fn["inner" + name] = function(){ +		return this[ name.toLowerCase() ]() +  +			num(this, "padding" + tl) +  +			num(this, "padding" + br); +	}; +	 +	// outerHeight and outerWidth +	jQuery.fn["outer" + name] = function(margin) { +		return this["inner" + name]() +  +			num(this, "border" + tl + "Width") + +			num(this, "border" + br + "Width") + +			(!!margin ?  +				num(this, "margin" + tl) + num(this, "margin" + br) : 0); +	}; +	 +}); + +function num(elem, prop) { +	elem = elem.jquery ? elem[0] : elem; +	return elem && parseInt( jQuery.curCSS(elem, prop, true) ) || 0; +}})(); diff --git a/vendors/jquery/ui.base.js b/vendors/jquery/ui.base.js new file mode 100755 index 000000000..36a623912 --- /dev/null +++ b/vendors/jquery/ui.base.js @@ -0,0 +1,204 @@ +/* + * jQuery UI @VERSION + * + * Copyright (c) 2008 Paul Bakaus (ui.jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI + * + * $Date: 2008-04-01 09:23:47 -0400 (Tue, 01 Apr 2008) $ + * $Rev: 5174 $ + */ +;(function($) { + +	//If the UI scope is not available, add it +	$.ui = $.ui || {}; +	 +	//Add methods that are vital for all mouse interaction stuff (plugin registering) +	$.extend($.ui, { +		plugin: { +			add: function(module, option, set) { +				var proto = $.ui[module].prototype; +				for(var i in set) { +					proto.plugins[i] = proto.plugins[i] || []; +					proto.plugins[i].push([option, set[i]]); +				} +			}, +			call: function(instance, name, arguments) { +				var set = instance.plugins[name]; if(!set) return; +				for (var i = 0; i < set.length; i++) { +					if (instance.options[set[i][0]]) set[i][1].apply(instance.element, arguments); +				} +			}	 +		}, +		cssCache: {}, +		css: function(name) { +			if ($.ui.cssCache[name]) return $.ui.cssCache[name]; +			var tmp = $('<div class="ui-resizable-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body'); +			 +			//if (!$.browser.safari) +				//tmp.appendTo('body');  +			 +			//Opera and Safari set width and height to 0px instead of auto +			//Safari returns rgba(0,0,0,0) when bgcolor is not set +			$.ui.cssCache[name] = !!( +				(!/auto|default/.test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) ||  +				!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor'))) +			); +			try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){} +			return $.ui.cssCache[name]; +		}, +		disableSelection: function(e) { +			e.unselectable = "on"; +			e.onselectstart = function() {	return false; }; +			if (e.style) e.style.MozUserSelect = "none"; +		}, +		enableSelection: function(e) { +			e.unselectable = "off"; +			e.onselectstart = function() { return true; }; +			if (e.style) e.style.MozUserSelect = ""; +		}, +		hasScroll: function(e, a) { +      		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false; +      		if (e[scroll] > 0) return true; e[scroll] = 1; +      		has = e[scroll] > 0 ? true : false; e[scroll] = 0; +      		return has;  +    	} +	}); + +	/******* fn scope modifications ********/ + +	$.each( ['Left', 'Top'], function(i, name) { +		if(!$.fn['scroll'+name]) $.fn['scroll'+name] = function(v) { +			return v != undefined ? +				this.each(function() { this == window || this == document ? window.scrollTo(name == 'Left' ? v : $(window)['scrollLeft'](), name == 'Top'  ? v : $(window)['scrollTop']()) : this['scroll'+name] = v; }) : +				this[0] == window || this[0] == document ? self[(name == 'Left' ? 'pageXOffset' : 'pageYOffset')] || $.boxModel && document.documentElement['scroll'+name] || document.body['scroll'+name] : this[0][ 'scroll' + name ]; +		}; +	}); + +	var _remove = $.fn.remove; +	$.fn.extend({ +		position: function() { +			var offset       = this.offset(); +			var offsetParent = this.offsetParent(); +			var parentOffset = offsetParent.offset(); + +			return { +				top:  offset.top - num(this[0], 'marginTop')  - parentOffset.top - num(offsetParent, 'borderTopWidth'), +				left: offset.left - num(this[0], 'marginLeft')  - parentOffset.left - num(offsetParent, 'borderLeftWidth') +			}; +		}, +		offsetParent: function() { +			var offsetParent = this[0].offsetParent; +			while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') ) +				offsetParent = offsetParent.offsetParent; +			return $(offsetParent); +		}, +		mouseInteraction: function(o) { +			return this.each(function() { +				new $.ui.mouseInteraction(this, o); +			}); +		}, +		removeMouseInteraction: function(o) { +			return this.each(function() { +				if($.data(this, "ui-mouse")) +					$.data(this, "ui-mouse").destroy(); +			}); +		}, +		remove: function() { +			jQuery("*", this).add(this).trigger("remove"); +			return _remove.apply(this, arguments ); +		} +	}); +	 +	function num(el, prop) { +		return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0; +	}; +	 +	 +	/********** Mouse Interaction Plugin *********/ +	 +	$.ui.mouseInteraction = function(element, options) { +	 +		var self = this; +		this.element = element; + +		$.data(this.element, "ui-mouse", this); +		this.options = $.extend({}, options); +		 +		$(element).bind('mousedown.draggable', function() { return self.click.apply(self, arguments); }); +		if($.browser.msie) $(element).attr('unselectable', 'on'); //Prevent text selection in IE +		 +		// prevent draggable-options-delay bug #2553 +		$(element).mouseup(function() { +			if(self.timer) clearInterval(self.timer); +		}); +	}; +	 +	$.extend($.ui.mouseInteraction.prototype, { +		 +		destroy: function() { $(this.element).unbind('mousedown.draggable'); }, +		trigger: function() { return this.click.apply(this, arguments); }, +		click: function(e) { +			 +			if( +				   e.which != 1 //only left click starts dragging +				|| $.inArray(e.target.nodeName.toLowerCase(), this.options.dragPrevention || []) != -1 // Prevent execution on defined elements +				|| (this.options.condition && !this.options.condition.apply(this.options.executor || this, [e, this.element])) //Prevent execution on condition +			) return true; +				 +			var self = this; +			var initialize = function() { +				self._MP = { left: e.pageX, top: e.pageY }; // Store the click mouse position +				$(document).bind('mouseup.draggable', function() { return self.stop.apply(self, arguments); }); +				$(document).bind('mousemove.draggable', function() { return self.drag.apply(self, arguments); }); +				 +				if(!self.initalized && Math.abs(self._MP.left-e.pageX) >= self.options.distance || Math.abs(self._MP.top-e.pageY) >= self.options.distance) {				 +					if(self.options.start) self.options.start.call(self.options.executor || self, e, self.element); +					if(self.options.drag) self.options.drag.call(self.options.executor || self, e, this.element); //This is actually not correct, but expected +					self.initialized = true; +				} +			}; + +			if(this.options.delay) { +				if(this.timer) clearInterval(this.timer); +				this.timer = setTimeout(initialize, this.options.delay); +			} else { +				initialize(); +			} +				 +			return false; +			 +		}, +		stop: function(e) {			 +			 +			var o = this.options; +			if(!this.initialized) return $(document).unbind('mouseup.draggable').unbind('mousemove.draggable'); + +			if(this.options.stop) this.options.stop.call(this.options.executor || this, e, this.element); +			$(document).unbind('mouseup.draggable').unbind('mousemove.draggable'); +			this.initialized = false; +			return false; +			 +		}, +		drag: function(e) { + +			var o = this.options; +			if ($.browser.msie && !e.button) return this.stop.apply(this, [e]); // IE mouseup check +			 +			if(!this.initialized && (Math.abs(this._MP.left-e.pageX) >= o.distance || Math.abs(this._MP.top-e.pageY) >= o.distance)) {				 +				if(this.options.start) this.options.start.call(this.options.executor || this, e, this.element); +				this.initialized = true; +			} else { +				if(!this.initialized) return false; +			} + +			if(o.drag) o.drag.call(this.options.executor || this, e, this.element); +			return false; +			 +		} +	}); +	 +})(jQuery); + 
\ No newline at end of file diff --git a/vendors/jquery/ui.draggable.js b/vendors/jquery/ui.draggable.js new file mode 100755 index 000000000..d26658176 --- /dev/null +++ b/vendors/jquery/ui.draggable.js @@ -0,0 +1,572 @@ +/* + * jQuery UI Draggable + * + * Copyright (c) 2008 Paul Bakaus + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + *  + * http://docs.jquery.com/UI/Draggables + * + * Depends: + *   ui.base.js + * + * Revision: $Id: ui.draggable.js 5194 2008-04-04 12:30:10Z paul.bakaus $ + */ +;(function($) { + +	$.fn.extend({ +		draggable: function(options) { +			var args = Array.prototype.slice.call(arguments, 1); +			 +			return this.each(function() { +				if (typeof options == "string") { +					var drag = $.data(this, "draggable"); +					if(drag) drag[options].apply(drag, args); + +				} else if(!$.data(this, "draggable")) +					new $.ui.draggable(this, options); +			}); +		} +	}); +	 +	$.ui.draggable = function(element, options) { +		//Initialize needed constants +		var self = this; +		 +		this.element = $(element); +		 +		$.data(element, "draggable", this); +		this.element.addClass("ui-draggable"); +		 +		//Prepare the passed options +		this.options = $.extend({}, options); +		var o = this.options; +		$.extend(o, { +			helper: o.ghosting == true ? 'clone' : (o.helper || 'original'), +			handle : o.handle ? ($(o.handle, element)[0] ? $(o.handle, element) : this.element) : this.element, +			appendTo: o.appendTo || 'parent'		 +		}); +		 +		$(element).bind("setData.draggable", function(event, key, value){ +			self.options[key] = value; +		}).bind("getData.draggable", function(event, key){ +			return self.options[key]; +		}); +		 +		//Initialize mouse events for interaction +		$(o.handle).mouseInteraction({ +			executor: this, +			delay: o.delay, +			distance: o.distance || 1, +			dragPrevention: o.cancel || o.cancel === '' ? o.cancel.toLowerCase().split(',') : ['input','textarea','button','select','option'], +			start: this.start, +			stop: this.stop, +			drag: this.drag, +			condition: function(e) { return !(e.target.className.indexOf("ui-resizable-handle") != -1 || this.options.disabled); } +		}); +		 +		//Position the node +		if(o.helper == 'original' && (this.element.css('position') == 'static' || this.element.css('position') == '')) +			this.element.css('position', 'relative'); +			 +		//Prepare cursorAt +		if(o.cursorAt && o.cursorAt.constructor == Array) +			o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] }; +		 +	}; +	 +	$.extend($.ui.draggable.prototype, { +		plugins: {}, +		ui: function(e) { +			return { +				helper: this.helper, +				position: this.position, +				absolutePosition: this.positionAbs, +				instance: this, +				options: this.options, +				element: this.element				 +			}; +		}, +		propagate: function(n,e) { +			$.ui.plugin.call(this, n, [e, this.ui()]); +			return this.element.triggerHandler(n == "drag" ? n : "drag"+n, [e, this.ui()], this.options[n]); +		}, +		destroy: function() { +			if(!$.data(this.element[0], 'draggable')) return; +			this.options.handle.removeMouseInteraction(); +			this.element +				.removeClass("ui-draggable ui-draggable-disabled") +				.removeData("draggable") +				.unbind(".draggable"); +		}, +		enable: function() { +			this.element.removeClass("ui-draggable-disabled"); +			this.options.disabled = false; +		}, +		disable: function() { +			this.element.addClass("ui-draggable-disabled"); +			this.options.disabled = true; +		}, +		setContrains: function(minLeft,maxLeft,minTop,maxTop) { +			this.minLeft = minLeft; this.maxLeft = maxLeft; +			this.minTop = minTop; this.maxTop = maxTop; +			this.constrainsSet = true; +		}, +		checkConstrains: function() { +			if(!this.constrainsSet) return; +			if(this.position.left < this.minLeft) this.position.left = this.minLeft; +			if(this.position.left > this.maxLeft - this.helperProportions.width) this.position.left = this.maxLeft - this.helperProportions.width; +			if(this.position.top < this.minTop) this.position.top = this.minTop; +			if(this.position.top > this.maxTop - this.helperProportions.height) this.position.top = this.maxTop - this.helperProportions.height; +		}, +		recallOffset: function(e) { + +			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top }; +			var r = this.helper.css('position') == 'relative'; + +			//Generate the original position +			this.originalPosition = { +				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)), +				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)) +			}; +			 +			//Generate a flexible offset that will later be subtracted from e.pageX/Y +			this.offset = {left: this._pageX - this.originalPosition.left, top: this._pageY - this.originalPosition.top }; +			 +		}, +		start: function(e) { +			var o = this.options; +			if($.ui.ddmanager) $.ui.ddmanager.current = this; +			 +			//Create and append the visible helper +			this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e])) : (o.helper == 'clone' ? this.element.clone().appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)) : this.element); +			if(this.helper[0] != this.element[0]) this.helper.css('position', 'absolute'); +			if(!this.helper.parents('body').length) this.helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); +			 +			 +			//Find out the next positioned parent +			this.offsetParent = (function(cp) { +				while(cp) { +					if(cp.style && (/(absolute|relative|fixed)/).test($.css(cp,'position'))) return $(cp); +					cp = cp.parentNode ? cp.parentNode : null; +				}; return $("body");		 +			})(this.helper[0].parentNode); +			 +			//Prepare variables for position generation +			this.elementOffset = this.element.offset(); +			this.offsetParentOffset = this.offsetParent.offset(); +			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top }; +			this._pageX = e.pageX; this._pageY = e.pageY; +			this.clickOffset = { left: e.pageX - this.elementOffset.left, top: e.pageY - this.elementOffset.top }; +			var r = this.helper.css('position') == 'relative'; + +			//Generate the original position +			this.originalPosition = { +				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)), +				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)) +			}; +			 +			//If we have a fixed element, we must subtract the scroll offset again +			if(this.element.css('position') == 'fixed') { +				this.originalPosition.top -= this.offsetParent[0] == document.body ? $(document).scrollTop() : this.offsetParent[0].scrollTop; +				this.originalPosition.left -= this.offsetParent[0] == document.body ? $(document).scrollLeft() : this.offsetParent[0].scrollLeft; +			} +			 +			//Generate a flexible offset that will later be subtracted from e.pageX/Y +			this.offset = {left: e.pageX - this.originalPosition.left, top: e.pageY - this.originalPosition.top }; +			 +			//Substract margins +			if(this.element[0] != this.helper[0]) { +				this.offset.left += parseInt(this.element.css('marginLeft'),10) || 0; +				this.offset.top += parseInt(this.element.css('marginTop'),10) || 0; +			} +			 +			//Call plugins and callbacks +			this.propagate("start", e); + +			this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() }; +			if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e); +			 +			//If we have something in cursorAt, we'll use it +			if(o.cursorAt) { +				if(o.cursorAt.top != undefined || o.cursorAt.bottom != undefined) { +					this.offset.top -= this.clickOffset.top - (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom)); +					this.clickOffset.top = (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom)); +				} +				if(o.cursorAt.left != undefined || o.cursorAt.right != undefined) { +					this.offset.left -= this.clickOffset.left - (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right)); +					this.clickOffset.left = (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right)); +				} +			} + +			return false; + +		}, +		clear: function() { +			if($.ui.ddmanager) $.ui.ddmanager.current = null; +			this.helper = null; +		}, +		stop: function(e) { + +			//If we are using droppables, inform the manager about the drop +			if ($.ui.ddmanager && !this.options.dropBehaviour) +				$.ui.ddmanager.drop(this, e); +				 +			//Call plugins and trigger callbacks +			this.propagate("stop", e); +			 +			if(this.cancelHelperRemoval) return false;			 +			if(this.options.helper != 'original') this.helper.remove(); +			this.clear(); + +			return false; +		}, +		drag: function(e) { + +			//Compute the helpers position +			this.position = { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left }; +			this.positionAbs = { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top }; + +			//Call plugins and callbacks +			this.checkConstrains();			 +			this.position = this.propagate("drag", e) || this.position; +			this.checkConstrains(); +			 +			$(this.helper).css({ left: this.position.left+'px', top: this.position.top+'px' }); // Stick the helper to the cursor +			if($.ui.ddmanager) $.ui.ddmanager.drag(this, e); +			return false; +			 +		} +	}); +	 +/* + * Draggable Extensions + */ +	  +	$.ui.plugin.add("draggable", "cursor", { +		start: function(e, ui) { +			var t = $('body'); +			if (t.css("cursor")) ui.options._cursor = t.css("cursor"); +			t.css("cursor", ui.options.cursor); +		}, +		stop: function(e, ui) { +			if (ui.options._cursor) $('body').css("cursor", ui.options._cursor); +		} +	}); + +	$.ui.plugin.add("draggable", "zIndex", { +		start: function(e, ui) { +			var t = $(ui.helper); +			if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex"); +			t.css('zIndex', ui.options.zIndex); +		}, +		stop: function(e, ui) { +			if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex); +		} +	}); + +	$.ui.plugin.add("draggable", "opacity", { +		start: function(e, ui) { +			var t = $(ui.helper); +			if(t.css("opacity")) ui.options._opacity = t.css("opacity"); +			t.css('opacity', ui.options.opacity); +		}, +		stop: function(e, ui) { +			if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity); +		} +	}); + + +	$.ui.plugin.add("draggable", "revert", { +		stop: function(e, ui) { +			var self = ui.instance, helper = $(self.helper); +			self.cancelHelperRemoval = true; +			 +			$(ui.helper).animate({ left: self.originalPosition.left, top: self.originalPosition.top }, parseInt(ui.options.revert, 10) || 500, function() { +				if(ui.options.helper != 'original') helper.remove(); +				if (!helper) self.clear(); +			}); +		} +	}); + +	$.ui.plugin.add("draggable", "iframeFix", { +		start: function(e, ui) { + +			var o = ui.options; +			if(ui.instance.slowMode) return; // Make clones on top of iframes (only if we are not in slowMode) +			 +			if(o.iframeFix.constructor == Array) { +				for(var i=0;i<o.iframeFix.length;i++) { +					var co = $(o.iframeFix[i]).offset({ border: false }); +					$('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width", $(o.iframeFix[i])[0].offsetWidth+"px").css("height", $(o.iframeFix[i])[0].offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body"); +				}		 +			} else { +				$("iframe").each(function() {					 +					var co = $(this).offset({ border: false }); +					$('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width", this.offsetWidth+"px").css("height", this.offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body"); +				});							 +			} + +		}, +		stop: function(e, ui) { +			if(ui.options.iframeFix) $("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers	 +		} +	}); +	 +	$.ui.plugin.add("draggable", "containment", { +		start: function(e, ui) { + +			var o = ui.options; +			var self = ui.instance; +			if((o.containment.left != undefined || o.containment.constructor == Array) && !o._containment) return; +			if(!o._containment) o._containment = o.containment; + +			if(o._containment == 'parent') o._containment = this[0].parentNode; +			if(o._containment == 'document') { +				o.containment = [ +					0, +					0, +					$(document).width(), +					($(document).height() || document.body.parentNode.scrollHeight) +				]; +			} else { //I'm a node, so compute top/left/right/bottom + +				var ce = $(o._containment)[0]; +				var co = $(o._containment).offset(); + +				o.containment = [ +					co.left, +					co.top, +					co.left+(ce.offsetWidth || ce.scrollWidth), +					co.top+(ce.offsetHeight || ce.scrollHeight) +				]; +			} +			 +			var c = o.containment; +			ui.instance.setContrains( +				c[0] - (self.offset.left - self.clickOffset.left), //min left +				c[2] - (self.offset.left - self.clickOffset.left), //max left +				c[1] - (self.offset.top - self.clickOffset.top), //min top +				c[3] - (self.offset.top - self.clickOffset.top) //max top +			); + +		} +	}); + +	$.ui.plugin.add("draggable", "grid", { +		drag: function(e, ui) { +			var o = ui.options; +			var newLeft = ui.instance.originalPosition.left + Math.round((e.pageX - ui.instance._pageX) / o.grid[0]) * o.grid[0]; +			var newTop = ui.instance.originalPosition.top + Math.round((e.pageY - ui.instance._pageY) / o.grid[1]) * o.grid[1]; +			 +			ui.instance.position.left = newLeft; +			ui.instance.position.top = newTop; + +		} +	}); + +	$.ui.plugin.add("draggable", "axis", { +		drag: function(e, ui) { +			var o = ui.options; +			if(o.constraint) o.axis = o.constraint; //Legacy check +			switch (o.axis) { +				case 'x' : ui.instance.position.top = ui.instance.originalPosition.top; break; +				case 'y' : ui.instance.position.left = ui.instance.originalPosition.left; break; +			} +		} +	}); + +	$.ui.plugin.add("draggable", "scroll", { +		start: function(e, ui) { +			var o = ui.options; +			o.scrollSensitivity	= o.scrollSensitivity || 20; +			o.scrollSpeed		= o.scrollSpeed || 20; + +			ui.instance.overflowY = function(el) { +				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode); +				return $(document); +			}(this); +			ui.instance.overflowX = function(el) { +				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode); +				return $(document); +			}(this); +		}, +		drag: function(e, ui) { +			 +			var o = ui.options; +			var i = ui.instance; + +			if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') { +				if(i.overflowY[0].offsetHeight - (ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity) +					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed; +				if((ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity) +					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;				 +			} else { +				//$(document.body).append('<p>'+(e.pageY - $(document).scrollTop())+'</p>'); +				if(e.pageY - $(document).scrollTop() < o.scrollSensitivity) +					$(document).scrollTop($(document).scrollTop() - o.scrollSpeed); +				if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity) +					$(document).scrollTop($(document).scrollTop() + o.scrollSpeed); +			} +			 +			if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') { +				if(i.overflowX[0].offsetWidth - (ui.position.left - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity) +					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed; +				if((ui.position.top - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity) +					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;				 +			} else { +				if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity) +					$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); +				if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity) +					$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); +			} +			 +			ui.instance.recallOffset(e); + +		} +	}); +	 +	$.ui.plugin.add("draggable", "snap", { +		start: function(e, ui) { +			 +			ui.instance.snapElements = []; +			$(ui.options.snap === true ? '.ui-draggable' : ui.options.snap).each(function() { +				var $t = $(this); var $o = $t.offset(); +				if(this != ui.instance.element[0]) ui.instance.snapElements.push({ +					item: this, +					width: $t.outerWidth(), +					height: $t.outerHeight(), +					top: $o.top, +					left: $o.left +				}); +			}); +			 +		}, +		drag: function(e, ui) { + +			var d = ui.options.snapTolerance || 20; +			var x1 = ui.absolutePosition.left, x2 = x1 + ui.instance.helperProportions.width, +			    y1 = ui.absolutePosition.top, y2 = y1 + ui.instance.helperProportions.height; + +			for (var i = ui.instance.snapElements.length - 1; i >= 0; i--){ + +				var l = ui.instance.snapElements[i].left, r = l + ui.instance.snapElements[i].width,  +				    t = ui.instance.snapElements[i].top,  b = t + ui.instance.snapElements[i].height; + +				//Yes, I know, this is insane ;) +				if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) continue; + +				if(ui.options.snapMode != 'inner') { +					var ts = Math.abs(t - y2) <= 20; +					var bs = Math.abs(b - y1) <= 20; +					var ls = Math.abs(l - x2) <= 20; +					var rs = Math.abs(r - x1) <= 20; +					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height; +					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top; +					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width; +					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left; +				} +				 +				if(ui.options.snapMode != 'outer') { +					var ts = Math.abs(t - y1) <= 20; +					var bs = Math.abs(b - y2) <= 20; +					var ls = Math.abs(l - x1) <= 20; +					var rs = Math.abs(r - x2) <= 20; +					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top; +					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height; +					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left; +					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width; +				} + +			}; +		} +	}); +	 +	$.ui.plugin.add("draggable", "connectToSortable", { +		start: function(e,ui) { +			ui.instance.sortable = $.data($(ui.options.connectToSortable)[0], 'sortable'); +			ui.instance.sortableOffset = ui.instance.sortable.element.offset(); +			ui.instance.sortableOuterWidth = ui.instance.sortable.element.outerWidth(); +			ui.instance.sortableOuterHeight = ui.instance.sortable.element.outerHeight(); +			if(ui.instance.sortable.options.revert) ui.instance.sortable.shouldRevert = true; +		}, +		stop: function(e,ui) { +			//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper +			var inst = ui.instance.sortable; +			if(inst.isOver) { +				inst.isOver = 0; +				ui.instance.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance +				inst.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) +				if(inst.shouldRevert) inst.options.revert = true; //revert here +				inst.stop(e); +				inst.options.helper = "original"; +			} +		}, +		drag: function(e,ui) { +			//This is handy: We reuse the intersectsWith method for checking if the current draggable helper +			//intersects with the sortable container +			var inst = ui.instance.sortable; +			ui.instance.position.absolute = ui.absolutePosition; //Sorry, this is an ugly API fix +			 +			if(inst.intersectsWith.call(ui.instance, { +				left: ui.instance.sortableOffset.left, top: ui.instance.sortableOffset.top, +				width: ui.instance.sortableOuterWidth, height: ui.instance.sortableOuterHeight +			})) { +				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once +				if(!inst.isOver) { +					inst.isOver = 1; +					 +					//Cache the width/height of the new helper +					var height = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerHeight() : $(inst.options.items, inst.element).innerHeight(); +					var width = inst.options.placeholderElement ? $(inst.options.placeholderElement, $(inst.options.items, inst.element)).innerWidth() : $(inst.options.items, inst.element).innerWidth(); + +					//Now we fake the start of dragging for the sortable instance, +					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem +					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) +					inst.currentItem = $(this).clone().appendTo(inst.element); +					inst.options.helper = function() { return ui.helper[0]; }; +					inst.start(e); +					 +					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes +					inst.clickOffset.top = ui.instance.clickOffset.top; +					inst.clickOffset.left = ui.instance.clickOffset.left; +					inst.offset.left -= ui.absolutePosition.left - inst.position.absolute.left; +					inst.offset.top -= ui.absolutePosition.top - inst.position.absolute.top; +					 +					//Do a nifty little helper animation: Animate it to the portlet's size (just takes the first 'li' element in the sortable now) +					inst.helperProportions = { width:  width, height: height}; //We have to reset the helper proportions, because we are doing our animation there +					ui.helper.animate({ height: height, width: width}, 500); +					ui.instance.propagate("toSortable", e); +				 +				} + +				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable +				if(inst.currentItem) inst.drag(e); +				 +			} else { +				 +				//If it doesn't intersect with the sortable, and it intersected before, +				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval +				if(inst.isOver) { +					inst.isOver = 0; +					inst.cancelHelperRemoval = true; +					inst.options.revert = false; //No revert here +					inst.stop(e); +					inst.options.helper = "original"; +					 +					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size +					inst.currentItem.remove(); +					inst.placeholder.remove(); +					 +					ui.helper.animate({ height: this.innerHeight(), width: this.innerWidth() }, 500); +					ui.instance.propagate("fromSortable", e); +				} +				 +			}; +		} +	}) + +	//TODO: wrapHelper + +})(jQuery); + diff --git a/vendors/jquery/ui.droppable.js b/vendors/jquery/ui.droppable.js new file mode 100755 index 000000000..9cc8388f1 --- /dev/null +++ b/vendors/jquery/ui.droppable.js @@ -0,0 +1,312 @@ +/* + * jQuery UI Droppable + * + * Copyright (c) 2008 Paul Bakaus + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + *  + * http://docs.jquery.com/UI/Droppables + * + * Depends: + *   ui.base.js + *   ui.draggable.js + * + * Revision: $Id: ui.droppable.js 5198 2008-04-04 13:06:40Z paul.bakaus $ + */ +;(function($) { +	 +	$.fn.extend({ +		droppable: function(options) { +			var args = Array.prototype.slice.call(arguments, 1); +			 +			return this.each(function() { +				if (typeof options == "string") { +					var drop = $.data(this, "droppable"); +					if(drop) drop[options].apply(drop, args); +					 +				} else if(!$.data(this, "droppable")) +					new $.ui.droppable(this, options); +			}); +		} +	}); +	 +	$.ui.droppable = function(element, options) { +		 +		//Initialize needed constants +		var instance = this; +		this.element = $(element); +		$.data(element, "droppable", this); +		this.element.addClass("ui-droppable"); +		 +		//Prepare the passed options +		var o = this.options = options = $.extend({}, $.ui.droppable.defaults, options); +		var accept = o.accept; +		o = $.extend(o, { +			accept: o.accept && o.accept.constructor == Function ? o.accept : function(d) { +				return $(d).is(accept); +			} +		}); +		 +		$(element).bind("setData.droppable", function(event, key, value){ +			o[key] = value; +		}).bind("getData.droppable", function(event, key){ +			return o[key]; +		}).bind('remove', function() { +			instance.destroy(); +		}); +		 +		//Store the droppable's proportions +		this.proportions = { width: this.element.outerWidth(), height: this.element.outerHeight() }; +		 +		// Add the reference and positions to the manager +		$.ui.ddmanager.droppables.push({ item: this, over: 0, out: 1 }); +		 +	}; +	 +	$.extend($.ui.droppable, { +		defaults: { +			disabled: false, +			tolerance: 'intersect' +		} +	}); +	 +	$.extend($.ui.droppable.prototype, { +		plugins: {}, +		ui: function(c) { +			return { +				instance: this, +				draggable: (c.currentItem || c.element), +				helper: c.helper, +				position: c.position, +				absolutePosition: c.positionAbs, +				options: this.options, +				element: this.element +			}; +		}, +		destroy: function() { +			var drop = $.ui.ddmanager.droppables; +			for ( var i = 0; i < drop.length; i++ ) +				if ( drop[i].item == this ) +					drop.splice(i, 1); +			 +			this.element +				.removeClass("ui-droppable ui-droppable-disabled") +				.removeData("droppable") +				.unbind(".droppable"); +		}, +		enable: function() { +			this.element.removeClass("ui-droppable-disabled"); +			this.options.disabled = false; +		}, +		disable: function() { +			this.element.addClass("ui-droppable-disabled"); +			this.options.disabled = true; +		}, +		over: function(e) { +			 +			var draggable = $.ui.ddmanager.current; +			if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element +			 +			if (this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) { +				$.ui.plugin.call(this, 'over', [e, this.ui(draggable)]); +				this.element.triggerHandler("dropover", [e, this.ui(draggable)], this.options.over); +			} +			 +		}, +		out: function(e) { +			 +			var draggable = $.ui.ddmanager.current; +			if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element +			 +			if (this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) { +				$.ui.plugin.call(this, 'out', [e, this.ui(draggable)]); +				this.element.triggerHandler("dropout", [e, this.ui(draggable)], this.options.out); +			} +			 +		}, +		drop: function(e,custom) { +			 +			var draggable = custom || $.ui.ddmanager.current; +			if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element +			 +			var childrenIntersection = false; +			this.element.find(".ui-droppable").each(function() { +				var inst = $.data(this, 'droppable'); +				if(inst.options.greedy && $.ui.intersect(draggable, { item: inst, offset: inst.element.offset() }, inst.options.tolerance)) { +					childrenIntersection = true; return false; +				} +			}); +			if(childrenIntersection) return; +			 +			if(this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) { +				$.ui.plugin.call(this, 'drop', [e, this.ui(draggable)]); +				this.element.triggerHandler("drop", [e, this.ui(draggable)], this.options.drop); +			} +			 +		}, +		activate: function(e) { +			 +			var draggable = $.ui.ddmanager.current; +			$.ui.plugin.call(this, 'activate', [e, this.ui(draggable)]); +			if(draggable) this.element.triggerHandler("dropactivate", [e, this.ui(draggable)], this.options.activate); +			 +		}, +		deactivate: function(e) { +			 +			var draggable = $.ui.ddmanager.current; +			$.ui.plugin.call(this, 'deactivate', [e, this.ui(draggable)]); +			if(draggable) this.element.triggerHandler("dropdeactivate", [e, this.ui(draggable)], this.options.deactivate); +			 +		} +	}); +	 +	$.ui.intersect = function(draggable, droppable, toleranceMode) { +		 +		if (!droppable.offset) return false; +		 +		var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, +		    y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; +		var l = droppable.offset.left, r = l + droppable.item.proportions.width, +		    t = droppable.offset.top,  b = t + droppable.item.proportions.height; +		 +		switch (toleranceMode) { +			case 'fit': +				 +				if(!((y2-(draggable.helperProportions.height/2) > t && y1 < t) || (y1 < b && y2 > b) || (x2 > l && x1 < l) || (x1 < r && x2 > r))) return false; +				 +				if(y2-(draggable.helperProportions.height/2) > t && y1 < t) return 1; //Crosses top edge +				if(y1 < b && y2 > b) return 2; //Crosses bottom edge +				if(x2 > l && x1 < l) return 1; //Crosses left edge +				if(x1 < r && x2 > r) return 2; //Crosses right edge +				 +				//return (   l < x1 && x2 < r +				//	&& t < y1 && y2 < b); +				break; +			case 'intersect': +				return (   l < x1 + (draggable.helperProportions.width  / 2)    // Right Half +					&&     x2 - (draggable.helperProportions.width  / 2) < r    // Left Half +					&& t < y1 + (draggable.helperProportions.height / 2)        // Bottom Half +					&&     y2 - (draggable.helperProportions.height / 2) < b ); // Top Half +				break; +			case 'pointer': +				return (   l < ((draggable.positionAbs || draggable.position.absolute).left + draggable.clickOffset.left) && ((draggable.positionAbs || draggable.position.absolute).left + draggable.clickOffset.left) < r +					&& t < ((draggable.positionAbs || draggable.position.absolute).top + draggable.clickOffset.top) && ((draggable.positionAbs || draggable.position.absolute).top + draggable.clickOffset.top) < b); +				break; +			case 'touch': +				return ( (y1 >= t && y1 <= b) ||	// Top edge touching +						 (y2 >= t && y2 <= b) ||	// Bottom edge touching +						 (y1 < t && y2 > b)		// Surrounded vertically +						 ) && ( +						 (x1 >= l && x1 <= r) ||	// Left edge touching +						 (x2 >= l && x2 <= r) ||	// Right edge touching +						 (x1 < l && x2 > r)		// Surrounded horizontally +						); +				break; +			default: +				return false; +				break; +			} +		 +	}; +	 +	/* +		This manager tracks offsets of draggables and droppables +	*/ +	$.ui.ddmanager = { +		current: null, +		droppables: [], +		prepareOffsets: function(t, e) { +			 +			var m = $.ui.ddmanager.droppables; +			var type = e ? e.type : null; // workaround for #2317 +			for (var i = 0; i < m.length; i++) { +				 +				if(m[i].item.options.disabled || (t && !m[i].item.options.accept.call(m[i].item.element,(t.currentItem || t.element)))) continue; +				m[i].offset = $(m[i].item.element).offset(); +				m[i].item.proportions = { width: m[i].item.element.outerWidth(), height: m[i].item.element.outerHeight() }; +				 +				if(type == "dragstart") m[i].item.activate.call(m[i].item, e); //Activate the droppable if used directly from draggables +			} +			 +		}, +		drop: function(draggable, e) { +			 +			$.each($.ui.ddmanager.droppables, function() { +				 +				if (!this.item.options.disabled && $.ui.intersect(draggable, this, this.item.options.tolerance)) +					this.item.drop.call(this.item, e); +				 +				if (!this.item.options.disabled && this.item.options.accept.call(this.item.element,(draggable.currentItem || draggable.element))) { +					this.out = 1; this.over = 0; +					this.item.deactivate.call(this.item, e); +				} +				 +			}); +			 +		}, +		drag: function(draggable, e) { +			 +			//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. +			if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, e); +			 +			//Run through all droppables and check their positions based on specific tolerance options +			$.each($.ui.ddmanager.droppables, function() { +				 +				if(this.item.disabled || this.greedyChild) return; +				var intersects = $.ui.intersect(draggable, this, this.item.options.tolerance); +				 +				var c = !intersects && this.over == 1 ? 'out' : (intersects && this.over == 0 ? 'over' : null); +				if(!c) return; +				 +				var instance = $.data(this.item.element[0], 'droppable'); +				if (instance.options.greedy) { +					this.item.element.parents('.ui-droppable:eq(0)').each(function() { +						var parent = this; +						$.each($.ui.ddmanager.droppables, function() { +							if (this.item.element[0] != parent) return; +							this[c] = 0; +							this[c == 'out' ? 'over' : 'out'] = 1; +							this.greedyChild = (c == 'over' ? 1 : 0); +							this.item[c == 'out' ? 'over' : 'out'].call(this.item, e); +							return false; +						}); +					}); +				} +				 +				this[c] = 1; this[c == 'out' ? 'over' : 'out'] = 0; +				this.item[c].call(this.item, e); +				 +			}); +			 +		} +	}; +	 +/* + * Droppable Extensions + */ +	 +	$.ui.plugin.add("droppable", "activeClass", { +		activate: function(e, ui) { +			$(this).addClass(ui.options.activeClass); +		}, +		deactivate: function(e, ui) { +			$(this).removeClass(ui.options.activeClass); +		}, +		drop: function(e, ui) { +			$(this).removeClass(ui.options.activeClass); +		} +	}); +	 +	$.ui.plugin.add("droppable", "hoverClass", { +		over: function(e, ui) { +			$(this).addClass(ui.options.hoverClass); +		}, +		out: function(e, ui) { +			$(this).removeClass(ui.options.hoverClass); +		}, +		drop: function(e, ui) { +			$(this).removeClass(ui.options.hoverClass); +		} +	}); +	 +})(jQuery); diff --git a/vendors/jquery/ui.sortable.js b/vendors/jquery/ui.sortable.js new file mode 100755 index 000000000..b0f7929f3 --- /dev/null +++ b/vendors/jquery/ui.sortable.js @@ -0,0 +1,676 @@ +/* + * jQuery UI Sortable + * + * Copyright (c) 2008 Paul Bakaus + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + *  + * http://docs.jquery.com/UI/Sortables + * + * Depends: + *   ui.base.js + * + * Revision: $Id: ui.sortable.js 5199 2008-04-04 14:04:32Z paul.bakaus $ + */ +;(function($) { + +	if (window.Node && Node.prototype && !Node.prototype.contains) { +		Node.prototype.contains = function (arg) { +			return !!(this.compareDocumentPosition(arg) & 16); +		}; +	} + +	$.fn.extend({ +		sortable: function(options) { +			 +			var args = Array.prototype.slice.call(arguments, 1); +			 +			if (options == "serialize" || options == "toArray") +				return $.data(this[0], "sortable")[options](arguments[1]); +			 +			return this.each(function() { +				if (typeof options == "string") { +					var sort = $.data(this, "sortable"); +					if (sort) sort[options].apply(sort, args); + +				} else if(!$.data(this, "sortable")) +					new $.ui.sortable(this, options); +			}); +		} +	}); +	 +	$.ui.sortable = function(element, options) { +		//Initialize needed constants +		var self = this; +		 +		this.element = $(element); +		this.containerCache = {}; +		 +		$.data(element, "sortable", this); +		this.element.addClass("ui-sortable"); + +		//Prepare the passed options +		this.options = $.extend({}, options); +		var o = this.options; +		$.extend(o, { +			items: this.options.items || '> *', +			zIndex: this.options.zIndex || 1000, +			startCondition: function() { +				return !self.options.disabled; +			} +		}); +		 +		$(element).bind("setData.sortable", function(event, key, value){ +			self.options[key] = value; +		}).bind("getData.sortable", function(event, key){ +			return self.options[key]; +		}); +		 +		//Get the items +		this.refresh(); + +		//Let's determine if the items are floating +		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false; +		 +		//Let's determine the parent's offset +		if(!(/(relative|absolute|fixed)/).test(this.element.css('position'))) this.element.css('position', 'relative'); +		this.offset = this.element.offset(); + +		//Initialize mouse events for interaction +		this.element.mouseInteraction({ +			executor: this, +			delay: o.delay, +			distance: o.distance || 0, +			dragPrevention: o.prevention ? o.prevention.toLowerCase().split(',') : ['input','textarea','button','select','option'], +			start: this.start, +			stop: this.stop, +			drag: this.drag, +			condition: function(e) { + +				if(this.options.disabled || this.options.type == 'static') return false; + +				//Find out if the clicked node (or one of its parents) is a actual item in this.items +				var currentItem = null, nodes = $(e.target).parents().each(function() {	 +					if($.data(this, 'sortable-item')) { +						currentItem = $(this); +						return false; +					} +				}); +				if($.data(e.target, 'sortable-item')) currentItem = $(e.target); +				 +				if(!currentItem) return false;	 +				if(this.options.handle) { +					var validHandle = false; +					$(this.options.handle, currentItem).each(function() { if(this == e.target) validHandle = true; }); +					if(!validHandle) return false; +				} +					 +				this.currentItem = currentItem; +				return true; + +			} +		}); +		 +		//Prepare cursorAt +		if(o.cursorAt && o.cursorAt.constructor == Array) +			o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] }; +	}; +	 +	$.extend($.ui.sortable.prototype, { +		plugins: {}, +		ui: function(inst) { +			return { +				helper: (inst || this)["helper"], +				placeholder: (inst || this)["placeholder"] || $([]), +				position: (inst || this)["position"].current, +				absolutePosition: (inst || this)["position"].absolute, +				instance: this, +				options: this.options, +				element: this.element, +				item: (inst || this)["currentItem"], +				sender: inst ? inst.element : null +			};		 +		}, +		propagate: function(n,e,inst) { +			$.ui.plugin.call(this, n, [e, this.ui(inst)]); +			this.element.triggerHandler(n == "sort" ? n : "sort"+n, [e, this.ui(inst)], this.options[n]); +		}, +		serialize: function(o) { +			 +			var items = $(this.options.items, this.element).not('.ui-sortable-helper'); //Only the items of the sortable itself +			var str = []; o = o || {}; +			 +			items.each(function() { +				var res = ($(this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); +				if(res) str.push((o.key || res[1])+'[]='+(o.key ? res[1] : res[2])); +			}); +			 +			return str.join('&'); +			 +		}, +		toArray: function(attr) { +			var items = $(this.options.items, this.element).not('.ui-sortable-helper'); //Only the items of the sortable itself +			var ret = []; + +			items.each(function() { ret.push($(this).attr(attr || 'id')); }); +			return ret; +		}, +		enable: function() { +			this.element.removeClass("ui-sortable-disabled"); +			this.options.disabled = false; +		}, +		disable: function() { +			this.element.addClass("ui-sortable-disabled"); +			this.options.disabled = true; +		}, +		/* Be careful with the following core functions */ +		intersectsWith: function(item) { +			 +			var x1 = this.position.absolute.left, x2 = x1 + this.helperProportions.width, +			    y1 = this.position.absolute.top, y2 = y1 + this.helperProportions.height; +			var l = item.left, r = l + item.width,  +			    t = item.top,  b = t + item.height; +			 +			return (   l < x1 + (this.helperProportions.width  / 2)    // Right Half +				&&     x2 - (this.helperProportions.width  / 2) < r    // Left Half +				&& t < y1 + (this.helperProportions.height / 2)        // Bottom Half +				&&     y2 - (this.helperProportions.height / 2) < b ); // Top Half +			 +		}, +		intersectsWithEdge: function(item) {	 +			var x1 = this.position.absolute.left, x2 = x1 + this.helperProportions.width, +			    y1 = this.position.absolute.top, y2 = y1 + this.helperProportions.height; +			var l = item.left, r = l + item.width,  +			    t = item.top,  b = t + item.height; + + +			if (!(   l < x1 + (this.helperProportions.width  / 2)    // Right Half +				&&     x2 - (this.helperProportions.width  / 2) < r    // Left Half +				&& t < y1 + (this.helperProportions.height / 2)        // Bottom Half +				&&     y2 - (this.helperProportions.height / 2) < b )) return false; // Top Half +			 +			if(this.floating) { +				if(x2 > l && x1 < l) return 2; //Crosses left edge +				if(x1 < r && x2 > r) return 1; //Crosses right edge +			} else { +				if(y2 > t && y1 < t) return 1; //Crosses top edge +				if(y1 < b && y2 > b) return 2; //Crosses bottom edge +			} +			 +			return false; +			 +		}, +		//This method checks approximately if the item is dragged in a container, but doesn't touch any items +		inEmptyZone: function(container) { + +			if(!$(container.options.items, container.element).length) { +				return container.options.dropOnEmpty ? true : false; +			}; + +			var last = $(container.options.items, container.element).not('.ui-sortable-helper'); last = $(last[last.length-1]); +			var top = last.offset()[this.floating ? 'left' : 'top'] + last[0][this.floating ? 'offsetWidth' : 'offsetHeight']; +			return (this.position.absolute[this.floating ? 'left' : 'top'] > top); +		}, +		refresh: function() { +			this.refreshItems(); +			this.refreshPositions(); +		}, +		refreshItems: function() { +			 +			this.items = []; +			this.containers = [this]; +			var items = this.items; +			var queries = [$(this.options.items, this.element)]; +			 +			if(this.options.connectWith) { +				for (var i = this.options.connectWith.length - 1; i >= 0; i--){ +					var cur = $(this.options.connectWith[i]); +					for (var j = cur.length - 1; j >= 0; j--){ +						var inst = $.data(cur[j], 'sortable'); +						if(inst && !inst.options.disabled) { +							queries.push($(inst.options.items, inst.element)); +							this.containers.push(inst); +						} +					}; +				}; +			} + +			for (var i = queries.length - 1; i >= 0; i--){ +				queries[i].each(function() { +					$.data(this, 'sortable-item', true); // Data for target checking (mouse manager) +					items.push({ +						item: $(this), +						width: 0, height: 0, +						left: 0, top: 0 +					}); +				}); +			}; + +		}, +		refreshPositions: function(fast) { +			for (var i = this.items.length - 1; i >= 0; i--){ +				if(!fast) this.items[i].width 			= this.items[i].item.outerWidth(); +				if(!fast) this.items[i].height 			= this.items[i].item.outerHeight(); +				var p = this.items[i].item.offset(); +				this.items[i].left 						= p.left; +				this.items[i].top 						= p.top; +			}; +			for (var i = this.containers.length - 1; i >= 0; i--){ +				var p =this.containers[i].element.offset(); +				this.containers[i].containerCache.left 	= p.left; +				this.containers[i].containerCache.top 	= p.top; +				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth(); +				this.containers[i].containerCache.height= this.containers[i].element.outerHeight(); +			}; +		}, +		destroy: function() { +			this.element +				.removeClass("ui-sortable ui-sortable-disabled") +				.removeData("sortable") +				.unbind(".sortable") +				.removeMouseInteraction(); +			 +			for ( var i = this.items.length - 1; i >= 0; i-- ) +				this.items[i].item.removeData("sortable-item"); +		}, +		createPlaceholder: function(that) { +			(that || this).placeholderElement = this.options.placeholderElement ? $(this.options.placeholderElement, (that || this).currentItem) : (that || this).currentItem; +			(that || this).placeholder = $('<div></div>') +				.addClass(this.options.placeholder) +				.appendTo('body') +				.css({ position: 'absolute' }) +				.css((that || this).placeholderElement.offset()) +				.css({ width: (that || this).placeholderElement.outerWidth(), height: (that || this).placeholderElement.outerHeight() }) +				; +		}, +		contactContainers: function(e) { +			for (var i = this.containers.length - 1; i >= 0; i--){ + +				if(this.intersectsWith(this.containers[i].containerCache)) { +					if(!this.containers[i].containerCache.over) { +						 + +						if(this.currentContainer != this.containers[i]) { +							 +							//When entering a new container, we will find the item with the least distance and append our item near it +							var dist = 10000; var itemWithLeastDistance = null; var base = this.position.absolute[this.containers[i].floating ? 'left' : 'top']; +							for (var j = this.items.length - 1; j >= 0; j--) { +								if(!this.containers[i].element[0].contains(this.items[j].item[0])) continue; +								var cur = this.items[j][this.containers[i].floating ? 'left' : 'top']; +								if(Math.abs(cur - base) < dist) { +									dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; +								} +							} +							 +							//We also need to exchange the placeholder +							if(this.placeholder) this.placeholder.remove(); +							if(this.containers[i].options.placeholder) { +								this.containers[i].createPlaceholder(this); +							} else { +								this.placeholder = null; this.placeholderElement = null; +							} +							 +							 +							itemWithLeastDistance ? this.rearrange(e, itemWithLeastDistance) : this.rearrange(e, null, this.containers[i].element); +							this.propagate("change", e); //Call plugins and callbacks +							this.containers[i].propagate("change", e, this); //Call plugins and callbacks +							this.currentContainer = this.containers[i]; + +						} +						 +						this.containers[i].propagate("over", e, this); +						this.containers[i].containerCache.over = 1; +					} +				} else { +					if(this.containers[i].containerCache.over) { +						this.containers[i].propagate("out", e, this); +						this.containers[i].containerCache.over = 0; +					} +				} +				 +			};			 +		}, +		start: function(e,el) { +			 +			var o = this.options; +			this.refresh(); + +			//Create and append the visible helper +			this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e, this.currentItem])) : this.currentItem.clone(); +			if(!this.helper.parents('body').length) this.helper.appendTo(o.appendTo || this.currentItem[0].parentNode); //Add the helper to the DOM if that didn't happen already +			this.helper.css({ position: 'absolute', clear: 'both' }).addClass('ui-sortable-helper'); //Position it absolutely and add a helper class +			 +			//Prepare variables for position generation +			$.extend(this, { +				offsetParent: this.helper.offsetParent(), +				offsets: { +					absolute: this.currentItem.offset() +				}, +				mouse: { +					start: { top: e.pageY, left: e.pageX } +				}, +				margins: { +					top: parseInt(this.currentItem.css("marginTop")) || 0, +					left: parseInt(this.currentItem.css("marginLeft")) || 0 +				} +			}); +			 +			//The relative click offset +			this.offsets.parent = this.offsetParent.offset(); +			this.clickOffset = { left: e.pageX - this.offsets.absolute.left, top: e.pageY - this.offsets.absolute.top }; +			 +			this.originalPosition = { +				left: this.offsets.absolute.left - this.offsets.parent.left - this.margins.left, +				top: this.offsets.absolute.top - this.offsets.parent.top - this.margins.top +			} +			 +			//Generate a flexible offset that will later be subtracted from e.pageX/Y +			//I hate margins - they need to be removed before positioning the element absolutely.. +			this.offset = { +				left: e.pageX - this.originalPosition.left, +				top: e.pageY - this.originalPosition.top +			}; + +			//Save the first time position +			$.extend(this, { +				position: { +					current: { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left }, +					absolute: { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top }, +					dom: this.currentItem.prev()[0] +				} +			}); + +			//If o.placeholder is used, create a new element at the given position with the class +			if(o.placeholder) this.createPlaceholder(); + +			this.propagate("start", e); //Call plugins and callbacks +			this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() }; //Save and store the helper proportions + +			//If we have something in cursorAt, we'll use it +			if(o.cursorAt) { +				if(o.cursorAt.top != undefined || o.cursorAt.bottom != undefined) { +					this.offset.top -= this.clickOffset.top - (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom)); +					this.clickOffset.top = (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom)); +				} +				if(o.cursorAt.left != undefined || o.cursorAt.right != undefined) { +					this.offset.left -= this.clickOffset.left - (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right)); +					this.clickOffset.left = (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right)); +				} +			} + +			if(this.options.placeholder != 'clone') $(this.currentItem).css('visibility', 'hidden'); //Set the original element visibility to hidden to still fill out the white space +			for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i].propagate("activate", e, this); } //Post 'activate' events to possible containers +			 +			//Prepare possible droppables +			if($.ui.ddmanager) $.ui.ddmanager.current = this; +			if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e); + +			this.dragging = true; +			return false; +			 +		}, +		stop: function(e) { + +			this.propagate("stop", e); //Call plugins and trigger callbacks +			if(this.position.dom != this.currentItem.prev()[0]) this.propagate("update", e); //Trigger update callback if the DOM position has changed +			if(!this.element[0].contains(this.currentItem[0])) { //Node was moved out of the current element +				this.propagate("remove", e); +				for (var i = this.containers.length - 1; i >= 0; i--){ +					if(this.containers[i].element[0].contains(this.currentItem[0])) { +						this.containers[i].propagate("update", e, this); +						this.containers[i].propagate("receive", e, this); +					} +				}; +			}; +			 +			//Post events to containers +			for (var i = this.containers.length - 1; i >= 0; i--){ +				this.containers[i].propagate("deactivate", e, this); +				if(this.containers[i].containerCache.over) { +					this.containers[i].propagate("out", e, this); +					this.containers[i].containerCache.over = 0; +				} +			} +			 +			//If we are using droppables, inform the manager about the drop +			if ($.ui.ddmanager && !this.options.dropBehaviour) $.ui.ddmanager.drop(this, e); +			 +			this.dragging = false; +			if(this.cancelHelperRemoval) return false; +			$(this.currentItem).css('visibility', ''); +			if(this.placeholder) this.placeholder.remove(); +			this.helper.remove(); + +			return false; +			 +		}, +		drag: function(e) { + +			//Compute the helpers position +			this.position.current = { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left }; +			this.position.absolute = { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top }; + +			//Rearrange +			for (var i = this.items.length - 1; i >= 0; i--) { +				var intersection = this.intersectsWithEdge(this.items[i]); +				if(!intersection) continue; +				 +				if(     this.items[i].item[0] != this.currentItem[0] //cannot intersect with itself +					&&	this.currentItem[intersection == 1 ? "next" : "prev"]()[0] != this.items[i].item[0] //no useless actions that have been done before +					&&	!this.currentItem[0].contains(this.items[i].item[0]) //no action if the item moved is the parent of the item checked +					&& (this.options.type == 'semi-dynamic' ? !this.element[0].contains(this.items[i].item[0]) : true) +				) { +					 +					this.direction = intersection == 1 ? "down" : "up"; +					this.rearrange(e, this.items[i]); +					this.propagate("change", e); //Call plugins and callbacks +					break; +				} +			} +			 +			//Post events to containers +			this.contactContainers(e); +			 +			//Interconnect with droppables +			if($.ui.ddmanager) $.ui.ddmanager.drag(this, e); + +			this.propagate("sort", e); //Call plugins and callbacks +			this.helper.css({ left: this.position.current.left+'px', top: this.position.current.top+'px' }); // Stick the helper to the cursor +			return false; +			 +		}, +		rearrange: function(e, i, a) { +			a ? a.append(this.currentItem) : i.item[this.direction == 'down' ? 'before' : 'after'](this.currentItem); +			this.refreshPositions(true); //Precompute after each DOM insertion, NOT on mousemove +			if(this.placeholderElement) this.placeholder.css(this.placeholderElement.offset()); +		} +	}); +	 +/* + * Sortable Extensions + */ + +	$.ui.plugin.add("sortable", "cursor", { +		start: function(e, ui) { +			var t = $('body'); +			if (t.css("cursor")) ui.options._cursor = t.css("cursor"); +			t.css("cursor", ui.options.cursor); +		}, +		stop: function(e, ui) { +			if (ui.options._cursor) $('body').css("cursor", ui.options._cursor); +		} +	}); + +	$.ui.plugin.add("sortable", "zIndex", { +		start: function(e, ui) { +			var t = ui.helper; +			if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex"); +			t.css('zIndex', ui.options.zIndex); +		}, +		stop: function(e, ui) { +			if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex); +		} +	}); + +	$.ui.plugin.add("sortable", "opacity", { +		start: function(e, ui) { +			var t = ui.helper; +			if(t.css("opacity")) ui.options._opacity = t.css("opacity"); +			t.css('opacity', ui.options.opacity); +		}, +		stop: function(e, ui) { +			if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity); +		} +	}); + + +	$.ui.plugin.add("sortable", "revert", { +		stop: function(e, ui) { +			var self = ui.instance; +			self.cancelHelperRemoval = true; +			var cur = self.currentItem.offset(); +			var op = self.helper.offsetParent().offset(); +			if(ui.instance.options.zIndex) ui.helper.css('zIndex', ui.instance.options.zIndex); //Do the zIndex again because it already was resetted by the plugin above on stop + +			//Also animate the placeholder if we have one +			if(ui.instance.placeholder) ui.instance.placeholder.animate({ opacity: 'hide' }, parseInt(ui.options.revert, 10) || 500); +			 +			 +			ui.helper.animate({ +				left: cur.left - op.left - self.margins.left, +				top: cur.top - op.top - self.margins.top +			}, parseInt(ui.options.revert, 10) || 500, function() { +				self.currentItem.css('visibility', 'visible'); +				window.setTimeout(function() { +					if(self.placeholder) self.placeholder.remove(); +					self.helper.remove(); +					if(ui.options._zIndex) ui.helper.css('zIndex', ui.options._zIndex); +				}, 50); +			}); +		} +	}); + +	 +	$.ui.plugin.add("sortable", "containment", { +		start: function(e, ui) { + +			var o = ui.options; +			if((o.containment.left != undefined || o.containment.constructor == Array) && !o._containment) return; +			if(!o._containment) o._containment = o.containment; + +			if(o._containment == 'parent') o._containment = this[0].parentNode; +			if(o._containment == 'sortable') o._containment = this[0]; +			if(o._containment == 'document') { +				o.containment = [ +					0, +					0, +					$(document).width(), +					($(document).height() || document.body.parentNode.scrollHeight) +				]; +			} else { //I'm a node, so compute top/left/right/bottom + +				var ce = $(o._containment); +				var co = ce.offset(); + +				o.containment = [ +					co.left, +					co.top, +					co.left+(ce.outerWidth() || ce[0].scrollWidth), +					co.top+(ce.outerHeight() || ce[0].scrollHeight) +				]; +			} + +		}, +		sort: function(e, ui) { + +			var o = ui.options; +			var h = ui.helper; +			var c = o.containment; +			var self = ui.instance; +			var borderLeft = (parseInt(self.offsetParent.css("borderLeftWidth"), 10) || 0); +			var borderRight = (parseInt(self.offsetParent.css("borderRightWidth"), 10) || 0); +			var borderTop = (parseInt(self.offsetParent.css("borderTopWidth"), 10) || 0); +			var borderBottom = (parseInt(self.offsetParent.css("borderBottomWidth"), 10) || 0); +			 +			if(c.constructor == Array) { +				if((self.position.absolute.left < c[0])) self.position.current.left = c[0] - self.offsets.parent.left - self.margins.left; +				if((self.position.absolute.top < c[1])) self.position.current.top = c[1] - self.offsets.parent.top - self.margins.top; +				if(self.position.absolute.left - c[2] + self.helperProportions.width >= 0) self.position.current.left = c[2] - self.offsets.parent.left - self.helperProportions.width - self.margins.left - borderLeft - borderRight; +				if(self.position.absolute.top - c[3] + self.helperProportions.height >= 0) self.position.current.top = c[3] - self.offsets.parent.top - self.helperProportions.height - self.margins.top - borderTop - borderBottom; +			} else { +				if((ui.position.left < c.left)) self.position.current.left = c.left; +				if((ui.position.top < c.top)) self.position.current.top = c.top; +				if(ui.position.left - self.offsetParent.innerWidth() + self.helperProportions.width + c.right + borderLeft + borderRight >= 0) self.position.current.left = self.offsetParent.innerWidth() - self.helperProportions.width - c.right - borderLeft - borderRight; +				if(ui.position.top - self.offsetParent.innerHeight() + self.helperProportions.height + c.bottom + borderTop + borderBottom >= 0) self.position.current.top = self.offsetParent.innerHeight() - self.helperProportions.height - c.bottom - borderTop - borderBottom; +			} + +		} +	}); + +	$.ui.plugin.add("sortable", "axis", { +		sort: function(e, ui) { +			var o = ui.options; +			if(o.constraint) o.axis = o.constraint; //Legacy check +			o.axis == 'x' ? ui.instance.position.top = ui.instance.originalPosition.top : ui.instance.position.left = ui.instance.originalPosition.left; +		} +	}); + +	$.ui.plugin.add("sortable", "scroll", { +		start: function(e, ui) { +			var o = ui.options; +			o.scrollSensitivity	= o.scrollSensitivity || 20; +			o.scrollSpeed		= o.scrollSpeed || 20; + +			ui.instance.overflowY = function(el) { +				do { if((/auto|scroll/).test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode); +				return $(document); +			}(this); +			ui.instance.overflowX = function(el) { +				do { if((/auto|scroll/).test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode); +				return $(document); +			}(this); +			 +			if(ui.instance.overflowY[0] != document && ui.instance.overflowY[0].tagName != 'HTML') ui.instance.overflowYstart = ui.instance.overflowY[0].scrollTop; +			if(ui.instance.overflowX[0] != document && ui.instance.overflowX[0].tagName != 'HTML') ui.instance.overflowXstart = ui.instance.overflowX[0].scrollLeft; +			 +		}, +		sort: function(e, ui) { +			 +			var o = ui.options; +			var i = ui.instance; + +			if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') { +				if(i.overflowY[0].offsetHeight - (ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity) +					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed; +				if((ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity) +					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;				 +			} else { +				//$(document.body).append('<p>'+(e.pageY - $(document).scrollTop())+'</p>'); +				if(e.pageY - $(document).scrollTop() < o.scrollSensitivity) +					$(document).scrollTop($(document).scrollTop() - o.scrollSpeed); +				if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity) +					$(document).scrollTop($(document).scrollTop() + o.scrollSpeed); +			} +			 +			if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') { +				if(i.overflowX[0].offsetWidth - (ui.position.left - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity) +					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed; +				if((ui.position.top - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity) +					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;				 +			} else { +				if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity) +					$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); +				if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity) +					$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); +			} +			 +			//ui.instance.recallOffset(e); +			i.offset = { +				left: i.mouse.start.left - i.originalPosition.left + (i.overflowXstart !== undefined ? i.overflowXstart - i.overflowX[0].scrollLeft : 0), +				top: i.mouse.start.top - i.originalPosition.top + (i.overflowYstart !== undefined ? i.overflowYstart - i.overflowX[0].scrollTop : 0) +			}; + +		} +	}); + +})(jQuery);  | 
