jquery-rails 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jquery-rails might be problematic. Click here for more details.

@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jquery-rails (2.1.2)
4
+ jquery-rails (2.1.3)
5
5
  railties (>= 3.1.0, < 5.0)
6
6
  thor (~> 0.14)
7
7
 
data/README.md CHANGED
@@ -4,11 +4,22 @@ jQuery! For Rails! So great.
4
4
 
5
5
  This gem provides:
6
6
 
7
- * jQuery 1.8.1
7
+ * jQuery 1.8.2
8
8
  * jQuery UI 1.8.23 (javascript only)
9
9
  * the jQuery UJS adapter
10
10
  * assert_select_jquery to test jQuery responses in Ruby tests
11
11
 
12
+ ## Versions
13
+
14
+ Starting with v2.1, the jquery-rails gem follows these version guidelines
15
+ to provide more control over your app's jquery version from your Gemfile:
16
+
17
+ ```
18
+ patch version bump = updates to jquery-ujs, jquery-rails, and patch-level updates to jquery
19
+ minor version bump = minor-level updates to jquery
20
+ major version bump = major-level updates to jquery and updates to rails which may be backwards-incompatible
21
+ ```
22
+
12
23
  ## Installation
13
24
 
14
25
  Apps generated with Rails 3.1 or later include jquery-rails in the Gemfile by default. So just make a new app:
@@ -1,7 +1,7 @@
1
1
  module Jquery
2
2
  module Rails
3
- VERSION = "2.1.2"
4
- JQUERY_VERSION = "1.8.1"
3
+ VERSION = "2.1.3"
4
+ JQUERY_VERSION = "1.8.2"
5
5
  JQUERY_UI_VERSION = "1.8.23"
6
6
  JQUERY_UJS_VERSION = "bddff6a677edc54f00e48bde740b0b22d68deef6"
7
7
  end
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * jQuery JavaScript Library v1.8.1
2
+ * jQuery JavaScript Library v1.8.2
3
3
  * http://jquery.com/
4
4
  *
5
5
  * Includes Sizzle.js
@@ -9,7 +9,7 @@
9
9
  * Released under the MIT license
10
10
  * http://jquery.org/license
11
11
  *
12
- * Date: Thu Aug 30 2012 17:17:22 GMT-0400 (Eastern Daylight Time)
12
+ * Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time)
13
13
  */
