jQuery 1.0.4 - New Wave Javascript(js坿猟周)

鹸崙旗鷹 旗鷹泌和:

  /* prevent execution of jQuery if included more then once */

  if(typeof window.jQuery == "undefined") {

  /*

  * jQuery 1.0.4 - New Wave Javascript

  *

  * Copyright (c) 2006 John Resig (jquery.com)

  * Dual licensed under the MIT (MIT-LICENSE.txt)

  * and GPL (GPL-LICENSE.txt) licenses.

  *

  * $Date: 2006-12-12 15:33:10 -0500 (Tue, 12 Dec 2006) $

  * $Rev: 696 $

  */

  // Global undefined variable

  window.undefined = window.undefined;

  var jQuery = function(a,c) {

  // Shortcut for document ready

  if ( a && typeof a == "function" && jQuery.fn.ready && !a.nodeType && a[0] == undefined ) // Safari reports typeof on DOM NodeLists as a function

  return jQuery(document).ready(a);

  // Make sure that a selection was provided

  a = a || document;

  // Watch for when a jQuery object is passed as the selector

  if ( a.jquery )

  return jQuery( jQuery.merge( a, [] ) );

  // Watch for when a jQuery object is passed at the context

  if ( c && c.jquery )

  return jQuery( c ).find(a);

  // If the context is global, return a new object

  if ( window == this )

  return new jQuery(a,c);

  // Handle HTML strings

  if ( typeof a  == "string" ) {

  var m = /^[^<]*(<.+>)[^>]*$/.exec(a);

  if ( m ) a = jQuery.clean( [ m[1] ] );

  }

  // Watch for when an array is passed in

  this.set( a.constructor == Array || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType ?

  // Assume that it is an array of DOM Elements

  jQuery.merge( a, [] ) :

  // Find the matching elements and save them for later

  jQuery.find( a, c ) );

  // See if an extra function was provided

  var fn = arguments[ arguments.length - 1 ];

  // If so, execute it in context

  if ( fn && typeof fn == "function" )

  this.each(fn);

  return this;

  };

  // Map over the $ in case of overwrite

  if ( typeof $ != "undefined" )

  jQuery._$ = $;

  // Map the jQuery namespace to the '$' one

  var $ = jQuery;

  jQuery.fn = jQuery.prototype = {

  jquery: "1.0.4",

  size: function() {

  return this.length;

  },

  get: function( num ) {

  return num == undefined ?

  // Return a 'clean' array

  jQuery.merge( this, [] ) :

  // Return just the object

  this[num];

  },

  set: function( array ) {

  // Use a tricky hack to make the jQuery object

  // look and feel like an array

  this.length = 0;

  [].push.apply( this, array );

  return this;

  },

  each: function( fn, args ) {

  return jQuery.each( this, fn, args );

  },

  index: function( obj ) {

  var pos = -1;

  this.each(function(i){

  if ( this == obj ) pos = i;

  });

  return pos;

  },

  attr: function( key, value, type ) {

  // Check to see if we're setting style values

  return key.constructor != String || value != undefined ?

  this.each(function(){

  // See if we're setting a hash of styles

  if ( value == undefined )

  // Set all the styles

  for ( var prop in key )

  jQuery.attr(

  type ? this.style : this,

  prop, key[prop]

  );

  // See if we're setting a single key/value style

  else

  jQuery.attr(

  type ? this.style : this,

  key, value

  );

  }) :

  // Look for the case where we're accessing a style value

  jQuery[ type || "attr" ]( this[0], key );

  },

  css: function( key, value ) {

  return this.attr( key, value, "curCSS" );

  },

  text: function(e) {

  e = e || this;

  var t = "";

  for ( var j = 0; j < e.length; j++ ) {

  var r = e[j].childNodes;

  for ( var i = 0; i < r.length; i++ )

  if ( r[i].nodeType != 8 )

  t += r[i].nodeType != 1 ?

  r[i].nodeValue : jQuery.fn.text([ r[i] ]);

  }

  return t;

  },

  wrap: function() {

  // The elements to wrap the target around

  var a = jQuery.clean(arguments);

  // Wrap each of the matched elements individually

  return this.each(function(){

  // Clone the structure that we're using to wrap

  var b = a[0].cloneNode(true);

  // Insert it before the element to be wrapped

  this.parentNode.insertBefore( b, this );

  // Find the deepest point in the wrap structure

  while ( b.firstChild )

  b = b.firstChild;

  // Move the matched element to within the wrap structure

  b.appendChild( this );

  });

  },

  append: function() {

  return this.domManip(arguments, true, 1, function(a){

  this.appendChild( a );

  });

  },

  prepend: function() {

  return this.domManip(arguments, true, -1, function(a){

  this.insertBefore( a, this.firstChild );

  });

  },

  before: function() {

  return this.domManip(arguments, false, 1, function(a){

  this.parentNode.insertBefore( a, this );

  });

  },

  after: function() {

  return this.domManip(arguments, false, -1, function(a){

  this.parentNode.insertBefore( a, this.nextSibling );

  });

  },

  end: function() {

  if( !(this.stack && this.stack.length) )

  return this;

  return this.set( this.stack.pop() );

  },

  find: function(t) {

  return this.pushStack( jQuery.map( this, function(a){

  return jQuery.find(t,a);

  }), arguments );

  },

  clone: function(deep) {

  return this.pushStack( jQuery.map( this, function(a){

  return a.cloneNode( deep != undefined ? deep : true );

  }), arguments );

  },

  filter: function(t) {

  return this.pushStack(

  t.constructor == Array &&

  jQuery.map(this,function(a){

  for ( var i = 0; i < t.length; i++ )

  if ( jQuery.filter(t[i],[a]).r.length )

  return a;

  return null;

  }) ||

  t.constructor == Boolean &&

  ( t ? this.get() : [] ) ||

  typeof t == "function" &&

  jQuery.grep( this, t ) ||

  jQuery.filter(t,this).r, arguments );

  },

  not: function(t) {

  return this.pushStack( typeof t == "string" ?

  jQuery.filter(t,this,false).r :

  jQuery.grep(this,function(a){ return a != t; }), arguments );

  },

  add: function(t) {

  return this.pushStack( jQuery.merge( this, typeof t == "string" ?

  jQuery.find(t) : t.constructor == Array ? t : [t] ), arguments );

  },

  is: function(expr) {

  return expr ? jQuery.filter(expr,this).r.length > 0 : false;

  },

  domManip: function(args, table, dir, fn){

  var clone = this.size() > 1;

  var a = jQuery.clean(args);

  return this.each(function(){

  var obj = this;

  if ( table && this.nodeName.toUpperCase() == "TABLE" && a[0].nodeName.toUpperCase() != "THEAD" ) {

  var tbody = this.getElementsByTagName("tbody");

  if ( !tbody.length ) {

  obj = document.createElement("tbody");

  this.appendChild( obj );

  } else

  obj = tbody[0];

  }

  for ( var i = ( dir < 0 ? a.length - 1 : 0 );

  i != ( dir < 0 ? dir : a.length ); i += dir ) {

  fn.apply( obj, [ clone ? a[i].cloneNode(true) : a[i] ] );

  }

  });

  },

  pushStack: function(a,args) {

  var fn = args && args[args.length-1];

  var fn2 = args && args[args.length-2];

  if ( fn && fn.constructor != Function ) fn = null;

  if ( fn2 && fn2.constructor != Function ) fn2 = null;

  if ( !fn ) {

  if ( !this.stack ) this.stack = [];

  this.stack.push( this.get() );

  this.set( a );

  } else {

  var old = this.get();

  this.set( a );

  if ( fn2 && a.length || !fn2 )

  this.each( fn2 || fn ).set( old );

  else

  this.set( old ).each( fn );

  }

  return this;

  }

  };

  jQuery.extend = jQuery.fn.extend = function() {

  // copy reference to target object

  var target = arguments[0],

  a = 1;

  // extend jQuery itself if only one argument is passed

  if ( arguments.length == 1 ) {

  target = this;

  a = 0;

  }

  var prop;

  while (prop = arguments[a++])

  // Extend the base object

  for ( var i in prop ) target[i] = prop[i];

  // Return the modified object

  return target;

  };

  jQuery.extend({

  init: function(){

  jQuery.initDone = true;

  jQuery.each( jQuery.macros.axis, function(i,n){

  jQuery.fn[ i ] = function(a) {

  var ret = jQuery.map(this,n);

  if ( a && typeof a == "string" )

  ret = jQuery.filter(a,ret).r;

  return this.pushStack( ret, arguments );

  };

  });

  jQuery.each( jQuery.macros.to, function(i,n){

  jQuery.fn[ i ] = function(){

  var a = arguments;

  return this.each(function(){

  for ( var j = 0; j < a.length; j++ )

  jQuery(a[j])[n]( this );

  });

  };

  });

  jQuery.each( jQuery.macros.each, function(i,n){

  jQuery.fn[ i ] = function() {

  return this.each( n, arguments );

  };

  });

  jQuery.each( jQuery.macros.filter, function(i,n){

  jQuery.fn[ n ] = function(num,fn) {

  return this.filter( ":" + n + "(" + num + ")", fn );

  };

  });

  jQuery.each( jQuery.macros.attr, function(i,n){

  n = n || i;

  jQuery.fn[ i ] = function(h) {

  return h == undefined ?

  this.length ? this[0][n] : null :

  this.attr( n, h );

  };

  });

  jQuery.each( jQuery.macros.css, function(i,n){

  jQuery.fn[ n ] = function(h) {

  return h == undefined ?

  ( this.length ? jQuery.css( this[0], n ) : null ) :

  this.css( n, h );

  };

  });

  },

  // args is for internal usage only

  each: function( obj, fn, args ) {

  if ( obj.length == undefined )

  for ( var i in obj )

  fn.apply( obj[i], args || [i, obj[i]] );

  else

  for ( var i = 0; i < obj.length; i++ )

  if ( fn.apply( obj[i], args || [i, obj[i]] ) === false ) break;

  return obj;

  },

  className: {

  add: function(o,c){

  if (jQuery.className.has(o,c)) return;

  o.className += ( o.className ? " " : "" ) + c;

  },

  remove: function(o,c){

  if( !c ) {

  o.className = "";

  } else {

  var classes = o.className.split(" ");

  for(var i=0; i<classes.length; i++) {

  if(classes[i] == c) {

  classes.splice(i, 1);

  break;

  }

  }

  o.className = classes.join(' ');

  }

  },

  has: function(e,a) {

  if ( e.className != undefined )

  e = e.className;

  return new RegExp("(^|\\s)" + a + "(\\s|$)").test(e);

  }

  },

  swap: function(e,o,f) {

  for ( var i in o ) {

  e.style["old"+i] = e.style[i];

  e.style[i] = o[i];

  }

  f.apply( e, [] );

  for ( var i in o )

  e.style[i] = e.style["old"+i];

  },

  css: function(e,p) {

  if ( p == "height" || p == "width" ) {

  var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"];

  for ( var i=0; i<d.length; i++ ) {

  old["padding" + d[i]] = 0;

  old["border" + d[i] + "Width"] = 0;

  }

  jQuery.swap( e, old, function() {

  if (jQuery.css(e,"display") != "none") {

  oHeight = e.offsetHeight;

  oWidth = e.offsetWidth;

  } else {

  e = jQuery(e.cloneNode(true))

  .find(":radio").removeAttr("checked").end()

  .css({

  visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0"

  }).appendTo(e.parentNode)[0];

  var parPos = jQuery.css(e.parentNode,"position");

  if ( parPos == "" || parPos == "static" )

  e.parentNode.style.position = "relative";

  oHeight = e.clientHeight;

  oWidth = e.clientWidth;

  if ( parPos == "" || parPos == "static" )

  e.parentNode.style.position = "static";

  e.parentNode.removeChild(e);

  }

  });

  return p == "height" ? oHeight : oWidth;

  }

  return jQuery.curCSS( e, p );

  },

  curCSS: function(elem, prop, force) {

  var ret;

  if (prop == 'opacity' && jQuery.browser.msie)

  return jQuery.attr(elem.style, 'opacity');

  if (prop == "float" || prop == "cssFloat")

  prop = jQuery.browser.msie ? "styleFloat" : "cssFloat";

  if (!force && elem.style[prop]) {

  ret = elem.style[prop];

  } else if (document.defaultView && document.defaultView.getComputedStyle) {

  if (prop == "cssFloat" || prop == "styleFloat")

  prop = "float";

  prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase();

  var cur = document.defaultView.getComputedStyle(elem, null);

  if ( cur )

  ret = cur.getPropertyValue(prop);

  else if ( prop == 'display' )

  ret = 'none';

  else

  jQuery.swap(elem, { display: 'block' }, function() {

  var c = document.defaultView.getComputedStyle(this, '');

  ret = c && c.getPropertyValue(prop) || '';

  });

  } else if (elem.currentStyle) {

  var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();});

  ret = elem.currentStyle[prop] || elem.currentStyle[newProp];

  }

  return ret;

  },

  clean: function(a) {

  var r = [];

  for ( var i = 0; i < a.length; i++ ) {

  var arg = a[i];

  if ( typeof arg == "string" ) { // Convert html string into DOM nodes

  // Trim whitespace, otherwise indexOf won't work as expected

  var s = jQuery.trim(arg), div = document.createElement("div"), wrap = [0,"",""];

  if ( !s.indexOf("<opt") ) // option or optgroup

  wrap = [1, "<select>", "</select>"];

  else if ( !s.indexOf("<thead") || !s.indexOf("<tbody") )

  wrap = [1, "<table>", "</table>"];

  else if ( !s.indexOf("<tr") )

  wrap = [2, "<table>", "</table>"];    // tbody auto-inserted

  else if ( !s.indexOf("<td") || !s.indexOf("<th") )

  wrap = [3, "<table><tbody><tr>", "</tr></tbody></table>"];

  // Go to html and back, then peel off extra wrappers

  div.innerHTML = wrap[1] + s + wrap[2];

  while ( wrap[0]-- ) div = div.firstChild;

  arg = div.childNodes;

  }

  if ( arg.length != undefined && ( (jQuery.browser.safari && typeof arg == 'function') || !arg.nodeType ) ) // Safari reports typeof on a DOM NodeList to be a function

  for ( var n = 0; n < arg.length; n++ ) // Handles Array, jQuery, DOM NodeList collections

  r.push(arg[n]);

  else

  r.push(    arg.nodeType ? arg : document.createTextNode(arg.toString()) );

  }

  return r;

  },

  expr: {

  "": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",

  "#": "a.getAttribute('id')&&a.getAttribute('id')==m[2]",

  ":": {

  // Position Checks

  lt: "i<m[3]-0",

  gt: "i>m[3]-0",

  nth: "m[3]-0==i",

  eq: "m[3]-0==i",

  first: "i==0",

  last: "i==r.length-1",

  even: "i%2==0",

  odd: "i%2",

  // Child Checks

  "nth-child": "jQuery.sibling(a,m[3]).cur",

  "first-child": "jQuery.sibling(a,0).cur",

  "last-child": "jQuery.sibling(a,0).last",

  "only-child": "jQuery.sibling(a).length==1",

  // Parent Checks

  parent: "a.childNodes.length",

  empty: "!a.childNodes.length",

  // Text Check

  contains: "jQuery.fn.text.apply([a]).indexOf(m[3])>=0",

  // Visibility

  visible: "a.type!='hidden'&&jQuery.css(a,'display')!='none'&&jQuery.css(a,'visibility')!='hidden'",

  hidden: "a.type=='hidden'||jQuery.css(a,'display')=='none'||jQuery.css(a,'visibility')=='hidden'",

  // Form attributes

  enabled: "!a.disabled",

  disabled: "a.disabled",

  checked: "a.checked",

  selected: "a.selected || jQuery.attr(a, 'selected')",

  // Form elements

  text: "a.type=='text'",

  radio: "a.type=='radio'",

  checkbox: "a.type=='checkbox'",

  file: "a.type=='file'",

  password: "a.type=='password'",

  submit: "a.type=='submit'",

  image: "a.type=='image'",

  reset: "a.type=='reset'",

  button: "a.type=='button'",

  input: "/input|select|textarea|button/i.test(a.nodeName)"

  },

  ".": "jQuery.className.has(a,m[2])",

  "@": {

  "=": "z==m[4]",

  "!=": "z!=m[4]",

  "^=": "z && !z.indexOf(m[4])",

  "$=": "z && z.substr(z.length - m[4].length,m[4].length)==m[4]",

  "*=": "z && z.indexOf(m[4])>=0",

  "": "z"

  },

  "[": "jQuery.find(m[2],a).length"

  },

  token: [

  "\\.\\.|/\\.\\.", "a.parentNode",

  ">|/", "jQuery.sibling(a.firstChild)",

  "\\+", "jQuery.sibling(a).next",

  "~", function(a){

  var s = jQuery.sibling(a);

  return s.n >= 0 ? s.slice(s.n+1) : [];

  }

  ],

  find: function( t, context ) {

  // Make sure that the context is a DOM Element

  if ( context && context.nodeType == undefined )

  context = null;

  // Set the correct context (if none is provided)

  context = context || document;

  if ( t.constructor != String ) return [t];

  if ( !t.indexOf("//") ) {

  context = context.documentElement;

  t = t.substr(2,t.length);

  } else if ( !t.indexOf("/") ) {

  context = context.documentElement;

  t = t.substr(1,t.length);

  // FIX Assume the root element is right :(

  if ( t.indexOf("/") >= 1 )

  t = t.substr(t.indexOf("/"),t.length);

  }

  var ret = [context];

  var done = [];

  var last = null;

  while ( t.length > 0 && last != t ) {

  var r = [];

  last = t;

  t = jQuery.trim(t).replace( /^\/\//i, "" );

  var foundToken = false;

  for ( var i = 0; i < jQuery.token.length; i += 2 ) {

  if ( foundToken ) continue;

  var re = new RegExp("^(" + jQuery.token[i] + ")");

  var m = re.exec(t);

  if ( m ) {

  r = ret = jQuery.map( ret, jQuery.token[i+1] );

  t = jQuery.trim( t.replace( re, "" ) );

  foundToken = true;

  }

  }

  if ( !foundToken ) {

  if ( !t.indexOf(",") || !t.indexOf("|") ) {

  if ( ret[0] == context ) ret.shift();

  done = jQuery.merge( done, ret );

  r = ret = [context];

  t = " " + t.substr(1,t.length);

  } else {

  var re2 = /^([#.]?)([a-z0-9\\*_-]*)/i;

  var m = re2.exec(t);

  if ( m[1] == "#" ) {

  // Ummm, should make this work in all XML docs

  var oid = document.getElementById(m[2]);

  r = ret = oid ? [oid] : [];

  t = t.replace( re2, "" );

  } else {

  if ( !m[2] || m[1] == "." ) m[2] = "*";

  for ( var i = 0; i < ret.length; i++ )

  r = jQuery.merge( r,

  m[2] == "*" ?

  jQuery.getAll(ret[i]) :

  ret[i].getElementsByTagName(m[2])

  );

  }

  }

  }

  if ( t ) {

  var val = jQuery.filter(t,r);

  ret = r = val.r;

  t = jQuery.trim(val.t);

  }

  }

  if ( ret && ret[0] == context ) ret.shift();

  done = jQuery.merge( done, ret );

  return done;

  },

  getAll: function(o,r) {

  r = r || [];

  var s = o.childNodes;

  for ( var i = 0; i < s.length; i++ )

  if ( s[i].nodeType == 1 ) {

  r.push( s[i] );

  jQuery.getAll( s[i], r );

  }

  return r;

  },

  attr: function(elem, name, value){

  var fix = {

  "for": "htmlFor",

  "class": "className",

  "float": jQuery.browser.msie ? "styleFloat" : "cssFloat",

  cssFloat: jQuery.browser.msie ? "styleFloat" : "cssFloat",

  innerHTML: "innerHTML",

  className: "className",

  value: "value",

  disabled: "disabled",

  checked: "checked",

  readonly: "readOnly"

  };

  // IE actually uses filters for opacity ... elem is actually elem.style

  if (name == "opacity" && jQuery.browser.msie && value != undefined) {

  // IE has trouble with opacity if it does not have layout

  // Would prefer to check element.hasLayout first but don't have access to the element here

  elem['zoom'] = 1;

  if (value == 1) // Remove filter to avoid more IE weirdness

  return elem["filter"] = elem["filter"].replace(/alpha\([^\)]*\)/gi,"");

  else

  return elem["filter"] = elem["filter"].replace(/alpha\([^\)]*\)/gi,"") + "alpha(opacity=" + value * 100 + ")";

  } else if (name == "opacity" && jQuery.browser.msie) {

  return elem["filter"] ? parseFloat( elem["filter"].match(/alpha\(opacity=(.*)\)/)[1] )/100 : 1;

  }

  // Mozilla doesn't play well with opacity 1

  if (name == "opacity" && jQuery.browser.mozilla && value == 1) value = 0.9999;

  if ( fix[name] ) {

  if ( value != undefined ) elem[fix[name]] = value;

  return elem[fix[name]];

  } else if( value == undefined && jQuery.browser.msie && elem.nodeName && elem.nodeName.toUpperCase() == 'FORM' && (name == 'action' || name == 'method') ) {

  return elem.getAttributeNode(name).nodeValue;

  } else if ( elem.tagName ) { // IE elem.getAttribute passes even for style

  if ( value != undefined ) elem.setAttribute( name, value );

  return elem.getAttribute( name );

  } else {

  name = name.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();});

  if ( value != undefined ) elem[name] = value;

  return elem[name];

  }

  },

  // The regular expressions that power the parsing engine

  parse: [

  // Match: [@value='test'], [@foo]

  "\\[ *(@)S *([!*$^=]*) *('?\"?)(.*?)\\4 *\\]",

  // Match: [div], [div p]

  "(\\[)\s*(.*?)\s*\\]",

  // Match: :contains('foo')

  "(:)S\\(\"?'?([^\\)]*?)\"?'?\\)",

  // Match: :even, :last-chlid

  "([:.#]*)S"

  ],

  filter: function(t,r,not) {

  // Figure out if we're doing regular, or inverse, filtering

  var g = not !== false ? jQuery.grep :

  function(a,f) {return jQuery.grep(a,f,true);};

  while ( t && /^[a-z[({<*:.#]/i.test(t) ) {

  var p = jQuery.parse;

  for ( var i = 0; i < p.length; i++ ) {

  // Look for, and replace, string-like sequences

  // and finally build a regexp out of it

  var re = new RegExp(

  "^" + p[i].replace("S", "([a-z*_-][a-z0-9_-]*)"), "i" );

  var m = re.exec( t );

  if ( m ) {

  // Re-organize the first match

  if ( !i )

  m = ["",m[1], m[3], m[2], m[5]];

  // Remove what we just matched

  t = t.replace( re, "" );

  break;

  }

  }

  // :not() is a special case that can be optimized by

  // keeping it out of the expression list

  if ( m[1] == ":" && m[2] == "not" )

  r = jQuery.filter(m[3],r,false).r;

  // Otherwise, find the expression to execute

  else {

  var f = jQuery.expr[m[1]];

  if ( f.constructor != String )

  f = jQuery.expr[m[1]][m[2]];

  // Build a custom macro to enclose it

  eval("f = function(a,i){" +

  ( m[1] == "@" ? "z=jQuery.attr(a,m[3]);" : "" ) +

  "return " + f + "}");

  // Execute it against the current filter

  r = g( r, f );

  }

  }

  // Return an array of filtered elements (r)

  // and the modified expression string (t)

  return { r: r, t: t };

  },

  trim: function(t){

  return t.replace(/^\s+|\s+$/g, "");

  },

  parents: function( elem ){

  var matched = [];

  var cur = elem.parentNode;

  while ( cur && cur != document ) {

  matched.push( cur );

  cur = cur.parentNode;

  }

  return matched;

  },

  sibling: function(elem, pos, not) {

  var elems = [];

  if(elem) {

  var siblings = elem.parentNode.childNodes;

  for ( var i = 0; i < siblings.length; i++ ) {

  if ( not === true && siblings[i] == elem ) continue;

  if ( siblings[i].nodeType == 1 )

  elems.push( siblings[i] );

  if ( siblings[i] == elem )

  elems.n = elems.length - 1;

  }

  }

  return jQuery.extend( elems, {

  last: elems.n == elems.length - 1,

  cur: pos == "even" && elems.n % 2 == 0 || pos == "odd" && elems.n % 2 || elems[pos] == elem,

  prev: elems[elems.n - 1],

  next: elems[elems.n + 1]

  });

  },

  merge: function(first, second) {

  var result = [];

  // Move b over to the new array (this helps to avoid

  // StaticNodeList instances)

  for ( var k = 0; k < first.length; k++ )

  result[k] = first[k];

  // Now check for duplicates between a and b and only

  // add the unique items

  for ( var i = 0; i < second.length; i++ ) {

  var noCollision = true;

  // The collision-checking process

  for ( var j = 0; j < first.length; j++ )

  if ( second[i] == first[j] )

  noCollision = false;

  // If the item is unique, add it

  if ( noCollision )

  result.push( second[i] );

  }

  return result;

  },

  grep: function(elems, fn, inv) {

  // If a string is passed in for the function, make a function

  // for it (a handy shortcut)

  if ( typeof fn == "string" )

  fn = new Function("a","i","return " + fn);

  var result = [];

  // Go through the array, only saving the items

  // that pass the validator function

  for ( var i = 0; i < elems.length; i++ )

  if ( !inv && fn(elems[i],i) || inv && !fn(elems[i],i) )

  result.push( elems[i] );

  return result;

  },

  map: function(elems, fn) {

  // If a string is passed in for the function, make a function

  // for it (a handy shortcut)

  if ( typeof fn == "string" )

  fn = new Function("a","return " + fn);

  var result = [];

  // Go through the array, translating each of the items to their

  // new value (or values).

  for ( var i = 0; i < elems.length; i++ ) {

  var val = fn(elems[i],i);

  if ( val !== null && val != undefined ) {

  if ( val.constructor != Array ) val = [val];

  result = jQuery.merge( result, val );

  }

  }

  return result;

  },

  /*

  * A number of helper functions used for managing events.

  * Many of the ideas behind this code orignated from Dean Edwards' addEvent library.

  */

  event: {

  // Bind an event to an element

  // Original by Dean Edwards

  add: function(element, type, handler) {

  // For whatever reason, IE has trouble passing the window object

  // around, causing it to be cloned in the process

  if ( jQuery.browser.msie && element.setInterval != undefined )

  element = window;

  // Make sure that the function being executed has a unique ID

  if ( !handler.guid )

  handler.guid = this.guid++;

  // Init the element's event structure

  if (!element.events)

  element.events = {};

  // Get the current list of functions bound to this event

  var handlers = element.events[type];

  // If it hasn't been initialized yet

  if (!handlers) {

  // Init the event handler queue

  handlers = element.events[type] = {};

  // Remember an existing handler, if it's already there

  if (element["on" + type])

  handlers[0] = element["on" + type];

  }

  // Add the function to the element's handler list

  handlers[handler.guid] = handler;

  // And bind the global event handler to the element

  element["on" + type] = this.handle;

  // Remember the function in a global list (for triggering)

  if (!this.global[type])

  this.global[type] = [];

  this.global[type].push( element );

  },

  guid: 1,

  global: {},

  // Detach an event or set of events from an element

  remove: function(element, type, handler) {

  if (element.events)

  if (type && element.events[type])

  if ( handler )

  delete element.events[type][handler.guid];

  else

  for ( var i in element.events[type] )

  delete element.events[type][i];

  else

  for ( var j in element.events )

  this.remove( element, j );

  },

  trigger: function(type,data,element) {

  // Clone the incoming data, if any

  data = $.merge([], data || []);

  // Handle a global trigger

  if ( !element ) {

  var g = this.global[type];

  if ( g )

  for ( var i = 0; i < g.length; i++ )

  this.trigger( type, data, g[i] );

  // Handle triggering a single element

  } else if ( element["on" + type] ) {

  // Pass along a fake event

  data.unshift( this.fix({ type: type, target: element }) );

  // Trigger the event

  element["on" + type].apply( element, data );

  }

  },

  handle: function(event) {

  if ( typeof jQuery == "undefined" ) return false;

  event = jQuery.event.fix( event || window.event || {} ); // Empty object is for triggered events with no data

  // If no correct event was found, fail

  if ( !event ) return false;

  var returnValue = true;

  var c = this.events[event.type];

  var args = [].slice.call( arguments, 1 );

  args.unshift( event );

  for ( var j in c ) {

  if ( c[j].apply( this, args ) === false ) {

  event.preventDefault();

  event.stopPropagation();

  returnValue = false;

  }

  }

  // Clean up added properties in IE to prevent memory leak

  if (jQuery.browser.msie) event.target = event.preventDefault = event.stopPropagation = null;

  return returnValue;

  },

  fix: function(event) {

  // check IE

  if(jQuery.browser.msie) {

  // fix target property, if available

  // check prevents overwriting of fake target coming from trigger

  if(event.srcElement)

  event.target = event.srcElement;

  // calculate pageX/Y

  var e = document.documentElement, b = document.body;

  event.pageX = event.clientX + (e.scrollLeft || b.scrollLeft);

  event.pageY = event.clientY + (e.scrollTop || b.scrollTop);

  // check safari and if target is a textnode

  } else if(jQuery.browser.safari && event.target.nodeType == 3) {

  // target is readonly, clone the event object

  event = jQuery.extend({}, event);

  // get parentnode from textnode

  event.target = event.target.parentNode;

  }

  // fix preventDefault and stopPropagation

  if (!event.preventDefault)

  event.preventDefault = function() {

  this.returnValue = false;

  };

  if (!event.stopPropagation)

  event.stopPropagation = function() {

  this.cancelBubble = true;

  };

  return event;

  }

  }

  });

  /*

  * Wheather the W3C compliant box model is being used.

  *

  * @property

  * @name $.boxModel

  * @type Boolean

  * @cat Javascript

  */

  new function() {

  var b = navigator.userAgent.toLowerCase();

  // Figure out what browser is being used

  jQuery.browser = {

  safari: /webkit/.test(b),

  opera: /opera/.test(b),

  msie: /msie/.test(b) && !/opera/.test(b),

  mozilla: /mozilla/.test(b) && !/(compatible|webkit)/.test(b)

  };

  // Check to see if the W3C box model is being used

  jQuery.boxModel = !jQuery.browser.msie || document.compatMode == "CSS1Compat";

  };

  jQuery.macros = {

  to: {

  appendTo: "append",

  prependTo: "prepend",

  insertBefore: "before",

  insertAfter: "after"

  },

  css: "width,height,top,left,position,float,overflow,color,background".split(","),

  filter: [ "eq", "lt", "gt", "contains" ],

  attr: {

  val: "value",

  html: "innerHTML",

  id: null,

  title: null,

  name: null,

  href: null,

  src: null,

  rel: null

  },

  axis: {

  parent: "a.parentNode",

  ancestors: jQuery.parents,

  parents: jQuery.parents,

  next: "jQuery.sibling(a).next",

  prev: "jQuery.sibling(a).prev",

  siblings: "jQuery.sibling(a, null, true)",

  children: "jQuery.sibling(a.firstChild)"

  },

  each: {

  removeAttr: function( key ) {

  jQuery.attr( this, key, "" );

  this.removeAttribute( key );

  },

  show: function(){

  this.style.display = this.oldblock ? this.oldblock : "";

  if ( jQuery.css(this,"display") == "none" )

  this.style.display = "block";

  },

  hide: function(){

  this.oldblock = this.oldblock || jQuery.css(this,"display");

  if ( this.oldblock == "none" )

  this.oldblock = "block";

  this.style.display = "none";

  },

  toggle: function(){

  jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ].apply( jQuery(this), arguments );

  },

  addClass: function(c){

  jQuery.className.add(this,c);

  },

  removeClass: function(c){

  jQuery.className.remove(this,c);

  },

  toggleClass: function( c ){

  jQuery.className[ jQuery.className.has(this,c) ? "remove" : "add" ](this, c);

  },

  remove: function(a){

  if ( !a || jQuery.filter( a, [this] ).r )

  this.parentNode.removeChild( this );

  },

  empty: function(){

  while ( this.firstChild )

  this.removeChild( this.firstChild );

  },

  bind: function( type, fn ) {

  jQuery.event.add( this, type, fn );

  },

  unbind: function( type, fn ) {

  jQuery.event.remove( this, type, fn );

  },

  trigger: function( type, data ) {

  jQuery.event.trigger( type, data, this );

  }

  }

  };

  jQuery.init();

  jQuery.fn.extend({

  // We're overriding the old toggle function, so

  // remember it for later

  _toggle: jQuery.fn.toggle,

  toggle: function(a,b) {

  // If two functions are passed in, we're

  // toggling on a click

  return a && b && a.constructor == Function && b.constructor == Function ? this.click(function(e){

  // Figure out which function to execute

  this.last = this.last == a ? b : a;

  // Make sure that clicks stop

  e.preventDefault();

  // and execute the function

  return this.last.apply( this, [e] ) || false;

  }) :

  // Otherwise, execute the old toggle function

  this._toggle.apply( this, arguments );

  },

  hover: function(f,g) {

  // A private function for haandling mouse 'hovering'

  function handleHover(e) {

  // Check if mouse(over|out) are still within the same parent element

  var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;

  // Traverse up the tree

  while ( p && p != this ) try { p = p.parentNode } catch(e) { p = this; };

  // If we actually just moused on to a sub-element, ignore it

  if ( p == this ) return false;

  // Execute the right function

  return (e.type == "mouseover" ? f : g).apply(this, [e]);

  }

  // Bind the function to the two event listeners

  return this.mouseover(handleHover).mouseout(handleHover);

  },

  ready: function(f) {

  // If the DOM is already ready

  if ( jQuery.isReady )

  // Execute the function immediately

  f.apply( document );

  // Otherwise, remember the function for later

  else {

  // Add the function to the wait list

  jQuery.readyList.push( f );

  }

  return this;

  }

  });

  jQuery.extend({

  /*

  * All the code that makes DOM Ready work nicely.

  */

  isReady: false,

  readyList: [],

  // Handle when the DOM is ready

  ready: function() {

  // Make sure that the DOM is not already loaded

  if ( !jQuery.isReady ) {

  // Remember that the DOM is ready

  jQuery.isReady = true;

  // If there are functions bound, to execute

  if ( jQuery.readyList ) {

  // Execute all of them

  for ( var i = 0; i < jQuery.readyList.length; i++ )

  jQuery.readyList[i].apply( document );

  // Reset the list of functions

  jQuery.readyList = null;

  }

  // Remove event lisenter to avoid memory leak

  if ( jQuery.browser.mozilla || jQuery.browser.opera )

  document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );

  }

  }

  });

  new function(){

  var e = ("blur,focus,load,resize,scroll,unload,click,dblclick," +

  "mousedown,mouseup,mousemove,mouseover,mouseout,change,reset,select," +

  "submit,keydown,keypress,keyup,error").split(",");

  // Go through all the event names, but make sure that

  // it is enclosed properly

  for ( var i = 0; i < e.length; i++ ) new function(){

  var o = e[i];

  // Handle event binding

  jQuery.fn[o] = function(f){

  return f ? this.bind(o, f) : this.trigger(o);

  };

  // Handle event unbinding

  jQuery.fn["un"+o] = function(f){ return this.unbind(o, f); };

  // Finally, handle events that only fire once

  jQuery.fn["one"+o] = function(f){

  // save cloned reference to this

  var element = jQuery(this);

  var handler = function() {

  // unbind itself when executed

  element.unbind(o, handler);

  element = null;

  // apply original handler with the same arguments

  return f.apply(this, arguments);

  };

  return this.bind(o, handler);

  };

  };

  // If Mozilla is used

  if ( jQuery.browser.mozilla || jQuery.browser.opera ) {

  // Use the handy event callback

  document.addEventListener( "DOMContentLoaded", jQuery.ready, false );

  // If IE is used, use the excellent hack by Matthias Miller

  // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited

  } else if ( jQuery.browser.msie ) {

  // Only works if you document.write() it

  document.write("<scr" + "ipt id=__ie_init defer=true " +

  "src=//:><\/script>");

  // Use the defer script hack

  var script = document.getElementById("__ie_init");

  if (script) // script does not exist if jQuery is loaded dynamically

  script.onreadystatechange = function() {

  if ( this.readyState != "complete" ) return;

  this.parentNode.removeChild( this );

  jQuery.ready();

  };

  // Clear from memory

  script = null;

  // If Safari  is used

  } else if ( jQuery.browser.safari ) {

  // Continually check to see if the document.readyState is valid

  jQuery.safariTimer = setInterval(function(){

  // loaded and complete are both valid states

  if ( document.readyState == "loaded" ||

  document.readyState == "complete" ) {

  // If either one are found, remove the timer

  clearInterval( jQuery.safariTimer );

  jQuery.safariTimer = null;

  // and execute any waiting functions

  jQuery.ready();

  }

  }, 10);

  }

  // A fallback to window.onload, that will always work

  jQuery.event.add( window, "load", jQuery.ready );

  };

  // Clean up after IE to avoid memory leaks

  if (jQuery.browser.msie) jQuery(window).unload(function() {

  var event = jQuery.event, global = event.global;

  for (var type in global) {

  var els = global[type], i = els.length;

  if (i>0) do if (type != 'unload') event.remove(els[i-1], type); while (--i);

  }

  });

  jQuery.fn.extend({

  // overwrite the old show method

  _show: jQuery.fn.show,

  show: function(speed,callback){

  return speed ? this.animate({

  height: "show", width: "show", opacity: "show"

  }, speed, callback) : this._show();

  },

  // Overwrite the old hide method

  _hide: jQuery.fn.hide,

  hide: function(speed,callback){

  return speed ? this.animate({

  height: "hide", width: "hide", opacity: "hide"

  }, speed, callback) : this._hide();

  },

  slideDown: function(speed,callback){

  return this.animate({height: "show"}, speed, callback);

  },

  slideUp: function(speed,callback){

  return this.animate({height: "hide"}, speed, callback);

  },

  slideToggle: function(speed,callback){

  return this.each(function(){

  var state = jQuery(this).is(":hidden") ? "show" : "hide";

  jQuery(this).animate({height: state}, speed, callback);

  });

  },

  fadeIn: function(speed,callback){

  return this.animate({opacity: "show"}, speed, callback);

  },

  fadeOut: function(speed,callback){

  return this.animate({opacity: "hide"}, speed, callback);

  },

  fadeTo: function(speed,to,callback){

  return this.animate({opacity: to}, speed, callback);

  },

  animate: function(prop,speed,callback) {

  return this.queue(function(){

  this.curAnim = jQuery.extend({}, prop);

  for ( var p in prop ) {

  var e = new jQuery.fx( this, jQuery.speed(speed,callback), p );

  if ( prop[p].constructor == Number )

  e.custom( e.cur(), prop[p] );

  else

  e[ prop[p] ]( prop );

  }

  });

  },

  queue: function(type,fn){

  if ( !fn ) {

  fn = type;

  type = "fx";

  }

  return this.each(function(){

  if ( !this.queue )

  this.queue = {};

  if ( !this.queue[type] )

  this.queue[type] = [];

  this.queue[type].push( fn );

  if ( this.queue[type].length == 1 )

  fn.apply(this);

  });

  }

  });

  jQuery.extend({

  speed: function(s,o) {

  o = o || {};

  if ( o.constructor == Function )

  o = { complete: o };

  var ss = { slow: 600, fast: 200 };

  o.duration = (s && s.constructor == Number ? s : ss[s]) || 400;

  // Queueing

  o.oldComplete = o.complete;

  o.complete = function(){

  jQuery.dequeue(this, "fx");

  if ( o.oldComplete && o.oldComplete.constructor == Function )

  o.oldComplete.apply( this );

  };

  return o;

  },

  queue: {},

  dequeue: function(elem,type){

  type = type || "fx";

  if ( elem.queue && elem.queue[type] ) {

  // Remove self

  elem.queue[type].shift();

  // Get next function

  var f = elem.queue[type][0];

  if ( f ) f.apply( elem );

  }

  },

  /*

  * I originally wrote fx() as a clone of moo.fx and in the process

  * of making it small in size the code became illegible to sane

  * people. You've been warned.

  */

  fx: function( elem, options, prop ){

  var z = this;

  // The users options

  z.o = {

  duration: options.duration || 400,

  complete: options.complete,

  step: options.step

  };

  // The element

  z.el = elem;

  // The styles

  var y = z.el.style;

  // Store display property

  var oldDisplay = jQuery.css(z.el, 'display');

  // Set display property to block for animation

  y.display = "block";

  // Make sure that nothing sneaks out

  y.overflow = "hidden";

  // Simple function for setting a style value

  z.a = function(){

  if ( options.step )

  options.step.apply( elem, [ z.now ] );

  if ( prop == "opacity" )

  jQuery.attr(y, "opacity", z.now); // Let attr handle opacity

  else if ( parseInt(z.now) ) // My hate for IE will never die

  y[prop] = parseInt(z.now) + "px";

  };

  // Figure out the maximum number to run to

  z.max = function(){

  return parseFloat( jQuery.css(z.el,prop) );

  };

  // Get the current size

  z.cur = function(){

  var r = parseFloat( jQuery.curCSS(z.el, prop) );

  return r && r > -10000 ? r : z.max();

  };

  // Start an animation from one number to another

  z.custom = function(from,to){

  z.startTime = (new Date()).getTime();

  z.now = from;

  z.a();

  z.timer = setInterval(function(){

  z.step(from, to);

  }, 13);

  };

  // Simple 'show' function

  z.show = function(){

  if ( !z.el.orig ) z.el.orig = {};

  // Remember where we started, so that we can go back to it later

  z.el.orig[prop] = this.cur();

  z.o.show = true;

  // Begin the animation

  z.custom(0, z.el.orig[prop]);

  // Stupid IE, look what you made me do

  if ( prop != "opacity" )

  y[prop] = "1px";

  };

  // Simple 'hide' function

  z.hide = function(){

  if ( !z.el.orig ) z.el.orig = {};

  // Remember where we started, so that we can go back to it later

  z.el.orig[prop] = this.cur();

  z.o.hide = true;

  // Begin the animation

  z.custom(z.el.orig[prop], 0);

  };

  //Simple 'toggle' function

  z.toggle = function() {

  if ( !z.el.orig ) z.el.orig = {};

  // Remember where we started, so that we can go back to it later

  z.el.orig[prop] = this.cur();

  if(oldDisplay == 'none')  {

  z.o.show = true;

  // Stupid IE, look what you made me do

  if ( prop != "opacity" )

  y[prop] = "1px";

  // Begin the animation

  z.custom(0, z.el.orig[prop]);

  } else {

  z.o.hide = true;

  // Begin the animation

  z.custom(z.el.orig[prop], 0);

  }

  };

  // Each step of an animation

  z.step = function(firstNum, lastNum){

  var t = (new Date()).getTime();

  if (t > z.o.duration + z.startTime) {

  // Stop the timer

  clearInterval(z.timer);

  z.timer = null;

  z.now = lastNum;

  z.a();

  z.el.curAnim[ prop ] = true;

  var done = true;

  for ( var i in z.el.curAnim )

  if ( z.el.curAnim[i] !== true )

  done = false;

  if ( done ) {

  // Reset the overflow

  y.overflow = '';

  // Reset the display

  y.display = oldDisplay;

  if (jQuery.css(z.el, 'display') == 'none')

  y.display = 'block';

  // Hide the element if the "hide" operation was done

  if ( z.o.hide )

  y.display = 'none';

  // Reset the properties, if the item has been hidden or shown

  if ( z.o.hide || z.o.show )

  for ( var p in z.el.curAnim )

  if (p == "opacity")

  jQuery.attr(y, p, z.el.orig[p]);

  else

  y[p] = '';

  }

  // If a callback was provided, execute it

  if( done && z.o.complete && z.o.complete.constructor == Function )

  // Execute the complete function

  z.o.complete.apply( z.el );

  } else {

  // Figure out where in the animation we are and set the number

  var p = (t - this.startTime) / z.o.duration;

  z.now = ((-Math.cos(p*Math.PI)/2) + 0.5) * (lastNum-firstNum) + firstNum;

  // Perform the next step of the animation

  z.a();

  }

  };

  }

  });

  jQuery.fn.extend({

  loadIfModified: function( url, params, callback ) {

  this.load( url, params, callback, 1 );

  },

  load: function( url, params, callback, ifModified ) {

  if ( url.constructor == Function )

  return this.bind("load", url);

  callback = callback || function(){};

  // Default to a GET request

  var type = "GET";

  // If the second parameter was provided

  if ( params ) {

  // If it's a function

  if ( params.constructor == Function ) {

  // We assume that it's the callback

  callback = params;

  params = null;

  // Otherwise, build a param string

  } else {

  params = jQuery.param( params );

  type = "POST";

  }

  }

  var self = this;

  // Request the remote document

  jQuery.ajax({

  url: url,

  type: type,

  data: params,

  ifModified: ifModified,

  complete: function(res, status){

  if ( status == "success" || !ifModified && status == "notmodified" ) {

  // Inject the HTML into all the matched elements

  self.html(res.responseText)

  // Execute all the scripts inside of the newly-injected HTML

  .evalScripts()

  // Execute callback

  .each( callback, [res.responseText, status, res] );

  } else

  callback.apply( self, [res.responseText, status, res] );

  }

  });

  return this;

  },

  serialize: function() {

  return jQuery.param( this );

  },

  evalScripts: function() {

  return this.find('script').each(function(){

  if ( this.src )

  // for some weird reason, it doesn't work if the callback is ommited

  jQuery.getScript( this.src );

  else {

  jQuery.globalEval( this.text || this.textContent || this.innerHTML || "" );

  }

  }).end();

  }

  });

  // If IE is used, create a wrapper for the XMLHttpRequest object

  if ( jQuery.browser.msie && typeof XMLHttpRequest == "undefined" )

  XMLHttpRequest = function(){

  return new ActiveXObject("Microsoft.XMLHTTP");

  };

  // Attach a bunch of functions for handling common AJAX events

  new function(){

  var e = "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(",");

  for ( var i = 0; i < e.length; i++ ) new function(){

  var o = e[i];

  jQuery.fn[o] = function(f){

  return this.bind(o, f);

  };

  };

  };

  jQuery.extend({

  get: function( url, data, callback, type, ifModified ) {

  // shift arguments if data argument was ommited

  if ( data && data.constructor == Function ) {

  callback = data;

  data = null;

  }

  // Delegate

  jQuery.ajax({

  url: url,

  data: data,

  success: callback,

  dataType: type,

  ifModified: ifModified

  });

  },

  getIfModified: function( url, data, callback, type ) {

  jQuery.get(url, data, callback, type, 1);

  },

  getScript: function( url, callback ) {

  if(callback)

  jQuery.get(url, null, callback, "script");

  else {

  jQuery.get(url, null, null, "script");

  }

  },

  getJSON: function( url, data, callback ) {

  jQuery.get(url, data, callback, "json");

  },

  post: function( url, data, callback, type ) {

  // Delegate

  jQuery.ajax({

  type: "POST",

  url: url,

  data: data,

  success: callback,

  dataType: type

  });

  },

  // timeout (ms)

  timeout: 0,

  ajaxTimeout: function(timeout) {

  jQuery.timeout = timeout;

  },

  // Last-Modified header cache for next request

  lastModified: {},

  ajax: function( s ) {

  // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout

  s = jQuery.extend({

  global: true,

  ifModified: false,

  type: "GET",

  timeout: jQuery.timeout,

  complete: null,

  success: null,

  error: null,

  dataType: null,

  url: null,

  data: null,

  contentType: "application/x-www-form-urlencoded",

  processData: true,

  async: true,

  beforeSend: null

  }, s);

  // if data available

  if ( s.data ) {

  // convert data if not already a string

  if (s.processData && typeof s.data != 'string')

  s.data = jQuery.param(s.data);

  // append data to url for get requests

  if( s.type.toLowerCase() == "get" )

  // "?" + data or "&" + data (in case there are already params)

  s.url += ((s.url.indexOf("?") > -1) ? "&" : "?") + s.data;

  }

  // Watch for a new set of requests

  if ( s.global && ! jQuery.active++ )

  jQuery.event.trigger( "ajaxStart" );

  var requestDone = false;

  // Create the request object

  var xml = new XMLHttpRequest();

  // Open the socket

  xml.open(s.type, s.url, s.async);

  // Set the correct header, if data is being sent

  if ( s.data )

  xml.setRequestHeader("Content-Type", s.contentType);

  // Set the If-Modified-Since header, if ifModified mode.

  if ( s.ifModified )

  xml.setRequestHeader("If-Modified-Since",

  jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );

  // Set header so the called script knows that it's an XMLHttpRequest

  xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");

  // Make sure the browser sends the right content length

  if ( xml.overrideMimeType )

  xml.setRequestHeader("Connection", "close");

  // Allow custom headers/mimetypes

  if( s.beforeSend )

  s.beforeSend(xml);

  if (s.global)

  jQuery.event.trigger("ajaxSend", [xml, s]);

  // Wait for a response to come back

  var onreadystatechange = function(isTimeout){

  // The transfer is complete and the data is available, or the request timed out

  if ( xml && (xml.readyState == 4 || isTimeout == "timeout") ) {

  requestDone = true;

  var status = jQuery.httpSuccess( xml ) && isTimeout != "timeout" ?

  s.ifModified && jQuery.httpNotModified( xml, s.url ) ? "notmodified" : "success" : "error";

  // Make sure that the request was successful or notmodified

  if ( status != "error" ) {

  // Cache Last-Modified header, if ifModified mode.

  var modRes;

  try {

  modRes = xml.getResponseHeader("Last-Modified");

  } catch(e) {} // swallow exception thrown by FF if header is not available

  if ( s.ifModified && modRes )

  jQuery.lastModified[s.url] = modRes;

  // process the data (runs the xml through httpData regardless of callback)

  var data = jQuery.httpData( xml, s.dataType );

  // If a local callback was specified, fire it and pass it the data

  if ( s.success )

  s.success( data, status );

  // Fire the global callback

  if( s.global )

  jQuery.event.trigger( "ajaxSuccess", [xml, s] );

  // Otherwise, the request was not successful

  } else {

  // If a local callback was specified, fire it

  if ( s.error ) s.error( xml, status );

  // Fire the global callback

  if( s.global )

  jQuery.event.trigger( "ajaxError", [xml, s] );

  }

  // The request was completed

  if( s.global )

  jQuery.event.trigger( "ajaxComplete", [xml, s] );

  // Handle the global AJAX counter

  if ( s.global && ! --jQuery.active )

  jQuery.event.trigger( "ajaxStop" );

  // Process result

  if ( s.complete ) s.complete(xml, status);

  // Stop memory leaks

  xml.onreadystatechange = function(){};

  xml = null;

  }

  };

  xml.onreadystatechange = onreadystatechange;

  // Timeout checker

  if(s.timeout > 0)

  setTimeout(function(){

  // Check to see if the request is still happening

  if (xml) {

  // Cancel the request

  xml.abort();

  if ( !requestDone ) onreadystatechange( "timeout" );

  // Clear from memory

  xml = null;

  }

  }, s.timeout);

  // Send the data

  xml.send(s.data);

  // return XMLHttpRequest to allow aborting the request etc.

  return xml;

  },

  // Counter for holding the number of active queries

  active: 0,

  // Determines if an XMLHttpRequest was successful or not

  httpSuccess: function(r) {

  try {

  return !r.status && location.protocol == "file:" ||

  ( r.status >= 200 && r.status < 300 ) || r.status == 304 ||

  jQuery.browser.safari && r.status == undefined;

  } catch(e){}

  return false;

  },

  // Determines if an XMLHttpRequest returns NotModified

  httpNotModified: function(xml, url) {

  try {

  var xmlRes = xml.getResponseHeader("Last-Modified");

  // Firefox always returns 200. check Last-Modified date

  return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||

  jQuery.browser.safari && xml.status == undefined;

  } catch(e){}

  return false;

  },

  /* Get the data out of an XMLHttpRequest.

  * Return parsed XML if content-type header is "xml" and type is "xml" or omitted,

  * otherwise return plain text.

  * (String) data - The type of data that you're expecting back,

  * (e.g. "xml", "html", "script")

  */

  httpData: function(r,type) {

  var ct = r.getResponseHeader("content-type");

  var data = !type && ct && ct.indexOf("xml") >= 0;

  data = type == "xml" || data ? r.responseXML : r.responseText;

  // If the type is "script", eval it in global context

  if ( type == "script" ) {

  jQuery.globalEval( data );

  }

  // Get the JavaScript object, if JSON is used.

  if ( type == "json" ) eval( "data = " + data );

  // evaluate scripts within html

  if ( type == "html" ) jQuery("<div>").html(data).evalScripts();

  return data;

  },

  // Serialize an array of form elements or a set of

  // key/values into a query string

  param: function(a) {

  var s = [];

  // If an array was passed in, assume that it is an array

  // of form elements

  if ( a.constructor == Array || a.jquery ) {

  // Serialize the form elements

  for ( var i = 0; i < a.length; i++ )

  s.push( a[i].name + "=" + encodeURIComponent( a[i].value ) );

  // Otherwise, assume that it's an object of key/value pairs

  } else {

  // Serialize the key/values

  for ( var j in a ) {

  // If the value is an array then the key names need to be repeated

  if( a[j].constructor == Array ) {

  for (var k = 0; k < a[j].length; k++) {

  s.push( j + "=" + encodeURIComponent( a[j][k] ) );

  }

  } else {

  s.push( j + "=" + encodeURIComponent( a[j] ) );

  }

  }

  }

  // Return the resulting serialization

  return s.join("&");

  },

  // evalulates a script in global context

  // not reliable for safari

  globalEval: function(data) {

  if (window.execScript)

  window.execScript( data );

  else if(jQuery.browser.safari)

  // safari doesn't provide a synchronous global eval

  window.setTimeout( data, 0 );

  else

  eval.call( window, data );

  }

  });

  } // close: if(typeof window.jQuery == "undefined") {