bgneal@45: (function(){ bgneal@45: /* bgneal@45: * jQuery 1.2.6 - New Wave Javascript bgneal@45: * bgneal@45: * Copyright (c) 2008 John Resig (jquery.com) bgneal@45: * Dual licensed under the MIT (MIT-LICENSE.txt) bgneal@45: * and GPL (GPL-LICENSE.txt) licenses. bgneal@45: * bgneal@45: * $Date: 2008-05-27 21:17:26 +0200 (Di, 27 Mai 2008) $ bgneal@45: * $Rev: 5700 $ bgneal@45: */ bgneal@45: bgneal@45: // Map over jQuery in case of overwrite bgneal@45: var _jQuery = window.jQuery, bgneal@45: // Map over the $ in case of overwrite bgneal@45: _$ = window.$; bgneal@45: bgneal@45: var jQuery = window.jQuery = window.$ = function( selector, context ) { bgneal@45: // The jQuery object is actually just the init constructor 'enhanced' bgneal@45: return new jQuery.fn.init( selector, context ); bgneal@45: }; bgneal@45: bgneal@45: // A simple way to check for HTML strings or ID strings bgneal@45: // (both of which we optimize for) bgneal@45: var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/, bgneal@45: bgneal@45: // Is it a simple selector bgneal@45: isSimple = /^.[^:#\[\.]*$/, bgneal@45: bgneal@45: // Will speed up references to undefined, and allows munging its name. bgneal@45: undefined; bgneal@45: bgneal@45: jQuery.fn = jQuery.prototype = { bgneal@45: init: function( selector, context ) { bgneal@45: // Make sure that a selection was provided bgneal@45: selector = selector || document; bgneal@45: bgneal@45: // Handle $(DOMElement) bgneal@45: if ( selector.nodeType ) { bgneal@45: this[0] = selector; bgneal@45: this.length = 1; bgneal@45: return this; bgneal@45: } bgneal@45: // Handle HTML strings bgneal@45: if ( typeof selector == "string" ) { bgneal@45: // Are we dealing with HTML string or an ID? bgneal@45: var match = quickExpr.exec( selector ); bgneal@45: bgneal@45: // Verify a match, and that no context was specified for #id bgneal@45: if ( match && (match[1] || !context) ) { bgneal@45: bgneal@45: // HANDLE: $(html) -> $(array) bgneal@45: if ( match[1] ) bgneal@45: selector = jQuery.clean( [ match[1] ], context ); bgneal@45: bgneal@45: // HANDLE: $("#id") bgneal@45: else { bgneal@45: var elem = document.getElementById( match[3] ); bgneal@45: bgneal@45: // Make sure an element was located bgneal@45: if ( elem ){ bgneal@45: // Handle the case where IE and Opera return items bgneal@45: // by name instead of ID bgneal@45: if ( elem.id != match[3] ) bgneal@45: return jQuery().find( selector ); bgneal@45: bgneal@45: // Otherwise, we inject the element directly into the jQuery object bgneal@45: return jQuery( elem ); bgneal@45: } bgneal@45: selector = []; bgneal@45: } bgneal@45: bgneal@45: // HANDLE: $(expr, [context]) bgneal@45: // (which is just equivalent to: $(content).find(expr) bgneal@45: } else bgneal@45: return jQuery( context ).find( selector ); bgneal@45: bgneal@45: // HANDLE: $(function) bgneal@45: // Shortcut for document ready bgneal@45: } else if ( jQuery.isFunction( selector ) ) bgneal@45: return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); bgneal@45: bgneal@45: return this.setArray(jQuery.makeArray(selector)); bgneal@45: }, bgneal@45: bgneal@45: // The current version of jQuery being used bgneal@45: jquery: "1.2.6", bgneal@45: bgneal@45: // The number of elements contained in the matched element set bgneal@45: size: function() { bgneal@45: return this.length; bgneal@45: }, bgneal@45: bgneal@45: // The number of elements contained in the matched element set bgneal@45: length: 0, bgneal@45: bgneal@45: // Get the Nth element in the matched element set OR bgneal@45: // Get the whole matched element set as a clean array bgneal@45: get: function( num ) { bgneal@45: return num == undefined ? bgneal@45: bgneal@45: // Return a 'clean' array bgneal@45: jQuery.makeArray( this ) : bgneal@45: bgneal@45: // Return just the object bgneal@45: this[ num ]; bgneal@45: }, bgneal@45: bgneal@45: // Take an array of elements and push it onto the stack bgneal@45: // (returning the new matched element set) bgneal@45: pushStack: function( elems ) { bgneal@45: // Build a new jQuery matched element set bgneal@45: var ret = jQuery( elems ); bgneal@45: bgneal@45: // Add the old object onto the stack (as a reference) bgneal@45: ret.prevObject = this; bgneal@45: bgneal@45: // Return the newly-formed element set bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: // Force the current matched set of elements to become bgneal@45: // the specified array of elements (destroying the stack in the process) bgneal@45: // You should use pushStack() in order to do this, but maintain the stack bgneal@45: setArray: function( elems ) { bgneal@45: // Resetting the length to 0, then using the native Array push bgneal@45: // is a super-fast way to populate an object with array-like properties bgneal@45: this.length = 0; bgneal@45: Array.prototype.push.apply( this, elems ); bgneal@45: bgneal@45: return this; bgneal@45: }, bgneal@45: bgneal@45: // Execute a callback for every element in the matched set. bgneal@45: // (You can seed the arguments with an array of args, but this is bgneal@45: // only used internally.) bgneal@45: each: function( callback, args ) { bgneal@45: return jQuery.each( this, callback, args ); bgneal@45: }, bgneal@45: bgneal@45: // Determine the position of an element within bgneal@45: // the matched set of elements bgneal@45: index: function( elem ) { bgneal@45: var ret = -1; bgneal@45: bgneal@45: // Locate the position of the desired element bgneal@45: return jQuery.inArray( bgneal@45: // If it receives a jQuery object, the first element is used bgneal@45: elem && elem.jquery ? elem[0] : elem bgneal@45: , this ); bgneal@45: }, bgneal@45: bgneal@45: attr: function( name, value, type ) { bgneal@45: var options = name; bgneal@45: bgneal@45: // Look for the case where we're accessing a style value bgneal@45: if ( name.constructor == String ) bgneal@45: if ( value === undefined ) bgneal@45: return this[0] && jQuery[ type || "attr" ]( this[0], name ); bgneal@45: bgneal@45: else { bgneal@45: options = {}; bgneal@45: options[ name ] = value; bgneal@45: } bgneal@45: bgneal@45: // Check to see if we're setting style values bgneal@45: return this.each(function(i){ bgneal@45: // Set all the styles bgneal@45: for ( name in options ) bgneal@45: jQuery.attr( bgneal@45: type ? bgneal@45: this.style : bgneal@45: this, bgneal@45: name, jQuery.prop( this, options[ name ], type, i, name ) bgneal@45: ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: css: function( key, value ) { bgneal@45: // ignore negative width and height values bgneal@45: if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) bgneal@45: value = undefined; bgneal@45: return this.attr( key, value, "curCSS" ); bgneal@45: }, bgneal@45: bgneal@45: text: function( text ) { bgneal@45: if ( typeof text != "object" && text != null ) bgneal@45: return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); bgneal@45: bgneal@45: var ret = ""; bgneal@45: bgneal@45: jQuery.each( text || this, function(){ bgneal@45: jQuery.each( this.childNodes, function(){ bgneal@45: if ( this.nodeType != 8 ) bgneal@45: ret += this.nodeType != 1 ? bgneal@45: this.nodeValue : bgneal@45: jQuery.fn.text( [ this ] ); bgneal@45: }); bgneal@45: }); bgneal@45: bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: wrapAll: function( html ) { bgneal@45: if ( this[0] ) bgneal@45: // The elements to wrap the target around bgneal@45: jQuery( html, this[0].ownerDocument ) bgneal@45: .clone() bgneal@45: .insertBefore( this[0] ) bgneal@45: .map(function(){ bgneal@45: var elem = this; bgneal@45: bgneal@45: while ( elem.firstChild ) bgneal@45: elem = elem.firstChild; bgneal@45: bgneal@45: return elem; bgneal@45: }) bgneal@45: .append(this); bgneal@45: bgneal@45: return this; bgneal@45: }, bgneal@45: bgneal@45: wrapInner: function( html ) { bgneal@45: return this.each(function(){ bgneal@45: jQuery( this ).contents().wrapAll( html ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: wrap: function( html ) { bgneal@45: return this.each(function(){ bgneal@45: jQuery( this ).wrapAll( html ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: append: function() { bgneal@45: return this.domManip(arguments, true, false, function(elem){ bgneal@45: if (this.nodeType == 1) bgneal@45: this.appendChild( elem ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: prepend: function() { bgneal@45: return this.domManip(arguments, true, true, function(elem){ bgneal@45: if (this.nodeType == 1) bgneal@45: this.insertBefore( elem, this.firstChild ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: before: function() { bgneal@45: return this.domManip(arguments, false, false, function(elem){ bgneal@45: this.parentNode.insertBefore( elem, this ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: after: function() { bgneal@45: return this.domManip(arguments, false, true, function(elem){ bgneal@45: this.parentNode.insertBefore( elem, this.nextSibling ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: end: function() { bgneal@45: return this.prevObject || jQuery( [] ); bgneal@45: }, bgneal@45: bgneal@45: find: function( selector ) { bgneal@45: var elems = jQuery.map(this, function(elem){ bgneal@45: return jQuery.find( selector, elem ); bgneal@45: }); bgneal@45: bgneal@45: return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? bgneal@45: jQuery.unique( elems ) : bgneal@45: elems ); bgneal@45: }, bgneal@45: bgneal@45: clone: function( events ) { bgneal@45: // Do the clone bgneal@45: var ret = this.map(function(){ bgneal@45: if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { bgneal@45: // IE copies events bound via attachEvent when bgneal@45: // using cloneNode. Calling detachEvent on the bgneal@45: // clone will also remove the events from the orignal bgneal@45: // In order to get around this, we use innerHTML. bgneal@45: // Unfortunately, this means some modifications to bgneal@45: // attributes in IE that are actually only stored bgneal@45: // as properties will not be copied (such as the bgneal@45: // the name attribute on an input). bgneal@45: var clone = this.cloneNode(true), bgneal@45: container = document.createElement("div"); bgneal@45: container.appendChild(clone); bgneal@45: return jQuery.clean([container.innerHTML])[0]; bgneal@45: } else bgneal@45: return this.cloneNode(true); bgneal@45: }); bgneal@45: bgneal@45: // Need to set the expando to null on the cloned set if it exists bgneal@45: // removeData doesn't work here, IE removes it from the original as well bgneal@45: // this is primarily for IE but the data expando shouldn't be copied over in any browser bgneal@45: var clone = ret.find("*").andSelf().each(function(){ bgneal@45: if ( this[ expando ] != undefined ) bgneal@45: this[ expando ] = null; bgneal@45: }); bgneal@45: bgneal@45: // Copy the events from the original to the clone bgneal@45: if ( events === true ) bgneal@45: this.find("*").andSelf().each(function(i){ bgneal@45: if (this.nodeType == 3) bgneal@45: return; bgneal@45: var events = jQuery.data( this, "events" ); bgneal@45: bgneal@45: for ( var type in events ) bgneal@45: for ( var handler in events[ type ] ) bgneal@45: jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); bgneal@45: }); bgneal@45: bgneal@45: // Return the cloned set bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: filter: function( selector ) { bgneal@45: return this.pushStack( bgneal@45: jQuery.isFunction( selector ) && bgneal@45: jQuery.grep(this, function(elem, i){ bgneal@45: return selector.call( elem, i ); bgneal@45: }) || bgneal@45: bgneal@45: jQuery.multiFilter( selector, this ) ); bgneal@45: }, bgneal@45: bgneal@45: not: function( selector ) { bgneal@45: if ( selector.constructor == String ) bgneal@45: // test special case where just one selector is passed in bgneal@45: if ( isSimple.test( selector ) ) bgneal@45: return this.pushStack( jQuery.multiFilter( selector, this, true ) ); bgneal@45: else bgneal@45: selector = jQuery.multiFilter( selector, this ); bgneal@45: bgneal@45: var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; bgneal@45: return this.filter(function() { bgneal@45: return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: add: function( selector ) { bgneal@45: return this.pushStack( jQuery.unique( jQuery.merge( bgneal@45: this.get(), bgneal@45: typeof selector == 'string' ? bgneal@45: jQuery( selector ) : bgneal@45: jQuery.makeArray( selector ) bgneal@45: ))); bgneal@45: }, bgneal@45: bgneal@45: is: function( selector ) { bgneal@45: return !!selector && jQuery.multiFilter( selector, this ).length > 0; bgneal@45: }, bgneal@45: bgneal@45: hasClass: function( selector ) { bgneal@45: return this.is( "." + selector ); bgneal@45: }, bgneal@45: bgneal@45: val: function( value ) { bgneal@45: if ( value == undefined ) { bgneal@45: bgneal@45: if ( this.length ) { bgneal@45: var elem = this[0]; bgneal@45: bgneal@45: // We need to handle select boxes special bgneal@45: if ( jQuery.nodeName( elem, "select" ) ) { bgneal@45: var index = elem.selectedIndex, bgneal@45: values = [], bgneal@45: options = elem.options, bgneal@45: one = elem.type == "select-one"; bgneal@45: bgneal@45: // Nothing was selected bgneal@45: if ( index < 0 ) bgneal@45: return null; bgneal@45: bgneal@45: // Loop through all the selected options bgneal@45: for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { bgneal@45: var option = options[ i ]; bgneal@45: bgneal@45: if ( option.selected ) { bgneal@45: // Get the specifc value for the option bgneal@45: value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; bgneal@45: bgneal@45: // We don't need an array for one selects bgneal@45: if ( one ) bgneal@45: return value; bgneal@45: bgneal@45: // Multi-Selects return an array bgneal@45: values.push( value ); bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: return values; bgneal@45: bgneal@45: // Everything else, we just grab the value bgneal@45: } else bgneal@45: return (this[0].value || "").replace(/\r/g, ""); bgneal@45: bgneal@45: } bgneal@45: bgneal@45: return undefined; bgneal@45: } bgneal@45: bgneal@45: if( value.constructor == Number ) bgneal@45: value += ''; bgneal@45: bgneal@45: return this.each(function(){ bgneal@45: if ( this.nodeType != 1 ) bgneal@45: return; bgneal@45: bgneal@45: if ( value.constructor == Array && /radio|checkbox/.test( this.type ) ) bgneal@45: this.checked = (jQuery.inArray(this.value, value) >= 0 || bgneal@45: jQuery.inArray(this.name, value) >= 0); bgneal@45: bgneal@45: else if ( jQuery.nodeName( this, "select" ) ) { bgneal@45: var values = jQuery.makeArray(value); bgneal@45: bgneal@45: jQuery( "option", this ).each(function(){ bgneal@45: this.selected = (jQuery.inArray( this.value, values ) >= 0 || bgneal@45: jQuery.inArray( this.text, values ) >= 0); bgneal@45: }); bgneal@45: bgneal@45: if ( !values.length ) bgneal@45: this.selectedIndex = -1; bgneal@45: bgneal@45: } else bgneal@45: this.value = value; bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: html: function( value ) { bgneal@45: return value == undefined ? bgneal@45: (this[0] ? bgneal@45: this[0].innerHTML : bgneal@45: null) : bgneal@45: this.empty().append( value ); bgneal@45: }, bgneal@45: bgneal@45: replaceWith: function( value ) { bgneal@45: return this.after( value ).remove(); bgneal@45: }, bgneal@45: bgneal@45: eq: function( i ) { bgneal@45: return this.slice( i, i + 1 ); bgneal@45: }, bgneal@45: bgneal@45: slice: function() { bgneal@45: return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); bgneal@45: }, bgneal@45: bgneal@45: map: function( callback ) { bgneal@45: return this.pushStack( jQuery.map(this, function(elem, i){ bgneal@45: return callback.call( elem, i, elem ); bgneal@45: })); bgneal@45: }, bgneal@45: bgneal@45: andSelf: function() { bgneal@45: return this.add( this.prevObject ); bgneal@45: }, bgneal@45: bgneal@45: data: function( key, value ){ bgneal@45: var parts = key.split("."); bgneal@45: parts[1] = parts[1] ? "." + parts[1] : ""; bgneal@45: bgneal@45: if ( value === undefined ) { bgneal@45: var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); bgneal@45: bgneal@45: if ( data === undefined && this.length ) bgneal@45: data = jQuery.data( this[0], key ); bgneal@45: bgneal@45: return data === undefined && parts[1] ? bgneal@45: this.data( parts[0] ) : bgneal@45: data; bgneal@45: } else bgneal@45: return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ bgneal@45: jQuery.data( this, key, value ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: removeData: function( key ){ bgneal@45: return this.each(function(){ bgneal@45: jQuery.removeData( this, key ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: domManip: function( args, table, reverse, callback ) { bgneal@45: var clone = this.length > 1, elems; bgneal@45: bgneal@45: return this.each(function(){ bgneal@45: if ( !elems ) { bgneal@45: elems = jQuery.clean( args, this.ownerDocument ); bgneal@45: bgneal@45: if ( reverse ) bgneal@45: elems.reverse(); bgneal@45: } bgneal@45: bgneal@45: var obj = this; bgneal@45: bgneal@45: if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) ) bgneal@45: obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") ); bgneal@45: bgneal@45: var scripts = jQuery( [] ); bgneal@45: bgneal@45: jQuery.each(elems, function(){ bgneal@45: var elem = clone ? bgneal@45: jQuery( this ).clone( true )[0] : bgneal@45: this; bgneal@45: bgneal@45: // execute all scripts after the elements have been injected bgneal@45: if ( jQuery.nodeName( elem, "script" ) ) bgneal@45: scripts = scripts.add( elem ); bgneal@45: else { bgneal@45: // Remove any inner scripts for later evaluation bgneal@45: if ( elem.nodeType == 1 ) bgneal@45: scripts = scripts.add( jQuery( "script", elem ).remove() ); bgneal@45: bgneal@45: // Inject the elements into the document bgneal@45: callback.call( obj, elem ); bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: scripts.each( evalScript ); bgneal@45: }); bgneal@45: } bgneal@45: }; bgneal@45: bgneal@45: // Give the init function the jQuery prototype for later instantiation bgneal@45: jQuery.fn.init.prototype = jQuery.fn; bgneal@45: bgneal@45: function evalScript( i, elem ) { bgneal@45: if ( elem.src ) bgneal@45: jQuery.ajax({ bgneal@45: url: elem.src, bgneal@45: async: false, bgneal@45: dataType: "script" bgneal@45: }); bgneal@45: bgneal@45: else bgneal@45: jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); bgneal@45: bgneal@45: if ( elem.parentNode ) bgneal@45: elem.parentNode.removeChild( elem ); bgneal@45: } bgneal@45: bgneal@45: function now(){ bgneal@45: return +new Date; bgneal@45: } bgneal@45: bgneal@45: jQuery.extend = jQuery.fn.extend = function() { bgneal@45: // copy reference to target object bgneal@45: var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; bgneal@45: bgneal@45: // Handle a deep copy situation bgneal@45: if ( target.constructor == Boolean ) { bgneal@45: deep = target; bgneal@45: target = arguments[1] || {}; bgneal@45: // skip the boolean and the target bgneal@45: i = 2; bgneal@45: } bgneal@45: bgneal@45: // Handle case when target is a string or something (possible in deep copy) bgneal@45: if ( typeof target != "object" && typeof target != "function" ) bgneal@45: target = {}; bgneal@45: bgneal@45: // extend jQuery itself if only one argument is passed bgneal@45: if ( length == i ) { bgneal@45: target = this; bgneal@45: --i; bgneal@45: } bgneal@45: bgneal@45: for ( ; i < length; i++ ) bgneal@45: // Only deal with non-null/undefined values bgneal@45: if ( (options = arguments[ i ]) != null ) bgneal@45: // Extend the base object bgneal@45: for ( var name in options ) { bgneal@45: var src = target[ name ], copy = options[ name ]; bgneal@45: bgneal@45: // Prevent never-ending loop bgneal@45: if ( target === copy ) bgneal@45: continue; bgneal@45: bgneal@45: // Recurse if we're merging object values bgneal@45: if ( deep && copy && typeof copy == "object" && !copy.nodeType ) bgneal@45: target[ name ] = jQuery.extend( deep, bgneal@45: // Never move original objects, clone them bgneal@45: src || ( copy.length != null ? [ ] : { } ) bgneal@45: , copy ); bgneal@45: bgneal@45: // Don't bring in undefined values bgneal@45: else if ( copy !== undefined ) bgneal@45: target[ name ] = copy; bgneal@45: bgneal@45: } bgneal@45: bgneal@45: // Return the modified object bgneal@45: return target; bgneal@45: }; bgneal@45: bgneal@45: var expando = "jQuery" + now(), uuid = 0, windowData = {}, bgneal@45: // exclude the following css properties to add px bgneal@45: exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, bgneal@45: // cache defaultView bgneal@45: defaultView = document.defaultView || {}; bgneal@45: bgneal@45: jQuery.extend({ bgneal@45: noConflict: function( deep ) { bgneal@45: window.$ = _$; bgneal@45: bgneal@45: if ( deep ) bgneal@45: window.jQuery = _jQuery; bgneal@45: bgneal@45: return jQuery; bgneal@45: }, bgneal@45: bgneal@45: // See test/unit/core.js for details concerning this function. bgneal@45: isFunction: function( fn ) { bgneal@45: return !!fn && typeof fn != "string" && !fn.nodeName && bgneal@45: fn.constructor != Array && /^[\s[]?function/.test( fn + "" ); bgneal@45: }, bgneal@45: bgneal@45: // check if an element is in a (or is an) XML document bgneal@45: isXMLDoc: function( elem ) { bgneal@45: return elem.documentElement && !elem.body || bgneal@45: elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; bgneal@45: }, bgneal@45: bgneal@45: // Evalulates a script in a global context bgneal@45: globalEval: function( data ) { bgneal@45: data = jQuery.trim( data ); bgneal@45: bgneal@45: if ( data ) { bgneal@45: // Inspired by code by Andrea Giammarchi bgneal@45: // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html bgneal@45: var head = document.getElementsByTagName("head")[0] || document.documentElement, bgneal@45: script = document.createElement("script"); bgneal@45: bgneal@45: script.type = "text/javascript"; bgneal@45: if ( jQuery.browser.msie ) bgneal@45: script.text = data; bgneal@45: else bgneal@45: script.appendChild( document.createTextNode( data ) ); bgneal@45: bgneal@45: // Use insertBefore instead of appendChild to circumvent an IE6 bug. bgneal@45: // This arises when a base node is used (#2709). bgneal@45: head.insertBefore( script, head.firstChild ); bgneal@45: head.removeChild( script ); bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: nodeName: function( elem, name ) { bgneal@45: return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); bgneal@45: }, bgneal@45: bgneal@45: cache: {}, bgneal@45: bgneal@45: data: function( elem, name, data ) { bgneal@45: elem = elem == window ? bgneal@45: windowData : bgneal@45: elem; bgneal@45: bgneal@45: var id = elem[ expando ]; bgneal@45: bgneal@45: // Compute a unique ID for the element bgneal@45: if ( !id ) bgneal@45: id = elem[ expando ] = ++uuid; bgneal@45: bgneal@45: // Only generate the data cache if we're bgneal@45: // trying to access or manipulate it bgneal@45: if ( name && !jQuery.cache[ id ] ) bgneal@45: jQuery.cache[ id ] = {}; bgneal@45: bgneal@45: // Prevent overriding the named cache with undefined values bgneal@45: if ( data !== undefined ) bgneal@45: jQuery.cache[ id ][ name ] = data; bgneal@45: bgneal@45: // Return the named cache data, or the ID for the element bgneal@45: return name ? bgneal@45: jQuery.cache[ id ][ name ] : bgneal@45: id; bgneal@45: }, bgneal@45: bgneal@45: removeData: function( elem, name ) { bgneal@45: elem = elem == window ? bgneal@45: windowData : bgneal@45: elem; bgneal@45: bgneal@45: var id = elem[ expando ]; bgneal@45: bgneal@45: // If we want to remove a specific section of the element's data bgneal@45: if ( name ) { bgneal@45: if ( jQuery.cache[ id ] ) { bgneal@45: // Remove the section of cache data bgneal@45: delete jQuery.cache[ id ][ name ]; bgneal@45: bgneal@45: // If we've removed all the data, remove the element's cache bgneal@45: name = ""; bgneal@45: bgneal@45: for ( name in jQuery.cache[ id ] ) bgneal@45: break; bgneal@45: bgneal@45: if ( !name ) bgneal@45: jQuery.removeData( elem ); bgneal@45: } bgneal@45: bgneal@45: // Otherwise, we want to remove all of the element's data bgneal@45: } else { bgneal@45: // Clean up the element expando bgneal@45: try { bgneal@45: delete elem[ expando ]; bgneal@45: } catch(e){ bgneal@45: // IE has trouble directly removing the expando bgneal@45: // but it's ok with using removeAttribute bgneal@45: if ( elem.removeAttribute ) bgneal@45: elem.removeAttribute( expando ); bgneal@45: } bgneal@45: bgneal@45: // Completely remove the data cache bgneal@45: delete jQuery.cache[ id ]; bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: // args is for internal usage only bgneal@45: each: function( object, callback, args ) { bgneal@45: var name, i = 0, length = object.length; bgneal@45: bgneal@45: if ( args ) { bgneal@45: if ( length == undefined ) { bgneal@45: for ( name in object ) bgneal@45: if ( callback.apply( object[ name ], args ) === false ) bgneal@45: break; bgneal@45: } else bgneal@45: for ( ; i < length; ) bgneal@45: if ( callback.apply( object[ i++ ], args ) === false ) bgneal@45: break; bgneal@45: bgneal@45: // A special, fast, case for the most common use of each bgneal@45: } else { bgneal@45: if ( length == undefined ) { bgneal@45: for ( name in object ) bgneal@45: if ( callback.call( object[ name ], name, object[ name ] ) === false ) bgneal@45: break; bgneal@45: } else bgneal@45: for ( var value = object[0]; bgneal@45: i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} bgneal@45: } bgneal@45: bgneal@45: return object; bgneal@45: }, bgneal@45: bgneal@45: prop: function( elem, value, type, i, name ) { bgneal@45: // Handle executable functions bgneal@45: if ( jQuery.isFunction( value ) ) bgneal@45: value = value.call( elem, i ); bgneal@45: bgneal@45: // Handle passing in a number to a CSS property bgneal@45: return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? bgneal@45: value + "px" : bgneal@45: value; bgneal@45: }, bgneal@45: bgneal@45: className: { bgneal@45: // internal only, use addClass("class") bgneal@45: add: function( elem, classNames ) { bgneal@45: jQuery.each((classNames || "").split(/\s+/), function(i, className){ bgneal@45: if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) bgneal@45: elem.className += (elem.className ? " " : "") + className; bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: // internal only, use removeClass("class") bgneal@45: remove: function( elem, classNames ) { bgneal@45: if (elem.nodeType == 1) bgneal@45: elem.className = classNames != undefined ? bgneal@45: jQuery.grep(elem.className.split(/\s+/), function(className){ bgneal@45: return !jQuery.className.has( classNames, className ); bgneal@45: }).join(" ") : bgneal@45: ""; bgneal@45: }, bgneal@45: bgneal@45: // internal only, use hasClass("class") bgneal@45: has: function( elem, className ) { bgneal@45: return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: // A method for quickly swapping in/out CSS properties to get correct calculations bgneal@45: swap: function( elem, options, callback ) { bgneal@45: var old = {}; bgneal@45: // Remember the old values, and insert the new ones bgneal@45: for ( var name in options ) { bgneal@45: old[ name ] = elem.style[ name ]; bgneal@45: elem.style[ name ] = options[ name ]; bgneal@45: } bgneal@45: bgneal@45: callback.call( elem ); bgneal@45: bgneal@45: // Revert the old values bgneal@45: for ( var name in options ) bgneal@45: elem.style[ name ] = old[ name ]; bgneal@45: }, bgneal@45: bgneal@45: css: function( elem, name, force ) { bgneal@45: if ( name == "width" || name == "height" ) { bgneal@45: var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; bgneal@45: bgneal@45: function getWH() { bgneal@45: val = name == "width" ? elem.offsetWidth : elem.offsetHeight; bgneal@45: var padding = 0, border = 0; bgneal@45: jQuery.each( which, function() { bgneal@45: padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; bgneal@45: border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; bgneal@45: }); bgneal@45: val -= Math.round(padding + border); bgneal@45: } bgneal@45: bgneal@45: if ( jQuery(elem).is(":visible") ) bgneal@45: getWH(); bgneal@45: else bgneal@45: jQuery.swap( elem, props, getWH ); bgneal@45: bgneal@45: return Math.max(0, val); bgneal@45: } bgneal@45: bgneal@45: return jQuery.curCSS( elem, name, force ); bgneal@45: }, bgneal@45: bgneal@45: curCSS: function( elem, name, force ) { bgneal@45: var ret, style = elem.style; bgneal@45: bgneal@45: // A helper method for determining if an element's values are broken bgneal@45: function color( elem ) { bgneal@45: if ( !jQuery.browser.safari ) bgneal@45: return false; bgneal@45: bgneal@45: // defaultView is cached bgneal@45: var ret = defaultView.getComputedStyle( elem, null ); bgneal@45: return !ret || ret.getPropertyValue("color") == ""; bgneal@45: } bgneal@45: bgneal@45: // We need to handle opacity special in IE bgneal@45: if ( name == "opacity" && jQuery.browser.msie ) { bgneal@45: ret = jQuery.attr( style, "opacity" ); bgneal@45: bgneal@45: return ret == "" ? bgneal@45: "1" : bgneal@45: ret; bgneal@45: } bgneal@45: // Opera sometimes will give the wrong display answer, this fixes it, see #2037 bgneal@45: if ( jQuery.browser.opera && name == "display" ) { bgneal@45: var save = style.outline; bgneal@45: style.outline = "0 solid black"; bgneal@45: style.outline = save; bgneal@45: } bgneal@45: bgneal@45: // Make sure we're using the right name for getting the float value bgneal@45: if ( name.match( /float/i ) ) bgneal@45: name = styleFloat; bgneal@45: bgneal@45: if ( !force && style && style[ name ] ) bgneal@45: ret = style[ name ]; bgneal@45: bgneal@45: else if ( defaultView.getComputedStyle ) { bgneal@45: bgneal@45: // Only "float" is needed here bgneal@45: if ( name.match( /float/i ) ) bgneal@45: name = "float"; bgneal@45: bgneal@45: name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); bgneal@45: bgneal@45: var computedStyle = defaultView.getComputedStyle( elem, null ); bgneal@45: bgneal@45: if ( computedStyle && !color( elem ) ) bgneal@45: ret = computedStyle.getPropertyValue( name ); bgneal@45: bgneal@45: // If the element isn't reporting its values properly in Safari bgneal@45: // then some display: none elements are involved bgneal@45: else { bgneal@45: var swap = [], stack = [], a = elem, i = 0; bgneal@45: bgneal@45: // Locate all of the parent display: none elements bgneal@45: for ( ; a && color(a); a = a.parentNode ) bgneal@45: stack.unshift(a); bgneal@45: bgneal@45: // Go through and make them visible, but in reverse bgneal@45: // (It would be better if we knew the exact display type that they had) bgneal@45: for ( ; i < stack.length; i++ ) bgneal@45: if ( color( stack[ i ] ) ) { bgneal@45: swap[ i ] = stack[ i ].style.display; bgneal@45: stack[ i ].style.display = "block"; bgneal@45: } bgneal@45: bgneal@45: // Since we flip the display style, we have to handle that bgneal@45: // one special, otherwise get the value bgneal@45: ret = name == "display" && swap[ stack.length - 1 ] != null ? bgneal@45: "none" : bgneal@45: ( computedStyle && computedStyle.getPropertyValue( name ) ) || ""; bgneal@45: bgneal@45: // Finally, revert the display styles back bgneal@45: for ( i = 0; i < swap.length; i++ ) bgneal@45: if ( swap[ i ] != null ) bgneal@45: stack[ i ].style.display = swap[ i ]; bgneal@45: } bgneal@45: bgneal@45: // We should always get a number back from opacity bgneal@45: if ( name == "opacity" && ret == "" ) bgneal@45: ret = "1"; bgneal@45: bgneal@45: } else if ( elem.currentStyle ) { bgneal@45: var camelCase = name.replace(/\-(\w)/g, function(all, letter){ bgneal@45: return letter.toUpperCase(); bgneal@45: }); bgneal@45: bgneal@45: ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; bgneal@45: bgneal@45: // From the awesome hack by Dean Edwards bgneal@45: // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 bgneal@45: bgneal@45: // If we're not dealing with a regular pixel number bgneal@45: // but a number that has a weird ending, we need to convert it to pixels bgneal@45: if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { bgneal@45: // Remember the original values bgneal@45: var left = style.left, rsLeft = elem.runtimeStyle.left; bgneal@45: bgneal@45: // Put in the new values to get a computed value out bgneal@45: elem.runtimeStyle.left = elem.currentStyle.left; bgneal@45: style.left = ret || 0; bgneal@45: ret = style.pixelLeft + "px"; bgneal@45: bgneal@45: // Revert the changed values bgneal@45: style.left = left; bgneal@45: elem.runtimeStyle.left = rsLeft; bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: clean: function( elems, context ) { bgneal@45: var ret = []; bgneal@45: context = context || document; bgneal@45: // !context.createElement fails in IE with an error but returns typeof 'object' bgneal@45: if (typeof context.createElement == 'undefined') bgneal@45: context = context.ownerDocument || context[0] && context[0].ownerDocument || document; bgneal@45: bgneal@45: jQuery.each(elems, function(i, elem){ bgneal@45: if ( !elem ) bgneal@45: return; bgneal@45: bgneal@45: if ( elem.constructor == Number ) bgneal@45: elem += ''; bgneal@45: bgneal@45: // Convert html string into DOM nodes bgneal@45: if ( typeof elem == "string" ) { bgneal@45: // Fix "XHTML"-style tags in all browsers bgneal@45: elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ bgneal@45: return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? bgneal@45: all : bgneal@45: front + "></" + tag + ">"; bgneal@45: }); bgneal@45: bgneal@45: // Trim whitespace, otherwise indexOf won't work as expected bgneal@45: var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); bgneal@45: bgneal@45: var wrap = bgneal@45: // option or optgroup bgneal@45: !tags.indexOf("<opt") && bgneal@45: [ 1, "<select multiple='multiple'>", "</select>" ] || bgneal@45: bgneal@45: !tags.indexOf("<leg") && bgneal@45: [ 1, "<fieldset>", "</fieldset>" ] || bgneal@45: bgneal@45: tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && bgneal@45: [ 1, "<table>", "</table>" ] || bgneal@45: bgneal@45: !tags.indexOf("<tr") && bgneal@45: [ 2, "<table><tbody>", "</tbody></table>" ] || bgneal@45: bgneal@45: // <thead> matched above bgneal@45: (!tags.indexOf("<td") || !tags.indexOf("<th")) && bgneal@45: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] || bgneal@45: bgneal@45: !tags.indexOf("<col") && bgneal@45: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] || bgneal@45: bgneal@45: // IE can't serialize <link> and <script> tags normally bgneal@45: jQuery.browser.msie && bgneal@45: [ 1, "div<div>", "</div>" ] || bgneal@45: bgneal@45: [ 0, "", "" ]; bgneal@45: bgneal@45: // Go to html and back, then peel off extra wrappers bgneal@45: div.innerHTML = wrap[1] + elem + wrap[2]; bgneal@45: bgneal@45: // Move to the right depth bgneal@45: while ( wrap[0]-- ) bgneal@45: div = div.lastChild; bgneal@45: bgneal@45: // Remove IE's autoinserted <tbody> from table fragments bgneal@45: if ( jQuery.browser.msie ) { bgneal@45: bgneal@45: // String was a <table>, *may* have spurious <tbody> bgneal@45: var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ? bgneal@45: div.firstChild && div.firstChild.childNodes : bgneal@45: bgneal@45: // String was a bare <thead> or <tfoot> bgneal@45: wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ? bgneal@45: div.childNodes : bgneal@45: []; bgneal@45: bgneal@45: for ( var j = tbody.length - 1; j >= 0 ; --j ) bgneal@45: if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) bgneal@45: tbody[ j ].parentNode.removeChild( tbody[ j ] ); bgneal@45: bgneal@45: // IE completely kills leading whitespace when innerHTML is used bgneal@45: if ( /^\s/.test( elem ) ) bgneal@45: div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild ); bgneal@45: bgneal@45: } bgneal@45: bgneal@45: elem = jQuery.makeArray( div.childNodes ); bgneal@45: } bgneal@45: bgneal@45: if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) ) bgneal@45: return; bgneal@45: bgneal@45: if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options ) bgneal@45: ret.push( elem ); bgneal@45: bgneal@45: else bgneal@45: ret = jQuery.merge( ret, elem ); bgneal@45: bgneal@45: }); bgneal@45: bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: attr: function( elem, name, value ) { bgneal@45: // don't set attributes on text and comment nodes bgneal@45: if (!elem || elem.nodeType == 3 || elem.nodeType == 8) bgneal@45: return undefined; bgneal@45: bgneal@45: var notxml = !jQuery.isXMLDoc( elem ), bgneal@45: // Whether we are setting (or getting) bgneal@45: set = value !== undefined, bgneal@45: msie = jQuery.browser.msie; bgneal@45: bgneal@45: // Try to normalize/fix the name bgneal@45: name = notxml && jQuery.props[ name ] || name; bgneal@45: bgneal@45: // Only do all the following if this is a node (faster for style) bgneal@45: // IE elem.getAttribute passes even for style bgneal@45: if ( elem.tagName ) { bgneal@45: bgneal@45: // These attributes require special treatment bgneal@45: var special = /href|src|style/.test( name ); bgneal@45: bgneal@45: // Safari mis-reports the default selected property of a hidden option bgneal@45: // Accessing the parent's selectedIndex property fixes it bgneal@45: if ( name == "selected" && jQuery.browser.safari ) bgneal@45: elem.parentNode.selectedIndex; bgneal@45: bgneal@45: // If applicable, access the attribute via the DOM 0 way bgneal@45: if ( name in elem && notxml && !special ) { bgneal@45: if ( set ){ bgneal@45: // We can't allow the type property to be changed (since it causes problems in IE) bgneal@45: if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode ) bgneal@45: throw "type property can't be changed"; bgneal@45: bgneal@45: elem[ name ] = value; bgneal@45: } bgneal@45: bgneal@45: // browsers index elements by id/name on forms, give priority to attributes. bgneal@45: if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) bgneal@45: return elem.getAttributeNode( name ).nodeValue; bgneal@45: bgneal@45: return elem[ name ]; bgneal@45: } bgneal@45: bgneal@45: if ( msie && notxml && name == "style" ) bgneal@45: return jQuery.attr( elem.style, "cssText", value ); bgneal@45: bgneal@45: if ( set ) bgneal@45: // convert the value to a string (all browsers do this but IE) see #1070 bgneal@45: elem.setAttribute( name, "" + value ); bgneal@45: bgneal@45: var attr = msie && notxml && special bgneal@45: // Some attributes require a special call on IE bgneal@45: ? elem.getAttribute( name, 2 ) bgneal@45: : elem.getAttribute( name ); bgneal@45: bgneal@45: // Non-existent attributes return null, we normalize to undefined bgneal@45: return attr === null ? undefined : attr; bgneal@45: } bgneal@45: bgneal@45: // elem is actually elem.style ... set the style bgneal@45: bgneal@45: // IE uses filters for opacity bgneal@45: if ( msie && name == "opacity" ) { bgneal@45: if ( set ) { bgneal@45: // IE has trouble with opacity if it does not have layout bgneal@45: // Force it by setting the zoom level bgneal@45: elem.zoom = 1; bgneal@45: bgneal@45: // Set the alpha filter to set the opacity bgneal@45: elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) + bgneal@45: (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")"); bgneal@45: } bgneal@45: bgneal@45: return elem.filter && elem.filter.indexOf("opacity=") >= 0 ? bgneal@45: (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '': bgneal@45: ""; bgneal@45: } bgneal@45: bgneal@45: name = name.replace(/-([a-z])/ig, function(all, letter){ bgneal@45: return letter.toUpperCase(); bgneal@45: }); bgneal@45: bgneal@45: if ( set ) bgneal@45: elem[ name ] = value; bgneal@45: bgneal@45: return elem[ name ]; bgneal@45: }, bgneal@45: bgneal@45: trim: function( text ) { bgneal@45: return (text || "").replace( /^\s+|\s+$/g, "" ); bgneal@45: }, bgneal@45: bgneal@45: makeArray: function( array ) { bgneal@45: var ret = []; bgneal@45: bgneal@45: if( array != null ){ bgneal@45: var i = array.length; bgneal@45: //the window, strings and functions also have 'length' bgneal@45: if( i == null || array.split || array.setInterval || array.call ) bgneal@45: ret[0] = array; bgneal@45: else bgneal@45: while( i ) bgneal@45: ret[--i] = array[i]; bgneal@45: } bgneal@45: bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: inArray: function( elem, array ) { bgneal@45: for ( var i = 0, length = array.length; i < length; i++ ) bgneal@45: // Use === because on IE, window == document bgneal@45: if ( array[ i ] === elem ) bgneal@45: return i; bgneal@45: bgneal@45: return -1; bgneal@45: }, bgneal@45: bgneal@45: merge: function( first, second ) { bgneal@45: // We have to loop this way because IE & Opera overwrite the length bgneal@45: // expando of getElementsByTagName bgneal@45: var i = 0, elem, pos = first.length; bgneal@45: // Also, we need to make sure that the correct elements are being returned bgneal@45: // (IE returns comment nodes in a '*' query) bgneal@45: if ( jQuery.browser.msie ) { bgneal@45: while ( elem = second[ i++ ] ) bgneal@45: if ( elem.nodeType != 8 ) bgneal@45: first[ pos++ ] = elem; bgneal@45: bgneal@45: } else bgneal@45: while ( elem = second[ i++ ] ) bgneal@45: first[ pos++ ] = elem; bgneal@45: bgneal@45: return first; bgneal@45: }, bgneal@45: bgneal@45: unique: function( array ) { bgneal@45: var ret = [], done = {}; bgneal@45: bgneal@45: try { bgneal@45: bgneal@45: for ( var i = 0, length = array.length; i < length; i++ ) { bgneal@45: var id = jQuery.data( array[ i ] ); bgneal@45: bgneal@45: if ( !done[ id ] ) { bgneal@45: done[ id ] = true; bgneal@45: ret.push( array[ i ] ); bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: } catch( e ) { bgneal@45: ret = array; bgneal@45: } bgneal@45: bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: grep: function( elems, callback, inv ) { bgneal@45: var ret = []; bgneal@45: bgneal@45: // Go through the array, only saving the items bgneal@45: // that pass the validator function bgneal@45: for ( var i = 0, length = elems.length; i < length; i++ ) bgneal@45: if ( !inv != !callback( elems[ i ], i ) ) bgneal@45: ret.push( elems[ i ] ); bgneal@45: bgneal@45: return ret; bgneal@45: }, bgneal@45: bgneal@45: map: function( elems, callback ) { bgneal@45: var ret = []; bgneal@45: bgneal@45: // Go through the array, translating each of the items to their bgneal@45: // new value (or values). bgneal@45: for ( var i = 0, length = elems.length; i < length; i++ ) { bgneal@45: var value = callback( elems[ i ], i ); bgneal@45: bgneal@45: if ( value != null ) bgneal@45: ret[ ret.length ] = value; bgneal@45: } bgneal@45: bgneal@45: return ret.concat.apply( [], ret ); bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: var userAgent = navigator.userAgent.toLowerCase(); bgneal@45: bgneal@45: // Figure out what browser is being used bgneal@45: jQuery.browser = { bgneal@45: version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1], bgneal@45: safari: /webkit/.test( userAgent ), bgneal@45: opera: /opera/.test( userAgent ), bgneal@45: msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), bgneal@45: mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) bgneal@45: }; bgneal@45: bgneal@45: var styleFloat = jQuery.browser.msie ? bgneal@45: "styleFloat" : bgneal@45: "cssFloat"; bgneal@45: bgneal@45: jQuery.extend({ bgneal@45: // Check to see if the W3C box model is being used bgneal@45: boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat", bgneal@45: bgneal@45: props: { bgneal@45: "for": "htmlFor", bgneal@45: "class": "className", bgneal@45: "float": styleFloat, bgneal@45: cssFloat: styleFloat, bgneal@45: styleFloat: styleFloat, bgneal@45: readonly: "readOnly", bgneal@45: maxlength: "maxLength", bgneal@45: cellspacing: "cellSpacing", bgneal@45: rowspan: "rowSpan" bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: jQuery.each({ bgneal@45: parent: function(elem){return elem.parentNode;}, bgneal@45: parents: function(elem){return jQuery.dir(elem,"parentNode");}, bgneal@45: next: function(elem){return jQuery.nth(elem,2,"nextSibling");}, bgneal@45: prev: function(elem){return jQuery.nth(elem,2,"previousSibling");}, bgneal@45: nextAll: function(elem){return jQuery.dir(elem,"nextSibling");}, bgneal@45: prevAll: function(elem){return jQuery.dir(elem,"previousSibling");}, bgneal@45: siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);}, bgneal@45: children: function(elem){return jQuery.sibling(elem.firstChild);}, bgneal@45: contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);} bgneal@45: }, function(name, fn){ bgneal@45: jQuery.fn[ name ] = function( selector ) { bgneal@45: var ret = jQuery.map( this, fn ); bgneal@45: bgneal@45: if ( selector && typeof selector == "string" ) bgneal@45: ret = jQuery.multiFilter( selector, ret ); bgneal@45: bgneal@45: return this.pushStack( jQuery.unique( ret ) ); bgneal@45: }; bgneal@45: }); bgneal@45: bgneal@45: jQuery.each({ bgneal@45: appendTo: "append", bgneal@45: prependTo: "prepend", bgneal@45: insertBefore: "before", bgneal@45: insertAfter: "after", bgneal@45: replaceAll: "replaceWith" bgneal@45: }, function(name, original){ bgneal@45: jQuery.fn[ name ] = function() { bgneal@45: var args = arguments; bgneal@45: bgneal@45: return this.each(function(){ bgneal@45: for ( var i = 0, length = args.length; i < length; i++ ) bgneal@45: jQuery( args[ i ] )[ original ]( this ); bgneal@45: }); bgneal@45: }; bgneal@45: }); bgneal@45: bgneal@45: jQuery.each({ bgneal@45: removeAttr: function( name ) { bgneal@45: jQuery.attr( this, name, "" ); bgneal@45: if (this.nodeType == 1) bgneal@45: this.removeAttribute( name ); bgneal@45: }, bgneal@45: bgneal@45: addClass: function( classNames ) { bgneal@45: jQuery.className.add( this, classNames ); bgneal@45: }, bgneal@45: bgneal@45: removeClass: function( classNames ) { bgneal@45: jQuery.className.remove( this, classNames ); bgneal@45: }, bgneal@45: bgneal@45: toggleClass: function( classNames ) { bgneal@45: jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames ); bgneal@45: }, bgneal@45: bgneal@45: remove: function( selector ) { bgneal@45: if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) { bgneal@45: // Prevent memory leaks bgneal@45: jQuery( "*", this ).add(this).each(function(){ bgneal@45: jQuery.event.remove(this); bgneal@45: jQuery.removeData(this); bgneal@45: }); bgneal@45: if (this.parentNode) bgneal@45: this.parentNode.removeChild( this ); bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: empty: function() { bgneal@45: // Remove element nodes and prevent memory leaks bgneal@45: jQuery( ">*", this ).remove(); bgneal@45: bgneal@45: // Remove any remaining nodes bgneal@45: while ( this.firstChild ) bgneal@45: this.removeChild( this.firstChild ); bgneal@45: } bgneal@45: }, function(name, fn){ bgneal@45: jQuery.fn[ name ] = function(){ bgneal@45: return this.each( fn, arguments ); bgneal@45: }; bgneal@45: }); bgneal@45: bgneal@45: jQuery.each([ "Height", "Width" ], function(i, name){ bgneal@45: var type = name.toLowerCase(); bgneal@45: bgneal@45: jQuery.fn[ type ] = function( size ) { bgneal@45: // Get window width or height bgneal@45: return this[0] == window ? bgneal@45: // Opera reports document.body.client[Width/Height] properly in both quirks and standards bgneal@45: jQuery.browser.opera && document.body[ "client" + name ] || bgneal@45: bgneal@45: // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths) bgneal@45: jQuery.browser.safari && window[ "inner" + name ] || bgneal@45: bgneal@45: // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode bgneal@45: document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] : bgneal@45: bgneal@45: // Get document width or height bgneal@45: this[0] == document ? bgneal@45: // Either scroll[Width/Height] or offset[Width/Height], whichever is greater bgneal@45: Math.max( bgneal@45: Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), bgneal@45: Math.max(document.body["offset" + name], document.documentElement["offset" + name]) bgneal@45: ) : bgneal@45: bgneal@45: // Get or set width or height on the element bgneal@45: size == undefined ? bgneal@45: // Get width or height on the element bgneal@45: (this.length ? jQuery.css( this[0], type ) : null) : bgneal@45: bgneal@45: // Set the width or height on the element (default to pixels if value is unitless) bgneal@45: this.css( type, size.constructor == String ? size : size + "px" ); bgneal@45: }; bgneal@45: }); bgneal@45: bgneal@45: // Helper function used by the dimensions and offset modules bgneal@45: function num(elem, prop) { bgneal@45: return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0; bgneal@45: }var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ? bgneal@45: "(?:[\\w*_-]|\\\\.)" : bgneal@45: "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)", bgneal@45: quickChild = new RegExp("^>\\s*(" + chars + "+)"), bgneal@45: quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"), bgneal@45: quickClass = new RegExp("^([#.]?)(" + chars + "*)"); bgneal@45: bgneal@45: jQuery.extend({ bgneal@45: expr: { bgneal@45: "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);}, bgneal@45: "#": function(a,i,m){return a.getAttribute("id")==m[2];}, bgneal@45: ":": { bgneal@45: // Position Checks bgneal@45: lt: function(a,i,m){return i<m[3]-0;}, bgneal@45: gt: function(a,i,m){return i>m[3]-0;}, bgneal@45: nth: function(a,i,m){return m[3]-0==i;}, bgneal@45: eq: function(a,i,m){return m[3]-0==i;}, bgneal@45: first: function(a,i){return i==0;}, bgneal@45: last: function(a,i,m,r){return i==r.length-1;}, bgneal@45: even: function(a,i){return i%2==0;}, bgneal@45: odd: function(a,i){return i%2;}, bgneal@45: bgneal@45: // Child Checks bgneal@45: "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;}, bgneal@45: "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;}, bgneal@45: "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");}, bgneal@45: bgneal@45: // Parent Checks bgneal@45: parent: function(a){return a.firstChild;}, bgneal@45: empty: function(a){return !a.firstChild;}, bgneal@45: bgneal@45: // Text Check bgneal@45: contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;}, bgneal@45: bgneal@45: // Visibility bgneal@45: visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";}, bgneal@45: hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";}, bgneal@45: bgneal@45: // Form attributes bgneal@45: enabled: function(a){return !a.disabled;}, bgneal@45: disabled: function(a){return a.disabled;}, bgneal@45: checked: function(a){return a.checked;}, bgneal@45: selected: function(a){return a.selected||jQuery.attr(a,"selected");}, bgneal@45: bgneal@45: // Form elements bgneal@45: text: function(a){return "text"==a.type;}, bgneal@45: radio: function(a){return "radio"==a.type;}, bgneal@45: checkbox: function(a){return "checkbox"==a.type;}, bgneal@45: file: function(a){return "file"==a.type;}, bgneal@45: password: function(a){return "password"==a.type;}, bgneal@45: submit: function(a){return "submit"==a.type;}, bgneal@45: image: function(a){return "image"==a.type;}, bgneal@45: reset: function(a){return "reset"==a.type;}, bgneal@45: button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");}, bgneal@45: input: function(a){return /input|select|textarea|button/i.test(a.nodeName);}, bgneal@45: bgneal@45: // :has() bgneal@45: has: function(a,i,m){return jQuery.find(m[3],a).length;}, bgneal@45: bgneal@45: // :header bgneal@45: header: function(a){return /h\d/i.test(a.nodeName);}, bgneal@45: bgneal@45: // :animated bgneal@45: animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;} bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: // The regular expressions that power the parsing engine bgneal@45: parse: [ bgneal@45: // Match: [@value='test'], [@foo] bgneal@45: /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/, bgneal@45: bgneal@45: // Match: :contains('foo') bgneal@45: /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/, bgneal@45: bgneal@45: // Match: :even, :last-child, #id, .class bgneal@45: new RegExp("^([:.#]*)(" + chars + "+)") bgneal@45: ], bgneal@45: bgneal@45: multiFilter: function( expr, elems, not ) { bgneal@45: var old, cur = []; bgneal@45: bgneal@45: while ( expr && expr != old ) { bgneal@45: old = expr; bgneal@45: var f = jQuery.filter( expr, elems, not ); bgneal@45: expr = f.t.replace(/^\s*,\s*/, "" ); bgneal@45: cur = not ? elems = f.r : jQuery.merge( cur, f.r ); bgneal@45: } bgneal@45: bgneal@45: return cur; bgneal@45: }, bgneal@45: bgneal@45: find: function( t, context ) { bgneal@45: // Quickly handle non-string expressions bgneal@45: if ( typeof t != "string" ) bgneal@45: return [ t ]; bgneal@45: bgneal@45: // check to make sure context is a DOM element or a document bgneal@45: if ( context && context.nodeType != 1 && context.nodeType != 9) bgneal@45: return [ ]; bgneal@45: bgneal@45: // Set the correct context (if none is provided) bgneal@45: context = context || document; bgneal@45: bgneal@45: // Initialize the search bgneal@45: var ret = [context], done = [], last, nodeName; bgneal@45: bgneal@45: // Continue while a selector expression exists, and while bgneal@45: // we're no longer looping upon ourselves bgneal@45: while ( t && last != t ) { bgneal@45: var r = []; bgneal@45: last = t; bgneal@45: bgneal@45: t = jQuery.trim(t); bgneal@45: bgneal@45: var foundToken = false, bgneal@45: bgneal@45: // An attempt at speeding up child selectors that bgneal@45: // point to a specific element tag bgneal@45: re = quickChild, bgneal@45: bgneal@45: m = re.exec(t); bgneal@45: bgneal@45: if ( m ) { bgneal@45: nodeName = m[1].toUpperCase(); bgneal@45: bgneal@45: // Perform our own iteration and filter bgneal@45: for ( var i = 0; ret[i]; i++ ) bgneal@45: for ( var c = ret[i].firstChild; c; c = c.nextSibling ) bgneal@45: if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) ) bgneal@45: r.push( c ); bgneal@45: bgneal@45: ret = r; bgneal@45: t = t.replace( re, "" ); bgneal@45: if ( t.indexOf(" ") == 0 ) continue; bgneal@45: foundToken = true; bgneal@45: } else { bgneal@45: re = /^([>+~])\s*(\w*)/i; bgneal@45: bgneal@45: if ( (m = re.exec(t)) != null ) { bgneal@45: r = []; bgneal@45: bgneal@45: var merge = {}; bgneal@45: nodeName = m[2].toUpperCase(); bgneal@45: m = m[1]; bgneal@45: bgneal@45: for ( var j = 0, rl = ret.length; j < rl; j++ ) { bgneal@45: var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild; bgneal@45: for ( ; n; n = n.nextSibling ) bgneal@45: if ( n.nodeType == 1 ) { bgneal@45: var id = jQuery.data(n); bgneal@45: bgneal@45: if ( m == "~" && merge[id] ) break; bgneal@45: bgneal@45: if (!nodeName || n.nodeName.toUpperCase() == nodeName ) { bgneal@45: if ( m == "~" ) merge[id] = true; bgneal@45: r.push( n ); bgneal@45: } bgneal@45: bgneal@45: if ( m == "+" ) break; bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: ret = r; bgneal@45: bgneal@45: // And remove the token bgneal@45: t = jQuery.trim( t.replace( re, "" ) ); bgneal@45: foundToken = true; bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: // See if there's still an expression, and that we haven't already bgneal@45: // matched a token bgneal@45: if ( t && !foundToken ) { bgneal@45: // Handle multiple expressions bgneal@45: if ( !t.indexOf(",") ) { bgneal@45: // Clean the result set bgneal@45: if ( context == ret[0] ) ret.shift(); bgneal@45: bgneal@45: // Merge the result sets bgneal@45: done = jQuery.merge( done, ret ); bgneal@45: bgneal@45: // Reset the context bgneal@45: r = ret = [context]; bgneal@45: bgneal@45: // Touch up the selector string bgneal@45: t = " " + t.substr(1,t.length); bgneal@45: bgneal@45: } else { bgneal@45: // Optimize for the case nodeName#idName bgneal@45: var re2 = quickID; bgneal@45: var m = re2.exec(t); bgneal@45: bgneal@45: // Re-organize the results, so that they're consistent bgneal@45: if ( m ) { bgneal@45: m = [ 0, m[2], m[3], m[1] ]; bgneal@45: bgneal@45: } else { bgneal@45: // Otherwise, do a traditional filter check for bgneal@45: // ID, class, and element selectors bgneal@45: re2 = quickClass; bgneal@45: m = re2.exec(t); bgneal@45: } bgneal@45: bgneal@45: m[2] = m[2].replace(/\\/g, ""); bgneal@45: bgneal@45: var elem = ret[ret.length-1]; bgneal@45: bgneal@45: // Try to do a global search by ID, where we can bgneal@45: if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) { bgneal@45: // Optimization for HTML document case bgneal@45: var oid = elem.getElementById(m[2]); bgneal@45: bgneal@45: // Do a quick check for the existence of the actual ID attribute bgneal@45: // to avoid selecting by the name attribute in IE bgneal@45: // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form bgneal@45: if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] ) bgneal@45: oid = jQuery('[@id="'+m[2]+'"]', elem)[0]; bgneal@45: bgneal@45: // Do a quick check for node name (where applicable) so bgneal@45: // that div#foo searches will be really fast bgneal@45: ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : []; bgneal@45: } else { bgneal@45: // We need to find all descendant elements bgneal@45: for ( var i = 0; ret[i]; i++ ) { bgneal@45: // Grab the tag name being searched for bgneal@45: var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2]; bgneal@45: bgneal@45: // Handle IE7 being really dumb about <object>s bgneal@45: if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" ) bgneal@45: tag = "param"; bgneal@45: bgneal@45: r = jQuery.merge( r, ret[i].getElementsByTagName( tag )); bgneal@45: } bgneal@45: bgneal@45: // It's faster to filter by class and be done with it bgneal@45: if ( m[1] == "." ) bgneal@45: r = jQuery.classFilter( r, m[2] ); bgneal@45: bgneal@45: // Same with ID filtering bgneal@45: if ( m[1] == "#" ) { bgneal@45: var tmp = []; bgneal@45: bgneal@45: // Try to find the element with the ID bgneal@45: for ( var i = 0; r[i]; i++ ) bgneal@45: if ( r[i].getAttribute("id") == m[2] ) { bgneal@45: tmp = [ r[i] ]; bgneal@45: break; bgneal@45: } bgneal@45: bgneal@45: r = tmp; bgneal@45: } bgneal@45: bgneal@45: ret = r; bgneal@45: } bgneal@45: bgneal@45: t = t.replace( re2, "" ); bgneal@45: } bgneal@45: bgneal@45: } bgneal@45: bgneal@45: // If a selector string still exists bgneal@45: if ( t ) { bgneal@45: // Attempt to filter it bgneal@45: var val = jQuery.filter(t,r); bgneal@45: ret = r = val.r; bgneal@45: t = jQuery.trim(val.t); bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: // An error occurred with the selector; bgneal@45: // just return an empty set instead bgneal@45: if ( t ) bgneal@45: ret = []; bgneal@45: bgneal@45: // Remove the root context bgneal@45: if ( ret && context == ret[0] ) bgneal@45: ret.shift(); bgneal@45: bgneal@45: // And combine the results bgneal@45: done = jQuery.merge( done, ret ); bgneal@45: bgneal@45: return done; bgneal@45: }, bgneal@45: bgneal@45: classFilter: function(r,m,not){ bgneal@45: m = " " + m + " "; bgneal@45: var tmp = []; bgneal@45: for ( var i = 0; r[i]; i++ ) { bgneal@45: var pass = (" " + r[i].className + " ").indexOf( m ) >= 0; bgneal@45: if ( !not && pass || not && !pass ) bgneal@45: tmp.push( r[i] ); bgneal@45: } bgneal@45: return tmp; bgneal@45: }, bgneal@45: bgneal@45: filter: function(t,r,not) { bgneal@45: var last; bgneal@45: bgneal@45: // Look for common filter expressions bgneal@45: while ( t && t != last ) { bgneal@45: last = t; bgneal@45: bgneal@45: var p = jQuery.parse, m; bgneal@45: bgneal@45: for ( var i = 0; p[i]; i++ ) { bgneal@45: m = p[i].exec( t ); bgneal@45: bgneal@45: if ( m ) { bgneal@45: // Remove what we just matched bgneal@45: t = t.substring( m[0].length ); bgneal@45: bgneal@45: m[2] = m[2].replace(/\\/g, ""); bgneal@45: break; bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: if ( !m ) bgneal@45: break; bgneal@45: bgneal@45: // :not() is a special case that can be optimized by bgneal@45: // keeping it out of the expression list bgneal@45: if ( m[1] == ":" && m[2] == "not" ) bgneal@45: // optimize if only one selector found (most common case) bgneal@45: r = isSimple.test( m[3] ) ? bgneal@45: jQuery.filter(m[3], r, true).r : bgneal@45: jQuery( r ).not( m[3] ); bgneal@45: bgneal@45: // We can get a big speed boost by filtering by class here bgneal@45: else if ( m[1] == "." ) bgneal@45: r = jQuery.classFilter(r, m[2], not); bgneal@45: bgneal@45: else if ( m[1] == "[" ) { bgneal@45: var tmp = [], type = m[3]; bgneal@45: bgneal@45: for ( var i = 0, rl = r.length; i < rl; i++ ) { bgneal@45: var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ]; bgneal@45: bgneal@45: if ( z == null || /href|src|selected/.test(m[2]) ) bgneal@45: z = jQuery.attr(a,m[2]) || ''; bgneal@45: bgneal@45: if ( (type == "" && !!z || bgneal@45: type == "=" && z == m[5] || bgneal@45: type == "!=" && z != m[5] || bgneal@45: type == "^=" && z && !z.indexOf(m[5]) || bgneal@45: type == "$=" && z.substr(z.length - m[5].length) == m[5] || bgneal@45: (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not ) bgneal@45: tmp.push( a ); bgneal@45: } bgneal@45: bgneal@45: r = tmp; bgneal@45: bgneal@45: // We can get a speed boost by handling nth-child here bgneal@45: } else if ( m[1] == ":" && m[2] == "nth-child" ) { bgneal@45: var merge = {}, tmp = [], bgneal@45: // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' bgneal@45: test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( bgneal@45: m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" || bgneal@45: !/\D/.test(m[3]) && "0n+" + m[3] || m[3]), bgneal@45: // calculate the numbers (first)n+(last) including if they are negative bgneal@45: first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0; bgneal@45: bgneal@45: // loop through all the elements left in the jQuery object bgneal@45: for ( var i = 0, rl = r.length; i < rl; i++ ) { bgneal@45: var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode); bgneal@45: bgneal@45: if ( !merge[id] ) { bgneal@45: var c = 1; bgneal@45: bgneal@45: for ( var n = parentNode.firstChild; n; n = n.nextSibling ) bgneal@45: if ( n.nodeType == 1 ) bgneal@45: n.nodeIndex = c++; bgneal@45: bgneal@45: merge[id] = true; bgneal@45: } bgneal@45: bgneal@45: var add = false; bgneal@45: bgneal@45: if ( first == 0 ) { bgneal@45: if ( node.nodeIndex == last ) bgneal@45: add = true; bgneal@45: } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 ) bgneal@45: add = true; bgneal@45: bgneal@45: if ( add ^ not ) bgneal@45: tmp.push( node ); bgneal@45: } bgneal@45: bgneal@45: r = tmp; bgneal@45: bgneal@45: // Otherwise, find the expression to execute bgneal@45: } else { bgneal@45: var fn = jQuery.expr[ m[1] ]; bgneal@45: if ( typeof fn == "object" ) bgneal@45: fn = fn[ m[2] ]; bgneal@45: bgneal@45: if ( typeof fn == "string" ) bgneal@45: fn = eval("false||function(a,i){return " + fn + ";}"); bgneal@45: bgneal@45: // Execute it against the current filter bgneal@45: r = jQuery.grep( r, function(elem, i){ bgneal@45: return fn(elem, i, m, r); bgneal@45: }, not ); bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: // Return an array of filtered elements (r) bgneal@45: // and the modified expression string (t) bgneal@45: return { r: r, t: t }; bgneal@45: }, bgneal@45: bgneal@45: dir: function( elem, dir ){ bgneal@45: var matched = [], bgneal@45: cur = elem[dir]; bgneal@45: while ( cur && cur != document ) { bgneal@45: if ( cur.nodeType == 1 ) bgneal@45: matched.push( cur ); bgneal@45: cur = cur[dir]; bgneal@45: } bgneal@45: return matched; bgneal@45: }, bgneal@45: bgneal@45: nth: function(cur,result,dir,elem){ bgneal@45: result = result || 1; bgneal@45: var num = 0; bgneal@45: bgneal@45: for ( ; cur; cur = cur[dir] ) bgneal@45: if ( cur.nodeType == 1 && ++num == result ) bgneal@45: break; bgneal@45: bgneal@45: return cur; bgneal@45: }, bgneal@45: bgneal@45: sibling: function( n, elem ) { bgneal@45: var r = []; bgneal@45: bgneal@45: for ( ; n; n = n.nextSibling ) { bgneal@45: if ( n.nodeType == 1 && n != elem ) bgneal@45: r.push( n ); bgneal@45: } bgneal@45: bgneal@45: return r; bgneal@45: } bgneal@45: }); bgneal@45: /* bgneal@45: * A number of helper functions used for managing events. bgneal@45: * Many of the ideas behind this code orignated from bgneal@45: * Dean Edwards' addEvent library. bgneal@45: */ bgneal@45: jQuery.event = { bgneal@45: bgneal@45: // Bind an event to an element bgneal@45: // Original by Dean Edwards bgneal@45: add: function(elem, types, handler, data) { bgneal@45: if ( elem.nodeType == 3 || elem.nodeType == 8 ) bgneal@45: return; bgneal@45: bgneal@45: // For whatever reason, IE has trouble passing the window object bgneal@45: // around, causing it to be cloned in the process bgneal@45: if ( jQuery.browser.msie && elem.setInterval ) bgneal@45: elem = window; bgneal@45: bgneal@45: // Make sure that the function being executed has a unique ID bgneal@45: if ( !handler.guid ) bgneal@45: handler.guid = this.guid++; bgneal@45: bgneal@45: // if data is passed, bind to handler bgneal@45: if( data != undefined ) { bgneal@45: // Create temporary function pointer to original handler bgneal@45: var fn = handler; bgneal@45: bgneal@45: // Create unique handler function, wrapped around original handler bgneal@45: handler = this.proxy( fn, function() { bgneal@45: // Pass arguments and context to original handler bgneal@45: return fn.apply(this, arguments); bgneal@45: }); bgneal@45: bgneal@45: // Store data in unique handler bgneal@45: handler.data = data; bgneal@45: } bgneal@45: bgneal@45: // Init the element's event structure bgneal@45: var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}), bgneal@45: handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){ bgneal@45: // Handle the second event of a trigger and when bgneal@45: // an event is called after a page has unloaded bgneal@45: if ( typeof jQuery != "undefined" && !jQuery.event.triggered ) bgneal@45: return jQuery.event.handle.apply(arguments.callee.elem, arguments); bgneal@45: }); bgneal@45: // Add elem as a property of the handle function bgneal@45: // This is to prevent a memory leak with non-native bgneal@45: // event in IE. bgneal@45: handle.elem = elem; bgneal@45: bgneal@45: // Handle multiple events separated by a space bgneal@45: // jQuery(...).bind("mouseover mouseout", fn); bgneal@45: jQuery.each(types.split(/\s+/), function(index, type) { bgneal@45: // Namespaced event handlers bgneal@45: var parts = type.split("."); bgneal@45: type = parts[0]; bgneal@45: handler.type = parts[1]; bgneal@45: bgneal@45: // Get the current list of functions bound to this event bgneal@45: var handlers = events[type]; bgneal@45: bgneal@45: // Init the event handler queue bgneal@45: if (!handlers) { bgneal@45: handlers = events[type] = {}; bgneal@45: bgneal@45: // Check for a special event handler bgneal@45: // Only use addEventListener/attachEvent if the special bgneal@45: // events handler returns false bgneal@45: if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) { bgneal@45: // Bind the global event handler to the element bgneal@45: if (elem.addEventListener) bgneal@45: elem.addEventListener(type, handle, false); bgneal@45: else if (elem.attachEvent) bgneal@45: elem.attachEvent("on" + type, handle); bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: // Add the function to the element's handler list bgneal@45: handlers[handler.guid] = handler; bgneal@45: bgneal@45: // Keep track of which events have been used, for global triggering bgneal@45: jQuery.event.global[type] = true; bgneal@45: }); bgneal@45: bgneal@45: // Nullify elem to prevent memory leaks in IE bgneal@45: elem = null; bgneal@45: }, bgneal@45: bgneal@45: guid: 1, bgneal@45: global: {}, bgneal@45: bgneal@45: // Detach an event or set of events from an element bgneal@45: remove: function(elem, types, handler) { bgneal@45: // don't do events on text and comment nodes bgneal@45: if ( elem.nodeType == 3 || elem.nodeType == 8 ) bgneal@45: return; bgneal@45: bgneal@45: var events = jQuery.data(elem, "events"), ret, index; bgneal@45: bgneal@45: if ( events ) { bgneal@45: // Unbind all events for the element bgneal@45: if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") ) bgneal@45: for ( var type in events ) bgneal@45: this.remove( elem, type + (types || "") ); bgneal@45: else { bgneal@45: // types is actually an event object here bgneal@45: if ( types.type ) { bgneal@45: handler = types.handler; bgneal@45: types = types.type; bgneal@45: } bgneal@45: bgneal@45: // Handle multiple events seperated by a space bgneal@45: // jQuery(...).unbind("mouseover mouseout", fn); bgneal@45: jQuery.each(types.split(/\s+/), function(index, type){ bgneal@45: // Namespaced event handlers bgneal@45: var parts = type.split("."); bgneal@45: type = parts[0]; bgneal@45: bgneal@45: if ( events[type] ) { bgneal@45: // remove the given handler for the given type bgneal@45: if ( handler ) bgneal@45: delete events[type][handler.guid]; bgneal@45: bgneal@45: // remove all handlers for the given type bgneal@45: else bgneal@45: for ( handler in events[type] ) bgneal@45: // Handle the removal of namespaced events bgneal@45: if ( !parts[1] || events[type][handler].type == parts[1] ) bgneal@45: delete events[type][handler]; bgneal@45: bgneal@45: // remove generic event handler if no more handlers exist bgneal@45: for ( ret in events[type] ) break; bgneal@45: if ( !ret ) { bgneal@45: if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) { bgneal@45: if (elem.removeEventListener) bgneal@45: elem.removeEventListener(type, jQuery.data(elem, "handle"), false); bgneal@45: else if (elem.detachEvent) bgneal@45: elem.detachEvent("on" + type, jQuery.data(elem, "handle")); bgneal@45: } bgneal@45: ret = null; bgneal@45: delete events[type]; bgneal@45: } bgneal@45: } bgneal@45: }); bgneal@45: } bgneal@45: bgneal@45: // Remove the expando if it's no longer used bgneal@45: for ( ret in events ) break; bgneal@45: if ( !ret ) { bgneal@45: var handle = jQuery.data( elem, "handle" ); bgneal@45: if ( handle ) handle.elem = null; bgneal@45: jQuery.removeData( elem, "events" ); bgneal@45: jQuery.removeData( elem, "handle" ); bgneal@45: } bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: trigger: function(type, data, elem, donative, extra) { bgneal@45: // Clone the incoming data, if any bgneal@45: data = jQuery.makeArray(data); bgneal@45: bgneal@45: if ( type.indexOf("!") >= 0 ) { bgneal@45: type = type.slice(0, -1); bgneal@45: var exclusive = true; bgneal@45: } bgneal@45: bgneal@45: // Handle a global trigger bgneal@45: if ( !elem ) { bgneal@45: // Only trigger if we've ever bound an event for it bgneal@45: if ( this.global[type] ) bgneal@45: jQuery("*").add([window, document]).trigger(type, data); bgneal@45: bgneal@45: // Handle triggering a single element bgneal@45: } else { bgneal@45: // don't do events on text and comment nodes bgneal@45: if ( elem.nodeType == 3 || elem.nodeType == 8 ) bgneal@45: return undefined; bgneal@45: bgneal@45: var val, ret, fn = jQuery.isFunction( elem[ type ] || null ), bgneal@45: // Check to see if we need to provide a fake event, or not bgneal@45: event = !data[0] || !data[0].preventDefault; bgneal@45: bgneal@45: // Pass along a fake event bgneal@45: if ( event ) { bgneal@45: data.unshift({ bgneal@45: type: type, bgneal@45: target: elem, bgneal@45: preventDefault: function(){}, bgneal@45: stopPropagation: function(){}, bgneal@45: timeStamp: now() bgneal@45: }); bgneal@45: data[0][expando] = true; // no need to fix fake event bgneal@45: } bgneal@45: bgneal@45: // Enforce the right trigger type bgneal@45: data[0].type = type; bgneal@45: if ( exclusive ) bgneal@45: data[0].exclusive = true; bgneal@45: bgneal@45: // Trigger the event, it is assumed that "handle" is a function bgneal@45: var handle = jQuery.data(elem, "handle"); bgneal@45: if ( handle ) bgneal@45: val = handle.apply( elem, data ); bgneal@45: bgneal@45: // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links) bgneal@45: if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false ) bgneal@45: val = false; bgneal@45: bgneal@45: // Extra functions don't get the custom event object bgneal@45: if ( event ) bgneal@45: data.shift(); bgneal@45: bgneal@45: // Handle triggering of extra function bgneal@45: if ( extra && jQuery.isFunction( extra ) ) { bgneal@45: // call the extra function and tack the current return value on the end for possible inspection bgneal@45: ret = extra.apply( elem, val == null ? data : data.concat( val ) ); bgneal@45: // if anything is returned, give it precedence and have it overwrite the previous value bgneal@45: if (ret !== undefined) bgneal@45: val = ret; bgneal@45: } bgneal@45: bgneal@45: // Trigger the native events (except for clicks on links) bgneal@45: if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) { bgneal@45: this.triggered = true; bgneal@45: try { bgneal@45: elem[ type ](); bgneal@45: // prevent IE from throwing an error for some hidden elements bgneal@45: } catch (e) {} bgneal@45: } bgneal@45: bgneal@45: this.triggered = false; bgneal@45: } bgneal@45: bgneal@45: return val; bgneal@45: }, bgneal@45: bgneal@45: handle: function(event) { bgneal@45: // returned undefined or false bgneal@45: var val, ret, namespace, all, handlers; bgneal@45: bgneal@45: event = arguments[0] = jQuery.event.fix( event || window.event ); bgneal@45: bgneal@45: // Namespaced event handlers bgneal@45: namespace = event.type.split("."); bgneal@45: event.type = namespace[0]; bgneal@45: namespace = namespace[1]; bgneal@45: // Cache this now, all = true means, any handler bgneal@45: all = !namespace && !event.exclusive; bgneal@45: bgneal@45: handlers = ( jQuery.data(this, "events") || {} )[event.type]; bgneal@45: bgneal@45: for ( var j in handlers ) { bgneal@45: var handler = handlers[j]; bgneal@45: bgneal@45: // Filter the functions by class bgneal@45: if ( all || handler.type == namespace ) { bgneal@45: // Pass in a reference to the handler function itself bgneal@45: // So that we can later remove it bgneal@45: event.handler = handler; bgneal@45: event.data = handler.data; bgneal@45: bgneal@45: ret = handler.apply( this, arguments ); bgneal@45: bgneal@45: if ( val !== false ) bgneal@45: val = ret; bgneal@45: bgneal@45: if ( ret === false ) { bgneal@45: event.preventDefault(); bgneal@45: event.stopPropagation(); bgneal@45: } bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: return val; bgneal@45: }, bgneal@45: bgneal@45: props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" "), bgneal@45: bgneal@45: fix: function(event) { bgneal@45: if ( event[expando] == true ) bgneal@45: return event; bgneal@45: bgneal@45: // store a copy of the original event object bgneal@45: // and "clone" to set read-only properties bgneal@45: var originalEvent = event; bgneal@45: event = { originalEvent: originalEvent }; bgneal@45: bgneal@45: for ( var i = this.props.length, prop; i; ){ bgneal@45: prop = this.props[ --i ]; bgneal@45: event[ prop ] = originalEvent[ prop ]; bgneal@45: } bgneal@45: bgneal@45: // Mark it as fixed bgneal@45: event[expando] = true; bgneal@45: bgneal@45: // add preventDefault and stopPropagation since bgneal@45: // they will not work on the clone bgneal@45: event.preventDefault = function() { bgneal@45: // if preventDefault exists run it on the original event bgneal@45: if (originalEvent.preventDefault) bgneal@45: originalEvent.preventDefault(); bgneal@45: // otherwise set the returnValue property of the original event to false (IE) bgneal@45: originalEvent.returnValue = false; bgneal@45: }; bgneal@45: event.stopPropagation = function() { bgneal@45: // if stopPropagation exists run it on the original event bgneal@45: if (originalEvent.stopPropagation) bgneal@45: originalEvent.stopPropagation(); bgneal@45: // otherwise set the cancelBubble property of the original event to true (IE) bgneal@45: originalEvent.cancelBubble = true; bgneal@45: }; bgneal@45: bgneal@45: // Fix timeStamp bgneal@45: event.timeStamp = event.timeStamp || now(); bgneal@45: bgneal@45: // Fix target property, if necessary bgneal@45: if ( !event.target ) bgneal@45: event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either bgneal@45: bgneal@45: // check if target is a textnode (safari) bgneal@45: if ( event.target.nodeType == 3 ) bgneal@45: event.target = event.target.parentNode; bgneal@45: bgneal@45: // Add relatedTarget, if necessary bgneal@45: if ( !event.relatedTarget && event.fromElement ) bgneal@45: event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement; bgneal@45: bgneal@45: // Calculate pageX/Y if missing and clientX/Y available bgneal@45: if ( event.pageX == null && event.clientX != null ) { bgneal@45: var doc = document.documentElement, body = document.body; bgneal@45: event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0); bgneal@45: event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0); bgneal@45: } bgneal@45: bgneal@45: // Add which for key events bgneal@45: if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) bgneal@45: event.which = event.charCode || event.keyCode; bgneal@45: bgneal@45: // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) bgneal@45: if ( !event.metaKey && event.ctrlKey ) bgneal@45: event.metaKey = event.ctrlKey; bgneal@45: bgneal@45: // Add which for click: 1 == left; 2 == middle; 3 == right bgneal@45: // Note: button is not normalized, so don't use it bgneal@45: if ( !event.which && event.button ) bgneal@45: event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); bgneal@45: bgneal@45: return event; bgneal@45: }, bgneal@45: bgneal@45: proxy: function( fn, proxy ){ bgneal@45: // Set the guid of unique handler to the same of original handler, so it can be removed bgneal@45: proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++; bgneal@45: // So proxy can be declared as an argument bgneal@45: return proxy; bgneal@45: }, bgneal@45: bgneal@45: special: { bgneal@45: ready: { bgneal@45: setup: function() { bgneal@45: // Make sure the ready event is setup bgneal@45: bindReady(); bgneal@45: return; bgneal@45: }, bgneal@45: bgneal@45: teardown: function() { return; } bgneal@45: }, bgneal@45: bgneal@45: mouseenter: { bgneal@45: setup: function() { bgneal@45: if ( jQuery.browser.msie ) return false; bgneal@45: jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler); bgneal@45: return true; bgneal@45: }, bgneal@45: bgneal@45: teardown: function() { bgneal@45: if ( jQuery.browser.msie ) return false; bgneal@45: jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler); bgneal@45: return true; bgneal@45: }, bgneal@45: bgneal@45: handler: function(event) { bgneal@45: // If we actually just moused on to a sub-element, ignore it bgneal@45: if ( withinElement(event, this) ) return true; bgneal@45: // Execute the right handlers by setting the event type to mouseenter bgneal@45: event.type = "mouseenter"; bgneal@45: return jQuery.event.handle.apply(this, arguments); bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: mouseleave: { bgneal@45: setup: function() { bgneal@45: if ( jQuery.browser.msie ) return false; bgneal@45: jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler); bgneal@45: return true; bgneal@45: }, bgneal@45: bgneal@45: teardown: function() { bgneal@45: if ( jQuery.browser.msie ) return false; bgneal@45: jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler); bgneal@45: return true; bgneal@45: }, bgneal@45: bgneal@45: handler: function(event) { bgneal@45: // If we actually just moused on to a sub-element, ignore it bgneal@45: if ( withinElement(event, this) ) return true; bgneal@45: // Execute the right handlers by setting the event type to mouseleave bgneal@45: event.type = "mouseleave"; bgneal@45: return jQuery.event.handle.apply(this, arguments); bgneal@45: } bgneal@45: } bgneal@45: } bgneal@45: }; bgneal@45: bgneal@45: jQuery.fn.extend({ bgneal@45: bind: function( type, data, fn ) { bgneal@45: return type == "unload" ? this.one(type, data, fn) : this.each(function(){ bgneal@45: jQuery.event.add( this, type, fn || data, fn && data ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: one: function( type, data, fn ) { bgneal@45: var one = jQuery.event.proxy( fn || data, function(event) { bgneal@45: jQuery(this).unbind(event, one); bgneal@45: return (fn || data).apply( this, arguments ); bgneal@45: }); bgneal@45: return this.each(function(){ bgneal@45: jQuery.event.add( this, type, one, fn && data); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: unbind: function( type, fn ) { bgneal@45: return this.each(function(){ bgneal@45: jQuery.event.remove( this, type, fn ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: trigger: function( type, data, fn ) { bgneal@45: return this.each(function(){ bgneal@45: jQuery.event.trigger( type, data, this, true, fn ); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: triggerHandler: function( type, data, fn ) { bgneal@45: return this[0] && jQuery.event.trigger( type, data, this[0], false, fn ); bgneal@45: }, bgneal@45: bgneal@45: toggle: function( fn ) { bgneal@45: // Save reference to arguments for access in closure bgneal@45: var args = arguments, i = 1; bgneal@45: bgneal@45: // link all the functions, so any of them can unbind this click handler bgneal@45: while( i < args.length ) bgneal@45: jQuery.event.proxy( fn, args[i++] ); bgneal@45: bgneal@45: return this.click( jQuery.event.proxy( fn, function(event) { bgneal@45: // Figure out which function to execute bgneal@45: this.lastToggle = ( this.lastToggle || 0 ) % i; bgneal@45: bgneal@45: // Make sure that clicks stop bgneal@45: event.preventDefault(); bgneal@45: bgneal@45: // and execute the function bgneal@45: return args[ this.lastToggle++ ].apply( this, arguments ) || false; bgneal@45: })); bgneal@45: }, bgneal@45: bgneal@45: hover: function(fnOver, fnOut) { bgneal@45: return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut); bgneal@45: }, bgneal@45: bgneal@45: ready: function(fn) { bgneal@45: // Attach the listeners bgneal@45: bindReady(); bgneal@45: bgneal@45: // If the DOM is already ready bgneal@45: if ( jQuery.isReady ) bgneal@45: // Execute the function immediately bgneal@45: fn.call( document, jQuery ); bgneal@45: bgneal@45: // Otherwise, remember the function for later bgneal@45: else bgneal@45: // Add the function to the wait list bgneal@45: jQuery.readyList.push( function() { return fn.call(this, jQuery); } ); bgneal@45: bgneal@45: return this; bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: jQuery.extend({ bgneal@45: isReady: false, bgneal@45: readyList: [], bgneal@45: // Handle when the DOM is ready bgneal@45: ready: function() { bgneal@45: // Make sure that the DOM is not already loaded bgneal@45: if ( !jQuery.isReady ) { bgneal@45: // Remember that the DOM is ready bgneal@45: jQuery.isReady = true; bgneal@45: bgneal@45: // If there are functions bound, to execute bgneal@45: if ( jQuery.readyList ) { bgneal@45: // Execute all of them bgneal@45: jQuery.each( jQuery.readyList, function(){ bgneal@45: this.call( document ); bgneal@45: }); bgneal@45: bgneal@45: // Reset the list of functions bgneal@45: jQuery.readyList = null; bgneal@45: } bgneal@45: bgneal@45: // Trigger any bound ready events bgneal@45: jQuery(document).triggerHandler("ready"); bgneal@45: } bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: var readyBound = false; bgneal@45: bgneal@45: function bindReady(){ bgneal@45: if ( readyBound ) return; bgneal@45: readyBound = true; bgneal@45: bgneal@45: // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event bgneal@45: if ( document.addEventListener && !jQuery.browser.opera) bgneal@45: // Use the handy event callback bgneal@45: document.addEventListener( "DOMContentLoaded", jQuery.ready, false ); bgneal@45: bgneal@45: // If IE is used and is not in a frame bgneal@45: // Continually check to see if the document is ready bgneal@45: if ( jQuery.browser.msie && window == top ) (function(){ bgneal@45: if (jQuery.isReady) return; bgneal@45: try { bgneal@45: // If IE is used, use the trick by Diego Perini bgneal@45: // http://javascript.nwbox.com/IEContentLoaded/ bgneal@45: document.documentElement.doScroll("left"); bgneal@45: } catch( error ) { bgneal@45: setTimeout( arguments.callee, 0 ); bgneal@45: return; bgneal@45: } bgneal@45: // and execute any waiting functions bgneal@45: jQuery.ready(); bgneal@45: })(); bgneal@45: bgneal@45: if ( jQuery.browser.opera ) bgneal@45: document.addEventListener( "DOMContentLoaded", function () { bgneal@45: if (jQuery.isReady) return; bgneal@45: for (var i = 0; i < document.styleSheets.length; i++) bgneal@45: if (document.styleSheets[i].disabled) { bgneal@45: setTimeout( arguments.callee, 0 ); bgneal@45: return; bgneal@45: } bgneal@45: // and execute any waiting functions bgneal@45: jQuery.ready(); bgneal@45: }, false); bgneal@45: bgneal@45: if ( jQuery.browser.safari ) { bgneal@45: var numStyles; bgneal@45: (function(){ bgneal@45: if (jQuery.isReady) return; bgneal@45: if ( document.readyState != "loaded" && document.readyState != "complete" ) { bgneal@45: setTimeout( arguments.callee, 0 ); bgneal@45: return; bgneal@45: } bgneal@45: if ( numStyles === undefined ) bgneal@45: numStyles = jQuery("style, link[rel=stylesheet]").length; bgneal@45: if ( document.styleSheets.length != numStyles ) { bgneal@45: setTimeout( arguments.callee, 0 ); bgneal@45: return; bgneal@45: } bgneal@45: // and execute any waiting functions bgneal@45: jQuery.ready(); bgneal@45: })(); bgneal@45: } bgneal@45: bgneal@45: // A fallback to window.onload, that will always work bgneal@45: jQuery.event.add( window, "load", jQuery.ready ); bgneal@45: } bgneal@45: bgneal@45: jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + bgneal@45: "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + bgneal@45: "submit,keydown,keypress,keyup,error").split(","), function(i, name){ bgneal@45: bgneal@45: // Handle event binding bgneal@45: jQuery.fn[name] = function(fn){ bgneal@45: return fn ? this.bind(name, fn) : this.trigger(name); bgneal@45: }; bgneal@45: }); bgneal@45: bgneal@45: // Checks if an event happened on an element within another element bgneal@45: // Used in jQuery.event.special.mouseenter and mouseleave handlers bgneal@45: var withinElement = function(event, elem) { bgneal@45: // Check if mouse(over|out) are still within the same parent element bgneal@45: var parent = event.relatedTarget; bgneal@45: // Traverse up the tree bgneal@45: while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; } bgneal@45: // Return true if we actually just moused on to a sub-element bgneal@45: return parent == elem; bgneal@45: }; bgneal@45: bgneal@45: // Prevent memory leaks in IE bgneal@45: // And prevent errors on refresh with events like mouseover in other browsers bgneal@45: // Window isn't included so as not to unbind existing unload events bgneal@45: jQuery(window).bind("unload", function() { bgneal@45: jQuery("*").add(document).unbind(); bgneal@45: }); bgneal@45: jQuery.fn.extend({ bgneal@45: // Keep a copy of the old load bgneal@45: _load: jQuery.fn.load, bgneal@45: bgneal@45: load: function( url, params, callback ) { bgneal@45: if ( typeof url != 'string' ) bgneal@45: return this._load( url ); bgneal@45: bgneal@45: var off = url.indexOf(" "); bgneal@45: if ( off >= 0 ) { bgneal@45: var selector = url.slice(off, url.length); bgneal@45: url = url.slice(0, off); bgneal@45: } bgneal@45: bgneal@45: callback = callback || function(){}; bgneal@45: bgneal@45: // Default to a GET request bgneal@45: var type = "GET"; bgneal@45: bgneal@45: // If the second parameter was provided bgneal@45: if ( params ) bgneal@45: // If it's a function bgneal@45: if ( jQuery.isFunction( params ) ) { bgneal@45: // We assume that it's the callback bgneal@45: callback = params; bgneal@45: params = null; bgneal@45: bgneal@45: // Otherwise, build a param string bgneal@45: } else if( typeof params == 'object' ) { bgneal@45: params = jQuery.param( params ); bgneal@45: type = "POST"; bgneal@45: } bgneal@45: bgneal@45: var self = this; bgneal@45: bgneal@45: // Request the remote document bgneal@45: jQuery.ajax({ bgneal@45: url: url, bgneal@45: type: type, bgneal@45: dataType: "html", bgneal@45: data: params, bgneal@45: complete: function(res, status){ bgneal@45: // If successful, inject the HTML into all the matched elements bgneal@45: if ( status == "success" || status == "notmodified" ) bgneal@45: // See if a selector was specified bgneal@45: self.html( selector ? bgneal@45: // Create a dummy div to hold the results bgneal@45: jQuery("<div/>") bgneal@45: // inject the contents of the document in, removing the scripts bgneal@45: // to avoid any 'Permission Denied' errors in IE bgneal@45: .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, "")) bgneal@45: bgneal@45: // Locate the specified elements bgneal@45: .find(selector) : bgneal@45: bgneal@45: // If not, just inject the full result bgneal@45: res.responseText ); bgneal@45: bgneal@45: self.each( callback, [res.responseText, status, res] ); bgneal@45: } bgneal@45: }); bgneal@45: return this; bgneal@45: }, bgneal@45: bgneal@45: serialize: function() { bgneal@45: return jQuery.param(this.serializeArray()); bgneal@45: }, bgneal@45: serializeArray: function() { bgneal@45: return this.map(function(){ bgneal@45: return jQuery.nodeName(this, "form") ? bgneal@45: jQuery.makeArray(this.elements) : this; bgneal@45: }) bgneal@45: .filter(function(){ bgneal@45: return this.name && !this.disabled && bgneal@45: (this.checked || /select|textarea/i.test(this.nodeName) || bgneal@45: /text|hidden|password/i.test(this.type)); bgneal@45: }) bgneal@45: .map(function(i, elem){ bgneal@45: var val = jQuery(this).val(); bgneal@45: return val == null ? null : bgneal@45: val.constructor == Array ? bgneal@45: jQuery.map( val, function(val, i){ bgneal@45: return {name: elem.name, value: val}; bgneal@45: }) : bgneal@45: {name: elem.name, value: val}; bgneal@45: }).get(); bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: // Attach a bunch of functions for handling common AJAX events bgneal@45: jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){ bgneal@45: jQuery.fn[o] = function(f){ bgneal@45: return this.bind(o, f); bgneal@45: }; bgneal@45: }); bgneal@45: bgneal@45: var jsc = now(); bgneal@45: bgneal@45: jQuery.extend({ bgneal@45: get: function( url, data, callback, type ) { bgneal@45: // shift arguments if data argument was ommited bgneal@45: if ( jQuery.isFunction( data ) ) { bgneal@45: callback = data; bgneal@45: data = null; bgneal@45: } bgneal@45: bgneal@45: return jQuery.ajax({ bgneal@45: type: "GET", bgneal@45: url: url, bgneal@45: data: data, bgneal@45: success: callback, bgneal@45: dataType: type bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: getScript: function( url, callback ) { bgneal@45: return jQuery.get(url, null, callback, "script"); bgneal@45: }, bgneal@45: bgneal@45: getJSON: function( url, data, callback ) { bgneal@45: return jQuery.get(url, data, callback, "json"); bgneal@45: }, bgneal@45: bgneal@45: post: function( url, data, callback, type ) { bgneal@45: if ( jQuery.isFunction( data ) ) { bgneal@45: callback = data; bgneal@45: data = {}; bgneal@45: } bgneal@45: bgneal@45: return jQuery.ajax({ bgneal@45: type: "POST", bgneal@45: url: url, bgneal@45: data: data, bgneal@45: success: callback, bgneal@45: dataType: type bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: ajaxSetup: function( settings ) { bgneal@45: jQuery.extend( jQuery.ajaxSettings, settings ); bgneal@45: }, bgneal@45: bgneal@45: ajaxSettings: { bgneal@45: url: location.href, bgneal@45: global: true, bgneal@45: type: "GET", bgneal@45: timeout: 0, bgneal@45: contentType: "application/x-www-form-urlencoded", bgneal@45: processData: true, bgneal@45: async: true, bgneal@45: data: null, bgneal@45: username: null, bgneal@45: password: null, bgneal@45: accepts: { bgneal@45: xml: "application/xml, text/xml", bgneal@45: html: "text/html", bgneal@45: script: "text/javascript, application/javascript", bgneal@45: json: "application/json, text/javascript", bgneal@45: text: "text/plain", bgneal@45: _default: "*/*" bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: // Last-Modified header cache for next request bgneal@45: lastModified: {}, bgneal@45: bgneal@45: ajax: function( s ) { bgneal@45: // Extend the settings, but re-extend 's' so that it can be bgneal@45: // checked again later (in the test suite, specifically) bgneal@45: s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); bgneal@45: bgneal@45: var jsonp, jsre = /=\?(&|$)/g, status, data, bgneal@45: type = s.type.toUpperCase(); bgneal@45: bgneal@45: // convert data if not already a string bgneal@45: if ( s.data && s.processData && typeof s.data != "string" ) bgneal@45: s.data = jQuery.param(s.data); bgneal@45: bgneal@45: // Handle JSONP Parameter Callbacks bgneal@45: if ( s.dataType == "jsonp" ) { bgneal@45: if ( type == "GET" ) { bgneal@45: if ( !s.url.match(jsre) ) bgneal@45: s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?"; bgneal@45: } else if ( !s.data || !s.data.match(jsre) ) bgneal@45: s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; bgneal@45: s.dataType = "json"; bgneal@45: } bgneal@45: bgneal@45: // Build temporary JSONP function bgneal@45: if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) { bgneal@45: jsonp = "jsonp" + jsc++; bgneal@45: bgneal@45: // Replace the =? sequence both in the query string and the data bgneal@45: if ( s.data ) bgneal@45: s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); bgneal@45: s.url = s.url.replace(jsre, "=" + jsonp + "$1"); bgneal@45: bgneal@45: // We need to make sure bgneal@45: // that a JSONP style response is executed properly bgneal@45: s.dataType = "script"; bgneal@45: bgneal@45: // Handle JSONP-style loading bgneal@45: window[ jsonp ] = function(tmp){ bgneal@45: data = tmp; bgneal@45: success(); bgneal@45: complete(); bgneal@45: // Garbage collect bgneal@45: window[ jsonp ] = undefined; bgneal@45: try{ delete window[ jsonp ]; } catch(e){} bgneal@45: if ( head ) bgneal@45: head.removeChild( script ); bgneal@45: }; bgneal@45: } bgneal@45: bgneal@45: if ( s.dataType == "script" && s.cache == null ) bgneal@45: s.cache = false; bgneal@45: bgneal@45: if ( s.cache === false && type == "GET" ) { bgneal@45: var ts = now(); bgneal@45: // try replacing _= if it is there bgneal@45: var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); bgneal@45: // if nothing was replaced, add timestamp to the end bgneal@45: s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : ""); bgneal@45: } bgneal@45: bgneal@45: // If data is available, append data to url for get requests bgneal@45: if ( s.data && type == "GET" ) { bgneal@45: s.url += (s.url.match(/\?/) ? "&" : "?") + s.data; bgneal@45: bgneal@45: // IE likes to send both get and post data, prevent this bgneal@45: s.data = null; bgneal@45: } bgneal@45: bgneal@45: // Watch for a new set of requests bgneal@45: if ( s.global && ! jQuery.active++ ) bgneal@45: jQuery.event.trigger( "ajaxStart" ); bgneal@45: bgneal@45: // Matches an absolute URL, and saves the domain bgneal@45: var remote = /^(?:\w+:)?\/\/([^\/?#]+)/; bgneal@45: bgneal@45: // If we're requesting a remote document bgneal@45: // and trying to load JSON or Script with a GET bgneal@45: if ( s.dataType == "script" && type == "GET" bgneal@45: && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){ bgneal@45: var head = document.getElementsByTagName("head")[0]; bgneal@45: var script = document.createElement("script"); bgneal@45: script.src = s.url; bgneal@45: if (s.scriptCharset) bgneal@45: script.charset = s.scriptCharset; bgneal@45: bgneal@45: // Handle Script loading bgneal@45: if ( !jsonp ) { bgneal@45: var done = false; bgneal@45: bgneal@45: // Attach handlers for all browsers bgneal@45: script.onload = script.onreadystatechange = function(){ bgneal@45: if ( !done && (!this.readyState || bgneal@45: this.readyState == "loaded" || this.readyState == "complete") ) { bgneal@45: done = true; bgneal@45: success(); bgneal@45: complete(); bgneal@45: head.removeChild( script ); bgneal@45: } bgneal@45: }; bgneal@45: } bgneal@45: bgneal@45: head.appendChild(script); bgneal@45: bgneal@45: // We handle everything using the script element injection bgneal@45: return undefined; bgneal@45: } bgneal@45: bgneal@45: var requestDone = false; bgneal@45: bgneal@45: // Create the request object; Microsoft failed to properly bgneal@45: // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available bgneal@45: var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); bgneal@45: bgneal@45: // Open the socket bgneal@45: // Passing null username, generates a login popup on Opera (#2865) bgneal@45: if( s.username ) bgneal@45: xhr.open(type, s.url, s.async, s.username, s.password); bgneal@45: else bgneal@45: xhr.open(type, s.url, s.async); bgneal@45: bgneal@45: // Need an extra try/catch for cross domain requests in Firefox 3 bgneal@45: try { bgneal@45: // Set the correct header, if data is being sent bgneal@45: if ( s.data ) bgneal@45: xhr.setRequestHeader("Content-Type", s.contentType); bgneal@45: bgneal@45: // Set the If-Modified-Since header, if ifModified mode. bgneal@45: if ( s.ifModified ) bgneal@45: xhr.setRequestHeader("If-Modified-Since", bgneal@45: jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" ); bgneal@45: bgneal@45: // Set header so the called script knows that it's an XMLHttpRequest bgneal@45: xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); bgneal@45: bgneal@45: // Set the Accepts header for the server, depending on the dataType bgneal@45: xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? bgneal@45: s.accepts[ s.dataType ] + ", */*" : bgneal@45: s.accepts._default ); bgneal@45: } catch(e){} bgneal@45: bgneal@45: // Allow custom headers/mimetypes bgneal@45: if ( s.beforeSend && s.beforeSend(xhr, s) === false ) { bgneal@45: // cleanup active request counter bgneal@45: s.global && jQuery.active--; bgneal@45: // close opended socket bgneal@45: xhr.abort(); bgneal@45: return false; bgneal@45: } bgneal@45: bgneal@45: if ( s.global ) bgneal@45: jQuery.event.trigger("ajaxSend", [xhr, s]); bgneal@45: bgneal@45: // Wait for a response to come back bgneal@45: var onreadystatechange = function(isTimeout){ bgneal@45: // The transfer is complete and the data is available, or the request timed out bgneal@45: if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) { bgneal@45: requestDone = true; bgneal@45: bgneal@45: // clear poll interval bgneal@45: if (ival) { bgneal@45: clearInterval(ival); bgneal@45: ival = null; bgneal@45: } bgneal@45: bgneal@45: status = isTimeout == "timeout" ? "timeout" : bgneal@45: !jQuery.httpSuccess( xhr ) ? "error" : bgneal@45: s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" : bgneal@45: "success"; bgneal@45: bgneal@45: if ( status == "success" ) { bgneal@45: // Watch for, and catch, XML document parse errors bgneal@45: try { bgneal@45: // process the data (runs the xml through httpData regardless of callback) bgneal@45: data = jQuery.httpData( xhr, s.dataType, s.dataFilter ); bgneal@45: } catch(e) { bgneal@45: status = "parsererror"; bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: // Make sure that the request was successful or notmodified bgneal@45: if ( status == "success" ) { bgneal@45: // Cache Last-Modified header, if ifModified mode. bgneal@45: var modRes; bgneal@45: try { bgneal@45: modRes = xhr.getResponseHeader("Last-Modified"); bgneal@45: } catch(e) {} // swallow exception thrown by FF if header is not available bgneal@45: bgneal@45: if ( s.ifModified && modRes ) bgneal@45: jQuery.lastModified[s.url] = modRes; bgneal@45: bgneal@45: // JSONP handles its own success callback bgneal@45: if ( !jsonp ) bgneal@45: success(); bgneal@45: } else bgneal@45: jQuery.handleError(s, xhr, status); bgneal@45: bgneal@45: // Fire the complete handlers bgneal@45: complete(); bgneal@45: bgneal@45: // Stop memory leaks bgneal@45: if ( s.async ) bgneal@45: xhr = null; bgneal@45: } bgneal@45: }; bgneal@45: bgneal@45: if ( s.async ) { bgneal@45: // don't attach the handler to the request, just poll it instead bgneal@45: var ival = setInterval(onreadystatechange, 13); bgneal@45: bgneal@45: // Timeout checker bgneal@45: if ( s.timeout > 0 ) bgneal@45: setTimeout(function(){ bgneal@45: // Check to see if the request is still happening bgneal@45: if ( xhr ) { bgneal@45: // Cancel the request bgneal@45: xhr.abort(); bgneal@45: bgneal@45: if( !requestDone ) bgneal@45: onreadystatechange( "timeout" ); bgneal@45: } bgneal@45: }, s.timeout); bgneal@45: } bgneal@45: bgneal@45: // Send the data bgneal@45: try { bgneal@45: xhr.send(s.data); bgneal@45: } catch(e) { bgneal@45: jQuery.handleError(s, xhr, null, e); bgneal@45: } bgneal@45: bgneal@45: // firefox 1.5 doesn't fire statechange for sync requests bgneal@45: if ( !s.async ) bgneal@45: onreadystatechange(); bgneal@45: bgneal@45: function success(){ bgneal@45: // If a local callback was specified, fire it and pass it the data bgneal@45: if ( s.success ) bgneal@45: s.success( data, status ); bgneal@45: bgneal@45: // Fire the global callback bgneal@45: if ( s.global ) bgneal@45: jQuery.event.trigger( "ajaxSuccess", [xhr, s] ); bgneal@45: } bgneal@45: bgneal@45: function complete(){ bgneal@45: // Process result bgneal@45: if ( s.complete ) bgneal@45: s.complete(xhr, status); bgneal@45: bgneal@45: // The request was completed bgneal@45: if ( s.global ) bgneal@45: jQuery.event.trigger( "ajaxComplete", [xhr, s] ); bgneal@45: bgneal@45: // Handle the global AJAX counter bgneal@45: if ( s.global && ! --jQuery.active ) bgneal@45: jQuery.event.trigger( "ajaxStop" ); bgneal@45: } bgneal@45: bgneal@45: // return XMLHttpRequest to allow aborting the request etc. bgneal@45: return xhr; bgneal@45: }, bgneal@45: bgneal@45: handleError: function( s, xhr, status, e ) { bgneal@45: // If a local callback was specified, fire it bgneal@45: if ( s.error ) s.error( xhr, status, e ); bgneal@45: bgneal@45: // Fire the global callback bgneal@45: if ( s.global ) bgneal@45: jQuery.event.trigger( "ajaxError", [xhr, s, e] ); bgneal@45: }, bgneal@45: bgneal@45: // Counter for holding the number of active queries bgneal@45: active: 0, bgneal@45: bgneal@45: // Determines if an XMLHttpRequest was successful or not bgneal@45: httpSuccess: function( xhr ) { bgneal@45: try { bgneal@45: // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 bgneal@45: return !xhr.status && location.protocol == "file:" || bgneal@45: ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 || bgneal@45: jQuery.browser.safari && xhr.status == undefined; bgneal@45: } catch(e){} bgneal@45: return false; bgneal@45: }, bgneal@45: bgneal@45: // Determines if an XMLHttpRequest returns NotModified bgneal@45: httpNotModified: function( xhr, url ) { bgneal@45: try { bgneal@45: var xhrRes = xhr.getResponseHeader("Last-Modified"); bgneal@45: bgneal@45: // Firefox always returns 200. check Last-Modified date bgneal@45: return xhr.status == 304 || xhrRes == jQuery.lastModified[url] || bgneal@45: jQuery.browser.safari && xhr.status == undefined; bgneal@45: } catch(e){} bgneal@45: return false; bgneal@45: }, bgneal@45: bgneal@45: httpData: function( xhr, type, filter ) { bgneal@45: var ct = xhr.getResponseHeader("content-type"), bgneal@45: xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0, bgneal@45: data = xml ? xhr.responseXML : xhr.responseText; bgneal@45: bgneal@45: if ( xml && data.documentElement.tagName == "parsererror" ) bgneal@45: throw "parsererror"; bgneal@45: bgneal@45: // Allow a pre-filtering function to sanitize the response bgneal@45: if( filter ) bgneal@45: data = filter( data, type ); bgneal@45: bgneal@45: // If the type is "script", eval it in global context bgneal@45: if ( type == "script" ) bgneal@45: jQuery.globalEval( data ); bgneal@45: bgneal@45: // Get the JavaScript object, if JSON is used. bgneal@45: if ( type == "json" ) bgneal@45: data = eval("(" + data + ")"); bgneal@45: bgneal@45: return data; bgneal@45: }, bgneal@45: bgneal@45: // Serialize an array of form elements or a set of bgneal@45: // key/values into a query string bgneal@45: param: function( a ) { bgneal@45: var s = [ ]; bgneal@45: bgneal@45: function add( key, value ){ bgneal@45: s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value); bgneal@45: }; bgneal@45: bgneal@45: // If an array was passed in, assume that it is an array bgneal@45: // of form elements bgneal@45: if ( a.constructor == Array || a.jquery ) bgneal@45: // Serialize the form elements bgneal@45: jQuery.each( a, function(){ bgneal@45: add( this.name, this.value ); bgneal@45: }); bgneal@45: bgneal@45: // Otherwise, assume that it's an object of key/value pairs bgneal@45: else bgneal@45: // Serialize the key/values bgneal@45: for ( var j in a ) bgneal@45: // If the value is an array then the key names need to be repeated bgneal@45: if ( a[j] && a[j].constructor == Array ) bgneal@45: jQuery.each( a[j], function(){ bgneal@45: add( j, this ); bgneal@45: }); bgneal@45: else bgneal@45: add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] ); bgneal@45: bgneal@45: // Return the resulting serialization bgneal@45: return s.join("&").replace(/%20/g, "+"); bgneal@45: } bgneal@45: bgneal@45: }); bgneal@45: jQuery.fn.extend({ bgneal@45: show: function(speed,callback){ bgneal@45: return speed ? bgneal@45: this.animate({ bgneal@45: height: "show", width: "show", opacity: "show" bgneal@45: }, speed, callback) : bgneal@45: bgneal@45: this.filter(":hidden").each(function(){ bgneal@45: this.style.display = this.oldblock || ""; bgneal@45: if ( jQuery.css(this,"display") == "none" ) { bgneal@45: var elem = jQuery("<" + this.tagName + " />").appendTo("body"); bgneal@45: this.style.display = elem.css("display"); bgneal@45: // handle an edge condition where css is - div { display:none; } or similar bgneal@45: if (this.style.display == "none") bgneal@45: this.style.display = "block"; bgneal@45: elem.remove(); bgneal@45: } bgneal@45: }).end(); bgneal@45: }, bgneal@45: bgneal@45: hide: function(speed,callback){ bgneal@45: return speed ? bgneal@45: this.animate({ bgneal@45: height: "hide", width: "hide", opacity: "hide" bgneal@45: }, speed, callback) : bgneal@45: bgneal@45: this.filter(":visible").each(function(){ bgneal@45: this.oldblock = this.oldblock || jQuery.css(this,"display"); bgneal@45: this.style.display = "none"; bgneal@45: }).end(); bgneal@45: }, bgneal@45: bgneal@45: // Save the old toggle function bgneal@45: _toggle: jQuery.fn.toggle, bgneal@45: bgneal@45: toggle: function( fn, fn2 ){ bgneal@45: return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ? bgneal@45: this._toggle.apply( this, arguments ) : bgneal@45: fn ? bgneal@45: this.animate({ bgneal@45: height: "toggle", width: "toggle", opacity: "toggle" bgneal@45: }, fn, fn2) : bgneal@45: this.each(function(){ bgneal@45: jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ](); bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: slideDown: function(speed,callback){ bgneal@45: return this.animate({height: "show"}, speed, callback); bgneal@45: }, bgneal@45: bgneal@45: slideUp: function(speed,callback){ bgneal@45: return this.animate({height: "hide"}, speed, callback); bgneal@45: }, bgneal@45: bgneal@45: slideToggle: function(speed, callback){ bgneal@45: return this.animate({height: "toggle"}, speed, callback); bgneal@45: }, bgneal@45: bgneal@45: fadeIn: function(speed, callback){ bgneal@45: return this.animate({opacity: "show"}, speed, callback); bgneal@45: }, bgneal@45: bgneal@45: fadeOut: function(speed, callback){ bgneal@45: return this.animate({opacity: "hide"}, speed, callback); bgneal@45: }, bgneal@45: bgneal@45: fadeTo: function(speed,to,callback){ bgneal@45: return this.animate({opacity: to}, speed, callback); bgneal@45: }, bgneal@45: bgneal@45: animate: function( prop, speed, easing, callback ) { bgneal@45: var optall = jQuery.speed(speed, easing, callback); bgneal@45: bgneal@45: return this[ optall.queue === false ? "each" : "queue" ](function(){ bgneal@45: if ( this.nodeType != 1) bgneal@45: return false; bgneal@45: bgneal@45: var opt = jQuery.extend({}, optall), p, bgneal@45: hidden = jQuery(this).is(":hidden"), self = this; bgneal@45: bgneal@45: for ( p in prop ) { bgneal@45: if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden ) bgneal@45: return opt.complete.call(this); bgneal@45: bgneal@45: if ( p == "height" || p == "width" ) { bgneal@45: // Store display property bgneal@45: opt.display = jQuery.css(this, "display"); bgneal@45: bgneal@45: // Make sure that nothing sneaks out bgneal@45: opt.overflow = this.style.overflow; bgneal@45: } bgneal@45: } bgneal@45: bgneal@45: if ( opt.overflow != null ) bgneal@45: this.style.overflow = "hidden"; bgneal@45: bgneal@45: opt.curAnim = jQuery.extend({}, prop); bgneal@45: bgneal@45: jQuery.each( prop, function(name, val){ bgneal@45: var e = new jQuery.fx( self, opt, name ); bgneal@45: bgneal@45: if ( /toggle|show|hide/.test(val) ) bgneal@45: e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop ); bgneal@45: else { bgneal@45: var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/), bgneal@45: start = e.cur(true) || 0; bgneal@45: bgneal@45: if ( parts ) { bgneal@45: var end = parseFloat(parts[2]), bgneal@45: unit = parts[3] || "px"; bgneal@45: bgneal@45: // We need to compute starting value bgneal@45: if ( unit != "px" ) { bgneal@45: self.style[ name ] = (end || 1) + unit; bgneal@45: start = ((end || 1) / e.cur(true)) * start; bgneal@45: self.style[ name ] = start + unit; bgneal@45: } bgneal@45: bgneal@45: // If a +=/-= token was provided, we're doing a relative animation bgneal@45: if ( parts[1] ) bgneal@45: end = ((parts[1] == "-=" ? -1 : 1) * end) + start; bgneal@45: bgneal@45: e.custom( start, end, unit ); bgneal@45: } else bgneal@45: e.custom( start, val, "" ); bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: // For JS strict compliance bgneal@45: return true; bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: queue: function(type, fn){ bgneal@45: if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) { bgneal@45: fn = type; bgneal@45: type = "fx"; bgneal@45: } bgneal@45: bgneal@45: if ( !type || (typeof type == "string" && !fn) ) bgneal@45: return queue( this[0], type ); bgneal@45: bgneal@45: return this.each(function(){ bgneal@45: if ( fn.constructor == Array ) bgneal@45: queue(this, type, fn); bgneal@45: else { bgneal@45: queue(this, type).push( fn ); bgneal@45: bgneal@45: if ( queue(this, type).length == 1 ) bgneal@45: fn.call(this); bgneal@45: } bgneal@45: }); bgneal@45: }, bgneal@45: bgneal@45: stop: function(clearQueue, gotoEnd){ bgneal@45: var timers = jQuery.timers; bgneal@45: bgneal@45: if (clearQueue) bgneal@45: this.queue([]); bgneal@45: bgneal@45: this.each(function(){ bgneal@45: // go in reverse order so anything added to the queue during the loop is ignored bgneal@45: for ( var i = timers.length - 1; i >= 0; i-- ) bgneal@45: if ( timers[i].elem == this ) { bgneal@45: if (gotoEnd) bgneal@45: // force the next step to be the last bgneal@45: timers[i](true); bgneal@45: timers.splice(i, 1); bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: // start the next in the queue if the last step wasn't forced bgneal@45: if (!gotoEnd) bgneal@45: this.dequeue(); bgneal@45: bgneal@45: return this; bgneal@45: } bgneal@45: bgneal@45: }); bgneal@45: bgneal@45: var queue = function( elem, type, array ) { bgneal@45: if ( elem ){ bgneal@45: bgneal@45: type = type || "fx"; bgneal@45: bgneal@45: var q = jQuery.data( elem, type + "queue" ); bgneal@45: bgneal@45: if ( !q || array ) bgneal@45: q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) ); bgneal@45: bgneal@45: } bgneal@45: return q; bgneal@45: }; bgneal@45: bgneal@45: jQuery.fn.dequeue = function(type){ bgneal@45: type = type || "fx"; bgneal@45: bgneal@45: return this.each(function(){ bgneal@45: var q = queue(this, type); bgneal@45: bgneal@45: q.shift(); bgneal@45: bgneal@45: if ( q.length ) bgneal@45: q[0].call( this ); bgneal@45: }); bgneal@45: }; bgneal@45: bgneal@45: jQuery.extend({ bgneal@45: bgneal@45: speed: function(speed, easing, fn) { bgneal@45: var opt = speed && speed.constructor == Object ? speed : { bgneal@45: complete: fn || !fn && easing || bgneal@45: jQuery.isFunction( speed ) && speed, bgneal@45: duration: speed, bgneal@45: easing: fn && easing || easing && easing.constructor != Function && easing bgneal@45: }; bgneal@45: bgneal@45: opt.duration = (opt.duration && opt.duration.constructor == Number ? bgneal@45: opt.duration : bgneal@45: jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def; bgneal@45: bgneal@45: // Queueing bgneal@45: opt.old = opt.complete; bgneal@45: opt.complete = function(){ bgneal@45: if ( opt.queue !== false ) bgneal@45: jQuery(this).dequeue(); bgneal@45: if ( jQuery.isFunction( opt.old ) ) bgneal@45: opt.old.call( this ); bgneal@45: }; bgneal@45: bgneal@45: return opt; bgneal@45: }, bgneal@45: bgneal@45: easing: { bgneal@45: linear: function( p, n, firstNum, diff ) { bgneal@45: return firstNum + diff * p; bgneal@45: }, bgneal@45: swing: function( p, n, firstNum, diff ) { bgneal@45: return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: timers: [], bgneal@45: timerId: null, bgneal@45: bgneal@45: fx: function( elem, options, prop ){ bgneal@45: this.options = options; bgneal@45: this.elem = elem; bgneal@45: this.prop = prop; bgneal@45: bgneal@45: if ( !options.orig ) bgneal@45: options.orig = {}; bgneal@45: } bgneal@45: bgneal@45: }); bgneal@45: bgneal@45: jQuery.fx.prototype = { bgneal@45: bgneal@45: // Simple function for setting a style value bgneal@45: update: function(){ bgneal@45: if ( this.options.step ) bgneal@45: this.options.step.call( this.elem, this.now, this ); bgneal@45: bgneal@45: (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); bgneal@45: bgneal@45: // Set display property to block for height/width animations bgneal@45: if ( this.prop == "height" || this.prop == "width" ) bgneal@45: this.elem.style.display = "block"; bgneal@45: }, bgneal@45: bgneal@45: // Get the current size bgneal@45: cur: function(force){ bgneal@45: if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null ) bgneal@45: return this.elem[ this.prop ]; bgneal@45: bgneal@45: var r = parseFloat(jQuery.css(this.elem, this.prop, force)); bgneal@45: return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0; bgneal@45: }, bgneal@45: bgneal@45: // Start an animation from one number to another bgneal@45: custom: function(from, to, unit){ bgneal@45: this.startTime = now(); bgneal@45: this.start = from; bgneal@45: this.end = to; bgneal@45: this.unit = unit || this.unit || "px"; bgneal@45: this.now = this.start; bgneal@45: this.pos = this.state = 0; bgneal@45: this.update(); bgneal@45: bgneal@45: var self = this; bgneal@45: function t(gotoEnd){ bgneal@45: return self.step(gotoEnd); bgneal@45: } bgneal@45: bgneal@45: t.elem = this.elem; bgneal@45: bgneal@45: jQuery.timers.push(t); bgneal@45: bgneal@45: if ( jQuery.timerId == null ) { bgneal@45: jQuery.timerId = setInterval(function(){ bgneal@45: var timers = jQuery.timers; bgneal@45: bgneal@45: for ( var i = 0; i < timers.length; i++ ) bgneal@45: if ( !timers[i]() ) bgneal@45: timers.splice(i--, 1); bgneal@45: bgneal@45: if ( !timers.length ) { bgneal@45: clearInterval( jQuery.timerId ); bgneal@45: jQuery.timerId = null; bgneal@45: } bgneal@45: }, 13); bgneal@45: } bgneal@45: }, bgneal@45: bgneal@45: // Simple 'show' function bgneal@45: show: function(){ bgneal@45: // Remember where we started, so that we can go back to it later bgneal@45: this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); bgneal@45: this.options.show = true; bgneal@45: bgneal@45: // Begin the animation bgneal@45: this.custom(0, this.cur()); bgneal@45: bgneal@45: // Make sure that we start at a small width/height to avoid any bgneal@45: // flash of content bgneal@45: if ( this.prop == "width" || this.prop == "height" ) bgneal@45: this.elem.style[this.prop] = "1px"; bgneal@45: bgneal@45: // Start by showing the element bgneal@45: jQuery(this.elem).show(); bgneal@45: }, bgneal@45: bgneal@45: // Simple 'hide' function bgneal@45: hide: function(){ bgneal@45: // Remember where we started, so that we can go back to it later bgneal@45: this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); bgneal@45: this.options.hide = true; bgneal@45: bgneal@45: // Begin the animation bgneal@45: this.custom(this.cur(), 0); bgneal@45: }, bgneal@45: bgneal@45: // Each step of an animation bgneal@45: step: function(gotoEnd){ bgneal@45: var t = now(); bgneal@45: bgneal@45: if ( gotoEnd || t > this.options.duration + this.startTime ) { bgneal@45: this.now = this.end; bgneal@45: this.pos = this.state = 1; bgneal@45: this.update(); bgneal@45: bgneal@45: this.options.curAnim[ this.prop ] = true; bgneal@45: bgneal@45: var done = true; bgneal@45: for ( var i in this.options.curAnim ) bgneal@45: if ( this.options.curAnim[i] !== true ) bgneal@45: done = false; bgneal@45: bgneal@45: if ( done ) { bgneal@45: if ( this.options.display != null ) { bgneal@45: // Reset the overflow bgneal@45: this.elem.style.overflow = this.options.overflow; bgneal@45: bgneal@45: // Reset the display bgneal@45: this.elem.style.display = this.options.display; bgneal@45: if ( jQuery.css(this.elem, "display") == "none" ) bgneal@45: this.elem.style.display = "block"; bgneal@45: } bgneal@45: bgneal@45: // Hide the element if the "hide" operation was done bgneal@45: if ( this.options.hide ) bgneal@45: this.elem.style.display = "none"; bgneal@45: bgneal@45: // Reset the properties, if the item has been hidden or shown bgneal@45: if ( this.options.hide || this.options.show ) bgneal@45: for ( var p in this.options.curAnim ) bgneal@45: jQuery.attr(this.elem.style, p, this.options.orig[p]); bgneal@45: } bgneal@45: bgneal@45: if ( done ) bgneal@45: // Execute the complete function bgneal@45: this.options.complete.call( this.elem ); bgneal@45: bgneal@45: return false; bgneal@45: } else { bgneal@45: var n = t - this.startTime; bgneal@45: this.state = n / this.options.duration; bgneal@45: bgneal@45: // Perform the easing function, defaults to swing bgneal@45: this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration); bgneal@45: this.now = this.start + ((this.end - this.start) * this.pos); bgneal@45: bgneal@45: // Perform the next step of the animation bgneal@45: this.update(); bgneal@45: } bgneal@45: bgneal@45: return true; bgneal@45: } bgneal@45: bgneal@45: }; bgneal@45: bgneal@45: jQuery.extend( jQuery.fx, { bgneal@45: speeds:{ bgneal@45: slow: 600, bgneal@45: fast: 200, bgneal@45: // Default speed bgneal@45: def: 400 bgneal@45: }, bgneal@45: step: { bgneal@45: scrollLeft: function(fx){ bgneal@45: fx.elem.scrollLeft = fx.now; bgneal@45: }, bgneal@45: bgneal@45: scrollTop: function(fx){ bgneal@45: fx.elem.scrollTop = fx.now; bgneal@45: }, bgneal@45: bgneal@45: opacity: function(fx){ bgneal@45: jQuery.attr(fx.elem.style, "opacity", fx.now); bgneal@45: }, bgneal@45: bgneal@45: _default: function(fx){ bgneal@45: fx.elem.style[ fx.prop ] = fx.now + fx.unit; bgneal@45: } bgneal@45: } bgneal@45: }); bgneal@45: // The Offset Method bgneal@45: // Originally By Brandon Aaron, part of the Dimension Plugin bgneal@45: // http://jquery.com/plugins/project/dimensions bgneal@45: jQuery.fn.offset = function() { bgneal@45: var left = 0, top = 0, elem = this[0], results; bgneal@45: bgneal@45: if ( elem ) with ( jQuery.browser ) { bgneal@45: var parent = elem.parentNode, bgneal@45: offsetChild = elem, bgneal@45: offsetParent = elem.offsetParent, bgneal@45: doc = elem.ownerDocument, bgneal@45: safari2 = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent), bgneal@45: css = jQuery.curCSS, bgneal@45: fixed = css(elem, "position") == "fixed"; bgneal@45: bgneal@45: // Use getBoundingClientRect if available bgneal@45: if ( !(mozilla && elem == document.body) && elem.getBoundingClientRect ) { bgneal@45: var box = elem.getBoundingClientRect(); bgneal@45: bgneal@45: // Add the document scroll offsets bgneal@45: add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), bgneal@45: box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop)); bgneal@45: bgneal@45: // IE adds the HTML element's border, by default it is medium which is 2px bgneal@45: // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; } bgneal@45: // IE 7 standards mode, the border is always 2px bgneal@45: // This border/offset is typically represented by the clientLeft and clientTop properties bgneal@45: // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS bgneal@45: // Therefore this method will be off by 2px in IE while in quirksmode bgneal@45: add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop ); bgneal@45: bgneal@45: // Otherwise loop through the offsetParents and parentNodes bgneal@45: } else { bgneal@45: bgneal@45: // Initial element offsets bgneal@45: add( elem.offsetLeft, elem.offsetTop ); bgneal@45: bgneal@45: // Get parent offsets bgneal@45: while ( offsetParent ) { bgneal@45: // Add offsetParent offsets bgneal@45: add( offsetParent.offsetLeft, offsetParent.offsetTop ); bgneal@45: bgneal@45: // Mozilla and Safari > 2 does not include the border on offset parents bgneal@45: // However Mozilla adds the border for table or table cells bgneal@45: if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 ) bgneal@45: border( offsetParent ); bgneal@45: bgneal@45: // Add the document scroll offsets if position is fixed on any offsetParent bgneal@45: if ( !fixed && css(offsetParent, "position") == "fixed" ) bgneal@45: fixed = true; bgneal@45: bgneal@45: // Set offsetChild to previous offsetParent unless it is the body element bgneal@45: offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent; bgneal@45: // Get next offsetParent bgneal@45: offsetParent = offsetParent.offsetParent; bgneal@45: } bgneal@45: bgneal@45: // Get parent scroll offsets bgneal@45: while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) { bgneal@45: // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug bgneal@45: if ( !/^inline|table.*$/i.test(css(parent, "display")) ) bgneal@45: // Subtract parent scroll offsets bgneal@45: add( -parent.scrollLeft, -parent.scrollTop ); bgneal@45: bgneal@45: // Mozilla does not add the border for a parent that has overflow != visible bgneal@45: if ( mozilla && css(parent, "overflow") != "visible" ) bgneal@45: border( parent ); bgneal@45: bgneal@45: // Get next parent bgneal@45: parent = parent.parentNode; bgneal@45: } bgneal@45: bgneal@45: // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild bgneal@45: // Mozilla doubles body offsets with a non-absolutely positioned offsetChild bgneal@45: if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) || bgneal@45: (mozilla && css(offsetChild, "position") != "absolute") ) bgneal@45: add( -doc.body.offsetLeft, -doc.body.offsetTop ); bgneal@45: bgneal@45: // Add the document scroll offsets if position is fixed bgneal@45: if ( fixed ) bgneal@45: add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), bgneal@45: Math.max(doc.documentElement.scrollTop, doc.body.scrollTop)); bgneal@45: } bgneal@45: bgneal@45: // Return an object with top and left properties bgneal@45: results = { top: top, left: left }; bgneal@45: } bgneal@45: bgneal@45: function border(elem) { bgneal@45: add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) ); bgneal@45: } bgneal@45: bgneal@45: function add(l, t) { bgneal@45: left += parseInt(l, 10) || 0; bgneal@45: top += parseInt(t, 10) || 0; bgneal@45: } bgneal@45: bgneal@45: return results; bgneal@45: }; bgneal@45: bgneal@45: bgneal@45: jQuery.fn.extend({ bgneal@45: position: function() { bgneal@45: var left = 0, top = 0, results; bgneal@45: bgneal@45: if ( this[0] ) { bgneal@45: // Get *real* offsetParent bgneal@45: var offsetParent = this.offsetParent(), bgneal@45: bgneal@45: // Get correct offsets bgneal@45: offset = this.offset(), bgneal@45: parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset(); bgneal@45: bgneal@45: // Subtract element margins bgneal@45: // note: when an element has margin: auto the offsetLeft and marginLeft bgneal@45: // are the same in Safari causing offset.left to incorrectly be 0 bgneal@45: offset.top -= num( this, 'marginTop' ); bgneal@45: offset.left -= num( this, 'marginLeft' ); bgneal@45: bgneal@45: // Add offsetParent borders bgneal@45: parentOffset.top += num( offsetParent, 'borderTopWidth' ); bgneal@45: parentOffset.left += num( offsetParent, 'borderLeftWidth' ); bgneal@45: bgneal@45: // Subtract the two offsets bgneal@45: results = { bgneal@45: top: offset.top - parentOffset.top, bgneal@45: left: offset.left - parentOffset.left bgneal@45: }; bgneal@45: } bgneal@45: bgneal@45: return results; bgneal@45: }, bgneal@45: bgneal@45: offsetParent: function() { bgneal@45: var offsetParent = this[0].offsetParent; bgneal@45: while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') ) bgneal@45: offsetParent = offsetParent.offsetParent; bgneal@45: return jQuery(offsetParent); bgneal@45: } bgneal@45: }); bgneal@45: bgneal@45: bgneal@45: // Create scrollLeft and scrollTop methods bgneal@45: jQuery.each( ['Left', 'Top'], function(i, name) { bgneal@45: var method = 'scroll' + name; bgneal@45: bgneal@45: jQuery.fn[ method ] = function(val) { bgneal@45: if (!this[0]) return; bgneal@45: bgneal@45: return val != undefined ? bgneal@45: bgneal@45: // Set the scroll offset bgneal@45: this.each(function() { bgneal@45: this == window || this == document ? bgneal@45: window.scrollTo( bgneal@45: !i ? val : jQuery(window).scrollLeft(), bgneal@45: i ? val : jQuery(window).scrollTop() bgneal@45: ) : bgneal@45: this[ method ] = val; bgneal@45: }) : bgneal@45: bgneal@45: // Return the scroll offset bgneal@45: this[0] == window || this[0] == document ? bgneal@45: self[ i ? 'pageYOffset' : 'pageXOffset' ] || bgneal@45: jQuery.boxModel && document.documentElement[ method ] || bgneal@45: document.body[ method ] : bgneal@45: this[0][ method ]; bgneal@45: }; bgneal@45: }); bgneal@45: // Create innerHeight, innerWidth, outerHeight and outerWidth methods bgneal@45: jQuery.each([ "Height", "Width" ], function(i, name){ bgneal@45: bgneal@45: var tl = i ? "Left" : "Top", // top or left bgneal@45: br = i ? "Right" : "Bottom"; // bottom or right bgneal@45: bgneal@45: // innerHeight and innerWidth bgneal@45: jQuery.fn["inner" + name] = function(){ bgneal@45: return this[ name.toLowerCase() ]() + bgneal@45: num(this, "padding" + tl) + bgneal@45: num(this, "padding" + br); bgneal@45: }; bgneal@45: bgneal@45: // outerHeight and outerWidth bgneal@45: jQuery.fn["outer" + name] = function(margin) { bgneal@45: return this["inner" + name]() + bgneal@45: num(this, "border" + tl + "Width") + bgneal@45: num(this, "border" + br + "Width") + bgneal@45: (margin ? bgneal@45: num(this, "margin" + tl) + num(this, "margin" + br) : 0); bgneal@45: }; bgneal@45: bgneal@45: });})();