14
14
  (function( window, undefined ) {
15
15
  var
@@ -186,7 +186,7 @@ jQuery.fn = jQuery.prototype = {
186
186
  selector: "",
187
187
 
188
188
  // The current version of jQuery being used
189
- jquery: "1.8.1",
189
+ jquery: "1.8.2",
190
190
 
191
191
  // The default length of a jQuery object is 0
192
192
  length: 0,
@@ -573,7 +573,7 @@ jQuery.extend({
573
573
  },
574
574
 
575
575
  nodeName: function( elem, name ) {
576
- return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
576
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
577
577
  },
578
578
 
579
579
  // args is for internal usage only
@@ -630,7 +630,7 @@ jQuery.extend({
630
630
  function( text ) {
631
631
  return text == null ?
632
632
  "" :
633
- text.toString().replace( rtrim, "" );
633
+ ( text + "" ).replace( rtrim, "" );
634
634
  },
635
635
 
636
636
  // results is for internal usage only
@@ -776,7 +776,7 @@ jQuery.extend({
776
776
  };
777
777
 
778
778
  // Set the guid of unique handler to the same of original handler, so it can be removed
779
- proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
779
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
780
780
 
781
781
  return proxy;
782
782
  },
@@ -1143,7 +1143,7 @@ jQuery.extend({
1143
1143
  // Get a promise for this deferred
1144
1144
  // If obj is provided, the promise aspect is added to the object
1145
1145
  promise: function( obj ) {
1146
- return typeof obj === "object" ? jQuery.extend( obj, promise ) : promise;
1146
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
1147
1147
  }
1148
1148
  },
1149
1149
  deferred = {};
@@ -1262,7 +1262,7 @@ jQuery.support = (function() {
1262
1262
  a.style.cssText = "top:1px;float:left;opacity:.5";
1263
1263
 
1264
1264
  // Can't get basic test support
1265
- if ( !all || !all.length || !a ) {
1265
+ if ( !all || !all.length ) {
1266
1266
  return {};
1267
1267
  }
1268
1268
 
@@ -1513,7 +1513,7 @@ jQuery.extend({
1513
1513
 
1514
1514
  deletedIds: [],
1515
1515
 
1516
- // Please use with caution
1516
+ // Remove at next major release (1.9/2.0)
1517
1517
  uuid: 0,
1518
1518
 
1519
1519
  // Unique for each copy of jQuery on the page
@@ -1565,7 +1565,7 @@ jQuery.extend({
1565
1565
  // Only DOM nodes need a new unique ID for each element since their data
1566
1566
  // ends up in the global cache
1567
1567
  if ( isNode ) {
1568
- elem[ internalKey ] = id = jQuery.deletedIds.pop() || ++jQuery.uuid;
1568
+ elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;
1569
1569
  } else {
1570
1570
  id = internalKey;
1571
1571
  }
@@ -1739,7 +1739,7 @@ jQuery.fn.extend({
1739
1739
  for ( l = attr.length; i < l; i++ ) {
1740
1740
  name = attr[i].name;
1741
1741
 
1742
- if ( name.indexOf( "data-" ) === 0 ) {
1742
+ if ( !name.indexOf( "data-" ) ) {
1743
1743
  name = jQuery.camelCase( name.substring(5) );
1744
1744
 
1745
1745
  dataAttr( elem, name, data[ name ] );
@@ -2049,7 +2049,7 @@ jQuery.fn.extend({
2049
2049
  setClass = " " + elem.className + " ";
2050
2050
 
2051
2051
  for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2052
- if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
2052
+ if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
2053
2053
  setClass += classNames[ c ] + " ";
2054
2054
  }
2055
2055
  }
@@ -2082,7 +2082,7 @@ jQuery.fn.extend({
2082
2082
  // loop over each item in the removal list
2083
2083
  for ( c = 0, cl = removes.length; c < cl; c++ ) {
2084
2084
  // Remove until there is nothing to remove,
2085
- while ( className.indexOf(" " + removes[ c ] + " ") > -1 ) {
2085
+ while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
2086
2086
  className = className.replace( " " + removes[ c ] + " " , " " );
2087
2087
  }
2088
2088
  }
@@ -2136,7 +2136,7 @@ jQuery.fn.extend({
2136
2136
  i = 0,
2137
2137
  l = this.length;
2138
2138
  for ( ; i < l; i++ ) {
2139
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2139
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
2140
2140
  return true;
2141
2141
  }
2142
2142
  }
@@ -2314,7 +2314,7 @@ jQuery.extend({
2314
2314
  return ret;
2315
2315
 
2316
2316
  } else {
2317
- elem.setAttribute( name, "" + value );
2317
+ elem.setAttribute( name, value + "" );
2318
2318
  return value;
2319
2319
  }
2320
2320
 
@@ -2578,7 +2578,7 @@ if ( !jQuery.support.style ) {
2578
2578
  return elem.style.cssText.toLowerCase() || undefined;
2579
2579
  },
2580
2580
  set: function( elem, value ) {
2581
- return ( elem.style.cssText = "" + value );
2581
+ return ( elem.style.cssText = value + "" );
2582
2582
  }
2583
2583
  };
2584
2584
  }
@@ -2711,6 +2711,7 @@ jQuery.event = {
2711
2711
  handler: handler,
2712
2712
  guid: handler.guid,
2713
2713
  selector: selector,
2714
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
2714
2715
  namespace: namespaces.join(".")
2715
2716
  }, handleObjIn );
2716
2717
 
@@ -2946,7 +2947,7 @@ jQuery.event = {
2946
2947
  }
2947
2948
  // Note that this is a bare JS function and not a jQuery handler
2948
2949
  handle = ontype && cur[ ontype ];
2949
- if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
2950
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
2950
2951
  event.preventDefault();
2951
2952
  }
2952
2953
  }
@@ -2994,7 +2995,7 @@ jQuery.event = {
2994
2995
  var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,
2995
2996
  handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
2996
2997
  delegateCount = handlers.delegateCount,
2997
- args = [].slice.call( arguments ),
2998
+ args = core_slice.call( arguments ),
2998
2999
  run_all = !event.exclusive && !event.namespace,
2999
3000
  special = jQuery.event.special[ event.type ] || {},
3000
3001
  handlerQueue = [];
@@ -3023,7 +3024,9 @@ jQuery.event = {
3023
3024
  sel = handleObj.selector;
3024
3025
 
3025
3026
  if ( selMatch[ sel ] === undefined ) {
3026
- selMatch[ sel ] = jQuery( sel, this ).index( cur ) >= 0;
3027
+ selMatch[ sel ] = handleObj.needsContext ?
3028
+ jQuery( sel, this ).index( cur ) >= 0 :
3029
+ jQuery.find( sel, this, null, [ cur ] ).length;
3027
3030
  }
3028
3031
  if ( selMatch[ sel ] ) {
3029
3032
  matches.push( handleObj );
@@ -3593,7 +3596,7 @@ jQuery.fn.extend({
3593
3596
  },
3594
3597
  undelegate: function( selector, types, fn ) {
3595
3598
  // ( namespace ) or ( selector, types [, fn] )
3596
- return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3599
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3597
3600
  },
3598
3601
 
3599
3602
  trigger: function( type, data ) {
@@ -3664,14 +3667,13 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
3664
3667
  });
3665
3668
  /*!
3666
3669
  * Sizzle CSS Selector Engine
3667
- * Copyright 2012 jQuery Foundation and other contributors
3668
- * Released under the MIT license
3669
- * http://sizzlejs.com/
3670
+ * Copyright 2012 jQuery Foundation and other contributors
3671
+ * Released under the MIT license
3672
+ * http://sizzlejs.com/
3670
3673
  */
3671
3674
  (function( window, undefined ) {
3672
3675
 
3673
- var dirruns,
3674
- cachedruns,
3676
+ var cachedruns,
3675
3677
  assertGetIdNotName,
3676
3678
  Expr,
3677
3679
  getText,
@@ -3680,21 +3682,36 @@ var dirruns,
3680
3682
  compile,
3681
3683
  sortOrder,
3682
3684
  hasDuplicate,
3685
+ outermostContext,
3683
3686
 
3684
3687
  baseHasDuplicate = true,
3685
3688
  strundefined = "undefined",
3686
3689
 
3687
3690
  expando = ( "sizcache" + Math.random() ).replace( ".", "" ),
3688
3691
 
3692
+ Token = String,
3689
3693
  document = window.document,
3690
3694
  docElem = document.documentElement,
3695
+ dirruns = 0,
3691
3696
  done = 0,
3692
- slice = [].slice,
3697
+ pop = [].pop,
3693
3698
  push = [].push,
3699
+ slice = [].slice,
3700
+ // Use a stripped-down indexOf if a native one is unavailable
3701
+ indexOf = [].indexOf || function( elem ) {
3702
+ var i = 0,
3703
+ len = this.length;
3704
+ for ( ; i < len; i++ ) {
3705
+ if ( this[i] === elem ) {
3706
+ return i;
3707
+ }
3708
+ }
3709
+ return -1;
3710
+ },
3694
3711
 
3695
3712
  // Augment a function for special use by Sizzle
3696
3713
  markFunction = function( fn, value ) {
3697
- fn[ expando ] = value || true;
3714
+ fn[ expando ] = value == null || value;
3698
3715
  return fn;
3699
3716
  },
3700
3717
 
@@ -3741,7 +3758,8 @@ var dirruns,
3741
3758
  pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",
3742
3759
 
3743
3760
  // For matchExpr.POS and matchExpr.needsContext
3744
- pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\(((?:-\\d)?\\d*)\\)|)(?=[^-]|$)",
3761
+ pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
3762
+ "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",
3745
3763
 
3746
3764
  // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3747
3765
  rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
@@ -3769,10 +3787,10 @@ var dirruns,
3769
3787
  "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3770
3788
  "ATTR": new RegExp( "^" + attributes ),
3771
3789
  "PSEUDO": new RegExp( "^" + pseudos ),
3772
- "CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace +
3790
+ "POS": new RegExp( pos, "i" ),
3791
+ "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace +
3773
3792
  "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3774
3793
  "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3775
- "POS": new RegExp( pos, "ig" ),
3776
3794
  // For use in libraries implementing .is()
3777
3795
  "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )
3778
3796
  },
@@ -3854,7 +3872,8 @@ try {
3854
3872
  slice.call( docElem.childNodes, 0 )[0].nodeType;
3855
3873
  } catch ( e ) {
3856
3874
  slice = function( i ) {
3857
- var elem, results = [];
3875
+ var elem,
3876
+ results = [];
3858
3877
  for ( ; (elem = this[i]); i++ ) {
3859
3878
  results.push( elem );
3860
3879
  }
@@ -3868,14 +3887,14 @@ function Sizzle( selector, context, results, seed ) {
3868
3887
  var match, elem, xml, m,
3869
3888
  nodeType = context.nodeType;
3870
3889
 
3871
- if ( nodeType !== 1 && nodeType !== 9 ) {
3872
- return [];
3873
- }
3874
-
3875
3890
  if ( !selector || typeof selector !== "string" ) {
3876
3891
  return results;
3877
3892
  }
3878
3893
 
3894
+ if ( nodeType !== 1 && nodeType !== 9 ) {
3895
+ return [];
3896
+ }
3897
+
3879
3898
  xml = isXML( context );
3880
3899
 
3881
3900
  if ( !xml && !seed ) {
@@ -3919,7 +3938,7 @@ function Sizzle( selector, context, results, seed ) {
3919
3938
  }
3920
3939
 
3921
3940
  // All others
3922
- return select( selector, context, results, seed, xml );
3941
+ return select( selector.replace( rtrim, "$1" ), context, results, seed, xml );
3923
3942
  }
3924
3943
 
3925
3944
  Sizzle.matches = function( expr, elements ) {
@@ -3946,6 +3965,25 @@ function createButtonPseudo( type ) {
3946
3965
  };
3947
3966
  }
3948
3967
 
3968
+ // Returns a function to use in pseudos for positionals
3969
+ function createPositionalPseudo( fn ) {
3970
+ return markFunction(function( argument ) {
3971
+ argument = +argument;
3972
+ return markFunction(function( seed, matches ) {
3973
+ var j,
3974
+ matchIndexes = fn( [], seed.length, argument ),
3975
+ i = matchIndexes.length;
3976
+
3977
+ // Match elements found at the specified indexes
3978
+ while ( i-- ) {
3979
+ if ( seed[ (j = matchIndexes[i]) ] ) {
3980
+ seed[j] = !(matches[j] = seed[j]);
3981
+ }
3982
+ }
3983
+ });
3984
+ });
3985
+ }
3986
+
3949
3987
  /**
3950
3988
  * Utility function for retrieving the text value of an array of DOM nodes
3951
3989
  * @param {Array|Element} elem
@@ -3983,7 +4021,7 @@ getText = Sizzle.getText = function( elem ) {
3983
4021
  return ret;
3984
4022
  };
3985
4023
 
3986
- isXML = Sizzle.isXML = function isXML( elem ) {
4024
+ isXML = Sizzle.isXML = function( elem ) {
3987
4025
  // documentElement is verified for cases where it doesn't yet exist
3988
4026
  // (such as loading iframes in IE - #4833)
3989
4027
  var documentElement = elem && (elem.ownerDocument || elem).documentElement;
@@ -4011,23 +4049,23 @@ contains = Sizzle.contains = docElem.contains ?
4011
4049
  };
4012
4050
 
4013
4051
  Sizzle.attr = function( elem, name ) {
4014
- var attr,
4052
+ var val,
4015
4053
  xml = isXML( elem );
4016
4054
 
4017
4055
  if ( !xml ) {
4018
4056
  name = name.toLowerCase();
4019
4057
  }
4020
- if ( Expr.attrHandle[ name ] ) {
4021
- return Expr.attrHandle[ name ]( elem );
4058
+ if ( (val = Expr.attrHandle[ name ]) ) {
4059
+ return val( elem );
4022
4060
  }
4023
- if ( assertAttributes || xml ) {
4061
+ if ( xml || assertAttributes ) {
4024
4062
  return elem.getAttribute( name );
4025
4063
  }
4026
- attr = elem.getAttributeNode( name );
4027
- return attr ?
4064
+ val = elem.getAttributeNode( name );
4065
+ return val ?
4028
4066
  typeof elem[ name ] === "boolean" ?
4029
4067
  elem[ name ] ? name : null :
4030
- attr.specified ? attr.value : null :
4068
+ val.specified ? val.value : null :
4031
4069
  null;
4032
4070
  };
4033
4071
 
@@ -4040,11 +4078,6 @@ Expr = Sizzle.selectors = {
4040
4078
 
4041
4079
  match: matchExpr,
4042
4080
 
4043
- order: new RegExp( "ID|TAG" +
4044
- (assertUsableName ? "|NAME" : "") +
4045
- (assertUsableClassName ? "|CLASS" : "")
4046
- ),
4047
-
4048
4081
  // IE6/7 return a modified href
4049
4082
  attrHandle: assertHrefNotNormalized ?
4050
4083
  {} :
@@ -4105,13 +4138,13 @@ Expr = Sizzle.selectors = {
4105
4138
  return results;
4106
4139
  },
4107
4140
 
4108
- "NAME": function( tag, context ) {
4141
+ "NAME": assertUsableName && function( tag, context ) {
4109
4142
  if ( typeof context.getElementsByName !== strundefined ) {
4110
4143
  return context.getElementsByName( name );
4111
4144
  }
4112
4145
  },
4113
4146
 
4114
- "CLASS": function( className, context, xml ) {
4147
+ "CLASS": assertUsableClassName && function( className, context, xml ) {
4115
4148
  if ( typeof context.getElementsByClassName !== strundefined && !xml ) {
4116
4149
  return context.getElementsByClassName( className );
4117
4150
  }
@@ -4140,7 +4173,7 @@ Expr = Sizzle.selectors = {
4140
4173
  },
4141
4174
 
4142
4175
  "CHILD": function( match ) {
4143
- /* matches from matchExpr.CHILD
4176
+ /* matches from matchExpr["CHILD"]
4144
4177
  1 type (only|nth|...)
4145
4178
  2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4146
4179
  3 xn-component of xn+y argument ([+-]?\d*n|)
@@ -4170,7 +4203,7 @@ Expr = Sizzle.selectors = {
4170
4203
  return match;
4171
4204
  },
4172
4205
 
4173
- "PSEUDO": function( match, context, xml ) {
4206
+ "PSEUDO": function( match ) {
4174
4207
  var unquoted, excess;
4175
4208
  if ( matchExpr["CHILD"].test( match[0] ) ) {
4176
4209
  return null;
@@ -4182,7 +4215,7 @@ Expr = Sizzle.selectors = {
4182
4215
  // Only check arguments that contain a pseudo
4183
4216
  if ( rpseudo.test(unquoted) &&
4184
4217
  // Get excess from tokenize (recursively)
4185
- (excess = tokenize( unquoted, context, xml, true )) &&
4218
+ (excess = tokenize( unquoted, true )) &&
4186
4219
  // advance to the next closing parenthesis
4187
4220
  (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4188
4221
 
@@ -4236,76 +4269,55 @@ Expr = Sizzle.selectors = {
4236
4269
  },
4237
4270
 
4238
4271
  "ATTR": function( name, operator, check ) {
4239
- if ( !operator ) {
4240
- return function( elem ) {
4241
- return Sizzle.attr( elem, name ) != null;
4242
- };
4243
- }
4244
-
4245
- return function( elem ) {
4246
- var result = Sizzle.attr( elem, name ),
4247
- value = result + "";
4272
+ return function( elem, context ) {
4273
+ var result = Sizzle.attr( elem, name );
4248
4274
 
4249
4275
  if ( result == null ) {
4250
4276
  return operator === "!=";
4251
4277
  }
4252
-
4253
- switch ( operator ) {
4254
- case "=":
4255
- return value === check;
4256
- case "!=":
4257
- return value !== check;
4258
- case "^=":
4259
- return check && value.indexOf( check ) === 0;
4260
- case "*=":
4261
- return check && value.indexOf( check ) > -1;
4262
- case "$=":
4263
- return check && value.substr( value.length - check.length ) === check;
4264
- case "~=":
4265
- return ( " " + value + " " ).indexOf( check ) > -1;
4266
- case "|=":
4267
- return value === check || value.substr( 0, check.length + 1 ) === check + "-";
4278
+ if ( !operator ) {
4279
+ return true;
4268
4280
  }
4281
+
4282
+ result += "";
4283
+
4284
+ return operator === "=" ? result === check :
4285
+ operator === "!=" ? result !== check :
4286
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
4287
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
4288
+ operator === "$=" ? check && result.substr( result.length - check.length ) === check :
4289
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
4290
+ operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" :
4291
+ false;
4269
4292
  };
4270
4293
  },
4271
4294
 
4272
4295
  "CHILD": function( type, argument, first, last ) {
4273
4296
 
4274
4297
  if ( type === "nth" ) {
4275
- var doneName = done++;
4276
-
4277
4298
  return function( elem ) {
4278
- var parent, diff,
4279
- count = 0,
4280
- node = elem;
4299
+ var node, diff,
4300
+ parent = elem.parentNode;
4281
4301
 
4282
4302
  if ( first === 1 && last === 0 ) {
4283
4303
  return true;
4284
4304
  }
4285
4305
 
4286
- parent = elem.parentNode;
4287
-
4288
- if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) {
4306
+ if ( parent ) {
4307
+ diff = 0;
4289
4308
  for ( node = parent.firstChild; node; node = node.nextSibling ) {
4290
4309
  if ( node.nodeType === 1 ) {
4291
- node.sizset = ++count;
4292
- if ( node === elem ) {
4310
+ diff++;
4311
+ if ( elem === node ) {
4293
4312
  break;
4294
4313
  }
4295
4314
  }
4296
4315
  }
4297
-
4298
- parent[ expando ] = doneName;
4299
4316
  }
4300
4317
 
4301
- diff = elem.sizset - last;
4302
-
4303
- if ( first === 0 ) {
4304
- return diff === 0;
4305
-
4306
- } else {
4307
- return ( diff % first === 0 && diff / first >= 0 );
4308
- }
4318
+ // Incorporate the offset (or cast to NaN), then check against cycle size
4319
+ diff -= last;
4320
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
4309
4321
  };
4310
4322
  }
4311
4323
 
@@ -4340,42 +4352,82 @@ Expr = Sizzle.selectors = {
4340
4352
  };
4341
4353
  },
4342
4354
 
4343
- "PSEUDO": function( pseudo, argument, context, xml ) {
4355
+ "PSEUDO": function( pseudo, argument ) {
4344
4356
  // pseudo-class names are case-insensitive
4345
4357
  // http://www.w3.org/TR/selectors/#pseudo-classes
4346
4358
  // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
4359
+ // Remember that setFilters inherits from pseudos
4347
4360
  var args,
4348
- fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ];
4349
-
4350
- if ( !fn ) {
4351
- Sizzle.error( "unsupported pseudo: " + pseudo );
4352
- }
4361
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
4362
+ Sizzle.error( "unsupported pseudo: " + pseudo );
4353
4363
 
4354
4364
  // The user may use createPseudo to indicate that
4355
4365
  // arguments are needed to create the filter function
4356
4366
  // just as Sizzle does
4357
- if ( !fn[ expando ] ) {
4358
- if ( fn.length > 1 ) {
4359
- args = [ pseudo, pseudo, "", argument ];
4360
- return function( elem ) {
4367
+ if ( fn[ expando ] ) {
4368
+ return fn( argument );
4369
+ }
4370
+
4371
+ // But maintain support for old signatures
4372
+ if ( fn.length > 1 ) {
4373
+ args = [ pseudo, pseudo, "", argument ];
4374
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
4375
+ markFunction(function( seed, matches ) {
4376
+ var idx,
4377
+ matched = fn( seed, argument ),
4378
+ i = matched.length;
4379
+ while ( i-- ) {
4380
+ idx = indexOf.call( seed, matched[i] );
4381
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
4382
+ }
4383
+ }) :
4384
+ function( elem ) {
4361
4385
  return fn( elem, 0, args );
4362
4386
  };
4363
- }
4364
- return fn;
4365
4387
  }
4366
4388
 
4367
- return fn( argument, context, xml );
4389
+ return fn;
4368
4390
  }
4369
4391
  },
4370
4392
 
4371
4393
  pseudos: {
4372
- "not": markFunction(function( selector, context, xml ) {
4394
+ "not": markFunction(function( selector ) {
4373
4395
  // Trim the selector passed to compile
4374
4396
  // to avoid treating leading and trailing
4375
4397
  // spaces as combinators
4376
- var matcher = compile( selector.replace( rtrim, "$1" ), context, xml );
4398
+ var input = [],
4399
+ results = [],
4400
+ matcher = compile( selector.replace( rtrim, "$1" ) );
4401
+
4402
+ return matcher[ expando ] ?
4403
+ markFunction(function( seed, matches, context, xml ) {
4404
+ var elem,
4405
+ unmatched = matcher( seed, null, xml, [] ),
4406
+ i = seed.length;
4407
+
4408
+ // Match elements unmatched by `matcher`
4409
+ while ( i-- ) {
4410
+ if ( (elem = unmatched[i]) ) {
4411
+ seed[i] = !(matches[i] = elem);
4412
+ }
4413
+ }
4414
+ }) :
4415
+ function( elem, context, xml ) {
4416
+ input[0] = elem;
4417
+ matcher( input, null, xml, results );
4418
+ return !results.pop();
4419
+ };
4420
+ }),
4421
+
4422
+ "has": markFunction(function( selector ) {
4377
4423
  return function( elem ) {
4378
- return !matcher( elem );
4424
+ return Sizzle( selector, elem ).length > 0;
4425
+ };
4426
+ }),
4427
+
4428
+ "contains": markFunction(function( text ) {
4429
+ return function( elem ) {
4430
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4379
4431
  };
4380
4432
  }),
4381
4433
 
@@ -4425,18 +4477,6 @@ Expr = Sizzle.selectors = {
4425
4477
  return true;
4426
4478
  },
4427
4479
 
4428
- "contains": markFunction(function( text ) {
4429
- return function( elem ) {
4430
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4431
- };
4432
- }),
4433
-
4434
- "has": markFunction(function( selector ) {
4435
- return function( elem ) {
4436
- return Sizzle( selector, elem ).length > 0;
4437
- };
4438
- }),
4439
-
4440
4480
  "header": function( elem ) {
4441
4481
  return rheader.test( elem.nodeName );
4442
4482
  },
@@ -4476,51 +4516,48 @@ Expr = Sizzle.selectors = {
4476
4516
 
4477
4517
  "active": function( elem ) {
4478
4518
  return elem === elem.ownerDocument.activeElement;
4479
- }
4480
- },
4481
-
4482
- setFilters: {
4483
- "first": function( elements, argument, not ) {
4484
- return not ? elements.slice( 1 ) : [ elements[0] ];
4485
4519
  },
4486
4520
 
4487
- "last": function( elements, argument, not ) {
4488
- var elem = elements.pop();
4489
- return not ? elements : [ elem ];
4490
- },
4521
+ // Positional types
4522
+ "first": createPositionalPseudo(function( matchIndexes, length, argument ) {
4523
+ return [ 0 ];
4524
+ }),
4491
4525
 
4492
- "even": function( elements, argument, not ) {
4493
- var results = [],
4494
- i = not ? 1 : 0,
4495
- len = elements.length;
4496
- for ( ; i < len; i = i + 2 ) {
4497
- results.push( elements[i] );
4498
- }
4499
- return results;
4500
- },
4526
+ "last": createPositionalPseudo(function( matchIndexes, length, argument ) {
4527
+ return [ length - 1 ];
4528
+ }),
4501
4529
 
4502
- "odd": function( elements, argument, not ) {
4503
- var results = [],
4504
- i = not ? 0 : 1,
4505
- len = elements.length;
4506
- for ( ; i < len; i = i + 2 ) {
4507
- results.push( elements[i] );
4530
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
4531
+ return [ argument < 0 ? argument + length : argument ];
4532
+ }),
4533
+
4534
+ "even": createPositionalPseudo(function( matchIndexes, length, argument ) {
4535
+ for ( var i = 0; i < length; i += 2 ) {
4536
+ matchIndexes.push( i );
4508
4537
  }
4509
- return results;
4510
- },
4538
+ return matchIndexes;
4539
+ }),
4511
4540
 
4512
- "lt": function( elements, argument, not ) {
4513
- return not ? elements.slice( +argument ) : elements.slice( 0, +argument );
4514
- },
4541
+ "odd": createPositionalPseudo(function( matchIndexes, length, argument ) {
4542
+ for ( var i = 1; i < length; i += 2 ) {
4543
+ matchIndexes.push( i );
4544
+ }
4545
+ return matchIndexes;
4546
+ }),
4515
4547
 
4516
- "gt": function( elements, argument, not ) {
4517
- return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 );
4518
- },
4548
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4549
+ for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {
4550
+ matchIndexes.push( i );
4551
+ }
4552
+ return matchIndexes;
4553
+ }),
4519
4554
 
4520
- "eq": function( elements, argument, not ) {
4521
- var elem = elements.splice( +argument, 1 );
4522
- return not ? elements : elem;
4523
- }
4555
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4556
+ for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {
4557
+ matchIndexes.push( i );
4558
+ }
4559
+ return matchIndexes;
4560
+ })
4524
4561
  }
4525
4562
  };
4526
4563
 
@@ -4642,24 +4679,17 @@ Sizzle.error = function( msg ) {
4642
4679
  throw new Error( "Syntax error, unrecognized expression: " + msg );
4643
4680
  };
4644
4681
 
4645
- function tokenize( selector, context, xml, parseOnly ) {
4646
- var matched, match, tokens, type,
4647
- soFar, groups, group, i,
4648
- preFilters, filters,
4649
- checkContext = !xml && context !== document,
4650
- // Token cache should maintain spaces
4651
- key = ( checkContext ? "<s>" : "" ) + selector.replace( rtrim, "$1<s>" ),
4652
- cached = tokenCache[ expando ][ key ];
4682
+ function tokenize( selector, parseOnly ) {
4683
+ var matched, match, tokens, type, soFar, groups, preFilters,
4684
+ cached = tokenCache[ expando ][ selector ];
4653
4685
 
4654
4686
  if ( cached ) {
4655
- return parseOnly ? 0 : slice.call( cached, 0 );
4687
+ return parseOnly ? 0 : cached.slice( 0 );
4656
4688
  }
4657
4689
 
4658
4690
  soFar = selector;
4659
4691
  groups = [];
4660
- i = 0;
4661
4692
  preFilters = Expr.preFilter;
4662
- filters = Expr.filter;
4663
4693
 
4664
4694
  while ( soFar ) {
4665
4695
 
@@ -4667,45 +4697,31 @@ function tokenize( selector, context, xml, parseOnly ) {
4667
4697
  if ( !matched || (match = rcomma.exec( soFar )) ) {
4668
4698
  if ( match ) {
4669
4699
  soFar = soFar.slice( match[0].length );
4670
- tokens.selector = group;
4671
4700
  }
4672
4701
  groups.push( tokens = [] );
4673
- group = "";
4674
-
4675
- // Need to make sure we're within a narrower context if necessary
4676
- // Adding a descendant combinator will generate what is needed
4677
- if ( checkContext ) {
4678
- soFar = " " + soFar;
4679
- }
4680
4702
  }
4681
4703
 
4682
4704
  matched = false;
4683
4705
 
4684
4706
  // Combinators
4685
4707
  if ( (match = rcombinators.exec( soFar )) ) {
4686
- group += match[0];
4687
- soFar = soFar.slice( match[0].length );
4708
+ tokens.push( matched = new Token( match.shift() ) );
4709
+ soFar = soFar.slice( matched.length );
4688
4710
 
4689
4711
  // Cast descendant combinators to space
4690
- matched = tokens.push({
4691
- part: match.pop().replace( rtrim, " " ),
4692
- string: match[0],
4693
- captures: match
4694
- });
4712
+ matched.type = match[0].replace( rtrim, " " );
4695
4713
  }
4696
4714
 
4697
4715
  // Filters
4698
- for ( type in filters ) {
4716
+ for ( type in Expr.filter ) {
4699
4717
  if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
4700
- ( match = preFilters[ type ](match, context, xml) )) ) {
4718
+ // The last two arguments here are (context, xml) for backCompat
4719
+ (match = preFilters[ type ]( match, document, true ))) ) {
4701
4720
 
4702
- group += match[0];
4703
- soFar = soFar.slice( match[0].length );
4704
- matched = tokens.push({
4705
- part: type,
4706
- string: match.shift(),
4707
- captures: match
4708
- });
4721
+ tokens.push( matched = new Token( match.shift() ) );
4722
+ soFar = soFar.slice( matched.length );
4723
+ matched.type = type;
4724
+ matched.matches = match;
4709
4725
  }
4710
4726
  }
4711
4727
 
@@ -4714,11 +4730,6 @@ function tokenize( selector, context, xml, parseOnly ) {
4714
4730
  }
4715
4731
  }
4716
4732
 
4717
- // Attach the full group as a selector
4718
- if ( group ) {
4719
- tokens.selector = group;
4720
- }
4721
-
4722
4733
  // Return the length of the invalid excess
4723
4734
  // if we're just parsing
4724
4735
  // Otherwise, throw an error or return tokens
@@ -4727,43 +4738,33 @@ function tokenize( selector, context, xml, parseOnly ) {
4727
4738
  soFar ?
4728
4739
  Sizzle.error( selector ) :
4729
4740
  // Cache the tokens
4730
- slice.call( tokenCache(key, groups), 0 );
4741
+ tokenCache( selector, groups ).slice( 0 );
4731
4742
  }
4732
4743
 
4733
- function addCombinator( matcher, combinator, context, xml ) {
4744
+ function addCombinator( matcher, combinator, base ) {
4734
4745
  var dir = combinator.dir,
4746
+ checkNonElements = base && combinator.dir === "parentNode",
4735
4747
  doneName = done++;
4736
4748
 
4737
- if ( !matcher ) {
4738
- // If there is no matcher to check, check against the context
4739
- matcher = function( elem ) {
4740
- return elem === context;
4741
- };
4742
- }
4743
4749
  return combinator.first ?
4744
- function( elem ) {
4750
+ // Check against closest ancestor/preceding element
4751
+ function( elem, context, xml ) {
4745
4752
  while ( (elem = elem[ dir ]) ) {
4746
- if ( elem.nodeType === 1 ) {
4747
- return matcher( elem ) && elem;
4753
+ if ( checkNonElements || elem.nodeType === 1 ) {
4754
+ return matcher( elem, context, xml );
4748
4755
  }
4749
4756
  }
4750
4757
  } :
4751
- xml ?
4752
- function( elem ) {
4753
- while ( (elem = elem[ dir ]) ) {
4754
- if ( elem.nodeType === 1 ) {
4755
- if ( matcher( elem ) ) {
4756
- return elem;
4757
- }
4758
- }
4759
- }
4760
- } :
4761
- function( elem ) {
4758
+
4759
+ // Check against all ancestor/preceding elements
4760
+ function( elem, context, xml ) {
4761
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
4762
+ if ( !xml ) {
4762
4763
  var cache,
4763
- dirkey = doneName + "." + dirruns,
4764
- cachedkey = dirkey + "." + cachedruns;
4764
+ dirkey = dirruns + " " + doneName + " ",
4765
+ cachedkey = dirkey + cachedruns;
4765
4766
  while ( (elem = elem[ dir ]) ) {
4766
- if ( elem.nodeType === 1 ) {
4767
+ if ( checkNonElements || elem.nodeType === 1 ) {
4767
4768
  if ( (cache = elem[ expando ]) === cachedkey ) {
4768
4769
  return elem.sizset;
4769
4770
  } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {
@@ -4772,7 +4773,7 @@ function addCombinator( matcher, combinator, context, xml ) {
4772
4773
  }
4773
4774
  } else {
4774
4775
  elem[ expando ] = cachedkey;
4775
- if ( matcher( elem ) ) {
4776
+ if ( matcher( elem, context, xml ) ) {
4776
4777
  elem.sizset = true;
4777
4778
  return elem;
4778
4779
  }
@@ -4780,254 +4781,382 @@ function addCombinator( matcher, combinator, context, xml ) {
4780
4781
  }
4781
4782
  }
4782
4783
  }
4783
- };
4784
+ } else {
4785
+ while ( (elem = elem[ dir ]) ) {
4786
+ if ( checkNonElements || elem.nodeType === 1 ) {
4787
+ if ( matcher( elem, context, xml ) ) {
4788
+ return elem;
4789
+ }
4790
+ }
4791
+ }
4792
+ }
4793
+ };
4784
4794
  }
4785
4795
 
4786
- function addMatcher( higher, deeper ) {
4787
- return higher ?
4788
- function( elem ) {
4789
- var result = deeper( elem );
4790
- return result && higher( result === true ? elem : result );
4796
+ function elementMatcher( matchers ) {
4797
+ return matchers.length > 1 ?
4798
+ function( elem, context, xml ) {
4799
+ var i = matchers.length;
4800
+ while ( i-- ) {
4801
+ if ( !matchers[i]( elem, context, xml ) ) {
4802
+ return false;
4803
+ }
4804
+ }
4805
+ return true;
4791
4806
  } :
4792
- deeper;
4807
+ matchers[0];
4793
4808
  }
4794
4809
 
4795
- // ["TAG", ">", "ID", " ", "CLASS"]
4796
- function matcherFromTokens( tokens, context, xml ) {
4797
- var token, matcher,
4798
- i = 0;
4810
+ function condense( unmatched, map, filter, context, xml ) {
4811
+ var elem,
4812
+ newUnmatched = [],
4813
+ i = 0,
4814
+ len = unmatched.length,
4815
+ mapped = map != null;
4799
4816
 
4800
- for ( ; (token = tokens[i]); i++ ) {
4801
- if ( Expr.relative[ token.part ] ) {
4802
- matcher = addCombinator( matcher, Expr.relative[ token.part ], context, xml );
4803
- } else {
4804
- matcher = addMatcher( matcher, Expr.filter[ token.part ].apply(null, token.captures.concat( context, xml )) );
4817
+ for ( ; i < len; i++ ) {
4818
+ if ( (elem = unmatched[i]) ) {
4819
+ if ( !filter || filter( elem, context, xml ) ) {
4820
+ newUnmatched.push( elem );
4821
+ if ( mapped ) {
4822
+ map.push( i );
4823
+ }
4824
+ }
4805
4825
  }
4806
4826
  }
4807
4827
 
4808
- return matcher;
4828
+ return newUnmatched;
4809
4829
  }
4810
4830
 
4811
- function matcherFromGroupMatchers( matchers ) {
4812
- return function( elem ) {
4813
- var matcher,
4814
- j = 0;
4815
- for ( ; (matcher = matchers[j]); j++ ) {
4816
- if ( matcher(elem) ) {
4817
- return true;
4818
- }
4831
+ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
4832
+ if ( postFilter && !postFilter[ expando ] ) {
4833
+ postFilter = setMatcher( postFilter );
4834
+ }
4835
+ if ( postFinder && !postFinder[ expando ] ) {
4836
+ postFinder = setMatcher( postFinder, postSelector );
4837
+ }
4838
+ return markFunction(function( seed, results, context, xml ) {
4839
+ // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones
4840
+ if ( seed && postFinder ) {
4841
+ return;
4819
4842
  }
4820
- return false;
4821
- };
4822
- }
4823
4843
 
4824
- compile = Sizzle.compile = function( selector, context, xml ) {
4825
- var group, i, len,
4826
- cached = compilerCache[ expando ][ selector ];
4844
+ var i, elem, postFilterIn,
4845
+ preMap = [],
4846
+ postMap = [],
4847
+ preexisting = results.length,
4827
4848
 
4828
- // Return a cached group function if already generated (context dependent)
4829
- if ( cached && cached.context === context ) {
4830
- return cached;
4831
- }
4849
+ // Get initial elements from seed or context
4850
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ),
4832
4851
 
4833
- // Generate a function of recursive functions that can be used to check each element
4834
- group = tokenize( selector, context, xml );
4835
- for ( i = 0, len = group.length; i < len; i++ ) {
4836
- group[i] = matcherFromTokens(group[i], context, xml);
4837
- }
4852
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
4853
+ matcherIn = preFilter && ( seed || !selector ) ?
4854
+ condense( elems, preMap, preFilter, context, xml ) :
4855
+ elems,
4838
4856
 
4839
- // Cache the compiled function
4840
- cached = compilerCache( selector, matcherFromGroupMatchers(group) );
4841
- cached.context = context;
4842
- cached.runs = cached.dirruns = 0;
4843
- return cached;
4844
- };
4857
+ matcherOut = matcher ?
4858
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
4859
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
4845
4860
 
4846
- function multipleContexts( selector, contexts, results, seed ) {
4847
- var i = 0,
4848
- len = contexts.length;
4849
- for ( ; i < len; i++ ) {
4850
- Sizzle( selector, contexts[i], results, seed );
4851
- }
4852
- }
4861
+ // ...intermediate processing is necessary
4862
+ [] :
4853
4863
 
4854
- function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) {
4855
- var results,
4856
- fn = Expr.setFilters[ posfilter.toLowerCase() ];
4864
+ // ...otherwise use results directly
4865
+ results :
4866
+ matcherIn;
4857
4867
 
4858
- if ( !fn ) {
4859
- Sizzle.error( posfilter );
4860
- }
4868
+ // Find primary matches
4869
+ if ( matcher ) {
4870
+ matcher( matcherIn, matcherOut, context, xml );
4871
+ }
4861
4872
 
4862
- if ( selector || !(results = seed) ) {
4863
- multipleContexts( selector || "*", contexts, (results = []), seed );
4864
- }
4873
+ // Apply postFilter
4874
+ if ( postFilter ) {
4875
+ postFilterIn = condense( matcherOut, postMap );
4876
+ postFilter( postFilterIn, [], context, xml );
4865
4877
 
4866
- return results.length > 0 ? fn( results, argument, not ) : [];
4867
- }
4878
+ // Un-match failing elements by moving them back to matcherIn
4879
+ i = postFilterIn.length;
4880
+ while ( i-- ) {
4881
+ if ( (elem = postFilterIn[i]) ) {
4882
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
4883
+ }
4884
+ }
4885
+ }
4868
4886
 
4869
- function handlePOS( groups, context, results, seed ) {
4870
- var group, part, j, groupLen, token, selector,
4871
- anchor, elements, match, matched,
4872
- lastIndex, currentContexts, not,
4873
- i = 0,
4874
- len = groups.length,
4875
- rpos = matchExpr["POS"],
4876
- // This is generated here in case matchExpr["POS"] is extended
4877
- rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ),
4878
- // This is for making sure non-participating
4879
- // matching groups are represented cross-browser (IE6-8)
4880
- setUndefined = function() {
4881
- var i = 1,
4882
- len = arguments.length - 2;
4883
- for ( ; i < len; i++ ) {
4884
- if ( arguments[i] === undefined ) {
4885
- match[i] = undefined;
4887
+ // Keep seed and results synchronized
4888
+ if ( seed ) {
4889
+ // Ignore postFinder because it can't coexist with seed
4890
+ i = preFilter && matcherOut.length;
4891
+ while ( i-- ) {
4892
+ if ( (elem = matcherOut[i]) ) {
4893
+ seed[ preMap[i] ] = !(results[ preMap[i] ] = elem);
4886
4894
  }
4887
4895
  }
4888
- };
4896
+ } else {
4897
+ matcherOut = condense(
4898
+ matcherOut === results ?
4899
+ matcherOut.splice( preexisting, matcherOut.length ) :
4900
+ matcherOut
4901
+ );
4902
+ if ( postFinder ) {
4903
+ postFinder( null, results, matcherOut, xml );
4904
+ } else {
4905
+ push.apply( results, matcherOut );
4906
+ }
4907
+ }
4908
+ });
4909
+ }
4910
+
4911
+ function matcherFromTokens( tokens ) {
4912
+ var checkContext, matcher, j,
4913
+ len = tokens.length,
4914
+ leadingRelative = Expr.relative[ tokens[0].type ],
4915
+ implicitRelative = leadingRelative || Expr.relative[" "],
4916
+ i = leadingRelative ? 1 : 0,
4917
+
4918
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
4919
+ matchContext = addCombinator( function( elem ) {
4920
+ return elem === checkContext;
4921
+ }, implicitRelative, true ),
4922
+ matchAnyContext = addCombinator( function( elem ) {
4923
+ return indexOf.call( checkContext, elem ) > -1;
4924
+ }, implicitRelative, true ),
4925
+ matchers = [ function( elem, context, xml ) {
4926
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
4927
+ (checkContext = context).nodeType ?
4928
+ matchContext( elem, context, xml ) :
4929
+ matchAnyContext( elem, context, xml ) );
4930
+ } ];
4889
4931
 
4890
4932
  for ( ; i < len; i++ ) {
4891
- group = groups[i];
4892
- part = "";
4893
- elements = seed;
4894
- for ( j = 0, groupLen = group.length; j < groupLen; j++ ) {
4895
- token = group[j];
4896
- selector = token.string;
4897
- if ( token.part === "PSEUDO" ) {
4898
- // Reset regex index to 0
4899
- rpos.exec("");
4900
- anchor = 0;
4901
- while ( (match = rpos.exec( selector )) ) {
4902
- matched = true;
4903
- lastIndex = rpos.lastIndex = match.index + match[0].length;
4904
- if ( lastIndex > anchor ) {
4905
- part += selector.slice( anchor, match.index );
4906
- anchor = lastIndex;
4907
- currentContexts = [ context ];
4908
-
4909
- if ( rcombinators.test(part) ) {
4910
- if ( elements ) {
4911
- currentContexts = elements;
4912
- }
4913
- elements = seed;
4914
- }
4933
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
4934
+ matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
4935
+ } else {
4936
+ // The concatenated values are (context, xml) for backCompat
4937
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
4938
+
4939
+ // Return special upon seeing a positional matcher
4940
+ if ( matcher[ expando ] ) {
4941
+ // Find the next relative operator (if any) for proper handling
4942
+ j = ++i;
4943
+ for ( ; j < len; j++ ) {
4944
+ if ( Expr.relative[ tokens[j].type ] ) {
4945
+ break;
4946
+ }
4947
+ }
4948
+ return setMatcher(
4949
+ i > 1 && elementMatcher( matchers ),
4950
+ i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ),
4951
+ matcher,
4952
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
4953
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
4954
+ j < len && tokens.join("")
4955
+ );
4956
+ }
4957
+ matchers.push( matcher );
4958
+ }
4959
+ }
4915
4960
 
4916
- if ( (not = rendsWithNot.test( part )) ) {
4917
- part = part.slice( 0, -5 ).replace( rcombinators, "$&*" );
4918
- anchor++;
4919
- }
4961
+ return elementMatcher( matchers );
4962
+ }
4920
4963
 
4921
- if ( match.length > 1 ) {
4922
- match[0].replace( rposgroups, setUndefined );
4964
+ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
4965
+ var bySet = setMatchers.length > 0,
4966
+ byElement = elementMatchers.length > 0,
4967
+ superMatcher = function( seed, context, xml, results, expandContext ) {
4968
+ var elem, j, matcher,
4969
+ setMatched = [],
4970
+ matchedCount = 0,
4971
+ i = "0",
4972
+ unmatched = seed && [],
4973
+ outermost = expandContext != null,
4974
+ contextBackup = outermostContext,
4975
+ // We must always have either seed elements or context
4976
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
4977
+ // Nested matchers should use non-integer dirruns
4978
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);
4979
+
4980
+ if ( outermost ) {
4981
+ outermostContext = context !== document && context;
4982
+ cachedruns = superMatcher.el;
4983
+ }
4984
+
4985
+ // Add elements passing elementMatchers directly to results
4986
+ for ( ; (elem = elems[i]) != null; i++ ) {
4987
+ if ( byElement && elem ) {
4988
+ for ( j = 0; (matcher = elementMatchers[j]); j++ ) {
4989
+ if ( matcher( elem, context, xml ) ) {
4990
+ results.push( elem );
4991
+ break;
4923
4992
  }
4924
- elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not );
4925
4993
  }
4926
- part = "";
4994
+ if ( outermost ) {
4995
+ dirruns = dirrunsUnique;
4996
+ cachedruns = ++superMatcher.el;
4997
+ }
4927
4998
  }
4928
4999
 
4929
- }
5000
+ // Track unmatched elements for set filters
5001
+ if ( bySet ) {
5002
+ // They will have gone through all possible matchers
5003
+ if ( (elem = !matcher && elem) ) {
5004
+ matchedCount--;
5005
+ }
4930
5006
 
4931
- if ( !matched ) {
4932
- part += selector;
5007
+ // Lengthen the array for every element, matched or not
5008
+ if ( seed ) {
5009
+ unmatched.push( elem );
5010
+ }
5011
+ }
4933
5012
  }
4934
- matched = false;
4935
- }
4936
5013
 
4937
- if ( part ) {
4938
- if ( rcombinators.test(part) ) {
4939
- multipleContexts( part, elements || [ context ], results, seed );
4940
- } else {
4941
- Sizzle( part, context, results, seed ? seed.concat(elements) : elements );
4942
- }
4943
- } else {
4944
- push.apply( results, elements );
4945
- }
4946
- }
5014
+ // Apply set filters to unmatched elements
5015
+ matchedCount += i;
5016
+ if ( bySet && i !== matchedCount ) {
5017
+ for ( j = 0; (matcher = setMatchers[j]); j++ ) {
5018
+ matcher( unmatched, setMatched, context, xml );
5019
+ }
4947
5020
 
4948
- // Do not sort if this is a single filter
4949
- return len === 1 ? results : Sizzle.uniqueSort( results );
4950
- }
5021
+ if ( seed ) {
5022
+ // Reintegrate element matches to eliminate the need for sorting
5023
+ if ( matchedCount > 0 ) {
5024
+ while ( i-- ) {
5025
+ if ( !(unmatched[i] || setMatched[i]) ) {
5026
+ setMatched[i] = pop.call( results );
5027
+ }
5028
+ }
5029
+ }
4951
5030
 
4952
- function select( selector, context, results, seed, xml ) {
4953
- // Remove excessive whitespace
4954
- selector = selector.replace( rtrim, "$1" );
4955
- var elements, matcher, cached, elem,
4956
- i, tokens, token, lastToken, findContext, type,
4957
- match = tokenize( selector, context, xml ),
4958
- contextNodeType = context.nodeType;
4959
-
4960
- // POS handling
4961
- if ( matchExpr["POS"].test(selector) ) {
4962
- return handlePOS( match, context, results, seed );
4963
- }
5031
+ // Discard index placeholder values to get only actual matches
5032
+ setMatched = condense( setMatched );
5033
+ }
4964
5034
 
4965
- if ( seed ) {
4966
- elements = slice.call( seed, 0 );
5035
+ // Add matches to results
5036
+ push.apply( results, setMatched );
4967
5037
 
4968
- // To maintain document order, only narrow the
4969
- // set if there is one group
4970
- } else if ( match.length === 1 ) {
5038
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
5039
+ if ( outermost && !seed && setMatched.length > 0 &&
5040
+ ( matchedCount + setMatchers.length ) > 1 ) {
4971
5041
 
4972
- // Take a shortcut and set the context if the root selector is an ID
4973
- if ( (tokens = slice.call( match[0], 0 )).length > 2 &&
4974
- (token = tokens[0]).part === "ID" &&
4975
- contextNodeType === 9 && !xml &&
4976
- Expr.relative[ tokens[1].part ] ) {
5042
+ Sizzle.uniqueSort( results );
5043
+ }
5044
+ }
4977
5045
 
4978
- context = Expr.find["ID"]( token.captures[0].replace( rbackslash, "" ), context, xml )[0];
4979
- if ( !context ) {
4980
- return results;
5046
+ // Override manipulation of globals by nested matchers
5047
+ if ( outermost ) {
5048
+ dirruns = dirrunsUnique;
5049
+ outermostContext = contextBackup;
4981
5050
  }
4982
5051
 
4983
- selector = selector.slice( tokens.shift().string.length );
4984
- }
5052
+ return unmatched;
5053
+ };
5054
+
5055
+ superMatcher.el = 0;
5056
+ return bySet ?
5057
+ markFunction( superMatcher ) :
5058
+ superMatcher;
5059
+ }
4985
5060
 
4986
- findContext = ( (match = rsibling.exec( tokens[0].string )) && !match.index && context.parentNode ) || context;
5061
+ compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
5062
+ var i,
5063
+ setMatchers = [],
5064
+ elementMatchers = [],
5065
+ cached = compilerCache[ expando ][ selector ];
4987
5066
 
4988
- // Reduce the set if possible
4989
- lastToken = "";
4990
- for ( i = tokens.length - 1; i >= 0; i-- ) {
4991
- token = tokens[i];
4992
- type = token.part;
4993
- lastToken = token.string + lastToken;
4994
- if ( Expr.relative[ type ] ) {
4995
- break;
5067
+ if ( !cached ) {
5068
+ // Generate a function of recursive functions that can be used to check each element
5069
+ if ( !group ) {
5070
+ group = tokenize( selector );
5071
+ }
5072
+ i = group.length;
5073
+ while ( i-- ) {
5074
+ cached = matcherFromTokens( group[i] );
5075
+ if ( cached[ expando ] ) {
5076
+ setMatchers.push( cached );
5077
+ } else {
5078
+ elementMatchers.push( cached );
4996
5079
  }
4997
- if ( Expr.order.test(type) ) {
4998
- elements = Expr.find[ type ]( token.captures[0].replace( rbackslash, "" ), findContext, xml );
4999
- if ( elements == null ) {
5000
- continue;
5001
- } else {
5002
- selector = selector.slice( 0, selector.length - lastToken.length ) +
5003
- lastToken.replace( matchExpr[ type ], "" );
5080
+ }
5004
5081
 
5005
- if ( !selector ) {
5006
- push.apply( results, slice.call(elements, 0) );
5007
- }
5082
+ // Cache the compiled function
5083
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
5084
+ }
5085
+ return cached;
5086
+ };
5008
5087
 
5009
- break;
5088
+ function multipleContexts( selector, contexts, results, seed ) {
5089
+ var i = 0,
5090
+ len = contexts.length;
5091
+ for ( ; i < len; i++ ) {
5092
+ Sizzle( selector, contexts[i], results, seed );
5093
+ }
5094
+ return results;
5095
+ }
5096
+
5097
+ function select( selector, context, results, seed, xml ) {
5098
+ var i, tokens, token, type, find,
5099
+ match = tokenize( selector ),
5100
+ j = match.length;
5101
+
5102
+ if ( !seed ) {
5103
+ // Try to minimize operations if there is only one group
5104
+ if ( match.length === 1 ) {
5105
+
5106
+ // Take a shortcut and set the context if the root selector is an ID
5107
+ tokens = match[0] = match[0].slice( 0 );
5108
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
5109
+ context.nodeType === 9 && !xml &&
5110
+ Expr.relative[ tokens[1].type ] ) {
5111
+
5112
+ context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0];
5113
+ if ( !context ) {
5114
+ return results;
5010
5115
  }
5116
+
5117
+ selector = selector.slice( tokens.shift().length );
5011
5118
  }
5012
- }
5013
- }
5014
5119
 
5015
- // Only loop over the given elements once
5016
- if ( selector ) {
5017
- matcher = compile( selector, context, xml );
5018
- dirruns = matcher.dirruns++;
5019
- if ( elements == null ) {
5020
- elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context );
5021
- }
5120
+ // Fetch a seed set for right-to-left matching
5121
+ for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {
5122
+ token = tokens[i];
5123
+
5124
+ // Abort if we hit a combinator
5125
+ if ( Expr.relative[ (type = token.type) ] ) {
5126
+ break;
5127
+ }
5128
+ if ( (find = Expr.find[ type ]) ) {
5129
+ // Search, expanding context for leading sibling combinators
5130
+ if ( (seed = find(
5131
+ token.matches[0].replace( rbackslash, "" ),
5132
+ rsibling.test( tokens[0].type ) && context.parentNode || context,
5133
+ xml
5134
+ )) ) {
5135
+
5136
+ // If seed is empty or no tokens remain, we can return early
5137
+ tokens.splice( i, 1 );
5138
+ selector = seed.length && tokens.join("");
5139
+ if ( !selector ) {
5140
+ push.apply( results, slice.call( seed, 0 ) );
5141
+ return results;
5142
+ }
5022
5143
 
5023
- for ( i = 0; (elem = elements[i]); i++ ) {
5024
- cachedruns = matcher.runs++;
5025
- if ( matcher(elem) ) {
5026
- results.push( elem );
5144
+ break;
5145
+ }
5146
+ }
5027
5147
  }
5028
5148
  }
5029
5149
  }
5030
5150
 
5151
+ // Compile and execute a filtering function
5152
+ // Provide `match` to avoid retokenization if we modified the selector above
5153
+ compile( selector, match )(
5154
+ seed,
5155
+ context,
5156
+ xml,
5157
+ results,
5158
+ rsibling.test( selector )
5159
+ );
5031
5160
  return results;
5032
5161
  }
5033
5162
 
@@ -5037,11 +5166,16 @@ if ( document.querySelectorAll ) {
5037
5166
  oldSelect = select,
5038
5167
  rescape = /'|\\/g,
5039
5168
  rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
5040
- rbuggyQSA = [],
5169
+
5170
+ // qSa(:focus) reports false when true (Chrome 21),
5171
+ // A support test would require too much code (would include document ready)
5172
+ rbuggyQSA = [":focus"],
5173
+
5174
+ // matchesSelector(:focus) reports false when true (Chrome 21),
5041
5175
  // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
5042
5176
  // A support test would require too much code (would include document ready)
5043
5177
  // just skip matchesSelector for :active
5044
- rbuggyMatches = [":active"],
5178
+ rbuggyMatches = [ ":active", ":focus" ],
5045
5179
  matches = docElem.matchesSelector ||
5046
5180
  docElem.mozMatchesSelector ||
5047
5181
  docElem.webkitMatchesSelector ||
@@ -5088,44 +5222,46 @@ if ( document.querySelectorAll ) {
5088
5222
  }
5089
5223
  });
5090
5224
 
5091
- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
5225
+ // rbuggyQSA always contains :focus, so no need for a length check
5226
+ rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") );
5092
5227
 
5093
5228
  select = function( selector, context, results, seed, xml ) {
5094
5229
  // Only use querySelectorAll when not filtering,
5095
5230
  // when this is not xml,
5096
5231
  // and when no QSA bugs apply
5097
5232
  if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
5098
- if ( context.nodeType === 9 ) {
5099
- try {
5100
- push.apply( results, slice.call(context.querySelectorAll( selector ), 0) );
5101
- return results;
5102
- } catch(qsaError) {}
5233
+ var groups, i,
5234
+ old = true,
5235
+ nid = expando,
5236
+ newContext = context,
5237
+ newSelector = context.nodeType === 9 && selector;
5238
+
5103
5239
  // qSA works strangely on Element-rooted queries
5104
5240
  // We can work around this by specifying an extra ID on the root
5105
5241
  // and working up from there (Thanks to Andrew Dupont for the technique)
5106
5242
  // IE 8 doesn't work on object elements
5107
- } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
5108
- var groups, i, len,
5109
- old = context.getAttribute("id"),
5110
- nid = old || expando,
5111
- newContext = rsibling.test( selector ) && context.parentNode || context;
5112
-
5113
- if ( old ) {
5114
- nid = nid.replace( rescape, "\\$&" );
5243
+ if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
5244
+ groups = tokenize( selector );
5245
+
5246
+ if ( (old = context.getAttribute("id")) ) {
5247
+ nid = old.replace( rescape, "\\$&" );
5115
5248
  } else {
5116
5249
  context.setAttribute( "id", nid );
5117
5250
  }
5251
+ nid = "[id='" + nid + "'] ";
5118
5252
 
5119
- groups = tokenize(selector, context, xml);
5120
- // Trailing space is unnecessary
5121
- // There is always a context check
5122
- nid = "[id='" + nid + "']";
5123
- for ( i = 0, len = groups.length; i < len; i++ ) {
5124
- groups[i] = nid + groups[i].selector;
5253
+ i = groups.length;
5254
+ while ( i-- ) {
5255
+ groups[i] = nid + groups[i].join("");
5125
5256
  }
5257
+ newContext = rsibling.test( selector ) && context.parentNode || context;
5258
+ newSelector = groups.join(",");
5259
+ }
5260
+
5261
+ if ( newSelector ) {
5126
5262
  try {
5127
5263
  push.apply( results, slice.call( newContext.querySelectorAll(
5128
- groups.join(",")
5264
+ newSelector
5129
5265
  ), 0 ) );
5130
5266
  return results;
5131
5267
  } catch(qsaError) {
@@ -5150,11 +5286,11 @@ if ( document.querySelectorAll ) {
5150
5286
  // Gecko does not error, returns false instead
5151
5287
  try {
5152
5288
  matches.call( div, "[test!='']:sizzle" );
5153
- rbuggyMatches.push( matchExpr["PSEUDO"].source, matchExpr["POS"].source, "!=" );
5289
+ rbuggyMatches.push( "!=", pseudos );
5154
5290
  } catch ( e ) {}
5155
5291
  });
5156
5292
 
5157
- // rbuggyMatches always contains :active, so no need for a length check
5293
+ // rbuggyMatches always contains :active and :focus, so no need for a length check
5158
5294
  rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );
5159
5295
 
5160
5296
  Sizzle.matchesSelector = function( elem, expr ) {
@@ -5183,10 +5319,12 @@ if ( document.querySelectorAll ) {
5183
5319
  }
5184
5320
 
5185
5321
  // Deprecated
5186
- Expr.setFilters["nth"] = Expr.setFilters["eq"];
5322
+ Expr.pseudos["nth"] = Expr.pseudos["eq"];
5187
5323
 
5188
5324
  // Back-compat
5189
- Expr.filters = Expr.pseudos;
5325
+ function setFilters() {}
5326
+ Expr.filters = setFilters.prototype = Expr.pseudos;
5327
+ Expr.setFilters = new setFilters();
5190
5328
 
5191
5329
  // Override sizzle attribute retrieval
5192
5330
  Sizzle.attr = jQuery.attr;
@@ -7123,10 +7261,10 @@ function buildParams( prefix, obj, traditional, add ) {
7123
7261
  add( prefix, obj );
7124
7262
  }
7125
7263
  }
7126
- var // Document location
7127
- ajaxLocation,
7128
- // Document location segments
7264
+ var
7265
+ // Document location
7129
7266
  ajaxLocParts,
7267
+ ajaxLocation,
7130
7268
 
7131
7269
  rhash = /#.*$/,
7132
7270
  rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
@@ -7643,7 +7781,7 @@ jQuery.extend({
7643
7781
 
7644
7782
  // Set data for the fake xhr object
7645
7783
  jqXHR.status = status;
7646
- jqXHR.statusText = "" + ( nativeStatusText || statusText );
7784
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
7647
7785
 
7648
7786
  // Success/Error
7649
7787
  if ( isSuccess ) {
@@ -7703,14 +7841,11 @@ jQuery.extend({
7703
7841
  // Extract dataTypes list
7704
7842
  s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
7705
7843
 
7706
- // Determine if a cross-domain request is in order
7844
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
7707
7845
  if ( s.crossDomain == null ) {
7708
- parts = rurl.exec( s.url.toLowerCase() );
7709
- s.crossDomain = !!( parts &&
7710
- ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
7711
- ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7712
- ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7713
- );
7846
+ parts = rurl.exec( s.url.toLowerCase() ) || false;
7847
+ s.crossDomain = parts && ( parts.join(":") + ( parts[ 3 ] ? "" : parts[ 1 ] === "http:" ? 80 : 443 ) ) !==
7848
+ ( ajaxLocParts.join(":") + ( ajaxLocParts[ 3 ] ? "" : ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) );
7714
7849
  }
7715
7850
 
7716
7851
  // Convert data if not already a string
@@ -8405,12 +8540,13 @@ var fxNow, timerId,
8405
8540
  animationPrefilters = [ defaultPrefilter ],
8406
8541
  tweeners = {
8407
8542
  "*": [function( prop, value ) {
8408
- var end, unit, prevScale,
8543
+ var end, unit,
8409
8544
  tween = this.createTween( prop, value ),
8410
8545
  parts = rfxnum.exec( value ),
8411
8546
  target = tween.cur(),
8412
8547
  start = +target || 0,
8413
- scale = 1;
8548
+ scale = 1,
8549
+ maxIterations = 20;
8414
8550
 
8415
8551
  if ( parts ) {
8416
8552
  end = +parts[2];
@@ -8426,17 +8562,15 @@ var fxNow, timerId,
8426
8562
  do {
8427
8563
  // If previous iteration zeroed out, double until we get *something*
8428
8564
  // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8429
- prevScale = scale = scale || ".5";
8565
+ scale = scale || ".5";
8430
8566
 
8431
8567
  // Adjust and apply
8432
8568
  start = start / scale;
8433
8569
  jQuery.style( tween.elem, prop, start + unit );
8434
8570
 
8435
- // Update scale, tolerating zeroes from tween.cur()
8436
- scale = tween.cur() / target;
8437
-
8438
- // Stop looping if we've hit the mark or scale is unchanged
8439
- } while ( scale !== 1 && scale !== prevScale );
8571
+ // Update scale, tolerating zero or NaN from tween.cur()
8572
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8573
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8440
8574
  }
8441
8575
 
8442
8576
  tween.unit = unit;
@@ -9069,7 +9203,8 @@ jQuery.fn.offset = function( options ) {
9069
9203
  });
9070
9204
  }
9071
9205
 
9072
- var box, docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, top, left,
9206
+ var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft,
9207
+ box = { top: 0, left: 0 },
9073
9208
  elem = this[ 0 ],
9074
9209
  doc = elem && elem.ownerDocument;
9075
9210
 
@@ -9083,21 +9218,25 @@ jQuery.fn.offset = function( options ) {
9083
9218
 
9084
9219
  docElem = doc.documentElement;
9085
9220
 
9086
- // Make sure we're not dealing with a disconnected DOM node
9221
+ // Make sure it's not a disconnected DOM node
9087
9222
  if ( !jQuery.contains( docElem, elem ) ) {
9088
- return { top: 0, left: 0 };
9223
+ return box;
9089
9224
  }
9090
9225
 
9091
- box = elem.getBoundingClientRect();
9226
+ // If we don't have gBCR, just use 0,0 rather than error
9227
+ // BlackBerry 5, iOS 3 (original iPhone)
9228
+ if ( typeof elem.getBoundingClientRect !== "undefined" ) {
9229
+ box = elem.getBoundingClientRect();
9230
+ }
9092
9231
  win = getWindow( doc );
9093
9232
  clientTop = docElem.clientTop || body.clientTop || 0;
9094
9233
  clientLeft = docElem.clientLeft || body.clientLeft || 0;
9095
9234
  scrollTop = win.pageYOffset || docElem.scrollTop;
9096
9235
  scrollLeft = win.pageXOffset || docElem.scrollLeft;
9097
- top = box.top + scrollTop - clientTop;
9098
- left = box.left + scrollLeft - clientLeft;
9099
-
9100
- return { top: top, left: left };
9236
+ return {
9237
+ top: box.top + scrollTop - clientTop,
9238
+ left: box.left + scrollLeft - clientLeft
9239
+ };
9101
9240
  };
9102
9241
 
9103
9242
  jQuery.offset = {