annotate media/js/jquery-autocomplete/lib/jquery.js @ 141:861f7d5f1b23

Rework r149 for #30. Got rid of the custom index. Put my dashboard in the nav-global block instead.
author Brian Neal <bgneal@gmail.com>
date Sun, 06 Dec 2009 07:55:48 +0000
parents a5b4c5ce0658
children
rev   line source
bgneal@45 1 (function(){
bgneal@45 2 /*
bgneal@45 3 * jQuery 1.2.6 - New Wave Javascript
bgneal@45 4 *
bgneal@45 5 * Copyright (c) 2008 John Resig (jquery.com)
bgneal@45 6 * Dual licensed under the MIT (MIT-LICENSE.txt)
bgneal@45 7 * and GPL (GPL-LICENSE.txt) licenses.
bgneal@45 8 *
bgneal@45 9 * $Date: 2008-05-27 21:17:26 +0200 (Di, 27 Mai 2008) $
bgneal@45 10 * $Rev: 5700 $
bgneal@45 11 */
bgneal@45 12
bgneal@45 13 // Map over jQuery in case of overwrite
bgneal@45 14 var _jQuery = window.jQuery,
bgneal@45 15 // Map over the $ in case of overwrite
bgneal@45 16 _$ = window.$;
bgneal@45 17
bgneal@45 18 var jQuery = window.jQuery = window.$ = function( selector, context ) {
bgneal@45 19 // The jQuery object is actually just the init constructor 'enhanced'
bgneal@45 20 return new jQuery.fn.init( selector, context );
bgneal@45 21 };
bgneal@45 22
bgneal@45 23 // A simple way to check for HTML strings or ID strings
bgneal@45 24 // (both of which we optimize for)
bgneal@45 25 var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
bgneal@45 26
bgneal@45 27 // Is it a simple selector
bgneal@45 28 isSimple = /^.[^:#\[\.]*$/,
bgneal@45 29
bgneal@45 30 // Will speed up references to undefined, and allows munging its name.
bgneal@45 31 undefined;
bgneal@45 32
bgneal@45 33 jQuery.fn = jQuery.prototype = {
bgneal@45 34 init: function( selector, context ) {
bgneal@45 35 // Make sure that a selection was provided
bgneal@45 36 selector = selector || document;
bgneal@45 37
bgneal@45 38 // Handle $(DOMElement)
bgneal@45 39 if ( selector.nodeType ) {
bgneal@45 40 this[0] = selector;
bgneal@45 41 this.length = 1;
bgneal@45 42 return this;
bgneal@45 43 }
bgneal@45 44 // Handle HTML strings
bgneal@45 45 if ( typeof selector == "string" ) {
bgneal@45 46 // Are we dealing with HTML string or an ID?
bgneal@45 47 var match = quickExpr.exec( selector );
bgneal@45 48
bgneal@45 49 // Verify a match, and that no context was specified for #id
bgneal@45 50 if ( match && (match[1] || !context) ) {
bgneal@45 51
bgneal@45 52 // HANDLE: $(html) -> $(array)
bgneal@45 53 if ( match[1] )
bgneal@45 54 selector = jQuery.clean( [ match[1] ], context );
bgneal@45 55
bgneal@45 56 // HANDLE: $("#id")
bgneal@45 57 else {
bgneal@45 58 var elem = document.getElementById( match[3] );
bgneal@45 59
bgneal@45 60 // Make sure an element was located
bgneal@45 61 if ( elem ){
bgneal@45 62 // Handle the case where IE and Opera return items
bgneal@45 63 // by name instead of ID
bgneal@45 64 if ( elem.id != match[3] )
bgneal@45 65 return jQuery().find( selector );
bgneal@45 66
bgneal@45 67 // Otherwise, we inject the element directly into the jQuery object
bgneal@45 68 return jQuery( elem );
bgneal@45 69 }
bgneal@45 70 selector = [];
bgneal@45 71 }
bgneal@45 72
bgneal@45 73 // HANDLE: $(expr, [context])
bgneal@45 74 // (which is just equivalent to: $(content).find(expr)
bgneal@45 75 } else
bgneal@45 76 return jQuery( context ).find( selector );
bgneal@45 77
bgneal@45 78 // HANDLE: $(function)
bgneal@45 79 // Shortcut for document ready
bgneal@45 80 } else if ( jQuery.isFunction( selector ) )
bgneal@45 81 return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
bgneal@45 82
bgneal@45 83 return this.setArray(jQuery.makeArray(selector));
bgneal@45 84 },
bgneal@45 85
bgneal@45 86 // The current version of jQuery being used
bgneal@45 87 jquery: "1.2.6",
bgneal@45 88
bgneal@45 89 // The number of elements contained in the matched element set
bgneal@45 90 size: function() {
bgneal@45 91 return this.length;
bgneal@45 92 },
bgneal@45 93
bgneal@45 94 // The number of elements contained in the matched element set
bgneal@45 95 length: 0,
bgneal@45 96
bgneal@45 97 // Get the Nth element in the matched element set OR
bgneal@45 98 // Get the whole matched element set as a clean array
bgneal@45 99 get: function( num ) {
bgneal@45 100 return num == undefined ?
bgneal@45 101
bgneal@45 102 // Return a 'clean' array
bgneal@45 103 jQuery.makeArray( this ) :
bgneal@45 104
bgneal@45 105 // Return just the object
bgneal@45 106 this[ num ];
bgneal@45 107 },
bgneal@45 108
bgneal@45 109 // Take an array of elements and push it onto the stack
bgneal@45 110 // (returning the new matched element set)
bgneal@45 111 pushStack: function( elems ) {
bgneal@45 112 // Build a new jQuery matched element set
bgneal@45 113 var ret = jQuery( elems );
bgneal@45 114
bgneal@45 115 // Add the old object onto the stack (as a reference)
bgneal@45 116 ret.prevObject = this;
bgneal@45 117
bgneal@45 118 // Return the newly-formed element set
bgneal@45 119 return ret;
bgneal@45 120 },
bgneal@45 121
bgneal@45 122 // Force the current matched set of elements to become
bgneal@45 123 // the specified array of elements (destroying the stack in the process)
bgneal@45 124 // You should use pushStack() in order to do this, but maintain the stack
bgneal@45 125 setArray: function( elems ) {
bgneal@45 126 // Resetting the length to 0, then using the native Array push
bgneal@45 127 // is a super-fast way to populate an object with array-like properties
bgneal@45 128 this.length = 0;
bgneal@45 129 Array.prototype.push.apply( this, elems );
bgneal@45 130
bgneal@45 131 return this;
bgneal@45 132 },
bgneal@45 133
bgneal@45 134 // Execute a callback for every element in the matched set.
bgneal@45 135 // (You can seed the arguments with an array of args, but this is
bgneal@45 136 // only used internally.)
bgneal@45 137 each: function( callback, args ) {
bgneal@45 138 return jQuery.each( this, callback, args );
bgneal@45 139 },
bgneal@45 140
bgneal@45 141 // Determine the position of an element within
bgneal@45 142 // the matched set of elements
bgneal@45 143 index: function( elem ) {
bgneal@45 144 var ret = -1;
bgneal@45 145
bgneal@45 146 // Locate the position of the desired element
bgneal@45 147 return jQuery.inArray(
bgneal@45 148 // If it receives a jQuery object, the first element is used
bgneal@45 149 elem && elem.jquery ? elem[0] : elem
bgneal@45 150 , this );
bgneal@45 151 },
bgneal@45 152
bgneal@45 153 attr: function( name, value, type ) {
bgneal@45 154 var options = name;
bgneal@45 155
bgneal@45 156 // Look for the case where we're accessing a style value
bgneal@45 157 if ( name.constructor == String )
bgneal@45 158 if ( value === undefined )
bgneal@45 159 return this[0] && jQuery[ type || "attr" ]( this[0], name );
bgneal@45 160
bgneal@45 161 else {
bgneal@45 162 options = {};
bgneal@45 163 options[ name ] = value;
bgneal@45 164 }
bgneal@45 165
bgneal@45 166 // Check to see if we're setting style values
bgneal@45 167 return this.each(function(i){
bgneal@45 168 // Set all the styles
bgneal@45 169 for ( name in options )
bgneal@45 170 jQuery.attr(
bgneal@45 171 type ?
bgneal@45 172 this.style :
bgneal@45 173 this,
bgneal@45 174 name, jQuery.prop( this, options[ name ], type, i, name )
bgneal@45 175 );
bgneal@45 176 });
bgneal@45 177 },
bgneal@45 178
bgneal@45 179 css: function( key, value ) {
bgneal@45 180 // ignore negative width and height values
bgneal@45 181 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
bgneal@45 182 value = undefined;
bgneal@45 183 return this.attr( key, value, "curCSS" );
bgneal@45 184 },
bgneal@45 185
bgneal@45 186 text: function( text ) {
bgneal@45 187 if ( typeof text != "object" && text != null )
bgneal@45 188 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
bgneal@45 189
bgneal@45 190 var ret = "";
bgneal@45 191
bgneal@45 192 jQuery.each( text || this, function(){
bgneal@45 193 jQuery.each( this.childNodes, function(){
bgneal@45 194 if ( this.nodeType != 8 )
bgneal@45 195 ret += this.nodeType != 1 ?
bgneal@45 196 this.nodeValue :
bgneal@45 197 jQuery.fn.text( [ this ] );
bgneal@45 198 });
bgneal@45 199 });
bgneal@45 200
bgneal@45 201 return ret;
bgneal@45 202 },
bgneal@45 203
bgneal@45 204 wrapAll: function( html ) {
bgneal@45 205 if ( this[0] )
bgneal@45 206 // The elements to wrap the target around
bgneal@45 207 jQuery( html, this[0].ownerDocument )
bgneal@45 208 .clone()
bgneal@45 209 .insertBefore( this[0] )
bgneal@45 210 .map(function(){
bgneal@45 211 var elem = this;
bgneal@45 212
bgneal@45 213 while ( elem.firstChild )
bgneal@45 214 elem = elem.firstChild;
bgneal@45 215
bgneal@45 216 return elem;
bgneal@45 217 })
bgneal@45 218 .append(this);
bgneal@45 219
bgneal@45 220 return this;
bgneal@45 221 },
bgneal@45 222
bgneal@45 223 wrapInner: function( html ) {
bgneal@45 224 return this.each(function(){
bgneal@45 225 jQuery( this ).contents().wrapAll( html );
bgneal@45 226 });
bgneal@45 227 },
bgneal@45 228
bgneal@45 229 wrap: function( html ) {
bgneal@45 230 return this.each(function(){
bgneal@45 231 jQuery( this ).wrapAll( html );
bgneal@45 232 });
bgneal@45 233 },
bgneal@45 234
bgneal@45 235 append: function() {
bgneal@45 236 return this.domManip(arguments, true, false, function(elem){
bgneal@45 237 if (this.nodeType == 1)
bgneal@45 238 this.appendChild( elem );
bgneal@45 239 });
bgneal@45 240 },
bgneal@45 241
bgneal@45 242 prepend: function() {
bgneal@45 243 return this.domManip(arguments, true, true, function(elem){
bgneal@45 244 if (this.nodeType == 1)
bgneal@45 245 this.insertBefore( elem, this.firstChild );
bgneal@45 246 });
bgneal@45 247 },
bgneal@45 248
bgneal@45 249 before: function() {
bgneal@45 250 return this.domManip(arguments, false, false, function(elem){
bgneal@45 251 this.parentNode.insertBefore( elem, this );
bgneal@45 252 });
bgneal@45 253 },
bgneal@45 254
bgneal@45 255 after: function() {
bgneal@45 256 return this.domManip(arguments, false, true, function(elem){
bgneal@45 257 this.parentNode.insertBefore( elem, this.nextSibling );
bgneal@45 258 });
bgneal@45 259 },
bgneal@45 260
bgneal@45 261 end: function() {
bgneal@45 262 return this.prevObject || jQuery( [] );
bgneal@45 263 },
bgneal@45 264
bgneal@45 265 find: function( selector ) {
bgneal@45 266 var elems = jQuery.map(this, function(elem){
bgneal@45 267 return jQuery.find( selector, elem );
bgneal@45 268 });
bgneal@45 269
bgneal@45 270 return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
bgneal@45 271 jQuery.unique( elems ) :
bgneal@45 272 elems );
bgneal@45 273 },
bgneal@45 274
bgneal@45 275 clone: function( events ) {
bgneal@45 276 // Do the clone
bgneal@45 277 var ret = this.map(function(){
bgneal@45 278 if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
bgneal@45 279 // IE copies events bound via attachEvent when
bgneal@45 280 // using cloneNode. Calling detachEvent on the
bgneal@45 281 // clone will also remove the events from the orignal
bgneal@45 282 // In order to get around this, we use innerHTML.
bgneal@45 283 // Unfortunately, this means some modifications to
bgneal@45 284 // attributes in IE that are actually only stored
bgneal@45 285 // as properties will not be copied (such as the
bgneal@45 286 // the name attribute on an input).
bgneal@45 287 var clone = this.cloneNode(true),
bgneal@45 288 container = document.createElement("div");
bgneal@45 289 container.appendChild(clone);
bgneal@45 290 return jQuery.clean([container.innerHTML])[0];
bgneal@45 291 } else
bgneal@45 292 return this.cloneNode(true);
bgneal@45 293 });
bgneal@45 294
bgneal@45 295 // Need to set the expando to null on the cloned set if it exists
bgneal@45 296 // removeData doesn't work here, IE removes it from the original as well
bgneal@45 297 // this is primarily for IE but the data expando shouldn't be copied over in any browser
bgneal@45 298 var clone = ret.find("*").andSelf().each(function(){
bgneal@45 299 if ( this[ expando ] != undefined )
bgneal@45 300 this[ expando ] = null;
bgneal@45 301 });
bgneal@45 302
bgneal@45 303 // Copy the events from the original to the clone
bgneal@45 304 if ( events === true )
bgneal@45 305 this.find("*").andSelf().each(function(i){
bgneal@45 306 if (this.nodeType == 3)
bgneal@45 307 return;
bgneal@45 308 var events = jQuery.data( this, "events" );
bgneal@45 309
bgneal@45 310 for ( var type in events )
bgneal@45 311 for ( var handler in events[ type ] )
bgneal@45 312 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
bgneal@45 313 });
bgneal@45 314
bgneal@45 315 // Return the cloned set
bgneal@45 316 return ret;
bgneal@45 317 },
bgneal@45 318
bgneal@45 319 filter: function( selector ) {
bgneal@45 320 return this.pushStack(
bgneal@45 321 jQuery.isFunction( selector ) &&
bgneal@45 322 jQuery.grep(this, function(elem, i){
bgneal@45 323 return selector.call( elem, i );
bgneal@45 324 }) ||
bgneal@45 325
bgneal@45 326 jQuery.multiFilter( selector, this ) );
bgneal@45 327 },
bgneal@45 328
bgneal@45 329 not: function( selector ) {
bgneal@45 330 if ( selector.constructor == String )
bgneal@45 331 // test special case where just one selector is passed in
bgneal@45 332 if ( isSimple.test( selector ) )
bgneal@45 333 return this.pushStack( jQuery.multiFilter( selector, this, true ) );
bgneal@45 334 else
bgneal@45 335 selector = jQuery.multiFilter( selector, this );
bgneal@45 336
bgneal@45 337 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
bgneal@45 338 return this.filter(function() {
bgneal@45 339 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
bgneal@45 340 });
bgneal@45 341 },
bgneal@45 342
bgneal@45 343 add: function( selector ) {
bgneal@45 344 return this.pushStack( jQuery.unique( jQuery.merge(
bgneal@45 345 this.get(),
bgneal@45 346 typeof selector == 'string' ?
bgneal@45 347 jQuery( selector ) :
bgneal@45 348 jQuery.makeArray( selector )
bgneal@45 349 )));
bgneal@45 350 },
bgneal@45 351
bgneal@45 352 is: function( selector ) {
bgneal@45 353 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
bgneal@45 354 },
bgneal@45 355
bgneal@45 356 hasClass: function( selector ) {
bgneal@45 357 return this.is( "." + selector );
bgneal@45 358 },
bgneal@45 359
bgneal@45 360 val: function( value ) {
bgneal@45 361 if ( value == undefined ) {
bgneal@45 362
bgneal@45 363 if ( this.length ) {
bgneal@45 364 var elem = this[0];
bgneal@45 365
bgneal@45 366 // We need to handle select boxes special
bgneal@45 367 if ( jQuery.nodeName( elem, "select" ) ) {
bgneal@45 368 var index = elem.selectedIndex,
bgneal@45 369 values = [],
bgneal@45 370 options = elem.options,
bgneal@45 371 one = elem.type == "select-one";
bgneal@45 372
bgneal@45 373 // Nothing was selected
bgneal@45 374 if ( index < 0 )
bgneal@45 375 return null;
bgneal@45 376
bgneal@45 377 // Loop through all the selected options
bgneal@45 378 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
bgneal@45 379 var option = options[ i ];
bgneal@45 380
bgneal@45 381 if ( option.selected ) {
bgneal@45 382 // Get the specifc value for the option
bgneal@45 383 value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
bgneal@45 384
bgneal@45 385 // We don't need an array for one selects
bgneal@45 386 if ( one )
bgneal@45 387 return value;
bgneal@45 388
bgneal@45 389 // Multi-Selects return an array
bgneal@45 390 values.push( value );
bgneal@45 391 }
bgneal@45 392 }
bgneal@45 393
bgneal@45 394 return values;
bgneal@45 395
bgneal@45 396 // Everything else, we just grab the value
bgneal@45 397 } else
bgneal@45 398 return (this[0].value || "").replace(/\r/g, "");
bgneal@45 399
bgneal@45 400 }
bgneal@45 401
bgneal@45 402 return undefined;
bgneal@45 403 }
bgneal@45 404
bgneal@45 405 if( value.constructor == Number )
bgneal@45 406 value += '';
bgneal@45 407
bgneal@45 408 return this.each(function(){
bgneal@45 409 if ( this.nodeType != 1 )
bgneal@45 410 return;
bgneal@45 411
bgneal@45 412 if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
bgneal@45 413 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
bgneal@45 414 jQuery.inArray(this.name, value) >= 0);
bgneal@45 415
bgneal@45 416 else if ( jQuery.nodeName( this, "select" ) ) {
bgneal@45 417 var values = jQuery.makeArray(value);
bgneal@45 418
bgneal@45 419 jQuery( "option", this ).each(function(){
bgneal@45 420 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
bgneal@45 421 jQuery.inArray( this.text, values ) >= 0);
bgneal@45 422 });
bgneal@45 423
bgneal@45 424 if ( !values.length )
bgneal@45 425 this.selectedIndex = -1;
bgneal@45 426
bgneal@45 427 } else
bgneal@45 428 this.value = value;
bgneal@45 429 });
bgneal@45 430 },
bgneal@45 431
bgneal@45 432 html: function( value ) {
bgneal@45 433 return value == undefined ?
bgneal@45 434 (this[0] ?
bgneal@45 435 this[0].innerHTML :
bgneal@45 436 null) :
bgneal@45 437 this.empty().append( value );
bgneal@45 438 },
bgneal@45 439
bgneal@45 440 replaceWith: function( value ) {
bgneal@45 441 return this.after( value ).remove();
bgneal@45 442 },
bgneal@45 443
bgneal@45 444 eq: function( i ) {
bgneal@45 445 return this.slice( i, i + 1 );
bgneal@45 446 },
bgneal@45 447
bgneal@45 448 slice: function() {
bgneal@45 449 return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
bgneal@45 450 },
bgneal@45 451
bgneal@45 452 map: function( callback ) {
bgneal@45 453 return this.pushStack( jQuery.map(this, function(elem, i){
bgneal@45 454 return callback.call( elem, i, elem );
bgneal@45 455 }));
bgneal@45 456 },
bgneal@45 457
bgneal@45 458 andSelf: function() {
bgneal@45 459 return this.add( this.prevObject );
bgneal@45 460 },
bgneal@45 461
bgneal@45 462 data: function( key, value ){
bgneal@45 463 var parts = key.split(".");
bgneal@45 464 parts[1] = parts[1] ? "." + parts[1] : "";
bgneal@45 465
bgneal@45 466 if ( value === undefined ) {
bgneal@45 467 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
bgneal@45 468
bgneal@45 469 if ( data === undefined && this.length )
bgneal@45 470 data = jQuery.data( this[0], key );
bgneal@45 471
bgneal@45 472 return data === undefined && parts[1] ?
bgneal@45 473 this.data( parts[0] ) :
bgneal@45 474 data;
bgneal@45 475 } else
bgneal@45 476 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
bgneal@45 477 jQuery.data( this, key, value );
bgneal@45 478 });
bgneal@45 479 },
bgneal@45 480
bgneal@45 481 removeData: function( key ){
bgneal@45 482 return this.each(function(){
bgneal@45 483 jQuery.removeData( this, key );
bgneal@45 484 });
bgneal@45 485 },
bgneal@45 486
bgneal@45 487 domManip: function( args, table, reverse, callback ) {
bgneal@45 488 var clone = this.length > 1, elems;
bgneal@45 489
bgneal@45 490 return this.each(function(){
bgneal@45 491 if ( !elems ) {
bgneal@45 492 elems = jQuery.clean( args, this.ownerDocument );
bgneal@45 493
bgneal@45 494 if ( reverse )
bgneal@45 495 elems.reverse();
bgneal@45 496 }
bgneal@45 497
bgneal@45 498 var obj = this;
bgneal@45 499
bgneal@45 500 if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
bgneal@45 501 obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
bgneal@45 502
bgneal@45 503 var scripts = jQuery( [] );
bgneal@45 504
bgneal@45 505 jQuery.each(elems, function(){
bgneal@45 506 var elem = clone ?
bgneal@45 507 jQuery( this ).clone( true )[0] :
bgneal@45 508 this;
bgneal@45 509
bgneal@45 510 // execute all scripts after the elements have been injected
bgneal@45 511 if ( jQuery.nodeName( elem, "script" ) )
bgneal@45 512 scripts = scripts.add( elem );
bgneal@45 513 else {
bgneal@45 514 // Remove any inner scripts for later evaluation
bgneal@45 515 if ( elem.nodeType == 1 )
bgneal@45 516 scripts = scripts.add( jQuery( "script", elem ).remove() );
bgneal@45 517
bgneal@45 518 // Inject the elements into the document
bgneal@45 519 callback.call( obj, elem );
bgneal@45 520 }
bgneal@45 521 });
bgneal@45 522
bgneal@45 523 scripts.each( evalScript );
bgneal@45 524 });
bgneal@45 525 }
bgneal@45 526 };
bgneal@45 527
bgneal@45 528 // Give the init function the jQuery prototype for later instantiation
bgneal@45 529 jQuery.fn.init.prototype = jQuery.fn;
bgneal@45 530
bgneal@45 531 function evalScript( i, elem ) {
bgneal@45 532 if ( elem.src )
bgneal@45 533 jQuery.ajax({
bgneal@45 534 url: elem.src,
bgneal@45 535 async: false,
bgneal@45 536 dataType: "script"
bgneal@45 537 });
bgneal@45 538
bgneal@45 539 else
bgneal@45 540 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
bgneal@45 541
bgneal@45 542 if ( elem.parentNode )
bgneal@45 543 elem.parentNode.removeChild( elem );
bgneal@45 544 }
bgneal@45 545
bgneal@45 546 function now(){
bgneal@45 547 return +new Date;
bgneal@45 548 }
bgneal@45 549
bgneal@45 550 jQuery.extend = jQuery.fn.extend = function() {
bgneal@45 551 // copy reference to target object
bgneal@45 552 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
bgneal@45 553
bgneal@45 554 // Handle a deep copy situation
bgneal@45 555 if ( target.constructor == Boolean ) {
bgneal@45 556 deep = target;
bgneal@45 557 target = arguments[1] || {};
bgneal@45 558 // skip the boolean and the target
bgneal@45 559 i = 2;
bgneal@45 560 }
bgneal@45 561
bgneal@45 562 // Handle case when target is a string or something (possible in deep copy)
bgneal@45 563 if ( typeof target != "object" && typeof target != "function" )
bgneal@45 564 target = {};
bgneal@45 565
bgneal@45 566 // extend jQuery itself if only one argument is passed
bgneal@45 567 if ( length == i ) {
bgneal@45 568 target = this;
bgneal@45 569 --i;
bgneal@45 570 }
bgneal@45 571
bgneal@45 572 for ( ; i < length; i++ )
bgneal@45 573 // Only deal with non-null/undefined values
bgneal@45 574 if ( (options = arguments[ i ]) != null )
bgneal@45 575 // Extend the base object
bgneal@45 576 for ( var name in options ) {
bgneal@45 577 var src = target[ name ], copy = options[ name ];
bgneal@45 578
bgneal@45 579 // Prevent never-ending loop
bgneal@45 580 if ( target === copy )
bgneal@45 581 continue;
bgneal@45 582
bgneal@45 583 // Recurse if we're merging object values
bgneal@45 584 if ( deep && copy && typeof copy == "object" && !copy.nodeType )
bgneal@45 585 target[ name ] = jQuery.extend( deep,
bgneal@45 586 // Never move original objects, clone them
bgneal@45 587 src || ( copy.length != null ? [ ] : { } )
bgneal@45 588 , copy );
bgneal@45 589
bgneal@45 590 // Don't bring in undefined values
bgneal@45 591 else if ( copy !== undefined )
bgneal@45 592 target[ name ] = copy;
bgneal@45 593
bgneal@45 594 }
bgneal@45 595
bgneal@45 596 // Return the modified object
bgneal@45 597 return target;
bgneal@45 598 };
bgneal@45 599
bgneal@45 600 var expando = "jQuery" + now(), uuid = 0, windowData = {},
bgneal@45 601 // exclude the following css properties to add px
bgneal@45 602 exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
bgneal@45 603 // cache defaultView
bgneal@45 604 defaultView = document.defaultView || {};
bgneal@45 605
bgneal@45 606 jQuery.extend({
bgneal@45 607 noConflict: function( deep ) {
bgneal@45 608 window.$ = _$;
bgneal@45 609
bgneal@45 610 if ( deep )
bgneal@45 611 window.jQuery = _jQuery;
bgneal@45 612
bgneal@45 613 return jQuery;
bgneal@45 614 },
bgneal@45 615
bgneal@45 616 // See test/unit/core.js for details concerning this function.
bgneal@45 617 isFunction: function( fn ) {
bgneal@45 618 return !!fn && typeof fn != "string" && !fn.nodeName &&
bgneal@45 619 fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
bgneal@45 620 },
bgneal@45 621
bgneal@45 622 // check if an element is in a (or is an) XML document
bgneal@45 623 isXMLDoc: function( elem ) {
bgneal@45 624 return elem.documentElement && !elem.body ||
bgneal@45 625 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
bgneal@45 626 },
bgneal@45 627
bgneal@45 628 // Evalulates a script in a global context
bgneal@45 629 globalEval: function( data ) {
bgneal@45 630 data = jQuery.trim( data );
bgneal@45 631
bgneal@45 632 if ( data ) {
bgneal@45 633 // Inspired by code by Andrea Giammarchi
bgneal@45 634 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
bgneal@45 635 var head = document.getElementsByTagName("head")[0] || document.documentElement,
bgneal@45 636 script = document.createElement("script");
bgneal@45 637
bgneal@45 638 script.type = "text/javascript";
bgneal@45 639 if ( jQuery.browser.msie )
bgneal@45 640 script.text = data;
bgneal@45 641 else
bgneal@45 642 script.appendChild( document.createTextNode( data ) );
bgneal@45 643
bgneal@45 644 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
bgneal@45 645 // This arises when a base node is used (#2709).
bgneal@45 646 head.insertBefore( script, head.firstChild );
bgneal@45 647 head.removeChild( script );
bgneal@45 648 }
bgneal@45 649 },
bgneal@45 650
bgneal@45 651 nodeName: function( elem, name ) {
bgneal@45 652 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
bgneal@45 653 },
bgneal@45 654
bgneal@45 655 cache: {},
bgneal@45 656
bgneal@45 657 data: function( elem, name, data ) {
bgneal@45 658 elem = elem == window ?
bgneal@45 659 windowData :
bgneal@45 660 elem;
bgneal@45 661
bgneal@45 662 var id = elem[ expando ];
bgneal@45 663
bgneal@45 664 // Compute a unique ID for the element
bgneal@45 665 if ( !id )
bgneal@45 666 id = elem[ expando ] = ++uuid;
bgneal@45 667
bgneal@45 668 // Only generate the data cache if we're
bgneal@45 669 // trying to access or manipulate it
bgneal@45 670 if ( name && !jQuery.cache[ id ] )
bgneal@45 671 jQuery.cache[ id ] = {};
bgneal@45 672
bgneal@45 673 // Prevent overriding the named cache with undefined values
bgneal@45 674 if ( data !== undefined )
bgneal@45 675 jQuery.cache[ id ][ name ] = data;
bgneal@45 676
bgneal@45 677 // Return the named cache data, or the ID for the element
bgneal@45 678 return name ?
bgneal@45 679 jQuery.cache[ id ][ name ] :
bgneal@45 680 id;
bgneal@45 681 },
bgneal@45 682
bgneal@45 683 removeData: function( elem, name ) {
bgneal@45 684 elem = elem == window ?
bgneal@45 685 windowData :
bgneal@45 686 elem;
bgneal@45 687
bgneal@45 688 var id = elem[ expando ];
bgneal@45 689
bgneal@45 690 // If we want to remove a specific section of the element's data
bgneal@45 691 if ( name ) {
bgneal@45 692 if ( jQuery.cache[ id ] ) {
bgneal@45 693 // Remove the section of cache data
bgneal@45 694 delete jQuery.cache[ id ][ name ];
bgneal@45 695
bgneal@45 696 // If we've removed all the data, remove the element's cache
bgneal@45 697 name = "";
bgneal@45 698
bgneal@45 699 for ( name in jQuery.cache[ id ] )
bgneal@45 700 break;
bgneal@45 701
bgneal@45 702 if ( !name )
bgneal@45 703 jQuery.removeData( elem );
bgneal@45 704 }
bgneal@45 705
bgneal@45 706 // Otherwise, we want to remove all of the element's data
bgneal@45 707 } else {
bgneal@45 708 // Clean up the element expando
bgneal@45 709 try {
bgneal@45 710 delete elem[ expando ];
bgneal@45 711 } catch(e){
bgneal@45 712 // IE has trouble directly removing the expando
bgneal@45 713 // but it's ok with using removeAttribute
bgneal@45 714 if ( elem.removeAttribute )
bgneal@45 715 elem.removeAttribute( expando );
bgneal@45 716 }
bgneal@45 717
bgneal@45 718 // Completely remove the data cache
bgneal@45 719 delete jQuery.cache[ id ];
bgneal@45 720 }
bgneal@45 721 },
bgneal@45 722
bgneal@45 723 // args is for internal usage only
bgneal@45 724 each: function( object, callback, args ) {
bgneal@45 725 var name, i = 0, length = object.length;
bgneal@45 726
bgneal@45 727 if ( args ) {
bgneal@45 728 if ( length == undefined ) {
bgneal@45 729 for ( name in object )
bgneal@45 730 if ( callback.apply( object[ name ], args ) === false )
bgneal@45 731 break;
bgneal@45 732 } else
bgneal@45 733 for ( ; i < length; )
bgneal@45 734 if ( callback.apply( object[ i++ ], args ) === false )
bgneal@45 735 break;
bgneal@45 736
bgneal@45 737 // A special, fast, case for the most common use of each
bgneal@45 738 } else {
bgneal@45 739 if ( length == undefined ) {
bgneal@45 740 for ( name in object )
bgneal@45 741 if ( callback.call( object[ name ], name, object[ name ] ) === false )
bgneal@45 742 break;
bgneal@45 743 } else
bgneal@45 744 for ( var value = object[0];
bgneal@45 745 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
bgneal@45 746 }
bgneal@45 747
bgneal@45 748 return object;
bgneal@45 749 },
bgneal@45 750
bgneal@45 751 prop: function( elem, value, type, i, name ) {
bgneal@45 752 // Handle executable functions
bgneal@45 753 if ( jQuery.isFunction( value ) )
bgneal@45 754 value = value.call( elem, i );
bgneal@45 755
bgneal@45 756 // Handle passing in a number to a CSS property
bgneal@45 757 return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
bgneal@45 758 value + "px" :
bgneal@45 759 value;
bgneal@45 760 },
bgneal@45 761
bgneal@45 762 className: {
bgneal@45 763 // internal only, use addClass("class")
bgneal@45 764 add: function( elem, classNames ) {
bgneal@45 765 jQuery.each((classNames || "").split(/\s+/), function(i, className){
bgneal@45 766 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
bgneal@45 767 elem.className += (elem.className ? " " : "") + className;
bgneal@45 768 });
bgneal@45 769 },
bgneal@45 770
bgneal@45 771 // internal only, use removeClass("class")
bgneal@45 772 remove: function( elem, classNames ) {
bgneal@45 773 if (elem.nodeType == 1)
bgneal@45 774 elem.className = classNames != undefined ?
bgneal@45 775 jQuery.grep(elem.className.split(/\s+/), function(className){
bgneal@45 776 return !jQuery.className.has( classNames, className );
bgneal@45 777 }).join(" ") :
bgneal@45 778 "";
bgneal@45 779 },
bgneal@45 780
bgneal@45 781 // internal only, use hasClass("class")
bgneal@45 782 has: function( elem, className ) {
bgneal@45 783 return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
bgneal@45 784 }
bgneal@45 785 },
bgneal@45 786
bgneal@45 787 // A method for quickly swapping in/out CSS properties to get correct calculations
bgneal@45 788 swap: function( elem, options, callback ) {
bgneal@45 789 var old = {};
bgneal@45 790 // Remember the old values, and insert the new ones
bgneal@45 791 for ( var name in options ) {
bgneal@45 792 old[ name ] = elem.style[ name ];
bgneal@45 793 elem.style[ name ] = options[ name ];
bgneal@45 794 }
bgneal@45 795
bgneal@45 796 callback.call( elem );
bgneal@45 797
bgneal@45 798 // Revert the old values
bgneal@45 799 for ( var name in options )
bgneal@45 800 elem.style[ name ] = old[ name ];
bgneal@45 801 },
bgneal@45 802
bgneal@45 803 css: function( elem, name, force ) {
bgneal@45 804 if ( name == "width" || name == "height" ) {
bgneal@45 805 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
bgneal@45 806
bgneal@45 807 function getWH() {
bgneal@45 808 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
bgneal@45 809 var padding = 0, border = 0;
bgneal@45 810 jQuery.each( which, function() {
bgneal@45 811 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
bgneal@45 812 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
bgneal@45 813 });
bgneal@45 814 val -= Math.round(padding + border);
bgneal@45 815 }
bgneal@45 816
bgneal@45 817 if ( jQuery(elem).is(":visible") )
bgneal@45 818 getWH();
bgneal@45 819 else
bgneal@45 820 jQuery.swap( elem, props, getWH );
bgneal@45 821
bgneal@45 822 return Math.max(0, val);
bgneal@45 823 }
bgneal@45 824
bgneal@45 825 return jQuery.curCSS( elem, name, force );
bgneal@45 826 },
bgneal@45 827
bgneal@45 828 curCSS: function( elem, name, force ) {
bgneal@45 829 var ret, style = elem.style;
bgneal@45 830
bgneal@45 831 // A helper method for determining if an element's values are broken
bgneal@45 832 function color( elem ) {
bgneal@45 833 if ( !jQuery.browser.safari )
bgneal@45 834 return false;
bgneal@45 835
bgneal@45 836 // defaultView is cached
bgneal@45 837 var ret = defaultView.getComputedStyle( elem, null );
bgneal@45 838 return !ret || ret.getPropertyValue("color") == "";
bgneal@45 839 }
bgneal@45 840
bgneal@45 841 // We need to handle opacity special in IE
bgneal@45 842 if ( name == "opacity" && jQuery.browser.msie ) {
bgneal@45 843 ret = jQuery.attr( style, "opacity" );
bgneal@45 844
bgneal@45 845 return ret == "" ?
bgneal@45 846 "1" :
bgneal@45 847 ret;
bgneal@45 848 }
bgneal@45 849 // Opera sometimes will give the wrong display answer, this fixes it, see #2037
bgneal@45 850 if ( jQuery.browser.opera && name == "display" ) {
bgneal@45 851 var save = style.outline;
bgneal@45 852 style.outline = "0 solid black";
bgneal@45 853 style.outline = save;
bgneal@45 854 }
bgneal@45 855
bgneal@45 856 // Make sure we're using the right name for getting the float value
bgneal@45 857 if ( name.match( /float/i ) )
bgneal@45 858 name = styleFloat;
bgneal@45 859
bgneal@45 860 if ( !force && style && style[ name ] )
bgneal@45 861 ret = style[ name ];
bgneal@45 862
bgneal@45 863 else if ( defaultView.getComputedStyle ) {
bgneal@45 864
bgneal@45 865 // Only "float" is needed here
bgneal@45 866 if ( name.match( /float/i ) )
bgneal@45 867 name = "float";
bgneal@45 868
bgneal@45 869 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
bgneal@45 870
bgneal@45 871 var computedStyle = defaultView.getComputedStyle( elem, null );
bgneal@45 872
bgneal@45 873 if ( computedStyle && !color( elem ) )
bgneal@45 874 ret = computedStyle.getPropertyValue( name );
bgneal@45 875
bgneal@45 876 // If the element isn't reporting its values properly in Safari
bgneal@45 877 // then some display: none elements are involved
bgneal@45 878 else {
bgneal@45 879 var swap = [], stack = [], a = elem, i = 0;
bgneal@45 880
bgneal@45 881 // Locate all of the parent display: none elements
bgneal@45 882 for ( ; a && color(a); a = a.parentNode )
bgneal@45 883 stack.unshift(a);
bgneal@45 884
bgneal@45 885 // Go through and make them visible, but in reverse
bgneal@45 886 // (It would be better if we knew the exact display type that they had)
bgneal@45 887 for ( ; i < stack.length; i++ )
bgneal@45 888 if ( color( stack[ i ] ) ) {
bgneal@45 889 swap[ i ] = stack[ i ].style.display;
bgneal@45 890 stack[ i ].style.display = "block";
bgneal@45 891 }
bgneal@45 892
bgneal@45 893 // Since we flip the display style, we have to handle that
bgneal@45 894 // one special, otherwise get the value
bgneal@45 895 ret = name == "display" && swap[ stack.length - 1 ] != null ?
bgneal@45 896 "none" :
bgneal@45 897 ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
bgneal@45 898
bgneal@45 899 // Finally, revert the display styles back
bgneal@45 900 for ( i = 0; i < swap.length; i++ )
bgneal@45 901 if ( swap[ i ] != null )
bgneal@45 902 stack[ i ].style.display = swap[ i ];
bgneal@45 903 }
bgneal@45 904
bgneal@45 905 // We should always get a number back from opacity
bgneal@45 906 if ( name == "opacity" && ret == "" )
bgneal@45 907 ret = "1";
bgneal@45 908
bgneal@45 909 } else if ( elem.currentStyle ) {
bgneal@45 910 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
bgneal@45 911 return letter.toUpperCase();
bgneal@45 912 });
bgneal@45 913
bgneal@45 914 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
bgneal@45 915
bgneal@45 916 // From the awesome hack by Dean Edwards
bgneal@45 917 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
bgneal@45 918
bgneal@45 919 // If we're not dealing with a regular pixel number
bgneal@45 920 // but a number that has a weird ending, we need to convert it to pixels
bgneal@45 921 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
bgneal@45 922 // Remember the original values
bgneal@45 923 var left = style.left, rsLeft = elem.runtimeStyle.left;
bgneal@45 924
bgneal@45 925 // Put in the new values to get a computed value out
bgneal@45 926 elem.runtimeStyle.left = elem.currentStyle.left;
bgneal@45 927 style.left = ret || 0;
bgneal@45 928 ret = style.pixelLeft + "px";
bgneal@45 929
bgneal@45 930 // Revert the changed values
bgneal@45 931 style.left = left;
bgneal@45 932 elem.runtimeStyle.left = rsLeft;
bgneal@45 933 }
bgneal@45 934 }
bgneal@45 935
bgneal@45 936 return ret;
bgneal@45 937 },
bgneal@45 938
bgneal@45 939 clean: function( elems, context ) {
bgneal@45 940 var ret = [];
bgneal@45 941 context = context || document;
bgneal@45 942 // !context.createElement fails in IE with an error but returns typeof 'object'
bgneal@45 943 if (typeof context.createElement == 'undefined')
bgneal@45 944 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
bgneal@45 945
bgneal@45 946 jQuery.each(elems, function(i, elem){
bgneal@45 947 if ( !elem )
bgneal@45 948 return;
bgneal@45 949
bgneal@45 950 if ( elem.constructor == Number )
bgneal@45 951 elem += '';
bgneal@45 952
bgneal@45 953 // Convert html string into DOM nodes
bgneal@45 954 if ( typeof elem == "string" ) {
bgneal@45 955 // Fix "XHTML"-style tags in all browsers
bgneal@45 956 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
bgneal@45 957 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
bgneal@45 958 all :
bgneal@45 959 front + "></" + tag + ">";
bgneal@45 960 });
bgneal@45 961
bgneal@45 962 // Trim whitespace, otherwise indexOf won't work as expected
bgneal@45 963 var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
bgneal@45 964
bgneal@45 965 var wrap =
bgneal@45 966 // option or optgroup
bgneal@45 967 !tags.indexOf("<opt") &&
bgneal@45 968 [ 1, "<select multiple='multiple'>", "</select>" ] ||
bgneal@45 969
bgneal@45 970 !tags.indexOf("<leg") &&
bgneal@45 971 [ 1, "<fieldset>", "</fieldset>" ] ||
bgneal@45 972
bgneal@45 973 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
bgneal@45 974 [ 1, "<table>", "</table>" ] ||
bgneal@45 975
bgneal@45 976 !tags.indexOf("<tr") &&
bgneal@45 977 [ 2, "<table><tbody>", "</tbody></table>" ] ||
bgneal@45 978
bgneal@45 979 // <thead> matched above
bgneal@45 980 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
bgneal@45 981 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
bgneal@45 982
bgneal@45 983 !tags.indexOf("<col") &&
bgneal@45 984 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
bgneal@45 985
bgneal@45 986 // IE can't serialize <link> and <script> tags normally
bgneal@45 987 jQuery.browser.msie &&
bgneal@45 988 [ 1, "div<div>", "</div>" ] ||
bgneal@45 989
bgneal@45 990 [ 0, "", "" ];
bgneal@45 991
bgneal@45 992 // Go to html and back, then peel off extra wrappers
bgneal@45 993 div.innerHTML = wrap[1] + elem + wrap[2];
bgneal@45 994
bgneal@45 995 // Move to the right depth
bgneal@45 996 while ( wrap[0]-- )
bgneal@45 997 div = div.lastChild;
bgneal@45 998
bgneal@45 999 // Remove IE's autoinserted <tbody> from table fragments
bgneal@45 1000 if ( jQuery.browser.msie ) {
bgneal@45 1001
bgneal@45 1002 // String was a <table>, *may* have spurious <tbody>
bgneal@45 1003 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
bgneal@45 1004 div.firstChild && div.firstChild.childNodes :
bgneal@45 1005
bgneal@45 1006 // String was a bare <thead> or <tfoot>
bgneal@45 1007 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
bgneal@45 1008 div.childNodes :
bgneal@45 1009 [];
bgneal@45 1010
bgneal@45 1011 for ( var j = tbody.length - 1; j >= 0 ; --j )
bgneal@45 1012 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
bgneal@45 1013 tbody[ j ].parentNode.removeChild( tbody[ j ] );
bgneal@45 1014
bgneal@45 1015 // IE completely kills leading whitespace when innerHTML is used
bgneal@45 1016 if ( /^\s/.test( elem ) )
bgneal@45 1017 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
bgneal@45 1018
bgneal@45 1019 }
bgneal@45 1020
bgneal@45 1021 elem = jQuery.makeArray( div.childNodes );
bgneal@45 1022 }
bgneal@45 1023
bgneal@45 1024 if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
bgneal@45 1025 return;
bgneal@45 1026
bgneal@45 1027 if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
bgneal@45 1028 ret.push( elem );
bgneal@45 1029
bgneal@45 1030 else
bgneal@45 1031 ret = jQuery.merge( ret, elem );
bgneal@45 1032
bgneal@45 1033 });
bgneal@45 1034
bgneal@45 1035 return ret;
bgneal@45 1036 },
bgneal@45 1037
bgneal@45 1038 attr: function( elem, name, value ) {
bgneal@45 1039 // don't set attributes on text and comment nodes
bgneal@45 1040 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
bgneal@45 1041 return undefined;
bgneal@45 1042
bgneal@45 1043 var notxml = !jQuery.isXMLDoc( elem ),
bgneal@45 1044 // Whether we are setting (or getting)
bgneal@45 1045 set = value !== undefined,
bgneal@45 1046 msie = jQuery.browser.msie;
bgneal@45 1047
bgneal@45 1048 // Try to normalize/fix the name
bgneal@45 1049 name = notxml && jQuery.props[ name ] || name;
bgneal@45 1050
bgneal@45 1051 // Only do all the following if this is a node (faster for style)
bgneal@45 1052 // IE elem.getAttribute passes even for style
bgneal@45 1053 if ( elem.tagName ) {
bgneal@45 1054
bgneal@45 1055 // These attributes require special treatment
bgneal@45 1056 var special = /href|src|style/.test( name );
bgneal@45 1057
bgneal@45 1058 // Safari mis-reports the default selected property of a hidden option
bgneal@45 1059 // Accessing the parent's selectedIndex property fixes it
bgneal@45 1060 if ( name == "selected" && jQuery.browser.safari )
bgneal@45 1061 elem.parentNode.selectedIndex;
bgneal@45 1062
bgneal@45 1063 // If applicable, access the attribute via the DOM 0 way
bgneal@45 1064 if ( name in elem && notxml && !special ) {
bgneal@45 1065 if ( set ){
bgneal@45 1066 // We can't allow the type property to be changed (since it causes problems in IE)
bgneal@45 1067 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
bgneal@45 1068 throw "type property can't be changed";
bgneal@45 1069
bgneal@45 1070 elem[ name ] = value;
bgneal@45 1071 }
bgneal@45 1072
bgneal@45 1073 // browsers index elements by id/name on forms, give priority to attributes.
bgneal@45 1074 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
bgneal@45 1075 return elem.getAttributeNode( name ).nodeValue;
bgneal@45 1076
bgneal@45 1077 return elem[ name ];
bgneal@45 1078 }
bgneal@45 1079
bgneal@45 1080 if ( msie && notxml && name == "style" )
bgneal@45 1081 return jQuery.attr( elem.style, "cssText", value );
bgneal@45 1082
bgneal@45 1083 if ( set )
bgneal@45 1084 // convert the value to a string (all browsers do this but IE) see #1070
bgneal@45 1085 elem.setAttribute( name, "" + value );
bgneal@45 1086
bgneal@45 1087 var attr = msie && notxml && special
bgneal@45 1088 // Some attributes require a special call on IE
bgneal@45 1089 ? elem.getAttribute( name, 2 )
bgneal@45 1090 : elem.getAttribute( name );
bgneal@45 1091
bgneal@45 1092 // Non-existent attributes return null, we normalize to undefined
bgneal@45 1093 return attr === null ? undefined : attr;
bgneal@45 1094 }
bgneal@45 1095
bgneal@45 1096 // elem is actually elem.style ... set the style
bgneal@45 1097
bgneal@45 1098 // IE uses filters for opacity
bgneal@45 1099 if ( msie && name == "opacity" ) {
bgneal@45 1100 if ( set ) {
bgneal@45 1101 // IE has trouble with opacity if it does not have layout
bgneal@45 1102 // Force it by setting the zoom level
bgneal@45 1103 elem.zoom = 1;
bgneal@45 1104
bgneal@45 1105 // Set the alpha filter to set the opacity
bgneal@45 1106 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
bgneal@45 1107 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
bgneal@45 1108 }
bgneal@45 1109
bgneal@45 1110 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
bgneal@45 1111 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
bgneal@45 1112 "";
bgneal@45 1113 }
bgneal@45 1114
bgneal@45 1115 name = name.replace(/-([a-z])/ig, function(all, letter){
bgneal@45 1116 return letter.toUpperCase();
bgneal@45 1117 });
bgneal@45 1118
bgneal@45 1119 if ( set )
bgneal@45 1120 elem[ name ] = value;
bgneal@45 1121
bgneal@45 1122 return elem[ name ];
bgneal@45 1123 },
bgneal@45 1124
bgneal@45 1125 trim: function( text ) {
bgneal@45 1126 return (text || "").replace( /^\s+|\s+$/g, "" );
bgneal@45 1127 },
bgneal@45 1128
bgneal@45 1129 makeArray: function( array ) {
bgneal@45 1130 var ret = [];
bgneal@45 1131
bgneal@45 1132 if( array != null ){
bgneal@45 1133 var i = array.length;
bgneal@45 1134 //the window, strings and functions also have 'length'
bgneal@45 1135 if( i == null || array.split || array.setInterval || array.call )
bgneal@45 1136 ret[0] = array;
bgneal@45 1137 else
bgneal@45 1138 while( i )
bgneal@45 1139 ret[--i] = array[i];
bgneal@45 1140 }
bgneal@45 1141
bgneal@45 1142 return ret;
bgneal@45 1143 },
bgneal@45 1144
bgneal@45 1145 inArray: function( elem, array ) {
bgneal@45 1146 for ( var i = 0, length = array.length; i < length; i++ )
bgneal@45 1147 // Use === because on IE, window == document
bgneal@45 1148 if ( array[ i ] === elem )
bgneal@45 1149 return i;
bgneal@45 1150
bgneal@45 1151 return -1;
bgneal@45 1152 },
bgneal@45 1153
bgneal@45 1154 merge: function( first, second ) {
bgneal@45 1155 // We have to loop this way because IE & Opera overwrite the length
bgneal@45 1156 // expando of getElementsByTagName
bgneal@45 1157 var i = 0, elem, pos = first.length;
bgneal@45 1158 // Also, we need to make sure that the correct elements are being returned
bgneal@45 1159 // (IE returns comment nodes in a '*' query)
bgneal@45 1160 if ( jQuery.browser.msie ) {
bgneal@45 1161 while ( elem = second[ i++ ] )
bgneal@45 1162 if ( elem.nodeType != 8 )
bgneal@45 1163 first[ pos++ ] = elem;
bgneal@45 1164
bgneal@45 1165 } else
bgneal@45 1166 while ( elem = second[ i++ ] )
bgneal@45 1167 first[ pos++ ] = elem;
bgneal@45 1168
bgneal@45 1169 return first;
bgneal@45 1170 },
bgneal@45 1171
bgneal@45 1172 unique: function( array ) {
bgneal@45 1173 var ret = [], done = {};
bgneal@45 1174
bgneal@45 1175 try {
bgneal@45 1176
bgneal@45 1177 for ( var i = 0, length = array.length; i < length; i++ ) {
bgneal@45 1178 var id = jQuery.data( array[ i ] );
bgneal@45 1179
bgneal@45 1180 if ( !done[ id ] ) {
bgneal@45 1181 done[ id ] = true;
bgneal@45 1182 ret.push( array[ i ] );
bgneal@45 1183 }
bgneal@45 1184 }
bgneal@45 1185
bgneal@45 1186 } catch( e ) {
bgneal@45 1187 ret = array;
bgneal@45 1188 }
bgneal@45 1189
bgneal@45 1190 return ret;
bgneal@45 1191 },
bgneal@45 1192
bgneal@45 1193 grep: function( elems, callback, inv ) {
bgneal@45 1194 var ret = [];
bgneal@45 1195
bgneal@45 1196 // Go through the array, only saving the items
bgneal@45 1197 // that pass the validator function
bgneal@45 1198 for ( var i = 0, length = elems.length; i < length; i++ )
bgneal@45 1199 if ( !inv != !callback( elems[ i ], i ) )
bgneal@45 1200 ret.push( elems[ i ] );
bgneal@45 1201
bgneal@45 1202 return ret;
bgneal@45 1203 },
bgneal@45 1204
bgneal@45 1205 map: function( elems, callback ) {
bgneal@45 1206 var ret = [];
bgneal@45 1207
bgneal@45 1208 // Go through the array, translating each of the items to their
bgneal@45 1209 // new value (or values).
bgneal@45 1210 for ( var i = 0, length = elems.length; i < length; i++ ) {
bgneal@45 1211 var value = callback( elems[ i ], i );
bgneal@45 1212
bgneal@45 1213 if ( value != null )
bgneal@45 1214 ret[ ret.length ] = value;
bgneal@45 1215 }
bgneal@45 1216
bgneal@45 1217 return ret.concat.apply( [], ret );
bgneal@45 1218 }
bgneal@45 1219 });
bgneal@45 1220
bgneal@45 1221 var userAgent = navigator.userAgent.toLowerCase();
bgneal@45 1222
bgneal@45 1223 // Figure out what browser is being used
bgneal@45 1224 jQuery.browser = {
bgneal@45 1225 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
bgneal@45 1226 safari: /webkit/.test( userAgent ),
bgneal@45 1227 opera: /opera/.test( userAgent ),
bgneal@45 1228 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
bgneal@45 1229 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
bgneal@45 1230 };
bgneal@45 1231
bgneal@45 1232 var styleFloat = jQuery.browser.msie ?
bgneal@45 1233 "styleFloat" :
bgneal@45 1234 "cssFloat";
bgneal@45 1235
bgneal@45 1236 jQuery.extend({
bgneal@45 1237 // Check to see if the W3C box model is being used
bgneal@45 1238 boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
bgneal@45 1239
bgneal@45 1240 props: {
bgneal@45 1241 "for": "htmlFor",
bgneal@45 1242 "class": "className",
bgneal@45 1243 "float": styleFloat,
bgneal@45 1244 cssFloat: styleFloat,
bgneal@45 1245 styleFloat: styleFloat,
bgneal@45 1246 readonly: "readOnly",
bgneal@45 1247 maxlength: "maxLength",
bgneal@45 1248 cellspacing: "cellSpacing",
bgneal@45 1249 rowspan: "rowSpan"
bgneal@45 1250 }
bgneal@45 1251 });
bgneal@45 1252
bgneal@45 1253 jQuery.each({
bgneal@45 1254 parent: function(elem){return elem.parentNode;},
bgneal@45 1255 parents: function(elem){return jQuery.dir(elem,"parentNode");},
bgneal@45 1256 next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
bgneal@45 1257 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
bgneal@45 1258 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
bgneal@45 1259 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
bgneal@45 1260 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
bgneal@45 1261 children: function(elem){return jQuery.sibling(elem.firstChild);},
bgneal@45 1262 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
bgneal@45 1263 }, function(name, fn){
bgneal@45 1264 jQuery.fn[ name ] = function( selector ) {
bgneal@45 1265 var ret = jQuery.map( this, fn );
bgneal@45 1266
bgneal@45 1267 if ( selector && typeof selector == "string" )
bgneal@45 1268 ret = jQuery.multiFilter( selector, ret );
bgneal@45 1269
bgneal@45 1270 return this.pushStack( jQuery.unique( ret ) );
bgneal@45 1271 };
bgneal@45 1272 });
bgneal@45 1273
bgneal@45 1274 jQuery.each({
bgneal@45 1275 appendTo: "append",
bgneal@45 1276 prependTo: "prepend",
bgneal@45 1277 insertBefore: "before",
bgneal@45 1278 insertAfter: "after",
bgneal@45 1279 replaceAll: "replaceWith"
bgneal@45 1280 }, function(name, original){
bgneal@45 1281 jQuery.fn[ name ] = function() {
bgneal@45 1282 var args = arguments;
bgneal@45 1283
bgneal@45 1284 return this.each(function(){
bgneal@45 1285 for ( var i = 0, length = args.length; i < length; i++ )
bgneal@45 1286 jQuery( args[ i ] )[ original ]( this );
bgneal@45 1287 });
bgneal@45 1288 };
bgneal@45 1289 });
bgneal@45 1290
bgneal@45 1291 jQuery.each({
bgneal@45 1292 removeAttr: function( name ) {
bgneal@45 1293 jQuery.attr( this, name, "" );
bgneal@45 1294 if (this.nodeType == 1)
bgneal@45 1295 this.removeAttribute( name );
bgneal@45 1296 },
bgneal@45 1297
bgneal@45 1298 addClass: function( classNames ) {
bgneal@45 1299 jQuery.className.add( this, classNames );
bgneal@45 1300 },
bgneal@45 1301
bgneal@45 1302 removeClass: function( classNames ) {
bgneal@45 1303 jQuery.className.remove( this, classNames );
bgneal@45 1304 },
bgneal@45 1305
bgneal@45 1306 toggleClass: function( classNames ) {
bgneal@45 1307 jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
bgneal@45 1308 },
bgneal@45 1309
bgneal@45 1310 remove: function( selector ) {
bgneal@45 1311 if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
bgneal@45 1312 // Prevent memory leaks
bgneal@45 1313 jQuery( "*", this ).add(this).each(function(){
bgneal@45 1314 jQuery.event.remove(this);
bgneal@45 1315 jQuery.removeData(this);
bgneal@45 1316 });
bgneal@45 1317 if (this.parentNode)
bgneal@45 1318 this.parentNode.removeChild( this );
bgneal@45 1319 }
bgneal@45 1320 },
bgneal@45 1321
bgneal@45 1322 empty: function() {
bgneal@45 1323 // Remove element nodes and prevent memory leaks
bgneal@45 1324 jQuery( ">*", this ).remove();
bgneal@45 1325
bgneal@45 1326 // Remove any remaining nodes
bgneal@45 1327 while ( this.firstChild )
bgneal@45 1328 this.removeChild( this.firstChild );
bgneal@45 1329 }
bgneal@45 1330 }, function(name, fn){
bgneal@45 1331 jQuery.fn[ name ] = function(){
bgneal@45 1332 return this.each( fn, arguments );
bgneal@45 1333 };
bgneal@45 1334 });
bgneal@45 1335
bgneal@45 1336 jQuery.each([ "Height", "Width" ], function(i, name){
bgneal@45 1337 var type = name.toLowerCase();
bgneal@45 1338
bgneal@45 1339 jQuery.fn[ type ] = function( size ) {
bgneal@45 1340 // Get window width or height
bgneal@45 1341 return this[0] == window ?
bgneal@45 1342 // Opera reports document.body.client[Width/Height] properly in both quirks and standards
bgneal@45 1343 jQuery.browser.opera && document.body[ "client" + name ] ||
bgneal@45 1344
bgneal@45 1345 // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
bgneal@45 1346 jQuery.browser.safari && window[ "inner" + name ] ||
bgneal@45 1347
bgneal@45 1348 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
bgneal@45 1349 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
bgneal@45 1350
bgneal@45 1351 // Get document width or height
bgneal@45 1352 this[0] == document ?
bgneal@45 1353 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
bgneal@45 1354 Math.max(
bgneal@45 1355 Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
bgneal@45 1356 Math.max(document.body["offset" + name], document.documentElement["offset" + name])
bgneal@45 1357 ) :
bgneal@45 1358
bgneal@45 1359 // Get or set width or height on the element
bgneal@45 1360 size == undefined ?
bgneal@45 1361 // Get width or height on the element
bgneal@45 1362 (this.length ? jQuery.css( this[0], type ) : null) :
bgneal@45 1363
bgneal@45 1364 // Set the width or height on the element (default to pixels if value is unitless)
bgneal@45 1365 this.css( type, size.constructor == String ? size : size + "px" );
bgneal@45 1366 };
bgneal@45 1367 });
bgneal@45 1368
bgneal@45 1369 // Helper function used by the dimensions and offset modules
bgneal@45 1370 function num(elem, prop) {
bgneal@45 1371 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
bgneal@45 1372 }var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
bgneal@45 1373 "(?:[\\w*_-]|\\\\.)" :
bgneal@45 1374 "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
bgneal@45 1375 quickChild = new RegExp("^>\\s*(" + chars + "+)"),
bgneal@45 1376 quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
bgneal@45 1377 quickClass = new RegExp("^([#.]?)(" + chars + "*)");
bgneal@45 1378
bgneal@45 1379 jQuery.extend({
bgneal@45 1380 expr: {
bgneal@45 1381 "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
bgneal@45 1382 "#": function(a,i,m){return a.getAttribute("id")==m[2];},
bgneal@45 1383 ":": {
bgneal@45 1384 // Position Checks
bgneal@45 1385 lt: function(a,i,m){return i<m[3]-0;},
bgneal@45 1386 gt: function(a,i,m){return i>m[3]-0;},
bgneal@45 1387 nth: function(a,i,m){return m[3]-0==i;},
bgneal@45 1388 eq: function(a,i,m){return m[3]-0==i;},
bgneal@45 1389 first: function(a,i){return i==0;},
bgneal@45 1390 last: function(a,i,m,r){return i==r.length-1;},
bgneal@45 1391 even: function(a,i){return i%2==0;},
bgneal@45 1392 odd: function(a,i){return i%2;},
bgneal@45 1393
bgneal@45 1394 // Child Checks
bgneal@45 1395 "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
bgneal@45 1396 "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
bgneal@45 1397 "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
bgneal@45 1398
bgneal@45 1399 // Parent Checks
bgneal@45 1400 parent: function(a){return a.firstChild;},
bgneal@45 1401 empty: function(a){return !a.firstChild;},
bgneal@45 1402
bgneal@45 1403 // Text Check
bgneal@45 1404 contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
bgneal@45 1405
bgneal@45 1406 // Visibility
bgneal@45 1407 visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
bgneal@45 1408 hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
bgneal@45 1409
bgneal@45 1410 // Form attributes
bgneal@45 1411 enabled: function(a){return !a.disabled;},
bgneal@45 1412 disabled: function(a){return a.disabled;},
bgneal@45 1413 checked: function(a){return a.checked;},
bgneal@45 1414 selected: function(a){return a.selected||jQuery.attr(a,"selected");},
bgneal@45 1415
bgneal@45 1416 // Form elements
bgneal@45 1417 text: function(a){return "text"==a.type;},
bgneal@45 1418 radio: function(a){return "radio"==a.type;},
bgneal@45 1419 checkbox: function(a){return "checkbox"==a.type;},
bgneal@45 1420 file: function(a){return "file"==a.type;},
bgneal@45 1421 password: function(a){return "password"==a.type;},
bgneal@45 1422 submit: function(a){return "submit"==a.type;},
bgneal@45 1423 image: function(a){return "image"==a.type;},
bgneal@45 1424 reset: function(a){return "reset"==a.type;},
bgneal@45 1425 button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
bgneal@45 1426 input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
bgneal@45 1427
bgneal@45 1428 // :has()
bgneal@45 1429 has: function(a,i,m){return jQuery.find(m[3],a).length;},
bgneal@45 1430
bgneal@45 1431 // :header
bgneal@45 1432 header: function(a){return /h\d/i.test(a.nodeName);},
bgneal@45 1433
bgneal@45 1434 // :animated
bgneal@45 1435 animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
bgneal@45 1436 }
bgneal@45 1437 },
bgneal@45 1438
bgneal@45 1439 // The regular expressions that power the parsing engine
bgneal@45 1440 parse: [
bgneal@45 1441 // Match: [@value='test'], [@foo]
bgneal@45 1442 /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
bgneal@45 1443
bgneal@45 1444 // Match: :contains('foo')
bgneal@45 1445 /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
bgneal@45 1446
bgneal@45 1447 // Match: :even, :last-child, #id, .class
bgneal@45 1448 new RegExp("^([:.#]*)(" + chars + "+)")
bgneal@45 1449 ],
bgneal@45 1450
bgneal@45 1451 multiFilter: function( expr, elems, not ) {
bgneal@45 1452 var old, cur = [];
bgneal@45 1453
bgneal@45 1454 while ( expr && expr != old ) {
bgneal@45 1455 old = expr;
bgneal@45 1456 var f = jQuery.filter( expr, elems, not );
bgneal@45 1457 expr = f.t.replace(/^\s*,\s*/, "" );
bgneal@45 1458 cur = not ? elems = f.r : jQuery.merge( cur, f.r );
bgneal@45 1459 }
bgneal@45 1460
bgneal@45 1461 return cur;
bgneal@45 1462 },
bgneal@45 1463
bgneal@45 1464 find: function( t, context ) {
bgneal@45 1465 // Quickly handle non-string expressions
bgneal@45 1466 if ( typeof t != "string" )
bgneal@45 1467 return [ t ];
bgneal@45 1468
bgneal@45 1469 // check to make sure context is a DOM element or a document
bgneal@45 1470 if ( context && context.nodeType != 1 && context.nodeType != 9)
bgneal@45 1471 return [ ];
bgneal@45 1472
bgneal@45 1473 // Set the correct context (if none is provided)
bgneal@45 1474 context = context || document;
bgneal@45 1475
bgneal@45 1476 // Initialize the search
bgneal@45 1477 var ret = [context], done = [], last, nodeName;
bgneal@45 1478
bgneal@45 1479 // Continue while a selector expression exists, and while
bgneal@45 1480 // we're no longer looping upon ourselves
bgneal@45 1481 while ( t && last != t ) {
bgneal@45 1482 var r = [];
bgneal@45 1483 last = t;
bgneal@45 1484
bgneal@45 1485 t = jQuery.trim(t);
bgneal@45 1486
bgneal@45 1487 var foundToken = false,
bgneal@45 1488
bgneal@45 1489 // An attempt at speeding up child selectors that
bgneal@45 1490 // point to a specific element tag
bgneal@45 1491 re = quickChild,
bgneal@45 1492
bgneal@45 1493 m = re.exec(t);
bgneal@45 1494
bgneal@45 1495 if ( m ) {
bgneal@45 1496 nodeName = m[1].toUpperCase();
bgneal@45 1497
bgneal@45 1498 // Perform our own iteration and filter
bgneal@45 1499 for ( var i = 0; ret[i]; i++ )
bgneal@45 1500 for ( var c = ret[i].firstChild; c; c = c.nextSibling )
bgneal@45 1501 if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
bgneal@45 1502 r.push( c );
bgneal@45 1503
bgneal@45 1504 ret = r;
bgneal@45 1505 t = t.replace( re, "" );
bgneal@45 1506 if ( t.indexOf(" ") == 0 ) continue;
bgneal@45 1507 foundToken = true;
bgneal@45 1508 } else {
bgneal@45 1509 re = /^([>+~])\s*(\w*)/i;
bgneal@45 1510
bgneal@45 1511 if ( (m = re.exec(t)) != null ) {
bgneal@45 1512 r = [];
bgneal@45 1513
bgneal@45 1514 var merge = {};
bgneal@45 1515 nodeName = m[2].toUpperCase();
bgneal@45 1516 m = m[1];
bgneal@45 1517
bgneal@45 1518 for ( var j = 0, rl = ret.length; j < rl; j++ ) {
bgneal@45 1519 var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
bgneal@45 1520 for ( ; n; n = n.nextSibling )
bgneal@45 1521 if ( n.nodeType == 1 ) {
bgneal@45 1522 var id = jQuery.data(n);
bgneal@45 1523
bgneal@45 1524 if ( m == "~" && merge[id] ) break;
bgneal@45 1525
bgneal@45 1526 if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
bgneal@45 1527 if ( m == "~" ) merge[id] = true;
bgneal@45 1528 r.push( n );
bgneal@45 1529 }
bgneal@45 1530
bgneal@45 1531 if ( m == "+" ) break;
bgneal@45 1532 }
bgneal@45 1533 }
bgneal@45 1534
bgneal@45 1535 ret = r;
bgneal@45 1536
bgneal@45 1537 // And remove the token
bgneal@45 1538 t = jQuery.trim( t.replace( re, "" ) );
bgneal@45 1539 foundToken = true;
bgneal@45 1540 }
bgneal@45 1541 }
bgneal@45 1542
bgneal@45 1543 // See if there's still an expression, and that we haven't already
bgneal@45 1544 // matched a token
bgneal@45 1545 if ( t && !foundToken ) {
bgneal@45 1546 // Handle multiple expressions
bgneal@45 1547 if ( !t.indexOf(",") ) {
bgneal@45 1548 // Clean the result set
bgneal@45 1549 if ( context == ret[0] ) ret.shift();
bgneal@45 1550
bgneal@45 1551 // Merge the result sets
bgneal@45 1552 done = jQuery.merge( done, ret );
bgneal@45 1553
bgneal@45 1554 // Reset the context
bgneal@45 1555 r = ret = [context];
bgneal@45 1556
bgneal@45 1557 // Touch up the selector string
bgneal@45 1558 t = " " + t.substr(1,t.length);
bgneal@45 1559
bgneal@45 1560 } else {
bgneal@45 1561 // Optimize for the case nodeName#idName
bgneal@45 1562 var re2 = quickID;
bgneal@45 1563 var m = re2.exec(t);
bgneal@45 1564
bgneal@45 1565 // Re-organize the results, so that they're consistent
bgneal@45 1566 if ( m ) {
bgneal@45 1567 m = [ 0, m[2], m[3], m[1] ];
bgneal@45 1568
bgneal@45 1569 } else {
bgneal@45 1570 // Otherwise, do a traditional filter check for
bgneal@45 1571 // ID, class, and element selectors
bgneal@45 1572 re2 = quickClass;
bgneal@45 1573 m = re2.exec(t);
bgneal@45 1574 }
bgneal@45 1575
bgneal@45 1576 m[2] = m[2].replace(/\\/g, "");
bgneal@45 1577
bgneal@45 1578 var elem = ret[ret.length-1];
bgneal@45 1579
bgneal@45 1580 // Try to do a global search by ID, where we can
bgneal@45 1581 if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
bgneal@45 1582 // Optimization for HTML document case
bgneal@45 1583 var oid = elem.getElementById(m[2]);
bgneal@45 1584
bgneal@45 1585 // Do a quick check for the existence of the actual ID attribute
bgneal@45 1586 // to avoid selecting by the name attribute in IE
bgneal@45 1587 // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
bgneal@45 1588 if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
bgneal@45 1589 oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
bgneal@45 1590
bgneal@45 1591 // Do a quick check for node name (where applicable) so
bgneal@45 1592 // that div#foo searches will be really fast
bgneal@45 1593 ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
bgneal@45 1594 } else {
bgneal@45 1595 // We need to find all descendant elements
bgneal@45 1596 for ( var i = 0; ret[i]; i++ ) {
bgneal@45 1597 // Grab the tag name being searched for
bgneal@45 1598 var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
bgneal@45 1599
bgneal@45 1600 // Handle IE7 being really dumb about <object>s
bgneal@45 1601 if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
bgneal@45 1602 tag = "param";
bgneal@45 1603
bgneal@45 1604 r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
bgneal@45 1605 }
bgneal@45 1606
bgneal@45 1607 // It's faster to filter by class and be done with it
bgneal@45 1608 if ( m[1] == "." )
bgneal@45 1609 r = jQuery.classFilter( r, m[2] );
bgneal@45 1610
bgneal@45 1611 // Same with ID filtering
bgneal@45 1612 if ( m[1] == "#" ) {
bgneal@45 1613 var tmp = [];
bgneal@45 1614
bgneal@45 1615 // Try to find the element with the ID
bgneal@45 1616 for ( var i = 0; r[i]; i++ )
bgneal@45 1617 if ( r[i].getAttribute("id") == m[2] ) {
bgneal@45 1618 tmp = [ r[i] ];
bgneal@45 1619 break;
bgneal@45 1620 }
bgneal@45 1621
bgneal@45 1622 r = tmp;
bgneal@45 1623 }
bgneal@45 1624
bgneal@45 1625 ret = r;
bgneal@45 1626 }
bgneal@45 1627
bgneal@45 1628 t = t.replace( re2, "" );
bgneal@45 1629 }
bgneal@45 1630
bgneal@45 1631 }
bgneal@45 1632
bgneal@45 1633 // If a selector string still exists
bgneal@45 1634 if ( t ) {
bgneal@45 1635 // Attempt to filter it
bgneal@45 1636 var val = jQuery.filter(t,r);
bgneal@45 1637 ret = r = val.r;
bgneal@45 1638 t = jQuery.trim(val.t);
bgneal@45 1639 }
bgneal@45 1640 }
bgneal@45 1641
bgneal@45 1642 // An error occurred with the selector;
bgneal@45 1643 // just return an empty set instead
bgneal@45 1644 if ( t )
bgneal@45 1645 ret = [];
bgneal@45 1646
bgneal@45 1647 // Remove the root context
bgneal@45 1648 if ( ret && context == ret[0] )
bgneal@45 1649 ret.shift();
bgneal@45 1650
bgneal@45 1651 // And combine the results
bgneal@45 1652 done = jQuery.merge( done, ret );
bgneal@45 1653
bgneal@45 1654 return done;
bgneal@45 1655 },
bgneal@45 1656
bgneal@45 1657 classFilter: function(r,m,not){
bgneal@45 1658 m = " " + m + " ";
bgneal@45 1659 var tmp = [];
bgneal@45 1660 for ( var i = 0; r[i]; i++ ) {
bgneal@45 1661 var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
bgneal@45 1662 if ( !not && pass || not && !pass )
bgneal@45 1663 tmp.push( r[i] );
bgneal@45 1664 }
bgneal@45 1665 return tmp;
bgneal@45 1666 },
bgneal@45 1667
bgneal@45 1668 filter: function(t,r,not) {
bgneal@45 1669 var last;
bgneal@45 1670
bgneal@45 1671 // Look for common filter expressions
bgneal@45 1672 while ( t && t != last ) {
bgneal@45 1673 last = t;
bgneal@45 1674
bgneal@45 1675 var p = jQuery.parse, m;
bgneal@45 1676
bgneal@45 1677 for ( var i = 0; p[i]; i++ ) {
bgneal@45 1678 m = p[i].exec( t );
bgneal@45 1679
bgneal@45 1680 if ( m ) {
bgneal@45 1681 // Remove what we just matched
bgneal@45 1682 t = t.substring( m[0].length );
bgneal@45 1683
bgneal@45 1684 m[2] = m[2].replace(/\\/g, "");
bgneal@45 1685 break;
bgneal@45 1686 }
bgneal@45 1687 }
bgneal@45 1688
bgneal@45 1689 if ( !m )
bgneal@45 1690 break;
bgneal@45 1691
bgneal@45 1692 // :not() is a special case that can be optimized by
bgneal@45 1693 // keeping it out of the expression list
bgneal@45 1694 if ( m[1] == ":" && m[2] == "not" )
bgneal@45 1695 // optimize if only one selector found (most common case)
bgneal@45 1696 r = isSimple.test( m[3] ) ?
bgneal@45 1697 jQuery.filter(m[3], r, true).r :
bgneal@45 1698 jQuery( r ).not( m[3] );
bgneal@45 1699
bgneal@45 1700 // We can get a big speed boost by filtering by class here
bgneal@45 1701 else if ( m[1] == "." )
bgneal@45 1702 r = jQuery.classFilter(r, m[2], not);
bgneal@45 1703
bgneal@45 1704 else if ( m[1] == "[" ) {
bgneal@45 1705 var tmp = [], type = m[3];
bgneal@45 1706
bgneal@45 1707 for ( var i = 0, rl = r.length; i < rl; i++ ) {
bgneal@45 1708 var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
bgneal@45 1709
bgneal@45 1710 if ( z == null || /href|src|selected/.test(m[2]) )
bgneal@45 1711 z = jQuery.attr(a,m[2]) || '';
bgneal@45 1712
bgneal@45 1713 if ( (type == "" && !!z ||
bgneal@45 1714 type == "=" && z == m[5] ||
bgneal@45 1715 type == "!=" && z != m[5] ||
bgneal@45 1716 type == "^=" && z && !z.indexOf(m[5]) ||
bgneal@45 1717 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
bgneal@45 1718 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
bgneal@45 1719 tmp.push( a );
bgneal@45 1720 }
bgneal@45 1721
bgneal@45 1722 r = tmp;
bgneal@45 1723
bgneal@45 1724 // We can get a speed boost by handling nth-child here
bgneal@45 1725 } else if ( m[1] == ":" && m[2] == "nth-child" ) {
bgneal@45 1726 var merge = {}, tmp = [],
bgneal@45 1727 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
bgneal@45 1728 test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
bgneal@45 1729 m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
bgneal@45 1730 !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
bgneal@45 1731 // calculate the numbers (first)n+(last) including if they are negative
bgneal@45 1732 first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
bgneal@45 1733
bgneal@45 1734 // loop through all the elements left in the jQuery object
bgneal@45 1735 for ( var i = 0, rl = r.length; i < rl; i++ ) {
bgneal@45 1736 var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
bgneal@45 1737
bgneal@45 1738 if ( !merge[id] ) {
bgneal@45 1739 var c = 1;
bgneal@45 1740
bgneal@45 1741 for ( var n = parentNode.firstChild; n; n = n.nextSibling )
bgneal@45 1742 if ( n.nodeType == 1 )
bgneal@45 1743 n.nodeIndex = c++;
bgneal@45 1744
bgneal@45 1745 merge[id] = true;
bgneal@45 1746 }
bgneal@45 1747
bgneal@45 1748 var add = false;
bgneal@45 1749
bgneal@45 1750 if ( first == 0 ) {
bgneal@45 1751 if ( node.nodeIndex == last )
bgneal@45 1752 add = true;
bgneal@45 1753 } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
bgneal@45 1754 add = true;
bgneal@45 1755
bgneal@45 1756 if ( add ^ not )
bgneal@45 1757 tmp.push( node );
bgneal@45 1758 }
bgneal@45 1759
bgneal@45 1760 r = tmp;
bgneal@45 1761
bgneal@45 1762 // Otherwise, find the expression to execute
bgneal@45 1763 } else {
bgneal@45 1764 var fn = jQuery.expr[ m[1] ];
bgneal@45 1765 if ( typeof fn == "object" )
bgneal@45 1766 fn = fn[ m[2] ];
bgneal@45 1767
bgneal@45 1768 if ( typeof fn == "string" )
bgneal@45 1769 fn = eval("false||function(a,i){return " + fn + ";}");
bgneal@45 1770
bgneal@45 1771 // Execute it against the current filter
bgneal@45 1772 r = jQuery.grep( r, function(elem, i){
bgneal@45 1773 return fn(elem, i, m, r);
bgneal@45 1774 }, not );
bgneal@45 1775 }
bgneal@45 1776 }
bgneal@45 1777
bgneal@45 1778 // Return an array of filtered elements (r)
bgneal@45 1779 // and the modified expression string (t)
bgneal@45 1780 return { r: r, t: t };
bgneal@45 1781 },
bgneal@45 1782
bgneal@45 1783 dir: function( elem, dir ){
bgneal@45 1784 var matched = [],
bgneal@45 1785 cur = elem[dir];
bgneal@45 1786 while ( cur && cur != document ) {
bgneal@45 1787 if ( cur.nodeType == 1 )
bgneal@45 1788 matched.push( cur );
bgneal@45 1789 cur = cur[dir];
bgneal@45 1790 }
bgneal@45 1791 return matched;
bgneal@45 1792 },
bgneal@45 1793
bgneal@45 1794 nth: function(cur,result,dir,elem){
bgneal@45 1795 result = result || 1;
bgneal@45 1796 var num = 0;
bgneal@45 1797
bgneal@45 1798 for ( ; cur; cur = cur[dir] )
bgneal@45 1799 if ( cur.nodeType == 1 && ++num == result )
bgneal@45 1800 break;
bgneal@45 1801
bgneal@45 1802 return cur;
bgneal@45 1803 },
bgneal@45 1804
bgneal@45 1805 sibling: function( n, elem ) {
bgneal@45 1806 var r = [];
bgneal@45 1807
bgneal@45 1808 for ( ; n; n = n.nextSibling ) {
bgneal@45 1809 if ( n.nodeType == 1 && n != elem )
bgneal@45 1810 r.push( n );
bgneal@45 1811 }
bgneal@45 1812
bgneal@45 1813 return r;
bgneal@45 1814 }
bgneal@45 1815 });
bgneal@45 1816 /*
bgneal@45 1817 * A number of helper functions used for managing events.
bgneal@45 1818 * Many of the ideas behind this code orignated from
bgneal@45 1819 * Dean Edwards' addEvent library.
bgneal@45 1820 */
bgneal@45 1821 jQuery.event = {
bgneal@45 1822
bgneal@45 1823 // Bind an event to an element
bgneal@45 1824 // Original by Dean Edwards
bgneal@45 1825 add: function(elem, types, handler, data) {
bgneal@45 1826 if ( elem.nodeType == 3 || elem.nodeType == 8 )
bgneal@45 1827 return;
bgneal@45 1828
bgneal@45 1829 // For whatever reason, IE has trouble passing the window object
bgneal@45 1830 // around, causing it to be cloned in the process
bgneal@45 1831 if ( jQuery.browser.msie && elem.setInterval )
bgneal@45 1832 elem = window;
bgneal@45 1833
bgneal@45 1834 // Make sure that the function being executed has a unique ID
bgneal@45 1835 if ( !handler.guid )
bgneal@45 1836 handler.guid = this.guid++;
bgneal@45 1837
bgneal@45 1838 // if data is passed, bind to handler
bgneal@45 1839 if( data != undefined ) {
bgneal@45 1840 // Create temporary function pointer to original handler
bgneal@45 1841 var fn = handler;
bgneal@45 1842
bgneal@45 1843 // Create unique handler function, wrapped around original handler
bgneal@45 1844 handler = this.proxy( fn, function() {
bgneal@45 1845 // Pass arguments and context to original handler
bgneal@45 1846 return fn.apply(this, arguments);
bgneal@45 1847 });
bgneal@45 1848
bgneal@45 1849 // Store data in unique handler
bgneal@45 1850 handler.data = data;
bgneal@45 1851 }
bgneal@45 1852
bgneal@45 1853 // Init the element's event structure
bgneal@45 1854 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
bgneal@45 1855 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
bgneal@45 1856 // Handle the second event of a trigger and when
bgneal@45 1857 // an event is called after a page has unloaded
bgneal@45 1858 if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
bgneal@45 1859 return jQuery.event.handle.apply(arguments.callee.elem, arguments);
bgneal@45 1860 });
bgneal@45 1861 // Add elem as a property of the handle function
bgneal@45 1862 // This is to prevent a memory leak with non-native
bgneal@45 1863 // event in IE.
bgneal@45 1864 handle.elem = elem;
bgneal@45 1865
bgneal@45 1866 // Handle multiple events separated by a space
bgneal@45 1867 // jQuery(...).bind("mouseover mouseout", fn);
bgneal@45 1868 jQuery.each(types.split(/\s+/), function(index, type) {
bgneal@45 1869 // Namespaced event handlers
bgneal@45 1870 var parts = type.split(".");
bgneal@45 1871 type = parts[0];
bgneal@45 1872 handler.type = parts[1];
bgneal@45 1873
bgneal@45 1874 // Get the current list of functions bound to this event
bgneal@45 1875 var handlers = events[type];
bgneal@45 1876
bgneal@45 1877 // Init the event handler queue
bgneal@45 1878 if (!handlers) {
bgneal@45 1879 handlers = events[type] = {};
bgneal@45 1880
bgneal@45 1881 // Check for a special event handler
bgneal@45 1882 // Only use addEventListener/attachEvent if the special
bgneal@45 1883 // events handler returns false
bgneal@45 1884 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
bgneal@45 1885 // Bind the global event handler to the element
bgneal@45 1886 if (elem.addEventListener)
bgneal@45 1887 elem.addEventListener(type, handle, false);
bgneal@45 1888 else if (elem.attachEvent)
bgneal@45 1889 elem.attachEvent("on" + type, handle);
bgneal@45 1890 }
bgneal@45 1891 }
bgneal@45 1892
bgneal@45 1893 // Add the function to the element's handler list
bgneal@45 1894 handlers[handler.guid] = handler;
bgneal@45 1895
bgneal@45 1896 // Keep track of which events have been used, for global triggering
bgneal@45 1897 jQuery.event.global[type] = true;
bgneal@45 1898 });
bgneal@45 1899
bgneal@45 1900 // Nullify elem to prevent memory leaks in IE
bgneal@45 1901 elem = null;
bgneal@45 1902 },
bgneal@45 1903
bgneal@45 1904 guid: 1,
bgneal@45 1905 global: {},
bgneal@45 1906
bgneal@45 1907 // Detach an event or set of events from an element
bgneal@45 1908 remove: function(elem, types, handler) {
bgneal@45 1909 // don't do events on text and comment nodes
bgneal@45 1910 if ( elem.nodeType == 3 || elem.nodeType == 8 )
bgneal@45 1911 return;
bgneal@45 1912
bgneal@45 1913 var events = jQuery.data(elem, "events"), ret, index;
bgneal@45 1914
bgneal@45 1915 if ( events ) {
bgneal@45 1916 // Unbind all events for the element
bgneal@45 1917 if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
bgneal@45 1918 for ( var type in events )
bgneal@45 1919 this.remove( elem, type + (types || "") );
bgneal@45 1920 else {
bgneal@45 1921 // types is actually an event object here
bgneal@45 1922 if ( types.type ) {
bgneal@45 1923 handler = types.handler;
bgneal@45 1924 types = types.type;
bgneal@45 1925 }
bgneal@45 1926
bgneal@45 1927 // Handle multiple events seperated by a space
bgneal@45 1928 // jQuery(...).unbind("mouseover mouseout", fn);
bgneal@45 1929 jQuery.each(types.split(/\s+/), function(index, type){
bgneal@45 1930 // Namespaced event handlers
bgneal@45 1931 var parts = type.split(".");
bgneal@45 1932 type = parts[0];
bgneal@45 1933
bgneal@45 1934 if ( events[type] ) {
bgneal@45 1935 // remove the given handler for the given type
bgneal@45 1936 if ( handler )
bgneal@45 1937 delete events[type][handler.guid];
bgneal@45 1938
bgneal@45 1939 // remove all handlers for the given type
bgneal@45 1940 else
bgneal@45 1941 for ( handler in events[type] )
bgneal@45 1942 // Handle the removal of namespaced events
bgneal@45 1943 if ( !parts[1] || events[type][handler].type == parts[1] )
bgneal@45 1944 delete events[type][handler];
bgneal@45 1945
bgneal@45 1946 // remove generic event handler if no more handlers exist
bgneal@45 1947 for ( ret in events[type] ) break;
bgneal@45 1948 if ( !ret ) {
bgneal@45 1949 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
bgneal@45 1950 if (elem.removeEventListener)
bgneal@45 1951 elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
bgneal@45 1952 else if (elem.detachEvent)
bgneal@45 1953 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
bgneal@45 1954 }
bgneal@45 1955 ret = null;
bgneal@45 1956 delete events[type];
bgneal@45 1957 }
bgneal@45 1958 }
bgneal@45 1959 });
bgneal@45 1960 }
bgneal@45 1961
bgneal@45 1962 // Remove the expando if it's no longer used
bgneal@45 1963 for ( ret in events ) break;
bgneal@45 1964 if ( !ret ) {
bgneal@45 1965 var handle = jQuery.data( elem, "handle" );
bgneal@45 1966 if ( handle ) handle.elem = null;
bgneal@45 1967 jQuery.removeData( elem, "events" );
bgneal@45 1968 jQuery.removeData( elem, "handle" );
bgneal@45 1969 }
bgneal@45 1970 }
bgneal@45 1971 },
bgneal@45 1972
bgneal@45 1973 trigger: function(type, data, elem, donative, extra) {
bgneal@45 1974 // Clone the incoming data, if any
bgneal@45 1975 data = jQuery.makeArray(data);
bgneal@45 1976
bgneal@45 1977 if ( type.indexOf("!") >= 0 ) {
bgneal@45 1978 type = type.slice(0, -1);
bgneal@45 1979 var exclusive = true;
bgneal@45 1980 }
bgneal@45 1981
bgneal@45 1982 // Handle a global trigger
bgneal@45 1983 if ( !elem ) {
bgneal@45 1984 // Only trigger if we've ever bound an event for it
bgneal@45 1985 if ( this.global[type] )
bgneal@45 1986 jQuery("*").add([window, document]).trigger(type, data);
bgneal@45 1987
bgneal@45 1988 // Handle triggering a single element
bgneal@45 1989 } else {
bgneal@45 1990 // don't do events on text and comment nodes
bgneal@45 1991 if ( elem.nodeType == 3 || elem.nodeType == 8 )
bgneal@45 1992 return undefined;
bgneal@45 1993
bgneal@45 1994 var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
bgneal@45 1995 // Check to see if we need to provide a fake event, or not
bgneal@45 1996 event = !data[0] || !data[0].preventDefault;
bgneal@45 1997
bgneal@45 1998 // Pass along a fake event
bgneal@45 1999 if ( event ) {
bgneal@45 2000 data.unshift({
bgneal@45 2001 type: type,
bgneal@45 2002 target: elem,
bgneal@45 2003 preventDefault: function(){},
bgneal@45 2004 stopPropagation: function(){},
bgneal@45 2005 timeStamp: now()
bgneal@45 2006 });
bgneal@45 2007 data[0][expando] = true; // no need to fix fake event
bgneal@45 2008 }
bgneal@45 2009
bgneal@45 2010 // Enforce the right trigger type
bgneal@45 2011 data[0].type = type;
bgneal@45 2012 if ( exclusive )
bgneal@45 2013 data[0].exclusive = true;
bgneal@45 2014
bgneal@45 2015 // Trigger the event, it is assumed that "handle" is a function
bgneal@45 2016 var handle = jQuery.data(elem, "handle");
bgneal@45 2017 if ( handle )
bgneal@45 2018 val = handle.apply( elem, data );
bgneal@45 2019
bgneal@45 2020 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
bgneal@45 2021 if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
bgneal@45 2022 val = false;
bgneal@45 2023
bgneal@45 2024 // Extra functions don't get the custom event object
bgneal@45 2025 if ( event )
bgneal@45 2026 data.shift();
bgneal@45 2027
bgneal@45 2028 // Handle triggering of extra function
bgneal@45 2029 if ( extra && jQuery.isFunction( extra ) ) {
bgneal@45 2030 // call the extra function and tack the current return value on the end for possible inspection
bgneal@45 2031 ret = extra.apply( elem, val == null ? data : data.concat( val ) );
bgneal@45 2032 // if anything is returned, give it precedence and have it overwrite the previous value
bgneal@45 2033 if (ret !== undefined)
bgneal@45 2034 val = ret;
bgneal@45 2035 }
bgneal@45 2036
bgneal@45 2037 // Trigger the native events (except for clicks on links)
bgneal@45 2038 if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
bgneal@45 2039 this.triggered = true;
bgneal@45 2040 try {
bgneal@45 2041 elem[ type ]();
bgneal@45 2042 // prevent IE from throwing an error for some hidden elements
bgneal@45 2043 } catch (e) {}
bgneal@45 2044 }
bgneal@45 2045
bgneal@45 2046 this.triggered = false;
bgneal@45 2047 }
bgneal@45 2048
bgneal@45 2049 return val;
bgneal@45 2050 },
bgneal@45 2051
bgneal@45 2052 handle: function(event) {
bgneal@45 2053 // returned undefined or false
bgneal@45 2054 var val, ret, namespace, all, handlers;
bgneal@45 2055
bgneal@45 2056 event = arguments[0] = jQuery.event.fix( event || window.event );
bgneal@45 2057
bgneal@45 2058 // Namespaced event handlers
bgneal@45 2059 namespace = event.type.split(".");
bgneal@45 2060 event.type = namespace[0];
bgneal@45 2061 namespace = namespace[1];
bgneal@45 2062 // Cache this now, all = true means, any handler
bgneal@45 2063 all = !namespace && !event.exclusive;
bgneal@45 2064
bgneal@45 2065 handlers = ( jQuery.data(this, "events") || {} )[event.type];
bgneal@45 2066
bgneal@45 2067 for ( var j in handlers ) {
bgneal@45 2068 var handler = handlers[j];
bgneal@45 2069
bgneal@45 2070 // Filter the functions by class
bgneal@45 2071 if ( all || handler.type == namespace ) {
bgneal@45 2072 // Pass in a reference to the handler function itself
bgneal@45 2073 // So that we can later remove it
bgneal@45 2074 event.handler = handler;
bgneal@45 2075 event.data = handler.data;
bgneal@45 2076
bgneal@45 2077 ret = handler.apply( this, arguments );
bgneal@45 2078
bgneal@45 2079 if ( val !== false )
bgneal@45 2080 val = ret;
bgneal@45 2081
bgneal@45 2082 if ( ret === false ) {
bgneal@45 2083 event.preventDefault();
bgneal@45 2084 event.stopPropagation();
bgneal@45 2085 }
bgneal@45 2086 }
bgneal@45 2087 }
bgneal@45 2088
bgneal@45 2089 return val;
bgneal@45 2090 },
bgneal@45 2091
bgneal@45 2092 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 2093
bgneal@45 2094 fix: function(event) {
bgneal@45 2095 if ( event[expando] == true )
bgneal@45 2096 return event;
bgneal@45 2097
bgneal@45 2098 // store a copy of the original event object
bgneal@45 2099 // and "clone" to set read-only properties
bgneal@45 2100 var originalEvent = event;
bgneal@45 2101 event = { originalEvent: originalEvent };
bgneal@45 2102
bgneal@45 2103 for ( var i = this.props.length, prop; i; ){
bgneal@45 2104 prop = this.props[ --i ];
bgneal@45 2105 event[ prop ] = originalEvent[ prop ];
bgneal@45 2106 }
bgneal@45 2107
bgneal@45 2108 // Mark it as fixed
bgneal@45 2109 event[expando] = true;
bgneal@45 2110
bgneal@45 2111 // add preventDefault and stopPropagation since
bgneal@45 2112 // they will not work on the clone
bgneal@45 2113 event.preventDefault = function() {
bgneal@45 2114 // if preventDefault exists run it on the original event
bgneal@45 2115 if (originalEvent.preventDefault)
bgneal@45 2116 originalEvent.preventDefault();
bgneal@45 2117 // otherwise set the returnValue property of the original event to false (IE)
bgneal@45 2118 originalEvent.returnValue = false;
bgneal@45 2119 };
bgneal@45 2120 event.stopPropagation = function() {
bgneal@45 2121 // if stopPropagation exists run it on the original event
bgneal@45 2122 if (originalEvent.stopPropagation)
bgneal@45 2123 originalEvent.stopPropagation();
bgneal@45 2124 // otherwise set the cancelBubble property of the original event to true (IE)
bgneal@45 2125 originalEvent.cancelBubble = true;
bgneal@45 2126 };
bgneal@45 2127
bgneal@45 2128 // Fix timeStamp
bgneal@45 2129 event.timeStamp = event.timeStamp || now();
bgneal@45 2130
bgneal@45 2131 // Fix target property, if necessary
bgneal@45 2132 if ( !event.target )
bgneal@45 2133 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
bgneal@45 2134
bgneal@45 2135 // check if target is a textnode (safari)
bgneal@45 2136 if ( event.target.nodeType == 3 )
bgneal@45 2137 event.target = event.target.parentNode;
bgneal@45 2138
bgneal@45 2139 // Add relatedTarget, if necessary
bgneal@45 2140 if ( !event.relatedTarget && event.fromElement )
bgneal@45 2141 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
bgneal@45 2142
bgneal@45 2143 // Calculate pageX/Y if missing and clientX/Y available
bgneal@45 2144 if ( event.pageX == null && event.clientX != null ) {
bgneal@45 2145 var doc = document.documentElement, body = document.body;
bgneal@45 2146 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
bgneal@45 2147 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
bgneal@45 2148 }
bgneal@45 2149
bgneal@45 2150 // Add which for key events
bgneal@45 2151 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
bgneal@45 2152 event.which = event.charCode || event.keyCode;
bgneal@45 2153
bgneal@45 2154 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
bgneal@45 2155 if ( !event.metaKey && event.ctrlKey )
bgneal@45 2156 event.metaKey = event.ctrlKey;
bgneal@45 2157
bgneal@45 2158 // Add which for click: 1 == left; 2 == middle; 3 == right
bgneal@45 2159 // Note: button is not normalized, so don't use it
bgneal@45 2160 if ( !event.which && event.button )
bgneal@45 2161 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
bgneal@45 2162
bgneal@45 2163 return event;
bgneal@45 2164 },
bgneal@45 2165
bgneal@45 2166 proxy: function( fn, proxy ){
bgneal@45 2167 // Set the guid of unique handler to the same of original handler, so it can be removed
bgneal@45 2168 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
bgneal@45 2169 // So proxy can be declared as an argument
bgneal@45 2170 return proxy;
bgneal@45 2171 },
bgneal@45 2172
bgneal@45 2173 special: {
bgneal@45 2174 ready: {
bgneal@45 2175 setup: function() {
bgneal@45 2176 // Make sure the ready event is setup
bgneal@45 2177 bindReady();
bgneal@45 2178 return;
bgneal@45 2179 },
bgneal@45 2180
bgneal@45 2181 teardown: function() { return; }
bgneal@45 2182 },
bgneal@45 2183
bgneal@45 2184 mouseenter: {
bgneal@45 2185 setup: function() {
bgneal@45 2186 if ( jQuery.browser.msie ) return false;
bgneal@45 2187 jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
bgneal@45 2188 return true;
bgneal@45 2189 },
bgneal@45 2190
bgneal@45 2191 teardown: function() {
bgneal@45 2192 if ( jQuery.browser.msie ) return false;
bgneal@45 2193 jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
bgneal@45 2194 return true;
bgneal@45 2195 },
bgneal@45 2196
bgneal@45 2197 handler: function(event) {
bgneal@45 2198 // If we actually just moused on to a sub-element, ignore it
bgneal@45 2199 if ( withinElement(event, this) ) return true;
bgneal@45 2200 // Execute the right handlers by setting the event type to mouseenter
bgneal@45 2201 event.type = "mouseenter";
bgneal@45 2202 return jQuery.event.handle.apply(this, arguments);
bgneal@45 2203 }
bgneal@45 2204 },
bgneal@45 2205
bgneal@45 2206 mouseleave: {
bgneal@45 2207 setup: function() {
bgneal@45 2208 if ( jQuery.browser.msie ) return false;
bgneal@45 2209 jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
bgneal@45 2210 return true;
bgneal@45 2211 },
bgneal@45 2212
bgneal@45 2213 teardown: function() {
bgneal@45 2214 if ( jQuery.browser.msie ) return false;
bgneal@45 2215 jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
bgneal@45 2216 return true;
bgneal@45 2217 },
bgneal@45 2218
bgneal@45 2219 handler: function(event) {
bgneal@45 2220 // If we actually just moused on to a sub-element, ignore it
bgneal@45 2221 if ( withinElement(event, this) ) return true;
bgneal@45 2222 // Execute the right handlers by setting the event type to mouseleave
bgneal@45 2223 event.type = "mouseleave";
bgneal@45 2224 return jQuery.event.handle.apply(this, arguments);
bgneal@45 2225 }
bgneal@45 2226 }
bgneal@45 2227 }
bgneal@45 2228 };
bgneal@45 2229
bgneal@45 2230 jQuery.fn.extend({
bgneal@45 2231 bind: function( type, data, fn ) {
bgneal@45 2232 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
bgneal@45 2233 jQuery.event.add( this, type, fn || data, fn && data );
bgneal@45 2234 });
bgneal@45 2235 },
bgneal@45 2236
bgneal@45 2237 one: function( type, data, fn ) {
bgneal@45 2238 var one = jQuery.event.proxy( fn || data, function(event) {
bgneal@45 2239 jQuery(this).unbind(event, one);
bgneal@45 2240 return (fn || data).apply( this, arguments );
bgneal@45 2241 });
bgneal@45 2242 return this.each(function(){
bgneal@45 2243 jQuery.event.add( this, type, one, fn && data);
bgneal@45 2244 });
bgneal@45 2245 },
bgneal@45 2246
bgneal@45 2247 unbind: function( type, fn ) {
bgneal@45 2248 return this.each(function(){
bgneal@45 2249 jQuery.event.remove( this, type, fn );
bgneal@45 2250 });
bgneal@45 2251 },
bgneal@45 2252
bgneal@45 2253 trigger: function( type, data, fn ) {
bgneal@45 2254 return this.each(function(){
bgneal@45 2255 jQuery.event.trigger( type, data, this, true, fn );
bgneal@45 2256 });
bgneal@45 2257 },
bgneal@45 2258
bgneal@45 2259 triggerHandler: function( type, data, fn ) {
bgneal@45 2260 return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
bgneal@45 2261 },
bgneal@45 2262
bgneal@45 2263 toggle: function( fn ) {
bgneal@45 2264 // Save reference to arguments for access in closure
bgneal@45 2265 var args = arguments, i = 1;
bgneal@45 2266
bgneal@45 2267 // link all the functions, so any of them can unbind this click handler
bgneal@45 2268 while( i < args.length )
bgneal@45 2269 jQuery.event.proxy( fn, args[i++] );
bgneal@45 2270
bgneal@45 2271 return this.click( jQuery.event.proxy( fn, function(event) {
bgneal@45 2272 // Figure out which function to execute
bgneal@45 2273 this.lastToggle = ( this.lastToggle || 0 ) % i;
bgneal@45 2274
bgneal@45 2275 // Make sure that clicks stop
bgneal@45 2276 event.preventDefault();
bgneal@45 2277
bgneal@45 2278 // and execute the function
bgneal@45 2279 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
bgneal@45 2280 }));
bgneal@45 2281 },
bgneal@45 2282
bgneal@45 2283 hover: function(fnOver, fnOut) {
bgneal@45 2284 return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
bgneal@45 2285 },
bgneal@45 2286
bgneal@45 2287 ready: function(fn) {
bgneal@45 2288 // Attach the listeners
bgneal@45 2289 bindReady();
bgneal@45 2290
bgneal@45 2291 // If the DOM is already ready
bgneal@45 2292 if ( jQuery.isReady )
bgneal@45 2293 // Execute the function immediately
bgneal@45 2294 fn.call( document, jQuery );
bgneal@45 2295
bgneal@45 2296 // Otherwise, remember the function for later
bgneal@45 2297 else
bgneal@45 2298 // Add the function to the wait list
bgneal@45 2299 jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
bgneal@45 2300
bgneal@45 2301 return this;
bgneal@45 2302 }
bgneal@45 2303 });
bgneal@45 2304
bgneal@45 2305 jQuery.extend({
bgneal@45 2306 isReady: false,
bgneal@45 2307 readyList: [],
bgneal@45 2308 // Handle when the DOM is ready
bgneal@45 2309 ready: function() {
bgneal@45 2310 // Make sure that the DOM is not already loaded
bgneal@45 2311 if ( !jQuery.isReady ) {
bgneal@45 2312 // Remember that the DOM is ready
bgneal@45 2313 jQuery.isReady = true;
bgneal@45 2314
bgneal@45 2315 // If there are functions bound, to execute
bgneal@45 2316 if ( jQuery.readyList ) {
bgneal@45 2317 // Execute all of them
bgneal@45 2318 jQuery.each( jQuery.readyList, function(){
bgneal@45 2319 this.call( document );
bgneal@45 2320 });
bgneal@45 2321
bgneal@45 2322 // Reset the list of functions
bgneal@45 2323 jQuery.readyList = null;
bgneal@45 2324 }
bgneal@45 2325
bgneal@45 2326 // Trigger any bound ready events
bgneal@45 2327 jQuery(document).triggerHandler("ready");
bgneal@45 2328 }
bgneal@45 2329 }
bgneal@45 2330 });
bgneal@45 2331
bgneal@45 2332 var readyBound = false;
bgneal@45 2333
bgneal@45 2334 function bindReady(){
bgneal@45 2335 if ( readyBound ) return;
bgneal@45 2336 readyBound = true;
bgneal@45 2337
bgneal@45 2338 // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
bgneal@45 2339 if ( document.addEventListener && !jQuery.browser.opera)
bgneal@45 2340 // Use the handy event callback
bgneal@45 2341 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
bgneal@45 2342
bgneal@45 2343 // If IE is used and is not in a frame
bgneal@45 2344 // Continually check to see if the document is ready
bgneal@45 2345 if ( jQuery.browser.msie && window == top ) (function(){
bgneal@45 2346 if (jQuery.isReady) return;
bgneal@45 2347 try {
bgneal@45 2348 // If IE is used, use the trick by Diego Perini
bgneal@45 2349 // http://javascript.nwbox.com/IEContentLoaded/
bgneal@45 2350 document.documentElement.doScroll("left");
bgneal@45 2351 } catch( error ) {
bgneal@45 2352 setTimeout( arguments.callee, 0 );
bgneal@45 2353 return;
bgneal@45 2354 }
bgneal@45 2355 // and execute any waiting functions
bgneal@45 2356 jQuery.ready();
bgneal@45 2357 })();
bgneal@45 2358
bgneal@45 2359 if ( jQuery.browser.opera )
bgneal@45 2360 document.addEventListener( "DOMContentLoaded", function () {
bgneal@45 2361 if (jQuery.isReady) return;
bgneal@45 2362 for (var i = 0; i < document.styleSheets.length; i++)
bgneal@45 2363 if (document.styleSheets[i].disabled) {
bgneal@45 2364 setTimeout( arguments.callee, 0 );
bgneal@45 2365 return;
bgneal@45 2366 }
bgneal@45 2367 // and execute any waiting functions
bgneal@45 2368 jQuery.ready();
bgneal@45 2369 }, false);
bgneal@45 2370
bgneal@45 2371 if ( jQuery.browser.safari ) {
bgneal@45 2372 var numStyles;
bgneal@45 2373 (function(){
bgneal@45 2374 if (jQuery.isReady) return;
bgneal@45 2375 if ( document.readyState != "loaded" && document.readyState != "complete" ) {
bgneal@45 2376 setTimeout( arguments.callee, 0 );
bgneal@45 2377 return;
bgneal@45 2378 }
bgneal@45 2379 if ( numStyles === undefined )
bgneal@45 2380 numStyles = jQuery("style, link[rel=stylesheet]").length;
bgneal@45 2381 if ( document.styleSheets.length != numStyles ) {
bgneal@45 2382 setTimeout( arguments.callee, 0 );
bgneal@45 2383 return;
bgneal@45 2384 }
bgneal@45 2385 // and execute any waiting functions
bgneal@45 2386 jQuery.ready();
bgneal@45 2387 })();
bgneal@45 2388 }
bgneal@45 2389
bgneal@45 2390 // A fallback to window.onload, that will always work
bgneal@45 2391 jQuery.event.add( window, "load", jQuery.ready );
bgneal@45 2392 }
bgneal@45 2393
bgneal@45 2394 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
bgneal@45 2395 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
bgneal@45 2396 "submit,keydown,keypress,keyup,error").split(","), function(i, name){
bgneal@45 2397
bgneal@45 2398 // Handle event binding
bgneal@45 2399 jQuery.fn[name] = function(fn){
bgneal@45 2400 return fn ? this.bind(name, fn) : this.trigger(name);
bgneal@45 2401 };
bgneal@45 2402 });
bgneal@45 2403
bgneal@45 2404 // Checks if an event happened on an element within another element
bgneal@45 2405 // Used in jQuery.event.special.mouseenter and mouseleave handlers
bgneal@45 2406 var withinElement = function(event, elem) {
bgneal@45 2407 // Check if mouse(over|out) are still within the same parent element
bgneal@45 2408 var parent = event.relatedTarget;
bgneal@45 2409 // Traverse up the tree
bgneal@45 2410 while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
bgneal@45 2411 // Return true if we actually just moused on to a sub-element
bgneal@45 2412 return parent == elem;
bgneal@45 2413 };
bgneal@45 2414
bgneal@45 2415 // Prevent memory leaks in IE
bgneal@45 2416 // And prevent errors on refresh with events like mouseover in other browsers
bgneal@45 2417 // Window isn't included so as not to unbind existing unload events
bgneal@45 2418 jQuery(window).bind("unload", function() {
bgneal@45 2419 jQuery("*").add(document).unbind();
bgneal@45 2420 });
bgneal@45 2421 jQuery.fn.extend({
bgneal@45 2422 // Keep a copy of the old load
bgneal@45 2423 _load: jQuery.fn.load,
bgneal@45 2424
bgneal@45 2425 load: function( url, params, callback ) {
bgneal@45 2426 if ( typeof url != 'string' )
bgneal@45 2427 return this._load( url );
bgneal@45 2428
bgneal@45 2429 var off = url.indexOf(" ");
bgneal@45 2430 if ( off >= 0 ) {
bgneal@45 2431 var selector = url.slice(off, url.length);
bgneal@45 2432 url = url.slice(0, off);
bgneal@45 2433 }
bgneal@45 2434
bgneal@45 2435 callback = callback || function(){};
bgneal@45 2436
bgneal@45 2437 // Default to a GET request
bgneal@45 2438 var type = "GET";
bgneal@45 2439
bgneal@45 2440 // If the second parameter was provided
bgneal@45 2441 if ( params )
bgneal@45 2442 // If it's a function
bgneal@45 2443 if ( jQuery.isFunction( params ) ) {
bgneal@45 2444 // We assume that it's the callback
bgneal@45 2445 callback = params;
bgneal@45 2446 params = null;
bgneal@45 2447
bgneal@45 2448 // Otherwise, build a param string
bgneal@45 2449 } else if( typeof params == 'object' ) {
bgneal@45 2450 params = jQuery.param( params );
bgneal@45 2451 type = "POST";
bgneal@45 2452 }
bgneal@45 2453
bgneal@45 2454 var self = this;
bgneal@45 2455
bgneal@45 2456 // Request the remote document
bgneal@45 2457 jQuery.ajax({
bgneal@45 2458 url: url,
bgneal@45 2459 type: type,
bgneal@45 2460 dataType: "html",
bgneal@45 2461 data: params,
bgneal@45 2462 complete: function(res, status){
bgneal@45 2463 // If successful, inject the HTML into all the matched elements
bgneal@45 2464 if ( status == "success" || status == "notmodified" )
bgneal@45 2465 // See if a selector was specified
bgneal@45 2466 self.html( selector ?
bgneal@45 2467 // Create a dummy div to hold the results
bgneal@45 2468 jQuery("<div/>")
bgneal@45 2469 // inject the contents of the document in, removing the scripts
bgneal@45 2470 // to avoid any 'Permission Denied' errors in IE
bgneal@45 2471 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
bgneal@45 2472
bgneal@45 2473 // Locate the specified elements
bgneal@45 2474 .find(selector) :
bgneal@45 2475
bgneal@45 2476 // If not, just inject the full result
bgneal@45 2477 res.responseText );
bgneal@45 2478
bgneal@45 2479 self.each( callback, [res.responseText, status, res] );
bgneal@45 2480 }
bgneal@45 2481 });
bgneal@45 2482 return this;
bgneal@45 2483 },
bgneal@45 2484
bgneal@45 2485 serialize: function() {
bgneal@45 2486 return jQuery.param(this.serializeArray());
bgneal@45 2487 },
bgneal@45 2488 serializeArray: function() {
bgneal@45 2489 return this.map(function(){
bgneal@45 2490 return jQuery.nodeName(this, "form") ?
bgneal@45 2491 jQuery.makeArray(this.elements) : this;
bgneal@45 2492 })
bgneal@45 2493 .filter(function(){
bgneal@45 2494 return this.name && !this.disabled &&
bgneal@45 2495 (this.checked || /select|textarea/i.test(this.nodeName) ||
bgneal@45 2496 /text|hidden|password/i.test(this.type));
bgneal@45 2497 })
bgneal@45 2498 .map(function(i, elem){
bgneal@45 2499 var val = jQuery(this).val();
bgneal@45 2500 return val == null ? null :
bgneal@45 2501 val.constructor == Array ?
bgneal@45 2502 jQuery.map( val, function(val, i){
bgneal@45 2503 return {name: elem.name, value: val};
bgneal@45 2504 }) :
bgneal@45 2505 {name: elem.name, value: val};
bgneal@45 2506 }).get();
bgneal@45 2507 }
bgneal@45 2508 });
bgneal@45 2509
bgneal@45 2510 // Attach a bunch of functions for handling common AJAX events
bgneal@45 2511 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
bgneal@45 2512 jQuery.fn[o] = function(f){
bgneal@45 2513 return this.bind(o, f);
bgneal@45 2514 };
bgneal@45 2515 });
bgneal@45 2516
bgneal@45 2517 var jsc = now();
bgneal@45 2518
bgneal@45 2519 jQuery.extend({
bgneal@45 2520 get: function( url, data, callback, type ) {
bgneal@45 2521 // shift arguments if data argument was ommited
bgneal@45 2522 if ( jQuery.isFunction( data ) ) {
bgneal@45 2523 callback = data;
bgneal@45 2524 data = null;
bgneal@45 2525 }
bgneal@45 2526
bgneal@45 2527 return jQuery.ajax({
bgneal@45 2528 type: "GET",
bgneal@45 2529 url: url,
bgneal@45 2530 data: data,
bgneal@45 2531 success: callback,
bgneal@45 2532 dataType: type
bgneal@45 2533 });
bgneal@45 2534 },
bgneal@45 2535
bgneal@45 2536 getScript: function( url, callback ) {
bgneal@45 2537 return jQuery.get(url, null, callback, "script");
bgneal@45 2538 },
bgneal@45 2539
bgneal@45 2540 getJSON: function( url, data, callback ) {
bgneal@45 2541 return jQuery.get(url, data, callback, "json");
bgneal@45 2542 },
bgneal@45 2543
bgneal@45 2544 post: function( url, data, callback, type ) {
bgneal@45 2545 if ( jQuery.isFunction( data ) ) {
bgneal@45 2546 callback = data;
bgneal@45 2547 data = {};
bgneal@45 2548 }
bgneal@45 2549
bgneal@45 2550 return jQuery.ajax({
bgneal@45 2551 type: "POST",
bgneal@45 2552 url: url,
bgneal@45 2553 data: data,
bgneal@45 2554 success: callback,
bgneal@45 2555 dataType: type
bgneal@45 2556 });
bgneal@45 2557 },
bgneal@45 2558
bgneal@45 2559 ajaxSetup: function( settings ) {
bgneal@45 2560 jQuery.extend( jQuery.ajaxSettings, settings );
bgneal@45 2561 },
bgneal@45 2562
bgneal@45 2563 ajaxSettings: {
bgneal@45 2564 url: location.href,
bgneal@45 2565 global: true,
bgneal@45 2566 type: "GET",
bgneal@45 2567 timeout: 0,
bgneal@45 2568 contentType: "application/x-www-form-urlencoded",
bgneal@45 2569 processData: true,
bgneal@45 2570 async: true,
bgneal@45 2571 data: null,
bgneal@45 2572 username: null,
bgneal@45 2573 password: null,
bgneal@45 2574 accepts: {
bgneal@45 2575 xml: "application/xml, text/xml",
bgneal@45 2576 html: "text/html",
bgneal@45 2577 script: "text/javascript, application/javascript",
bgneal@45 2578 json: "application/json, text/javascript",
bgneal@45 2579 text: "text/plain",
bgneal@45 2580 _default: "*/*"
bgneal@45 2581 }
bgneal@45 2582 },
bgneal@45 2583
bgneal@45 2584 // Last-Modified header cache for next request
bgneal@45 2585 lastModified: {},
bgneal@45 2586
bgneal@45 2587 ajax: function( s ) {
bgneal@45 2588 // Extend the settings, but re-extend 's' so that it can be
bgneal@45 2589 // checked again later (in the test suite, specifically)
bgneal@45 2590 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
bgneal@45 2591
bgneal@45 2592 var jsonp, jsre = /=\?(&|$)/g, status, data,
bgneal@45 2593 type = s.type.toUpperCase();
bgneal@45 2594
bgneal@45 2595 // convert data if not already a string
bgneal@45 2596 if ( s.data && s.processData && typeof s.data != "string" )
bgneal@45 2597 s.data = jQuery.param(s.data);
bgneal@45 2598
bgneal@45 2599 // Handle JSONP Parameter Callbacks
bgneal@45 2600 if ( s.dataType == "jsonp" ) {
bgneal@45 2601 if ( type == "GET" ) {
bgneal@45 2602 if ( !s.url.match(jsre) )
bgneal@45 2603 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
bgneal@45 2604 } else if ( !s.data || !s.data.match(jsre) )
bgneal@45 2605 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
bgneal@45 2606 s.dataType = "json";
bgneal@45 2607 }
bgneal@45 2608
bgneal@45 2609 // Build temporary JSONP function
bgneal@45 2610 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
bgneal@45 2611 jsonp = "jsonp" + jsc++;
bgneal@45 2612
bgneal@45 2613 // Replace the =? sequence both in the query string and the data
bgneal@45 2614 if ( s.data )
bgneal@45 2615 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
bgneal@45 2616 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
bgneal@45 2617
bgneal@45 2618 // We need to make sure
bgneal@45 2619 // that a JSONP style response is executed properly
bgneal@45 2620 s.dataType = "script";
bgneal@45 2621
bgneal@45 2622 // Handle JSONP-style loading
bgneal@45 2623 window[ jsonp ] = function(tmp){
bgneal@45 2624 data = tmp;
bgneal@45 2625 success();
bgneal@45 2626 complete();
bgneal@45 2627 // Garbage collect
bgneal@45 2628 window[ jsonp ] = undefined;
bgneal@45 2629 try{ delete window[ jsonp ]; } catch(e){}
bgneal@45 2630 if ( head )
bgneal@45 2631 head.removeChild( script );
bgneal@45 2632 };
bgneal@45 2633 }
bgneal@45 2634
bgneal@45 2635 if ( s.dataType == "script" && s.cache == null )
bgneal@45 2636 s.cache = false;
bgneal@45 2637
bgneal@45 2638 if ( s.cache === false && type == "GET" ) {
bgneal@45 2639 var ts = now();
bgneal@45 2640 // try replacing _= if it is there
bgneal@45 2641 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
bgneal@45 2642 // if nothing was replaced, add timestamp to the end
bgneal@45 2643 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
bgneal@45 2644 }
bgneal@45 2645
bgneal@45 2646 // If data is available, append data to url for get requests
bgneal@45 2647 if ( s.data && type == "GET" ) {
bgneal@45 2648 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
bgneal@45 2649
bgneal@45 2650 // IE likes to send both get and post data, prevent this
bgneal@45 2651 s.data = null;
bgneal@45 2652 }
bgneal@45 2653
bgneal@45 2654 // Watch for a new set of requests
bgneal@45 2655 if ( s.global && ! jQuery.active++ )
bgneal@45 2656 jQuery.event.trigger( "ajaxStart" );
bgneal@45 2657
bgneal@45 2658 // Matches an absolute URL, and saves the domain
bgneal@45 2659 var remote = /^(?:\w+:)?\/\/([^\/?#]+)/;
bgneal@45 2660
bgneal@45 2661 // If we're requesting a remote document
bgneal@45 2662 // and trying to load JSON or Script with a GET
bgneal@45 2663 if ( s.dataType == "script" && type == "GET"
bgneal@45 2664 && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){
bgneal@45 2665 var head = document.getElementsByTagName("head")[0];
bgneal@45 2666 var script = document.createElement("script");
bgneal@45 2667 script.src = s.url;
bgneal@45 2668 if (s.scriptCharset)
bgneal@45 2669 script.charset = s.scriptCharset;
bgneal@45 2670
bgneal@45 2671 // Handle Script loading
bgneal@45 2672 if ( !jsonp ) {
bgneal@45 2673 var done = false;
bgneal@45 2674
bgneal@45 2675 // Attach handlers for all browsers
bgneal@45 2676 script.onload = script.onreadystatechange = function(){
bgneal@45 2677 if ( !done && (!this.readyState ||
bgneal@45 2678 this.readyState == "loaded" || this.readyState == "complete") ) {
bgneal@45 2679 done = true;
bgneal@45 2680 success();
bgneal@45 2681 complete();
bgneal@45 2682 head.removeChild( script );
bgneal@45 2683 }
bgneal@45 2684 };
bgneal@45 2685 }
bgneal@45 2686
bgneal@45 2687 head.appendChild(script);
bgneal@45 2688
bgneal@45 2689 // We handle everything using the script element injection
bgneal@45 2690 return undefined;
bgneal@45 2691 }
bgneal@45 2692
bgneal@45 2693 var requestDone = false;
bgneal@45 2694
bgneal@45 2695 // Create the request object; Microsoft failed to properly
bgneal@45 2696 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
bgneal@45 2697 var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
bgneal@45 2698
bgneal@45 2699 // Open the socket
bgneal@45 2700 // Passing null username, generates a login popup on Opera (#2865)
bgneal@45 2701 if( s.username )
bgneal@45 2702 xhr.open(type, s.url, s.async, s.username, s.password);
bgneal@45 2703 else
bgneal@45 2704 xhr.open(type, s.url, s.async);
bgneal@45 2705
bgneal@45 2706 // Need an extra try/catch for cross domain requests in Firefox 3
bgneal@45 2707 try {
bgneal@45 2708 // Set the correct header, if data is being sent
bgneal@45 2709 if ( s.data )
bgneal@45 2710 xhr.setRequestHeader("Content-Type", s.contentType);
bgneal@45 2711
bgneal@45 2712 // Set the If-Modified-Since header, if ifModified mode.
bgneal@45 2713 if ( s.ifModified )
bgneal@45 2714 xhr.setRequestHeader("If-Modified-Since",
bgneal@45 2715 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
bgneal@45 2716
bgneal@45 2717 // Set header so the called script knows that it's an XMLHttpRequest
bgneal@45 2718 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
bgneal@45 2719
bgneal@45 2720 // Set the Accepts header for the server, depending on the dataType
bgneal@45 2721 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
bgneal@45 2722 s.accepts[ s.dataType ] + ", */*" :
bgneal@45 2723 s.accepts._default );
bgneal@45 2724 } catch(e){}
bgneal@45 2725
bgneal@45 2726 // Allow custom headers/mimetypes
bgneal@45 2727 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
bgneal@45 2728 // cleanup active request counter
bgneal@45 2729 s.global && jQuery.active--;
bgneal@45 2730 // close opended socket
bgneal@45 2731 xhr.abort();
bgneal@45 2732 return false;
bgneal@45 2733 }
bgneal@45 2734
bgneal@45 2735 if ( s.global )
bgneal@45 2736 jQuery.event.trigger("ajaxSend", [xhr, s]);
bgneal@45 2737
bgneal@45 2738 // Wait for a response to come back
bgneal@45 2739 var onreadystatechange = function(isTimeout){
bgneal@45 2740 // The transfer is complete and the data is available, or the request timed out
bgneal@45 2741 if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
bgneal@45 2742 requestDone = true;
bgneal@45 2743
bgneal@45 2744 // clear poll interval
bgneal@45 2745 if (ival) {
bgneal@45 2746 clearInterval(ival);
bgneal@45 2747 ival = null;
bgneal@45 2748 }
bgneal@45 2749
bgneal@45 2750 status = isTimeout == "timeout" ? "timeout" :
bgneal@45 2751 !jQuery.httpSuccess( xhr ) ? "error" :
bgneal@45 2752 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
bgneal@45 2753 "success";
bgneal@45 2754
bgneal@45 2755 if ( status == "success" ) {
bgneal@45 2756 // Watch for, and catch, XML document parse errors
bgneal@45 2757 try {
bgneal@45 2758 // process the data (runs the xml through httpData regardless of callback)
bgneal@45 2759 data = jQuery.httpData( xhr, s.dataType, s.dataFilter );
bgneal@45 2760 } catch(e) {
bgneal@45 2761 status = "parsererror";
bgneal@45 2762 }
bgneal@45 2763 }
bgneal@45 2764
bgneal@45 2765 // Make sure that the request was successful or notmodified
bgneal@45 2766 if ( status == "success" ) {
bgneal@45 2767 // Cache Last-Modified header, if ifModified mode.
bgneal@45 2768 var modRes;
bgneal@45 2769 try {
bgneal@45 2770 modRes = xhr.getResponseHeader("Last-Modified");
bgneal@45 2771 } catch(e) {} // swallow exception thrown by FF if header is not available
bgneal@45 2772
bgneal@45 2773 if ( s.ifModified && modRes )
bgneal@45 2774 jQuery.lastModified[s.url] = modRes;
bgneal@45 2775
bgneal@45 2776 // JSONP handles its own success callback
bgneal@45 2777 if ( !jsonp )
bgneal@45 2778 success();
bgneal@45 2779 } else
bgneal@45 2780 jQuery.handleError(s, xhr, status);
bgneal@45 2781
bgneal@45 2782 // Fire the complete handlers
bgneal@45 2783 complete();
bgneal@45 2784
bgneal@45 2785 // Stop memory leaks
bgneal@45 2786 if ( s.async )
bgneal@45 2787 xhr = null;
bgneal@45 2788 }
bgneal@45 2789 };
bgneal@45 2790
bgneal@45 2791 if ( s.async ) {
bgneal@45 2792 // don't attach the handler to the request, just poll it instead
bgneal@45 2793 var ival = setInterval(onreadystatechange, 13);
bgneal@45 2794
bgneal@45 2795 // Timeout checker
bgneal@45 2796 if ( s.timeout > 0 )
bgneal@45 2797 setTimeout(function(){
bgneal@45 2798 // Check to see if the request is still happening
bgneal@45 2799 if ( xhr ) {
bgneal@45 2800 // Cancel the request
bgneal@45 2801 xhr.abort();
bgneal@45 2802
bgneal@45 2803 if( !requestDone )
bgneal@45 2804 onreadystatechange( "timeout" );
bgneal@45 2805 }
bgneal@45 2806 }, s.timeout);
bgneal@45 2807 }
bgneal@45 2808
bgneal@45 2809 // Send the data
bgneal@45 2810 try {
bgneal@45 2811 xhr.send(s.data);
bgneal@45 2812 } catch(e) {
bgneal@45 2813 jQuery.handleError(s, xhr, null, e);
bgneal@45 2814 }
bgneal@45 2815
bgneal@45 2816 // firefox 1.5 doesn't fire statechange for sync requests
bgneal@45 2817 if ( !s.async )
bgneal@45 2818 onreadystatechange();
bgneal@45 2819
bgneal@45 2820 function success(){
bgneal@45 2821 // If a local callback was specified, fire it and pass it the data
bgneal@45 2822 if ( s.success )
bgneal@45 2823 s.success( data, status );
bgneal@45 2824
bgneal@45 2825 // Fire the global callback
bgneal@45 2826 if ( s.global )
bgneal@45 2827 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
bgneal@45 2828 }
bgneal@45 2829
bgneal@45 2830 function complete(){
bgneal@45 2831 // Process result
bgneal@45 2832 if ( s.complete )
bgneal@45 2833 s.complete(xhr, status);
bgneal@45 2834
bgneal@45 2835 // The request was completed
bgneal@45 2836 if ( s.global )
bgneal@45 2837 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
bgneal@45 2838
bgneal@45 2839 // Handle the global AJAX counter
bgneal@45 2840 if ( s.global && ! --jQuery.active )
bgneal@45 2841 jQuery.event.trigger( "ajaxStop" );
bgneal@45 2842 }
bgneal@45 2843
bgneal@45 2844 // return XMLHttpRequest to allow aborting the request etc.
bgneal@45 2845 return xhr;
bgneal@45 2846 },
bgneal@45 2847
bgneal@45 2848 handleError: function( s, xhr, status, e ) {
bgneal@45 2849 // If a local callback was specified, fire it
bgneal@45 2850 if ( s.error ) s.error( xhr, status, e );
bgneal@45 2851
bgneal@45 2852 // Fire the global callback
bgneal@45 2853 if ( s.global )
bgneal@45 2854 jQuery.event.trigger( "ajaxError", [xhr, s, e] );
bgneal@45 2855 },
bgneal@45 2856
bgneal@45 2857 // Counter for holding the number of active queries
bgneal@45 2858 active: 0,
bgneal@45 2859
bgneal@45 2860 // Determines if an XMLHttpRequest was successful or not
bgneal@45 2861 httpSuccess: function( xhr ) {
bgneal@45 2862 try {
bgneal@45 2863 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
bgneal@45 2864 return !xhr.status && location.protocol == "file:" ||
bgneal@45 2865 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
bgneal@45 2866 jQuery.browser.safari && xhr.status == undefined;
bgneal@45 2867 } catch(e){}
bgneal@45 2868 return false;
bgneal@45 2869 },
bgneal@45 2870
bgneal@45 2871 // Determines if an XMLHttpRequest returns NotModified
bgneal@45 2872 httpNotModified: function( xhr, url ) {
bgneal@45 2873 try {
bgneal@45 2874 var xhrRes = xhr.getResponseHeader("Last-Modified");
bgneal@45 2875
bgneal@45 2876 // Firefox always returns 200. check Last-Modified date
bgneal@45 2877 return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
bgneal@45 2878 jQuery.browser.safari && xhr.status == undefined;
bgneal@45 2879 } catch(e){}
bgneal@45 2880 return false;
bgneal@45 2881 },
bgneal@45 2882
bgneal@45 2883 httpData: function( xhr, type, filter ) {
bgneal@45 2884 var ct = xhr.getResponseHeader("content-type"),
bgneal@45 2885 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
bgneal@45 2886 data = xml ? xhr.responseXML : xhr.responseText;
bgneal@45 2887
bgneal@45 2888 if ( xml && data.documentElement.tagName == "parsererror" )
bgneal@45 2889 throw "parsererror";
bgneal@45 2890
bgneal@45 2891 // Allow a pre-filtering function to sanitize the response
bgneal@45 2892 if( filter )
bgneal@45 2893 data = filter( data, type );
bgneal@45 2894
bgneal@45 2895 // If the type is "script", eval it in global context
bgneal@45 2896 if ( type == "script" )
bgneal@45 2897 jQuery.globalEval( data );
bgneal@45 2898
bgneal@45 2899 // Get the JavaScript object, if JSON is used.
bgneal@45 2900 if ( type == "json" )
bgneal@45 2901 data = eval("(" + data + ")");
bgneal@45 2902
bgneal@45 2903 return data;
bgneal@45 2904 },
bgneal@45 2905
bgneal@45 2906 // Serialize an array of form elements or a set of
bgneal@45 2907 // key/values into a query string
bgneal@45 2908 param: function( a ) {
bgneal@45 2909 var s = [ ];
bgneal@45 2910
bgneal@45 2911 function add( key, value ){
bgneal@45 2912 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
bgneal@45 2913 };
bgneal@45 2914
bgneal@45 2915 // If an array was passed in, assume that it is an array
bgneal@45 2916 // of form elements
bgneal@45 2917 if ( a.constructor == Array || a.jquery )
bgneal@45 2918 // Serialize the form elements
bgneal@45 2919 jQuery.each( a, function(){
bgneal@45 2920 add( this.name, this.value );
bgneal@45 2921 });
bgneal@45 2922
bgneal@45 2923 // Otherwise, assume that it's an object of key/value pairs
bgneal@45 2924 else
bgneal@45 2925 // Serialize the key/values
bgneal@45 2926 for ( var j in a )
bgneal@45 2927 // If the value is an array then the key names need to be repeated
bgneal@45 2928 if ( a[j] && a[j].constructor == Array )
bgneal@45 2929 jQuery.each( a[j], function(){
bgneal@45 2930 add( j, this );
bgneal@45 2931 });
bgneal@45 2932 else
bgneal@45 2933 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
bgneal@45 2934
bgneal@45 2935 // Return the resulting serialization
bgneal@45 2936 return s.join("&").replace(/%20/g, "+");
bgneal@45 2937 }
bgneal@45 2938
bgneal@45 2939 });
bgneal@45 2940 jQuery.fn.extend({
bgneal@45 2941 show: function(speed,callback){
bgneal@45 2942 return speed ?
bgneal@45 2943 this.animate({
bgneal@45 2944 height: "show", width: "show", opacity: "show"
bgneal@45 2945 }, speed, callback) :
bgneal@45 2946
bgneal@45 2947 this.filter(":hidden").each(function(){
bgneal@45 2948 this.style.display = this.oldblock || "";
bgneal@45 2949 if ( jQuery.css(this,"display") == "none" ) {
bgneal@45 2950 var elem = jQuery("<" + this.tagName + " />").appendTo("body");
bgneal@45 2951 this.style.display = elem.css("display");
bgneal@45 2952 // handle an edge condition where css is - div { display:none; } or similar
bgneal@45 2953 if (this.style.display == "none")
bgneal@45 2954 this.style.display = "block";
bgneal@45 2955 elem.remove();
bgneal@45 2956 }
bgneal@45 2957 }).end();
bgneal@45 2958 },
bgneal@45 2959
bgneal@45 2960 hide: function(speed,callback){
bgneal@45 2961 return speed ?
bgneal@45 2962 this.animate({
bgneal@45 2963 height: "hide", width: "hide", opacity: "hide"
bgneal@45 2964 }, speed, callback) :
bgneal@45 2965
bgneal@45 2966 this.filter(":visible").each(function(){
bgneal@45 2967 this.oldblock = this.oldblock || jQuery.css(this,"display");
bgneal@45 2968 this.style.display = "none";
bgneal@45 2969 }).end();
bgneal@45 2970 },
bgneal@45 2971
bgneal@45 2972 // Save the old toggle function
bgneal@45 2973 _toggle: jQuery.fn.toggle,
bgneal@45 2974
bgneal@45 2975 toggle: function( fn, fn2 ){
bgneal@45 2976 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
bgneal@45 2977 this._toggle.apply( this, arguments ) :
bgneal@45 2978 fn ?
bgneal@45 2979 this.animate({
bgneal@45 2980 height: "toggle", width: "toggle", opacity: "toggle"
bgneal@45 2981 }, fn, fn2) :
bgneal@45 2982 this.each(function(){
bgneal@45 2983 jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
bgneal@45 2984 });
bgneal@45 2985 },
bgneal@45 2986
bgneal@45 2987 slideDown: function(speed,callback){
bgneal@45 2988 return this.animate({height: "show"}, speed, callback);
bgneal@45 2989 },
bgneal@45 2990
bgneal@45 2991 slideUp: function(speed,callback){
bgneal@45 2992 return this.animate({height: "hide"}, speed, callback);
bgneal@45 2993 },
bgneal@45 2994
bgneal@45 2995 slideToggle: function(speed, callback){
bgneal@45 2996 return this.animate({height: "toggle"}, speed, callback);
bgneal@45 2997 },
bgneal@45 2998
bgneal@45 2999 fadeIn: function(speed, callback){
bgneal@45 3000 return this.animate({opacity: "show"}, speed, callback);
bgneal@45 3001 },
bgneal@45 3002
bgneal@45 3003 fadeOut: function(speed, callback){
bgneal@45 3004 return this.animate({opacity: "hide"}, speed, callback);
bgneal@45 3005 },
bgneal@45 3006
bgneal@45 3007 fadeTo: function(speed,to,callback){
bgneal@45 3008 return this.animate({opacity: to}, speed, callback);
bgneal@45 3009 },
bgneal@45 3010
bgneal@45 3011 animate: function( prop, speed, easing, callback ) {
bgneal@45 3012 var optall = jQuery.speed(speed, easing, callback);
bgneal@45 3013
bgneal@45 3014 return this[ optall.queue === false ? "each" : "queue" ](function(){
bgneal@45 3015 if ( this.nodeType != 1)
bgneal@45 3016 return false;
bgneal@45 3017
bgneal@45 3018 var opt = jQuery.extend({}, optall), p,
bgneal@45 3019 hidden = jQuery(this).is(":hidden"), self = this;
bgneal@45 3020
bgneal@45 3021 for ( p in prop ) {
bgneal@45 3022 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
bgneal@45 3023 return opt.complete.call(this);
bgneal@45 3024
bgneal@45 3025 if ( p == "height" || p == "width" ) {
bgneal@45 3026 // Store display property
bgneal@45 3027 opt.display = jQuery.css(this, "display");
bgneal@45 3028
bgneal@45 3029 // Make sure that nothing sneaks out
bgneal@45 3030 opt.overflow = this.style.overflow;
bgneal@45 3031 }
bgneal@45 3032 }
bgneal@45 3033
bgneal@45 3034 if ( opt.overflow != null )
bgneal@45 3035 this.style.overflow = "hidden";
bgneal@45 3036
bgneal@45 3037 opt.curAnim = jQuery.extend({}, prop);
bgneal@45 3038
bgneal@45 3039 jQuery.each( prop, function(name, val){
bgneal@45 3040 var e = new jQuery.fx( self, opt, name );
bgneal@45 3041
bgneal@45 3042 if ( /toggle|show|hide/.test(val) )
bgneal@45 3043 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
bgneal@45 3044 else {
bgneal@45 3045 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
bgneal@45 3046 start = e.cur(true) || 0;
bgneal@45 3047
bgneal@45 3048 if ( parts ) {
bgneal@45 3049 var end = parseFloat(parts[2]),
bgneal@45 3050 unit = parts[3] || "px";
bgneal@45 3051
bgneal@45 3052 // We need to compute starting value
bgneal@45 3053 if ( unit != "px" ) {
bgneal@45 3054 self.style[ name ] = (end || 1) + unit;
bgneal@45 3055 start = ((end || 1) / e.cur(true)) * start;
bgneal@45 3056 self.style[ name ] = start + unit;
bgneal@45 3057 }
bgneal@45 3058
bgneal@45 3059 // If a +=/-= token was provided, we're doing a relative animation
bgneal@45 3060 if ( parts[1] )
bgneal@45 3061 end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
bgneal@45 3062
bgneal@45 3063 e.custom( start, end, unit );
bgneal@45 3064 } else
bgneal@45 3065 e.custom( start, val, "" );
bgneal@45 3066 }
bgneal@45 3067 });
bgneal@45 3068
bgneal@45 3069 // For JS strict compliance
bgneal@45 3070 return true;
bgneal@45 3071 });
bgneal@45 3072 },
bgneal@45 3073
bgneal@45 3074 queue: function(type, fn){
bgneal@45 3075 if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
bgneal@45 3076 fn = type;
bgneal@45 3077 type = "fx";
bgneal@45 3078 }
bgneal@45 3079
bgneal@45 3080 if ( !type || (typeof type == "string" && !fn) )
bgneal@45 3081 return queue( this[0], type );
bgneal@45 3082
bgneal@45 3083 return this.each(function(){
bgneal@45 3084 if ( fn.constructor == Array )
bgneal@45 3085 queue(this, type, fn);
bgneal@45 3086 else {
bgneal@45 3087 queue(this, type).push( fn );
bgneal@45 3088
bgneal@45 3089 if ( queue(this, type).length == 1 )
bgneal@45 3090 fn.call(this);
bgneal@45 3091 }
bgneal@45 3092 });
bgneal@45 3093 },
bgneal@45 3094
bgneal@45 3095 stop: function(clearQueue, gotoEnd){
bgneal@45 3096 var timers = jQuery.timers;
bgneal@45 3097
bgneal@45 3098 if (clearQueue)
bgneal@45 3099 this.queue([]);
bgneal@45 3100
bgneal@45 3101 this.each(function(){
bgneal@45 3102 // go in reverse order so anything added to the queue during the loop is ignored
bgneal@45 3103 for ( var i = timers.length - 1; i >= 0; i-- )
bgneal@45 3104 if ( timers[i].elem == this ) {
bgneal@45 3105 if (gotoEnd)
bgneal@45 3106 // force the next step to be the last
bgneal@45 3107 timers[i](true);
bgneal@45 3108 timers.splice(i, 1);
bgneal@45 3109 }
bgneal@45 3110 });
bgneal@45 3111
bgneal@45 3112 // start the next in the queue if the last step wasn't forced
bgneal@45 3113 if (!gotoEnd)
bgneal@45 3114 this.dequeue();
bgneal@45 3115
bgneal@45 3116 return this;
bgneal@45 3117 }
bgneal@45 3118
bgneal@45 3119 });
bgneal@45 3120
bgneal@45 3121 var queue = function( elem, type, array ) {
bgneal@45 3122 if ( elem ){
bgneal@45 3123
bgneal@45 3124 type = type || "fx";
bgneal@45 3125
bgneal@45 3126 var q = jQuery.data( elem, type + "queue" );
bgneal@45 3127
bgneal@45 3128 if ( !q || array )
bgneal@45 3129 q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
bgneal@45 3130
bgneal@45 3131 }
bgneal@45 3132 return q;
bgneal@45 3133 };
bgneal@45 3134
bgneal@45 3135 jQuery.fn.dequeue = function(type){
bgneal@45 3136 type = type || "fx";
bgneal@45 3137
bgneal@45 3138 return this.each(function(){
bgneal@45 3139 var q = queue(this, type);
bgneal@45 3140
bgneal@45 3141 q.shift();
bgneal@45 3142
bgneal@45 3143 if ( q.length )
bgneal@45 3144 q[0].call( this );
bgneal@45 3145 });
bgneal@45 3146 };
bgneal@45 3147
bgneal@45 3148 jQuery.extend({
bgneal@45 3149
bgneal@45 3150 speed: function(speed, easing, fn) {
bgneal@45 3151 var opt = speed && speed.constructor == Object ? speed : {
bgneal@45 3152 complete: fn || !fn && easing ||
bgneal@45 3153 jQuery.isFunction( speed ) && speed,
bgneal@45 3154 duration: speed,
bgneal@45 3155 easing: fn && easing || easing && easing.constructor != Function && easing
bgneal@45 3156 };
bgneal@45 3157
bgneal@45 3158 opt.duration = (opt.duration && opt.duration.constructor == Number ?
bgneal@45 3159 opt.duration :
bgneal@45 3160 jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def;
bgneal@45 3161
bgneal@45 3162 // Queueing
bgneal@45 3163 opt.old = opt.complete;
bgneal@45 3164 opt.complete = function(){
bgneal@45 3165 if ( opt.queue !== false )
bgneal@45 3166 jQuery(this).dequeue();
bgneal@45 3167 if ( jQuery.isFunction( opt.old ) )
bgneal@45 3168 opt.old.call( this );
bgneal@45 3169 };
bgneal@45 3170
bgneal@45 3171 return opt;
bgneal@45 3172 },
bgneal@45 3173
bgneal@45 3174 easing: {
bgneal@45 3175 linear: function( p, n, firstNum, diff ) {
bgneal@45 3176 return firstNum + diff * p;
bgneal@45 3177 },
bgneal@45 3178 swing: function( p, n, firstNum, diff ) {
bgneal@45 3179 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
bgneal@45 3180 }
bgneal@45 3181 },
bgneal@45 3182
bgneal@45 3183 timers: [],
bgneal@45 3184 timerId: null,
bgneal@45 3185
bgneal@45 3186 fx: function( elem, options, prop ){
bgneal@45 3187 this.options = options;
bgneal@45 3188 this.elem = elem;
bgneal@45 3189 this.prop = prop;
bgneal@45 3190
bgneal@45 3191 if ( !options.orig )
bgneal@45 3192 options.orig = {};
bgneal@45 3193 }
bgneal@45 3194
bgneal@45 3195 });
bgneal@45 3196
bgneal@45 3197 jQuery.fx.prototype = {
bgneal@45 3198
bgneal@45 3199 // Simple function for setting a style value
bgneal@45 3200 update: function(){
bgneal@45 3201 if ( this.options.step )
bgneal@45 3202 this.options.step.call( this.elem, this.now, this );
bgneal@45 3203
bgneal@45 3204 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
bgneal@45 3205
bgneal@45 3206 // Set display property to block for height/width animations
bgneal@45 3207 if ( this.prop == "height" || this.prop == "width" )
bgneal@45 3208 this.elem.style.display = "block";
bgneal@45 3209 },
bgneal@45 3210
bgneal@45 3211 // Get the current size
bgneal@45 3212 cur: function(force){
bgneal@45 3213 if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
bgneal@45 3214 return this.elem[ this.prop ];
bgneal@45 3215
bgneal@45 3216 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
bgneal@45 3217 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
bgneal@45 3218 },
bgneal@45 3219
bgneal@45 3220 // Start an animation from one number to another
bgneal@45 3221 custom: function(from, to, unit){
bgneal@45 3222 this.startTime = now();
bgneal@45 3223 this.start = from;
bgneal@45 3224 this.end = to;
bgneal@45 3225 this.unit = unit || this.unit || "px";
bgneal@45 3226 this.now = this.start;
bgneal@45 3227 this.pos = this.state = 0;
bgneal@45 3228 this.update();
bgneal@45 3229
bgneal@45 3230 var self = this;
bgneal@45 3231 function t(gotoEnd){
bgneal@45 3232 return self.step(gotoEnd);
bgneal@45 3233 }
bgneal@45 3234
bgneal@45 3235 t.elem = this.elem;
bgneal@45 3236
bgneal@45 3237 jQuery.timers.push(t);
bgneal@45 3238
bgneal@45 3239 if ( jQuery.timerId == null ) {
bgneal@45 3240 jQuery.timerId = setInterval(function(){
bgneal@45 3241 var timers = jQuery.timers;
bgneal@45 3242
bgneal@45 3243 for ( var i = 0; i < timers.length; i++ )
bgneal@45 3244 if ( !timers[i]() )
bgneal@45 3245 timers.splice(i--, 1);
bgneal@45 3246
bgneal@45 3247 if ( !timers.length ) {
bgneal@45 3248 clearInterval( jQuery.timerId );
bgneal@45 3249 jQuery.timerId = null;
bgneal@45 3250 }
bgneal@45 3251 }, 13);
bgneal@45 3252 }
bgneal@45 3253 },
bgneal@45 3254
bgneal@45 3255 // Simple 'show' function
bgneal@45 3256 show: function(){
bgneal@45 3257 // Remember where we started, so that we can go back to it later
bgneal@45 3258 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
bgneal@45 3259 this.options.show = true;
bgneal@45 3260
bgneal@45 3261 // Begin the animation
bgneal@45 3262 this.custom(0, this.cur());
bgneal@45 3263
bgneal@45 3264 // Make sure that we start at a small width/height to avoid any
bgneal@45 3265 // flash of content
bgneal@45 3266 if ( this.prop == "width" || this.prop == "height" )
bgneal@45 3267 this.elem.style[this.prop] = "1px";
bgneal@45 3268
bgneal@45 3269 // Start by showing the element
bgneal@45 3270 jQuery(this.elem).show();
bgneal@45 3271 },
bgneal@45 3272
bgneal@45 3273 // Simple 'hide' function
bgneal@45 3274 hide: function(){
bgneal@45 3275 // Remember where we started, so that we can go back to it later
bgneal@45 3276 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
bgneal@45 3277 this.options.hide = true;
bgneal@45 3278
bgneal@45 3279 // Begin the animation
bgneal@45 3280 this.custom(this.cur(), 0);
bgneal@45 3281 },
bgneal@45 3282
bgneal@45 3283 // Each step of an animation
bgneal@45 3284 step: function(gotoEnd){
bgneal@45 3285 var t = now();
bgneal@45 3286
bgneal@45 3287 if ( gotoEnd || t > this.options.duration + this.startTime ) {
bgneal@45 3288 this.now = this.end;
bgneal@45 3289 this.pos = this.state = 1;
bgneal@45 3290 this.update();
bgneal@45 3291
bgneal@45 3292 this.options.curAnim[ this.prop ] = true;
bgneal@45 3293
bgneal@45 3294 var done = true;
bgneal@45 3295 for ( var i in this.options.curAnim )
bgneal@45 3296 if ( this.options.curAnim[i] !== true )
bgneal@45 3297 done = false;
bgneal@45 3298
bgneal@45 3299 if ( done ) {
bgneal@45 3300 if ( this.options.display != null ) {
bgneal@45 3301 // Reset the overflow
bgneal@45 3302 this.elem.style.overflow = this.options.overflow;
bgneal@45 3303
bgneal@45 3304 // Reset the display
bgneal@45 3305 this.elem.style.display = this.options.display;
bgneal@45 3306 if ( jQuery.css(this.elem, "display") == "none" )
bgneal@45 3307 this.elem.style.display = "block";
bgneal@45 3308 }
bgneal@45 3309
bgneal@45 3310 // Hide the element if the "hide" operation was done
bgneal@45 3311 if ( this.options.hide )
bgneal@45 3312 this.elem.style.display = "none";
bgneal@45 3313
bgneal@45 3314 // Reset the properties, if the item has been hidden or shown
bgneal@45 3315 if ( this.options.hide || this.options.show )
bgneal@45 3316 for ( var p in this.options.curAnim )
bgneal@45 3317 jQuery.attr(this.elem.style, p, this.options.orig[p]);
bgneal@45 3318 }
bgneal@45 3319
bgneal@45 3320 if ( done )
bgneal@45 3321 // Execute the complete function
bgneal@45 3322 this.options.complete.call( this.elem );
bgneal@45 3323
bgneal@45 3324 return false;
bgneal@45 3325 } else {
bgneal@45 3326 var n = t - this.startTime;
bgneal@45 3327 this.state = n / this.options.duration;
bgneal@45 3328
bgneal@45 3329 // Perform the easing function, defaults to swing
bgneal@45 3330 this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
bgneal@45 3331 this.now = this.start + ((this.end - this.start) * this.pos);
bgneal@45 3332
bgneal@45 3333 // Perform the next step of the animation
bgneal@45 3334 this.update();
bgneal@45 3335 }
bgneal@45 3336
bgneal@45 3337 return true;
bgneal@45 3338 }
bgneal@45 3339
bgneal@45 3340 };
bgneal@45 3341
bgneal@45 3342 jQuery.extend( jQuery.fx, {
bgneal@45 3343 speeds:{
bgneal@45 3344 slow: 600,
bgneal@45 3345 fast: 200,
bgneal@45 3346 // Default speed
bgneal@45 3347 def: 400
bgneal@45 3348 },
bgneal@45 3349 step: {
bgneal@45 3350 scrollLeft: function(fx){
bgneal@45 3351 fx.elem.scrollLeft = fx.now;
bgneal@45 3352 },
bgneal@45 3353
bgneal@45 3354 scrollTop: function(fx){
bgneal@45 3355 fx.elem.scrollTop = fx.now;
bgneal@45 3356 },
bgneal@45 3357
bgneal@45 3358 opacity: function(fx){
bgneal@45 3359 jQuery.attr(fx.elem.style, "opacity", fx.now);
bgneal@45 3360 },
bgneal@45 3361
bgneal@45 3362 _default: function(fx){
bgneal@45 3363 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
bgneal@45 3364 }
bgneal@45 3365 }
bgneal@45 3366 });
bgneal@45 3367 // The Offset Method
bgneal@45 3368 // Originally By Brandon Aaron, part of the Dimension Plugin
bgneal@45 3369 // http://jquery.com/plugins/project/dimensions
bgneal@45 3370 jQuery.fn.offset = function() {
bgneal@45 3371 var left = 0, top = 0, elem = this[0], results;
bgneal@45 3372
bgneal@45 3373 if ( elem ) with ( jQuery.browser ) {
bgneal@45 3374 var parent = elem.parentNode,
bgneal@45 3375 offsetChild = elem,
bgneal@45 3376 offsetParent = elem.offsetParent,
bgneal@45 3377 doc = elem.ownerDocument,
bgneal@45 3378 safari2 = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
bgneal@45 3379 css = jQuery.curCSS,
bgneal@45 3380 fixed = css(elem, "position") == "fixed";
bgneal@45 3381
bgneal@45 3382 // Use getBoundingClientRect if available
bgneal@45 3383 if ( !(mozilla && elem == document.body) && elem.getBoundingClientRect ) {
bgneal@45 3384 var box = elem.getBoundingClientRect();
bgneal@45 3385
bgneal@45 3386 // Add the document scroll offsets
bgneal@45 3387 add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
bgneal@45 3388 box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
bgneal@45 3389
bgneal@45 3390 // IE adds the HTML element's border, by default it is medium which is 2px
bgneal@45 3391 // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
bgneal@45 3392 // IE 7 standards mode, the border is always 2px
bgneal@45 3393 // This border/offset is typically represented by the clientLeft and clientTop properties
bgneal@45 3394 // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
bgneal@45 3395 // Therefore this method will be off by 2px in IE while in quirksmode
bgneal@45 3396 add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
bgneal@45 3397
bgneal@45 3398 // Otherwise loop through the offsetParents and parentNodes
bgneal@45 3399 } else {
bgneal@45 3400
bgneal@45 3401 // Initial element offsets
bgneal@45 3402 add( elem.offsetLeft, elem.offsetTop );
bgneal@45 3403
bgneal@45 3404 // Get parent offsets
bgneal@45 3405 while ( offsetParent ) {
bgneal@45 3406 // Add offsetParent offsets
bgneal@45 3407 add( offsetParent.offsetLeft, offsetParent.offsetTop );
bgneal@45 3408
bgneal@45 3409 // Mozilla and Safari > 2 does not include the border on offset parents
bgneal@45 3410 // However Mozilla adds the border for table or table cells
bgneal@45 3411 if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
bgneal@45 3412 border( offsetParent );
bgneal@45 3413
bgneal@45 3414 // Add the document scroll offsets if position is fixed on any offsetParent
bgneal@45 3415 if ( !fixed && css(offsetParent, "position") == "fixed" )
bgneal@45 3416 fixed = true;
bgneal@45 3417
bgneal@45 3418 // Set offsetChild to previous offsetParent unless it is the body element
bgneal@45 3419 offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
bgneal@45 3420 // Get next offsetParent
bgneal@45 3421 offsetParent = offsetParent.offsetParent;
bgneal@45 3422 }
bgneal@45 3423
bgneal@45 3424 // Get parent scroll offsets
bgneal@45 3425 while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
bgneal@45 3426 // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
bgneal@45 3427 if ( !/^inline|table.*$/i.test(css(parent, "display")) )
bgneal@45 3428 // Subtract parent scroll offsets
bgneal@45 3429 add( -parent.scrollLeft, -parent.scrollTop );
bgneal@45 3430
bgneal@45 3431 // Mozilla does not add the border for a parent that has overflow != visible
bgneal@45 3432 if ( mozilla && css(parent, "overflow") != "visible" )
bgneal@45 3433 border( parent );
bgneal@45 3434
bgneal@45 3435 // Get next parent
bgneal@45 3436 parent = parent.parentNode;
bgneal@45 3437 }
bgneal@45 3438
bgneal@45 3439 // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
bgneal@45 3440 // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
bgneal@45 3441 if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
bgneal@45 3442 (mozilla && css(offsetChild, "position") != "absolute") )
bgneal@45 3443 add( -doc.body.offsetLeft, -doc.body.offsetTop );
bgneal@45 3444
bgneal@45 3445 // Add the document scroll offsets if position is fixed
bgneal@45 3446 if ( fixed )
bgneal@45 3447 add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
bgneal@45 3448 Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
bgneal@45 3449 }
bgneal@45 3450
bgneal@45 3451 // Return an object with top and left properties
bgneal@45 3452 results = { top: top, left: left };
bgneal@45 3453 }
bgneal@45 3454
bgneal@45 3455 function border(elem) {
bgneal@45 3456 add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
bgneal@45 3457 }
bgneal@45 3458
bgneal@45 3459 function add(l, t) {
bgneal@45 3460 left += parseInt(l, 10) || 0;
bgneal@45 3461 top += parseInt(t, 10) || 0;
bgneal@45 3462 }
bgneal@45 3463
bgneal@45 3464 return results;
bgneal@45 3465 };
bgneal@45 3466
bgneal@45 3467
bgneal@45 3468 jQuery.fn.extend({
bgneal@45 3469 position: function() {
bgneal@45 3470 var left = 0, top = 0, results;
bgneal@45 3471
bgneal@45 3472 if ( this[0] ) {
bgneal@45 3473 // Get *real* offsetParent
bgneal@45 3474 var offsetParent = this.offsetParent(),
bgneal@45 3475
bgneal@45 3476 // Get correct offsets
bgneal@45 3477 offset = this.offset(),
bgneal@45 3478 parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
bgneal@45 3479
bgneal@45 3480 // Subtract element margins
bgneal@45 3481 // note: when an element has margin: auto the offsetLeft and marginLeft
bgneal@45 3482 // are the same in Safari causing offset.left to incorrectly be 0
bgneal@45 3483 offset.top -= num( this, 'marginTop' );
bgneal@45 3484 offset.left -= num( this, 'marginLeft' );
bgneal@45 3485
bgneal@45 3486 // Add offsetParent borders
bgneal@45 3487 parentOffset.top += num( offsetParent, 'borderTopWidth' );
bgneal@45 3488 parentOffset.left += num( offsetParent, 'borderLeftWidth' );
bgneal@45 3489
bgneal@45 3490 // Subtract the two offsets
bgneal@45 3491 results = {
bgneal@45 3492 top: offset.top - parentOffset.top,
bgneal@45 3493 left: offset.left - parentOffset.left
bgneal@45 3494 };
bgneal@45 3495 }
bgneal@45 3496
bgneal@45 3497 return results;
bgneal@45 3498 },
bgneal@45 3499
bgneal@45 3500 offsetParent: function() {
bgneal@45 3501 var offsetParent = this[0].offsetParent;
bgneal@45 3502 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
bgneal@45 3503 offsetParent = offsetParent.offsetParent;
bgneal@45 3504 return jQuery(offsetParent);
bgneal@45 3505 }
bgneal@45 3506 });
bgneal@45 3507
bgneal@45 3508
bgneal@45 3509 // Create scrollLeft and scrollTop methods
bgneal@45 3510 jQuery.each( ['Left', 'Top'], function(i, name) {
bgneal@45 3511 var method = 'scroll' + name;
bgneal@45 3512
bgneal@45 3513 jQuery.fn[ method ] = function(val) {
bgneal@45 3514 if (!this[0]) return;
bgneal@45 3515
bgneal@45 3516 return val != undefined ?
bgneal@45 3517
bgneal@45 3518 // Set the scroll offset
bgneal@45 3519 this.each(function() {
bgneal@45 3520 this == window || this == document ?
bgneal@45 3521 window.scrollTo(
bgneal@45 3522 !i ? val : jQuery(window).scrollLeft(),
bgneal@45 3523 i ? val : jQuery(window).scrollTop()
bgneal@45 3524 ) :
bgneal@45 3525 this[ method ] = val;
bgneal@45 3526 }) :
bgneal@45 3527
bgneal@45 3528 // Return the scroll offset
bgneal@45 3529 this[0] == window || this[0] == document ?
bgneal@45 3530 self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
bgneal@45 3531 jQuery.boxModel && document.documentElement[ method ] ||
bgneal@45 3532 document.body[ method ] :
bgneal@45 3533 this[0][ method ];
bgneal@45 3534 };
bgneal@45 3535 });
bgneal@45 3536 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
bgneal@45 3537 jQuery.each([ "Height", "Width" ], function(i, name){
bgneal@45 3538
bgneal@45 3539 var tl = i ? "Left" : "Top", // top or left
bgneal@45 3540 br = i ? "Right" : "Bottom"; // bottom or right
bgneal@45 3541
bgneal@45 3542 // innerHeight and innerWidth
bgneal@45 3543 jQuery.fn["inner" + name] = function(){
bgneal@45 3544 return this[ name.toLowerCase() ]() +
bgneal@45 3545 num(this, "padding" + tl) +
bgneal@45 3546 num(this, "padding" + br);
bgneal@45 3547 };
bgneal@45 3548
bgneal@45 3549 // outerHeight and outerWidth
bgneal@45 3550 jQuery.fn["outer" + name] = function(margin) {
bgneal@45 3551 return this["inner" + name]() +
bgneal@45 3552 num(this, "border" + tl + "Width") +
bgneal@45 3553 num(this, "border" + br + "Width") +
bgneal@45 3554 (margin ?
bgneal@45 3555 num(this, "margin" + tl) + num(this, "margin" + br) : 0);
bgneal@45 3556 };
bgneal@45 3557
bgneal@45 3558 });})();