Template:Paris2009 slidemenu
From 2009.igem.org
/*!
* jQuery JavaScript Library v1.3.2 * http://jquery.com/ * * Copyright (c) 2009 John Resig * Dual licensed under the MIT and GPL licenses. * http://docs.jquery.com/License * * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) * Revision: 6246 */
(function(){
var // Will speed up references to window, and allows munging its name. window = this, // Will speed up references to undefined, and allows munging its name. undefined, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$,
jQuery = window.jQuery = window.$ = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context ); },
// A simple way to check for HTML strings or ID strings // (both of which we optimize for) quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, // Is it a simple selector isSimple = /^.[^:#\[\.,]*$/;
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; this.context = selector; return this; } // Handle HTML strings 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] );
// Handle the case where IE and Opera return items // by name instead of ID if ( elem && elem.id != match[3] ) return jQuery().find( selector );
// Otherwise, we inject the element directly into the jQuery object var ret = jQuery( elem || [] ); ret.context = document; ret.selector = selector; return ret; }
// HANDLE: $(expr, [context]) // (which is just equivalent to: $(content).find(expr) } else return jQuery( context ).find( selector );
// HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) return jQuery( document ).ready( selector );
// Make sure that old selector state is passed along if ( selector.selector && selector.context ) { this.selector = selector.selector; this.context = selector.context; }
return this.setArray(jQuery.isArray( selector ) ? selector : jQuery.makeArray(selector)); },
// Start with an empty selector selector: "",
// The current version of jQuery being used jquery: "1.3.2",
// The number of elements contained in the matched element set size: function() { return this.length; },
// 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 Array.prototype.slice.call( 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, name, selector ) { // Build a new jQuery matched element set var ret = jQuery( elems );
// Add the old object onto the stack (as a reference) ret.prevObject = this;
ret.context = this.context;
if ( name === "find" ) ret.selector = this.selector + (this.selector ? " " : "") + selector; else if ( name ) ret.selector = this.selector + "." + name + "(" + selector + ")";
// Return the newly-formed element set return ret; },
// Force the current matched set of elements to become // the specified array of elements (destroying the stack in the process) // You should use pushStack() in order to do this, but maintain the stack setArray: function( elems ) { // Resetting the length to 0, then using the native Array push // is a super-fast way to populate an object with array-like properties this.length = 0; Array.prototype.push.apply( this, elems );
return this; },
// Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); },
// Determine the position of an element within // the matched set of elements index: function( elem ) { // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem && elem.jquery ? elem[0] : elem , this ); },
attr: function( name, value, type ) { var options = name;
// Look for the case where we're accessing a style value if ( typeof name === "string" ) if ( value === undefined ) return this[0] && jQuery[ type || "attr" ]( this[0], name );
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 var wrap = jQuery( html, this[0].ownerDocument ).clone();
if ( this[0].parentNode ) wrap.insertBefore( this[0] );
wrap.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, function(elem){ if (this.nodeType == 1) this.appendChild( elem ); }); },
prepend: function() { return this.domManip(arguments, true, function(elem){ if (this.nodeType == 1) this.insertBefore( elem, this.firstChild ); }); },
before: function() { return this.domManip(arguments, false, function(elem){ this.parentNode.insertBefore( elem, this ); }); },
after: function() { return this.domManip(arguments, false, function(elem){ this.parentNode.insertBefore( elem, this.nextSibling ); }); },
end: function() { return this.prevObject || jQuery( [] ); },
// For internal use only. // Behaves like an Array's method, not like a jQuery method. push: [].push, sort: [].sort, splice: [].splice,
find: function( selector ) { if ( this.length === 1 ) { var ret = this.pushStack( [], "find", selector ); ret.length = 0; jQuery.find( selector, this[0], ret ); return ret; } else { return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ return jQuery.find( selector, elem ); })), "find", selector ); } },
clone: function( events ) { // Do the clone var ret = this.map(function(){ if ( !jQuery.support.noCloneEvent && !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 html = this.outerHTML; if ( !html ) { var div = this.ownerDocument.createElement("div"); div.appendChild( this.cloneNode(true) ); html = div.innerHTML; }
return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; } else return this.cloneNode(true); });
// Copy the events from the original to the clone if ( events === true ) { var orig = this.find("*").andSelf(), i = 0;
ret.find("*").andSelf().each(function(){ if ( this.nodeName !== orig[i].nodeName ) return;
var events = jQuery.data( orig[i], "events" );
for ( var type in events ) { for ( var handler in events[ type ] ) { jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); } }
i++; }); }
// 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, jQuery.grep(this, function(elem){ return elem.nodeType === 1; }) ), "filter", selector ); },
closest: function( selector ) { var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, closer = 0;
return this.map(function(){ var cur = this; while ( cur && cur.ownerDocument ) { if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { jQuery.data(cur, "closest", closer); return cur; } cur = cur.parentNode; closer++; } }); },
not: function( selector ) { if ( typeof selector === "string" ) // test special case where just one selector is passed in if ( isSimple.test( selector ) ) return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); 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 this.pushStack( jQuery.unique( jQuery.merge( this.get(), typeof selector === "string" ? jQuery( selector ) : jQuery.makeArray( selector ) ))); },
is: function( selector ) { return !!selector && jQuery.multiFilter( selector, this ).length > 0; },
hasClass: function( selector ) { return !!selector && this.is( "." + selector ); },
val: function( value ) { if ( value === undefined ) { var elem = this[0];
if ( elem ) { if( jQuery.nodeName( elem, 'option' ) ) return (elem.attributes.value || {}).specified ? elem.value : elem.text;
// 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(option).val();
// 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 return (elem.value || "").replace(/\r/g, "");
}
return undefined; }
if ( typeof value === "number" ) value += ;
return this.each(function(){ if ( this.nodeType != 1 ) return;
if ( jQuery.isArray(value) && /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 = jQuery.makeArray(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[0] ? this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : 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 ), "slice", Array.prototype.slice.call(arguments).join(",") ); },
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 ); },
domManip: function( args, table, callback ) { if ( this[0] ) { var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), first = fragment.firstChild;
if ( first ) for ( var i = 0, l = this.length; i < l; i++ ) callback.call( root(this[i], first), this.length > 1 || i > 0 ? fragment.cloneNode(true) : fragment );
if ( scripts ) jQuery.each( scripts, evalScript ); }
return this;
function root( elem, cur ) { return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? (elem.getElementsByTagName("tbody")[0] || elem.appendChild(elem.ownerDocument.createElement("tbody"))) : elem; } } };
// Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn;
function evalScript( i, elem ) { if ( elem.src ) jQuery.ajax({ url: elem.src, async: false, dataType: "script" });
else jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
if ( elem.parentNode ) elem.parentNode.removeChild( elem ); }
function now(){ return +new Date; }
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 ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; }
// Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) target = {};
// extend jQuery itself if only one argument is passed if ( length == i ) { target = this; --i; }
for ( ; i < length; i++ ) // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) // Extend the base object for ( var name in options ) { var src = target[ name ], copy = options[ name ];
// Prevent never-ending loop if ( target === copy ) continue;
// Recurse if we're merging object values if ( deep && copy && typeof copy === "object" && !copy.nodeType ) target[ name ] = jQuery.extend( deep, // Never move original objects, clone them src || ( copy.length != null ? [ ] : { } ) , copy );
// Don't bring in undefined values else if ( copy !== undefined ) target[ name ] = copy;
}
// Return the modified object return target; };
// exclude the following css properties to add px var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, // cache defaultView defaultView = document.defaultView || {}, toString = Object.prototype.toString;
jQuery.extend({ noConflict: function( deep ) { window.$ = _$;
if ( deep ) window.jQuery = _jQuery;
return jQuery; },
// See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return toString.call(obj) === "[object Function]"; },
isArray: function( obj ) { return toString.call(obj) === "[object Array]"; },
// check if an element is in a (or is an) XML document isXMLDoc: function( elem ) { return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); },
// Evalulates a script in a global context globalEval: function( data ) { if ( data && /\S/.test(data) ) { // Inspired by code by Andrea Giammarchi // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html var head = document.getElementsByTagName("head")[0] || document.documentElement, script = document.createElement("script");
script.type = "text/javascript"; if ( jQuery.support.scriptEval ) script.appendChild( document.createTextNode( data ) ); else script.text = data;
// Use insertBefore instead of appendChild to circumvent an IE6 bug. // This arises when a base node is used (#2709). head.insertBefore( script, head.firstChild ); head.removeChild( script ); } },
nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); },
// args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length;
if ( args ) { if ( length === undefined ) { for ( name in object ) if ( callback.apply( object[ name ], args ) === false ) break; } else for ( ; i < length; ) if ( callback.apply( object[ i++ ], args ) === false ) break;
// A special, fast, case for the most common use of each } else { if ( length === undefined ) { for ( name in object ) if ( callback.call( object[ name ], name, object[ name ] ) === false ) break; } else for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} }
return object; },
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 typeof value === "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 hasClass("class") has: function( elem, className ) { return elem && 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, extra ) { 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;
if ( extra === "border" ) return;
jQuery.each( which, function() { if ( !extra ) val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; if ( extra === "margin" ) val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; else val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; }); }
if ( elem.offsetWidth !== 0 ) getWH(); else jQuery.swap( elem, props, getWH );
return Math.max(0, Math.round(val)); }
return jQuery.curCSS( elem, name, force ); },
curCSS: function( elem, name, force ) { var ret, style = elem.style;
// We need to handle opacity special in IE if ( name == "opacity" && !jQuery.support.opacity ) { ret = jQuery.attr( style, "opacity" );
return ret == "" ? "1" : ret; }
// Make sure we're using the right name for getting the float value if ( name.match( /float/i ) ) name = styleFloat;
if ( !force && style && style[ name ] ) ret = style[ name ];
else if ( defaultView.getComputedStyle ) {
// Only "float" is needed here if ( name.match( /float/i ) ) name = "float";
name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
var computedStyle = defaultView.getComputedStyle( elem, null );
if ( computedStyle ) ret = computedStyle.getPropertyValue( name );
// 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 left = style.left, rsLeft = elem.runtimeStyle.left;
// Put in the new values to get a computed value out elem.runtimeStyle.left = elem.currentStyle.left; style.left = ret || 0; ret = style.pixelLeft + "px";
// Revert the changed values style.left = left; elem.runtimeStyle.left = rsLeft; } }
return ret; },
clean: function( elems, context, fragment ) { 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;
// If a single string is passed in and it's a single tag // just do a createElement and skip the rest if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); if ( match ) return [ context.createElement( match[1] ) ]; }
var ret = [], scripts = [], div = context.createElement("div");
jQuery.each(elems, function(i, elem){ if ( typeof elem === "number" ) elem += ;
if ( !elem ) return;
// 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 = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
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, "!tags.indexOf("<tr") &&
[ 2, "// <thead> matched above (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
[ 3, "!tags.indexOf("<col") &&
[ 2, "// IE can't serialize <link> and <script> tags normally !jQuery.support.htmlSerialize &&
[ 1, "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.support.tbody ) {
// String was avar all = div.getElementsByTagName("*"), a = div.getElementsByTagName("a")[0];
// Can't get basic test support if ( !all || !all.length || !a ) { return; }
jQuery.support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: div.firstChild.nodeType == 3,
// Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables tbody: !div.getElementsByTagName("tbody").length,
// Make sure that you can get all elements in an <object> element // IE 7 always returns no results objectAll: !!div.getElementsByTagName("object")[0] .getElementsByTagName("*").length,
// Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName("link").length,
// Get the style information from getAttribute // (IE uses .cssText insted) style: /red/.test( a.getAttribute("style") ),
// Make sure that URLs aren't manipulated // (IE normalizes it by default) hrefNormalized: a.getAttribute("href") === "/a",
// Make sure that element opacity exists // (IE uses filter instead) opacity: a.style.opacity === "0.5",
// Verify style float existence // (IE uses styleFloat instead of cssFloat) cssFloat: !!a.style.cssFloat,
// Will be defined later scriptEval: false, noCloneEvent: true, boxModel: null };
script.type = "text/javascript"; try { script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); } catch(e){}
root.insertBefore( script, root.firstChild );
// Make sure that the execution of code works by injecting a script // tag with appendChild/createTextNode // (IE doesn't support this, fails, and uses .text instead) if ( window[ id ] ) { jQuery.support.scriptEval = true; delete window[ id ]; }
root.removeChild( script );
if ( div.attachEvent && div.fireEvent ) { div.attachEvent("onclick", function(){ // Cloning a node shouldn't copy over any // bound event handlers (IE does this) jQuery.support.noCloneEvent = false; div.detachEvent("onclick", arguments.callee); }); div.cloneNode(true).fireEvent("onclick"); }
// Figure out if the W3C box model works as expected // document.body must exist before we can do this jQuery(function(){ var div = document.createElement("div"); div.style.width = div.style.paddingLeft = "1px";
document.body.appendChild( div ); jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; document.body.removeChild( div ).style.display = 'none'; }); })();
var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
jQuery.props = { "for": "htmlFor", "class": "className", "float": styleFloat, cssFloat: styleFloat, styleFloat: styleFloat, readonly: "readOnly", maxlength: "maxLength", cellspacing: "cellSpacing", rowspan: "rowSpan", tabindex: "tabIndex" }; jQuery.fn.extend({ // Keep a copy of the old load _load: jQuery.fn.load,
load: function( url, params, callback ) { if ( typeof url !== "string" ) return this._load( url );
var off = url.indexOf(" "); if ( off >= 0 ) { var selector = url.slice(off, url.length); url = url.slice(0, off); }
// 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 if( typeof params === "object" ) { 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 );
if( callback ) self.each( callback, [res.responseText, status, res] ); } }); return this; },
serialize: function() { return jQuery.param(this.serializeArray()); }, serializeArray: function() { return this.map(function(){ return this.elements ? jQuery.makeArray(this.elements) : this; }) .filter(function(){ return this.name && !this.disabled && (this.checked || /select|textarea/i.test(this.nodeName) || /text|hidden|password|search/i.test(this.type)); }) .map(function(i, elem){ var val = jQuery(this).val(); return val == null ? null : jQuery.isArray(val) ? 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 = now();
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: { url: location.href, global: true, type: "GET", contentType: "application/x-www-form-urlencoded", processData: true, async: true, /* timeout: 0, data: null, username: null, password: null, */ // Create the request object; Microsoft failed to properly // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available // This function can be overriden by calling jQuery.ajaxSetup xhr:function(){ return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); }, 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 ) { // 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));
var jsonp, jsre = /=\?(&|$)/g, status, data, type = s.type.toUpperCase();
// 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 ( type == "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 && type == "GET" ) { var ts = now(); // 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 && type == "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" );
// Matches an absolute URL, and saves the domain var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
// If we're requesting a remote document // and trying to load JSON or Script with a GET if ( s.dataType == "script" && type == "GET" && parts && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
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();
// Handle memory leak in IE script.onload = script.onreadystatechange = null; head.removeChild( script ); } }; }
head.appendChild(script);
// We handle everything using the script element injection return undefined; }
var requestDone = false;
// Create the request object var xhr = s.xhr();
// Open the socket // Passing null username, generates a login popup on Opera (#2865) if( s.username ) xhr.open(type, s.url, s.async, s.username, s.password); else xhr.open(type, s.url, s.async);
// 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 ) xhr.setRequestHeader("Content-Type", s.contentType);
// Set the If-Modified-Since header, if ifModified mode. if ( s.ifModified ) xhr.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 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
// Set the Accepts header for the server, depending on the dataType xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? s.accepts[ s.dataType ] + ", */*" : s.accepts._default ); } catch(e){}
// Allow custom headers/mimetypes and early abort if ( s.beforeSend && s.beforeSend(xhr, s) === false ) { // Handle the global AJAX counter if ( s.global && ! --jQuery.active ) jQuery.event.trigger( "ajaxStop" ); // close opended socket xhr.abort(); return false; }
if ( s.global ) jQuery.event.trigger("ajaxSend", [xhr, s]);
// Wait for a response to come back var onreadystatechange = function(isTimeout){ // The request was aborted, clear the interval and decrement jQuery.active if (xhr.readyState == 0) { if (ival) { // clear poll interval clearInterval(ival); ival = null; // Handle the global AJAX counter if ( s.global && ! --jQuery.active ) jQuery.event.trigger( "ajaxStop" ); } // The transfer is complete and the data is available, or the request timed out } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) { requestDone = true;
// clear poll interval if (ival) { clearInterval(ival); ival = null; }
status = isTimeout == "timeout" ? "timeout" : !jQuery.httpSuccess( xhr ) ? "error" : s.ifModified && jQuery.httpNotModified( xhr, 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( xhr, s.dataType, s ); } 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 = xhr.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, xhr, status);
// Fire the complete handlers complete();
if ( isTimeout ) xhr.abort();
// Stop memory leaks if ( s.async ) xhr = 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 ( xhr && !requestDone ) onreadystatechange( "timeout" ); }, s.timeout); }
// Send the data try { xhr.send(s.data); } catch(e) { jQuery.handleError(s, xhr, 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", [xhr, s] ); }
function complete(){ // Process result if ( s.complete ) s.complete(xhr, status);
// The request was completed if ( s.global ) jQuery.event.trigger( "ajaxComplete", [xhr, s] );
// Handle the global AJAX counter if ( s.global && ! --jQuery.active ) jQuery.event.trigger( "ajaxStop" ); }
// return XMLHttpRequest to allow aborting the request etc. return xhr; },
handleError: function( s, xhr, status, e ) { // If a local callback was specified, fire it if ( s.error ) s.error( xhr, status, e );
// Fire the global callback if ( s.global ) jQuery.event.trigger( "ajaxError", [xhr, s, e] ); },
// Counter for holding the number of active queries active: 0,
// Determines if an XMLHttpRequest was successful or not httpSuccess: function( xhr ) { try { // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 return !xhr.status && location.protocol == "file:" || ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223; } catch(e){} return false; },
// Determines if an XMLHttpRequest returns NotModified httpNotModified: function( xhr, url ) { try { var xhrRes = xhr.getResponseHeader("Last-Modified");
// Firefox always returns 200. check Last-Modified date return xhr.status == 304 || xhrRes == jQuery.lastModified[url]; } catch(e){} return false; },
httpData: function( xhr, type, s ) { var ct = xhr.getResponseHeader("content-type"), xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0, data = xml ? xhr.responseXML : xhr.responseText;
if ( xml && data.documentElement.tagName == "parsererror" ) throw "parsererror";
// Allow a pre-filtering function to sanitize the response // s != null is checked to keep backwards compatibility if( s && s.dataFilter ) data = s.dataFilter( data, type );
// The filter can actually parse the response if( typeof data === "string" ){
// 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 = window["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 = [ ];
function add( key, value ){ s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value); };
// If an array was passed in, assume that it is an array // of form elements if ( jQuery.isArray(a) || a.jquery ) // Serialize the form elements jQuery.each( a, function(){ add( this.name, 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 ( jQuery.isArray(a[j]) ) jQuery.each( a[j], function(){ add( j, this ); }); else add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
// Return the resulting serialization return s.join("&").replace(/%20/g, "+"); }
}); var elemdisplay = {}, timerId, fxAttrs = [ // height animations [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], // width animations [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], // opacity animations [ "opacity" ] ];
function genFx( type, num ){ var obj = {}; jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){ obj[ this ] = type; }); return obj; }
jQuery.fn.extend({ show: function(speed,callback){ if ( speed ) { return this.animate( genFx("show", 3), speed, callback); } else { for ( var i = 0, l = this.length; i < l; i++ ){ var old = jQuery.data(this[i], "olddisplay");
this[i].style.display = old || "";
if ( jQuery.css(this[i], "display") === "none" ) { var tagName = this[i].tagName, display;
if ( elemdisplay[ tagName ] ) { display = elemdisplay[ tagName ]; } else { var elem = jQuery("<" + tagName + " />").appendTo("body");
display = elem.css("display"); if ( display === "none" ) display = "block";
elem.remove();
elemdisplay[ tagName ] = display; }
jQuery.data(this[i], "olddisplay", display); } }
// Set the display of the elements in a second loop // to avoid the constant reflow for ( var i = 0, l = this.length; i < l; i++ ){ this[i].style.display = jQuery.data(this[i], "olddisplay") || ""; }
return this; } },
hide: function(speed,callback){ if ( speed ) { return this.animate( genFx("hide", 3), speed, callback); } else { for ( var i = 0, l = this.length; i < l; i++ ){ var old = jQuery.data(this[i], "olddisplay"); if ( !old && old !== "none" ) jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display")); }
// Set the display of the elements in a second loop // to avoid the constant reflow for ( var i = 0, l = this.length; i < l; i++ ){ this[i].style.display = "none"; }
return this; } },
// Save the old toggle function _toggle: jQuery.fn.toggle,
toggle: function( fn, fn2 ){ var bool = typeof fn === "boolean";
return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ? this._toggle.apply( this, arguments ) : fn == null || bool ? this.each(function(){ var state = bool ? fn : jQuery(this).is(":hidden"); jQuery(this)[ state ? "show" : "hide" ](); }) : this.animate(genFx("toggle", 3), fn, fn2); },
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(){
var opt = jQuery.extend({}, optall), p, hidden = this.nodeType == 1 && jQuery(this).is(":hidden"), self = this;
for ( p in prop ) { if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden ) return opt.complete.call(this);
if ( ( p == "height" || p == "width" ) && this.style ) { // 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; }); },
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; }
});
// Generate shortcuts for custom animations jQuery.each({ slideDown: genFx("show", 1), slideUp: genFx("hide", 1), slideToggle: genFx("toggle", 1), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide" } }, function( name, props ){ jQuery.fn[ name ] = function( speed, callback ){ return this.animate( props, speed, callback ); }; });
jQuery.extend({
speed: function(speed, easing, fn) { var opt = typeof speed === "object" ? speed : { complete: fn || !fn && easing || jQuery.isFunction( speed ) && speed, duration: speed, easing: fn && easing || easing && !jQuery.isFunction(easing) && easing };
opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
// Queueing opt.old = opt.complete; opt.complete = function(){ if ( opt.queue !== false ) jQuery(this).dequeue(); if ( jQuery.isFunction( opt.old ) ) opt.old.call( 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: [],
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.call( 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 ) this.elem.style.display = "block"; },
// Get the current size cur: function(force){ if ( this.elem[this.prop] != null && (!this.elem.style || 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 = now(); this.start = from; this.end = to; this.unit = unit || this.unit || "px"; this.now = this.start; this.pos = this.state = 0;
var self = this; function t(gotoEnd){ return self.step(gotoEnd); }
t.elem = this.elem;
if ( t() && jQuery.timers.push(t) && !timerId ) { 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( timerId ); timerId = undefined; } }, 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 // Make sure that we start at a small width/height to avoid any // flash of content this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
// 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 = now();
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 ) jQuery(this.elem).hide();
// 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]);
// Execute the complete function this.options.complete.call( 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.extend( jQuery.fx, { speeds:{ slow: 600,
fast: 200, // Default speed _default: 400
}, step: {
opacity: function(fx){ jQuery.attr(fx.elem.style, "opacity", fx.now); },
_default: function(fx){ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) fx.elem.style[ fx.prop ] = fx.now + fx.unit; else fx.elem[ fx.prop ] = fx.now; } } }); if ( document.documentElement["getBoundingClientRect"] ) jQuery.fn.offset = function() { if ( !this[0] ) return { top: 0, left: 0 }; if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement, clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop, left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft; return { top: top, left: left }; }; else jQuery.fn.offset = function() { if ( !this[0] ) return { top: 0, left: 0 }; if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); jQuery.offset.initialized || jQuery.offset.initialize();
var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem, doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement, body = doc.body, defaultView = doc.defaultView, prevComputedStyle = defaultView.getComputedStyle(elem, null), top = elem.offsetTop, left = elem.offsetLeft;
while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { computedStyle = defaultView.getComputedStyle(elem, null); top -= elem.scrollTop, left -= elem.scrollLeft; if ( elem === offsetParent ) { top += elem.offsetTop, left += elem.offsetLeft; if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) ) top += parseInt( computedStyle.borderTopWidth, 10) || 0, left += parseInt( computedStyle.borderLeftWidth, 10) || 0; prevOffsetParent = offsetParent, offsetParent = elem.offsetParent; } if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) top += parseInt( computedStyle.borderTopWidth, 10) || 0, left += parseInt( computedStyle.borderLeftWidth, 10) || 0; prevComputedStyle = computedStyle; }
if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) top += body.offsetTop, left += body.offsetLeft;
if ( prevComputedStyle.position === "fixed" ) top += Math.max(docElem.scrollTop, body.scrollTop), left += Math.max(docElem.scrollLeft, body.scrollLeft);
return { top: top, left: left }; };
jQuery.offset = { initialize: function() { if ( this.initialized ) return; var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
html = 'rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' }; for ( prop in rules ) container.style[prop] = rules[prop];
container.innerHTML = html; body.insertBefore(container, body.firstChild); innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
this.doesNotAddBorder = (checkDiv.offsetTop !== 5); this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative'; this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
body.style.marginTop = '1px'; this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0); body.style.marginTop = bodyMarginTop;
body.removeChild(container); this.initialized = true; },
bodyOffset: function(body) { jQuery.offset.initialized || jQuery.offset.initialize(); var top = body.offsetTop, left = body.offsetLeft; if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0, left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0; return { top: top, left: left }; } };
jQuery.fn.extend({
position: function() {
var left = 0, top = 0, results;
if ( this[0] ) { // Get *real* offsetParent var offsetParent = this.offsetParent(),
// Get correct offsets offset = this.offset(), parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
// Subtract element margins // note: when an element has margin: auto the offsetLeft and marginLeft // are the same in Safari causing offset.left to incorrectly be 0 offset.top -= num( this, 'marginTop' ); offset.left -= num( this, 'marginLeft' );
// Add offsetParent borders parentOffset.top += num( offsetParent, 'borderTopWidth' ); parentOffset.left += num( offsetParent, 'borderLeftWidth' );
// Subtract the two offsets results = { top: offset.top - parentOffset.top, left: offset.left - parentOffset.left }; }
return results; },
offsetParent: function() { var offsetParent = this[0].offsetParent || document.body; while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') ) offsetParent = offsetParent.offsetParent; return jQuery(offsetParent); } });
// Create scrollLeft and scrollTop methods
jQuery.each( ['Left', 'Top'], function(i, name) {
var method = 'scroll' + name;
jQuery.fn[ method ] = function(val) { if (!this[0]) return null;
return val !== undefined ?
// Set the scroll offset this.each(function() { this == window || this == document ? window.scrollTo( !i ? val : jQuery(window).scrollLeft(), i ? val : jQuery(window).scrollTop() ) : this[ method ] = val; }) :
// Return the scroll offset this[0] == window || this[0] == document ? self[ i ? 'pageYOffset' : 'pageXOffset' ] || jQuery.boxModel && document.documentElement[ method ] || document.body[ method ] : this[0][ method ]; }; }); // Create innerHeight, innerWidth, outerHeight and outerWidth methods jQuery.each([ "Height", "Width" ], function(i, name){
var tl = i ? "Left" : "Top", // top or left br = i ? "Right" : "Bottom", // bottom or right lower = name.toLowerCase();
// innerHeight and innerWidth jQuery.fn["inner" + name] = function(){ return this[0] ? jQuery.css( this[0], lower, false, "padding" ) : null; };
// outerHeight and outerWidth jQuery.fn["outer" + name] = function(margin) { return this[0] ? jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) : null; };
var type = name.toLowerCase();
jQuery.fn[ type ] = function( size ) { // Get window width or height return this[0] == window ? // 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( document.documentElement["client" + name], document.body["scroll" + name], document.documentElement["scroll" + name], 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, typeof size === "string" ? size : size + "px" ); };
});
})();