Streber PM PHP Cross Reference Groupware Applications

Source: /js/jquery-1.2.6.js - 3549 lines - 100196 bytes - Summary - Text - Print

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

title

Description

title

Description

title

Description

title

title

Body