sproutcore 0.9.14 → 0.9.15

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.
Files changed (61) hide show
  1. data/History.txt +43 -0
  2. data/Manifest.txt +12 -3
  3. data/bin/sc-build +19 -3
  4. data/bin/sc-install +5 -0
  5. data/bin/sc-remove +5 -0
  6. data/bin/sc-update +5 -0
  7. data/frameworks/prototype/prototype.js +267 -230
  8. data/frameworks/sproutcore/HISTORY +281 -135
  9. data/frameworks/sproutcore/controllers/array.js +133 -22
  10. data/frameworks/sproutcore/controllers/collection.js +4 -5
  11. data/frameworks/sproutcore/controllers/object.js +8 -2
  12. data/frameworks/sproutcore/core.js +361 -159
  13. data/frameworks/sproutcore/{foundation → debug}/unittest.js +3 -3
  14. data/frameworks/sproutcore/english.lproj/detect-browser +1 -1
  15. data/frameworks/sproutcore/english.lproj/theme.css +2 -2
  16. data/frameworks/sproutcore/foundation/application.js +6 -1
  17. data/frameworks/sproutcore/foundation/benchmark.js +37 -11
  18. data/frameworks/sproutcore/foundation/date.js +1 -1
  19. data/frameworks/sproutcore/foundation/enumerator.js +105 -0
  20. data/frameworks/sproutcore/foundation/object.js +19 -20
  21. data/frameworks/sproutcore/foundation/responder.js +1 -1
  22. data/frameworks/sproutcore/foundation/set.js +164 -57
  23. data/frameworks/sproutcore/foundation/string.js +151 -47
  24. data/frameworks/sproutcore/foundation/utils.js +84 -3
  25. data/frameworks/sproutcore/lib/collection_view.rb +1 -0
  26. data/frameworks/sproutcore/license.js +28 -0
  27. data/frameworks/sproutcore/mixins/array.js +73 -209
  28. data/frameworks/sproutcore/mixins/delegate_support.js +1 -1
  29. data/frameworks/sproutcore/mixins/enumerable.js +1006 -0
  30. data/frameworks/sproutcore/mixins/observable.js +153 -84
  31. data/frameworks/sproutcore/mixins/selection_support.js +13 -1
  32. data/frameworks/sproutcore/models/record.js +74 -27
  33. data/frameworks/sproutcore/models/store.js +7 -3
  34. data/frameworks/sproutcore/server/rails_server.js +82 -0
  35. data/frameworks/sproutcore/server/rest_server.js +178 -0
  36. data/frameworks/sproutcore/{foundation → server}/server.js +101 -48
  37. data/frameworks/sproutcore/tests/core/guidFor.rhtml +114 -0
  38. data/frameworks/sproutcore/tests/foundation/array.rhtml +6 -7
  39. data/frameworks/sproutcore/tests/foundation/set.rhtml +254 -0
  40. data/frameworks/sproutcore/tests/mixins/enumerable.rhtml +421 -0
  41. data/frameworks/sproutcore/tests/mixins/observable.rhtml +127 -0
  42. data/frameworks/sproutcore/tests/models/model.rhtml +23 -22
  43. data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +2 -2
  44. data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +112 -109
  45. data/frameworks/sproutcore/tests/views/view/frame.rhtml +91 -88
  46. data/frameworks/sproutcore/validators/date.js +1 -7
  47. data/frameworks/sproutcore/views/collection/collection.js +7 -2
  48. data/frameworks/sproutcore/views/list_item.js +141 -3
  49. data/frameworks/sproutcore/views/split.js +14 -11
  50. data/frameworks/sproutcore/views/view.js +9 -6
  51. data/lib/sproutcore/build_tools/html_builder.rb +19 -3
  52. data/lib/sproutcore/build_tools/resource_builder.rb +9 -3
  53. data/lib/sproutcore/bundle.rb +21 -0
  54. data/lib/sproutcore/bundle_manifest.rb +64 -20
  55. data/lib/sproutcore/helpers/capture_helper.rb +2 -2
  56. data/lib/sproutcore/library.rb +33 -9
  57. data/lib/sproutcore/merb/bundle_controller.rb +16 -5
  58. data/lib/sproutcore/version.rb +1 -1
  59. data/lib/sproutcore/view_helpers.rb +1 -1
  60. data/{sc-config.rb → sc-config} +5 -2
  61. metadata +24 -5
@@ -9,7 +9,7 @@
9
9
  @license */
10
10
 
11
11
  var Prototype = {
12
- Version: '1.6.0',
12
+ Version: '1.6.0.2',
13
13
 
14
14
  Browser: {
15
15
  IE: !!(window.attachEvent && !window.opera),
@@ -38,8 +38,6 @@ var Prototype = {
38
38
  if (Prototype.Browser.MobileSafari)
39
39
  Prototype.BrowserFeatures.SpecificElementExtensions = false;
40
40
 
41
- if (Prototype.Browser.WebKit)
42
- Prototype.BrowserFeatures.XPath = false;
43
41
 
44
42
  /* Based on Alex Arnell's inheritance implementation. */
45
43
  var Class = {
@@ -112,9 +110,9 @@ Object.extend = function(destination, source) {
112
110
  Object.extend(Object, {
113
111
  inspect: function(object) {
114
112
  try {
115
- if (object === undefined) return 'undefined';
113
+ if (Object.isUndefined(object)) return 'undefined';
116
114
  if (object === null) return 'null';
117
- return object.inspect ? object.inspect() : object.toString();
115
+ return object.inspect ? object.inspect() : String(object);
118
116
  } catch (e) {
119
117
  if (e instanceof RangeError) return '...';
120
118
  throw e;
@@ -137,7 +135,7 @@ Object.extend(Object, {
137
135
  var results = [];
138
136
  for (var property in object) {
139
137
  var value = Object.toJSON(object[property]);
140
- if (value !== undefined)
138
+ if (!Object.isUndefined(value))
141
139
  results.push(property.toJSON() + ': ' + value);
142
140
  }
143
141
 
@@ -175,7 +173,8 @@ Object.extend(Object, {
175
173
  },
176
174
 
177
175
  isArray: function(object) {
178
- return object && object.constructor === Array;
176
+ return object != null && typeof object == "object" &&
177
+ 'splice' in object && 'join' in object;
179
178
  },
180
179
 
181
180
  isHash: function(object) {
@@ -206,7 +205,7 @@ Object.extend(Function.prototype, {
206
205
  },
207
206
 
208
207
  bind: function() {
209
- if (arguments.length < 2 && arguments[0] === undefined) return this;
208
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
210
209
  var __method = this, args = $A(arguments), object = args.shift();
211
210
  return function() {
212
211
  return __method.apply(object, args.concat($A(arguments)));
@@ -353,7 +352,7 @@ Object.extend(String.prototype, {
353
352
 
354
353
  sub: function(pattern, replacement, count) {
355
354
  replacement = this.gsub.prepareReplacement(replacement);
356
- count = count === undefined ? 1 : count;
355
+ count = Object.isUndefined(count) ? 1 : count;
357
356
 
358
357
  return this.gsub(pattern, function(match) {
359
358
  if (--count < 0) return match[0];
@@ -368,7 +367,7 @@ Object.extend(String.prototype, {
368
367
 
369
368
  truncate: function(length, truncation) {
370
369
  length = length || 30;
371
- truncation = truncation === undefined ? '...' : truncation;
370
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
372
371
  return this.length > length ?
373
372
  this.slice(0, length - truncation.length) + truncation : String(this);
374
373
  },
@@ -488,7 +487,9 @@ Object.extend(String.prototype, {
488
487
  },
489
488
 
490
489
  isJSON: function() {
491
- var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
490
+ var str = this;
491
+ if (str.blank()) return false;
492
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
492
493
  return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
493
494
  },
494
495
 
@@ -567,7 +568,8 @@ var Template = Class.create({
567
568
  if (before == '\\') return match[2];
568
569
 
569
570
  var ctx = object, expr = match[3];
570
- var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
571
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
572
+ match = pattern.exec(expr);
571
573
  if (match == null) return before;
572
574
 
573
575
  while (match != null) {
@@ -579,7 +581,7 @@ var Template = Class.create({
579
581
  }
580
582
 
581
583
  return before + String.interpret(ctx);
582
- }.bind(this));
584
+ });
583
585
  }
584
586
  });
585
587
  Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
@@ -688,7 +690,7 @@ var Enumerable = {
688
690
  },
689
691
 
690
692
  inGroupsOf: function(number, fillWith) {
691
- fillWith = fillWith === undefined ? null : fillWith;
693
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
692
694
  return this.eachSlice(number, function(slice) {
693
695
  while(slice.length < number) slice.push(fillWith);
694
696
  return slice;
@@ -715,7 +717,7 @@ var Enumerable = {
715
717
  var result;
716
718
  this.each(function(value, index) {
717
719
  value = iterator(value, index);
718
- if (result == undefined || value >= result)
720
+ if (result == null || value >= result)
719
721
  result = value;
720
722
  });
721
723
  return result;
@@ -726,7 +728,7 @@ var Enumerable = {
726
728
  var result;
727
729
  this.each(function(value, index) {
728
730
  value = iterator(value, index);
729
- if (result == undefined || value < result)
731
+ if (result == null || value < result)
730
732
  result = value;
731
733
  });
732
734
  return result;
@@ -807,20 +809,20 @@ Object.extend(Enumerable, {
807
809
  function $A(iterable) {
808
810
  if (!iterable) return [];
809
811
  if (iterable.toArray) return iterable.toArray();
810
- var length = iterable.length, results = new Array(length);
812
+ var length = iterable.length || 0, results = new Array(length);
811
813
  while (length--) results[length] = iterable[length];
812
814
  return results;
813
815
  }
814
816
 
815
817
  if (Prototype.Browser.WebKit) {
816
- function $A(iterable) {
818
+ $A = function(iterable) {
817
819
  if (!iterable) return [];
818
820
  if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
819
821
  iterable.toArray) return iterable.toArray();
820
- var length = iterable.length, results = new Array(length);
822
+ var length = iterable.length || 0, results = new Array(length);
821
823
  while (length--) results[length] = iterable[length];
822
824
  return results;
823
- }
825
+ };
824
826
  }
825
827
 
826
828
  Array.from = $A;
@@ -906,7 +908,7 @@ Object.extend(Array.prototype, {
906
908
  var results = [];
907
909
  this.each(function(object) {
908
910
  var value = Object.toJSON(object);
909
- if (value !== undefined) results.push(value);
911
+ if (!Object.isUndefined(value)) results.push(value);
910
912
  });
911
913
  return '[' + results.join(', ') + ']';
912
914
  }
@@ -986,34 +988,6 @@ function $H(object) {
986
988
  };
987
989
 
988
990
  var Hash = Class.create(Enumerable, (function() {
989
- if (function() {
990
- var i = 0, Test = function(value) { this.key = value; };
991
- Test.prototype.key = 'foo';
992
- for (var property in new Test('bar')) i++;
993
- return i > 1;
994
- }()) {
995
- function each(iterator) {
996
- var cache = [];
997
- for (var key in this._object) {
998
- var value = this._object[key];
999
- if (cache.include(key)) continue;
1000
- cache.push(key);
1001
- var pair = [key, value];
1002
- pair.key = key;
1003
- pair.value = value;
1004
- iterator(pair);
1005
- }
1006
- }
1007
- } else {
1008
- function each(iterator) {
1009
- for (var key in this._object) {
1010
- var value = this._object[key], pair = [key, value];
1011
- pair.key = key;
1012
- pair.value = value;
1013
- iterator(pair);
1014
- }
1015
- }
1016
- }
1017
991
 
1018
992
  function toQueryPair(key, value) {
1019
993
  if (Object.isUndefined(value)) return key;
@@ -1025,7 +999,14 @@ var Hash = Class.create(Enumerable, (function() {
1025
999
  this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1026
1000
  },
1027
1001
 
1028
- _each: each,
1002
+ _each: function(iterator) {
1003
+ for (var key in this._object) {
1004
+ var value = this._object[key], pair = [key, value];
1005
+ pair.key = key;
1006
+ pair.value = value;
1007
+ iterator(pair);
1008
+ }
1009
+ },
1029
1010
 
1030
1011
  set: function(key, value) {
1031
1012
  return this._object[key] = value;
@@ -1189,8 +1170,11 @@ Ajax.Base = Class.create({
1189
1170
  Object.extend(this.options, options || { });
1190
1171
 
1191
1172
  this.options.method = this.options.method.toLowerCase();
1173
+
1192
1174
  if (Object.isString(this.options.parameters))
1193
1175
  this.options.parameters = this.options.parameters.toQueryParams();
1176
+ else if (Object.isHash(this.options.parameters))
1177
+ this.options.parameters = this.options.parameters.toObject();
1194
1178
  }
1195
1179
  });
1196
1180
 
@@ -1208,7 +1192,7 @@ Ajax.Request = Class.create(Ajax.Base, {
1208
1192
  this.method = this.options.method;
1209
1193
  var params = Object.clone(this.options.parameters);
1210
1194
 
1211
- if (!['get', 'post'].include(this.method)) {
1195
+ if (this.options.emulateUncommonMethods && !['get', 'post'].include(this.method)) {
1212
1196
  // simulate other verbs over post
1213
1197
  params['_method'] = this.method;
1214
1198
  this.method = 'post';
@@ -1230,14 +1214,14 @@ Ajax.Request = Class.create(Ajax.Base, {
1230
1214
  Ajax.Responders.dispatch('onCreate', this, response);
1231
1215
 
1232
1216
  this.transport.open(this.method.toUpperCase(), this.url,
1233
- this.options.asynchronous);
1217
+ this.options.asynchronous);
1234
1218
 
1235
1219
  if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1236
1220
 
1237
1221
  this.transport.onreadystatechange = this.onStateChange.bind(this);
1238
1222
  this.setRequestHeaders();
1239
1223
 
1240
- this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1224
+ this.body = this.method != 'get' ? (this.options.postBody || params) : null;
1241
1225
  this.transport.send(this.body);
1242
1226
 
1243
1227
  /* Force Firefox to handle ready state 4 for synchronous requests */
@@ -1317,7 +1301,7 @@ Ajax.Request = Class.create(Ajax.Base, {
1317
1301
 
1318
1302
  var contentType = response.getHeader('Content-type');
1319
1303
  if (this.options.evalJS == 'force'
1320
- || (this.options.evalJS && contentType
1304
+ || (this.options.evalJS && this.isSameOrigin() && contentType
1321
1305
  && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1322
1306
  this.evalResponse();
1323
1307
  }
@@ -1335,9 +1319,18 @@ Ajax.Request = Class.create(Ajax.Base, {
1335
1319
  }
1336
1320
  },
1337
1321
 
1322
+ isSameOrigin: function() {
1323
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1324
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1325
+ protocol: location.protocol,
1326
+ domain: document.domain,
1327
+ port: location.port ? ':' + location.port : ''
1328
+ }));
1329
+ },
1330
+
1338
1331
  getHeader: function(name) {
1339
1332
  try {
1340
- return this.transport.getResponseHeader(name);
1333
+ return this.transport.getResponseHeader(name) || null;
1341
1334
  } catch (e) { return null; }
1342
1335
  },
1343
1336
 
@@ -1373,7 +1366,7 @@ Ajax.Response = Class.create({
1373
1366
 
1374
1367
  if(readyState == 4) {
1375
1368
  var xml = transport.responseXML;
1376
- this.responseXML = xml === undefined ? null : xml;
1369
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
1377
1370
  this.responseJSON = this._getResponseJSON();
1378
1371
  }
1379
1372
  },
@@ -1410,7 +1403,8 @@ Ajax.Response = Class.create({
1410
1403
  if (!json) return null;
1411
1404
  json = decodeURIComponent(escape(json));
1412
1405
  try {
1413
- return json.evalJSON(this.request.options.sanitizeJSON);
1406
+ return json.evalJSON(this.request.options.sanitizeJSON ||
1407
+ !this.request.isSameOrigin());
1414
1408
  } catch (e) {
1415
1409
  this.request.dispatchException(e);
1416
1410
  }
@@ -1419,10 +1413,12 @@ Ajax.Response = Class.create({
1419
1413
  _getResponseJSON: function() {
1420
1414
  var options = this.request.options;
1421
1415
  if (!options.evalJSON || (options.evalJSON != 'force' &&
1422
- !(this.getHeader('Content-type') || '').include('application/json')))
1423
- return null;
1416
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
1417
+ this.responseText.blank())
1418
+ return null;
1424
1419
  try {
1425
- return this.transport.responseText.evalJSON(options.sanitizeJSON);
1420
+ return this.responseText.evalJSON(options.sanitizeJSON ||
1421
+ !this.request.isSameOrigin());
1426
1422
  } catch (e) {
1427
1423
  this.request.dispatchException(e);
1428
1424
  }
@@ -1436,11 +1432,11 @@ Ajax.Updater = Class.create(Ajax.Request, {
1436
1432
  failure: (container.failure || (container.success ? null : container))
1437
1433
  };
1438
1434
 
1439
- options = options || { };
1435
+ options = Object.clone(options);
1440
1436
  var onComplete = options.onComplete;
1441
- options.onComplete = (function(response, param) {
1437
+ options.onComplete = (function(response, json) {
1442
1438
  this.updateContent(response.responseText);
1443
- if (Object.isFunction(onComplete)) onComplete(response, param);
1439
+ if (Object.isFunction(onComplete)) onComplete(response, json);
1444
1440
  }).bind(this);
1445
1441
 
1446
1442
  $super(url, options);
@@ -1462,10 +1458,6 @@ Ajax.Updater = Class.create(Ajax.Request, {
1462
1458
  }
1463
1459
  else receiver.update(responseText);
1464
1460
  }
1465
-
1466
- if (this.success()) {
1467
- if (this.onComplete) this.onComplete.bind(this).defer();
1468
- }
1469
1461
  }
1470
1462
  });
1471
1463
 
@@ -1630,24 +1622,28 @@ Element.Methods = {
1630
1622
  Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
1631
1623
  insertions = {bottom:insertions};
1632
1624
 
1633
- var content, t, range;
1625
+ var content, insert, tagName, childNodes;
1634
1626
 
1635
- for (position in insertions) {
1627
+ for (var position in insertions) {
1636
1628
  content = insertions[position];
1637
1629
  position = position.toLowerCase();
1638
- t = Element._insertionTranslations[position];
1630
+ insert = Element._insertionTranslations[position];
1639
1631
 
1640
1632
  if (content && content.toElement) content = content.toElement();
1641
1633
  if (Object.isElement(content)) {
1642
- t.insert(element, content);
1634
+ insert(element, content);
1643
1635
  continue;
1644
1636
  }
1645
1637
 
1646
1638
  content = Object.toHTML(content);
1647
1639
 
1648
- range = element.ownerDocument.createRange();
1649
- t.initializeRange(element, range);
1650
- t.insert(element, range.createContextualFragment(content.stripScripts()));
1640
+ tagName = ((position == 'before' || position == 'after')
1641
+ ? element.parentNode : element).tagName.toUpperCase();
1642
+
1643
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
1644
+
1645
+ if (position == 'top' || position == 'after') childNodes.reverse();
1646
+ childNodes.each(insert.curry(element));
1651
1647
 
1652
1648
  content.evalScripts.bind(content).defer();
1653
1649
  }
@@ -1692,7 +1688,7 @@ Element.Methods = {
1692
1688
  },
1693
1689
 
1694
1690
  descendants: function(element) {
1695
- return $A($(element).getElementsByTagName('*')).each(Element.extend);
1691
+ return $(element).select("*");
1696
1692
  },
1697
1693
 
1698
1694
  firstDescendant: function(element) {
@@ -1731,32 +1727,31 @@ Element.Methods = {
1731
1727
  element = $(element);
1732
1728
  if (arguments.length == 1) return $(element.parentNode);
1733
1729
  var ancestors = element.ancestors();
1734
- return expression ? Selector.findElement(ancestors, expression, index) :
1735
- ancestors[index || 0];
1730
+ return Object.isNumber(expression) ? ancestors[expression] :
1731
+ Selector.findElement(ancestors, expression, index);
1736
1732
  },
1737
1733
 
1738
1734
  down: function(element, expression, index) {
1739
1735
  element = $(element);
1740
1736
  if (arguments.length == 1) return element.firstDescendant();
1741
- var descendants = element.descendants();
1742
- return expression ? Selector.findElement(descendants, expression, index) :
1743
- descendants[index || 0];
1737
+ return Object.isNumber(expression) ? element.descendants()[expression] :
1738
+ element.select(expression)[index || 0];
1744
1739
  },
1745
1740
 
1746
1741
  previous: function(element, expression, index) {
1747
1742
  element = $(element);
1748
1743
  if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1749
1744
  var previousSiblings = element.previousSiblings();
1750
- return expression ? Selector.findElement(previousSiblings, expression, index) :
1751
- previousSiblings[index || 0];
1745
+ return Object.isNumber(expression) ? previousSiblings[expression] :
1746
+ Selector.findElement(previousSiblings, expression, index);
1752
1747
  },
1753
1748
 
1754
1749
  next: function(element, expression, index) {
1755
1750
  element = $(element);
1756
1751
  if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1757
1752
  var nextSiblings = element.nextSiblings();
1758
- return expression ? Selector.findElement(nextSiblings, expression, index) :
1759
- nextSiblings[index || 0];
1753
+ return Object.isNumber(expression) ? nextSiblings[expression] :
1754
+ Selector.findElement(nextSiblings, expression, index);
1760
1755
  },
1761
1756
 
1762
1757
  select: function() {
@@ -1797,10 +1792,11 @@ Element.Methods = {
1797
1792
  var attributes = { }, t = Element._attributeTranslations.write;
1798
1793
 
1799
1794
  if (typeof name == 'object') attributes = name;
1800
- else attributes[name] = value === undefined ? true : value;
1795
+ else attributes[name] = Object.isUndefined(value) ? true : value;
1801
1796
 
1802
1797
  for (var attr in attributes) {
1803
- var name = t.names[attr] || attr, value = attributes[attr];
1798
+ name = t.names[attr] || attr;
1799
+ value = attributes[attr];
1804
1800
  if (t.values[attr]) name = t.values[attr](element, value);
1805
1801
  if (value === false || value === null)
1806
1802
  element.removeAttribute(name);
@@ -1869,6 +1865,7 @@ Element.Methods = {
1869
1865
 
1870
1866
  descendantOf: function(element, ancestor) {
1871
1867
  element = $(element); ancestor = $(ancestor);
1868
+ var originalAncestor = ancestor;
1872
1869
 
1873
1870
  if (element.compareDocumentPosition)
1874
1871
  return (element.compareDocumentPosition(ancestor) & 8) === 8;
@@ -1880,11 +1877,12 @@ Element.Methods = {
1880
1877
  do { ancestor = ancestor.parentNode; }
1881
1878
  while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
1882
1879
  }
1883
- if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
1880
+ if (nextAncestor && nextAncestor.sourceIndex)
1881
+ return (e > a && e < nextAncestor.sourceIndex);
1884
1882
  }
1885
1883
 
1886
1884
  while (element = element.parentNode)
1887
- if (element == ancestor) return true;
1885
+ if (element == originalAncestor) return true;
1888
1886
  return false;
1889
1887
  },
1890
1888
 
@@ -1923,7 +1921,7 @@ Element.Methods = {
1923
1921
  if (property == 'opacity') element.setOpacity(styles[property]);
1924
1922
  else
1925
1923
  elementStyle[(property == 'float' || property == 'cssFloat') ?
1926
- (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
1924
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
1927
1925
  property] = styles[property];
1928
1926
 
1929
1927
  return element;
@@ -2024,7 +2022,7 @@ Element.Methods = {
2024
2022
  if (element) {
2025
2023
  if (element.tagName == 'BODY') break;
2026
2024
  var p = Element.getStyle(element, 'position');
2027
- if (p == 'relative' || p == 'absolute') break;
2025
+ if (p !== 'static') break;
2028
2026
  }
2029
2027
  } while (element);
2030
2028
  return Element._returnOffset(valueL, valueT);
@@ -2173,72 +2171,75 @@ Element._attributeTranslations = {
2173
2171
  }
2174
2172
  };
2175
2173
 
2176
-
2177
- if (!document.createRange || Prototype.Browser.Opera) {
2178
- Element.Methods.insert = function(element, insertions) {
2179
- element = $(element);
2180
-
2181
- if (Object.isString(insertions) || Object.isNumber(insertions) ||
2182
- Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
2183
- insertions = { bottom: insertions };
2184
-
2185
- var t = Element._insertionTranslations, content, position, pos, tagName;
2186
-
2187
- for (position in insertions) {
2188
- content = insertions[position];
2189
- position = position.toLowerCase();
2190
- pos = t[position];
2191
-
2192
- if (content && content.toElement) content = content.toElement();
2193
- if (Object.isElement(content)) {
2194
- pos.insert(element, content);
2195
- continue;
2196
- }
2197
-
2198
- content = Object.toHTML(content);
2199
- tagName = ((position == 'before' || position == 'after')
2200
- ? element.parentNode : element).tagName.toUpperCase();
2201
-
2202
- if (t.tags[tagName]) {
2203
- var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2204
- if (position == 'top' || position == 'after') fragments.reverse();
2205
- fragments.each(pos.insert.curry(element));
2174
+ if (Prototype.Browser.Opera) {
2175
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
2176
+ function(proceed, element, style) {
2177
+ switch (style) {
2178
+ case 'left': case 'top': case 'right': case 'bottom':
2179
+ if (proceed(element, 'position') === 'static') return null;
2180
+ case 'height': case 'width':
2181
+ // returns '0px' for hidden elements; we want it to return null
2182
+ if (!Element.visible(element)) return null;
2183
+
2184
+ // returns the border-box dimensions rather than the content-box
2185
+ // dimensions, so we subtract padding and borders from the value
2186
+ var dim = parseInt(proceed(element, style), 10);
2187
+
2188
+ if (dim !== element['offset' + style.capitalize()])
2189
+ return dim + 'px';
2190
+
2191
+ var properties;
2192
+ if (style === 'height') {
2193
+ properties = ['border-top-width', 'padding-top',
2194
+ 'padding-bottom', 'border-bottom-width'];
2195
+ }
2196
+ else {
2197
+ properties = ['border-left-width', 'padding-left',
2198
+ 'padding-right', 'border-right-width'];
2199
+ }
2200
+ return properties.inject(dim, function(memo, property) {
2201
+ var val = proceed(element, property);
2202
+ return val === null ? memo : memo - parseInt(val, 10);
2203
+ }) + 'px';
2204
+ default: return proceed(element, style);
2206
2205
  }
2207
- else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
2208
-
2209
- content.evalScripts.bind(content).defer();
2210
2206
  }
2207
+ );
2211
2208
 
2212
- return element;
2213
- };
2214
- }
2215
-
2216
- if (Prototype.Browser.Opera) {
2217
- Element.Methods._getStyle = Element.Methods.getStyle;
2218
- Element.Methods.getStyle = function(element, style) {
2219
- switch(style) {
2220
- case 'left':
2221
- case 'top':
2222
- case 'right':
2223
- case 'bottom':
2224
- if (Element._getStyle(element, 'position') == 'static') return null;
2225
- default: return Element._getStyle(element, style);
2209
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
2210
+ function(proceed, element, attribute) {
2211
+ if (attribute === 'title') return element.title;
2212
+ return proceed(element, attribute);
2226
2213
  }
2227
- };
2228
- Element.Methods._readAttribute = Element.Methods.readAttribute;
2229
- Element.Methods.readAttribute = function(element, attribute) {
2230
- if (attribute == 'title') return element.title;
2231
- return Element._readAttribute(element, attribute);
2232
- };
2214
+ );
2233
2215
  }
2234
2216
 
2235
2217
  else if (Prototype.Browser.IE) {
2236
- $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
2218
+ // IE doesn't report offsets correctly for static elements, so we change them
2219
+ // to "relative" to get the values, then change them back.
2220
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
2221
+ function(proceed, element) {
2222
+ element = $(element);
2223
+ var position = element.getStyle('position');
2224
+ if (position !== 'static') return proceed(element);
2225
+ element.setStyle({ position: 'relative' });
2226
+ var value = proceed(element);
2227
+ element.setStyle({ position: position });
2228
+ return value;
2229
+ }
2230
+ );
2231
+
2232
+ $w('positionedOffset viewportOffset').each(function(method) {
2237
2233
  Element.Methods[method] = Element.Methods[method].wrap(
2238
2234
  function(proceed, element) {
2239
2235
  element = $(element);
2240
2236
  var position = element.getStyle('position');
2241
- if (position != 'static') return proceed(element);
2237
+ if (position !== 'static') return proceed(element);
2238
+ // Trigger hasLayout on the offset parent so that IE6 reports
2239
+ // accurate offsetTop and offsetLeft values for position: fixed.
2240
+ var offsetParent = element.getOffsetParent();
2241
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
2242
+ offsetParent.setStyle({ zoom: 1 });
2242
2243
  element.setStyle({ position: 'relative' });
2243
2244
  var value = proceed(element);
2244
2245
  element.setStyle({ position: position });
@@ -2303,7 +2304,7 @@ else if (Prototype.Browser.IE) {
2303
2304
  return node ? node.value : "";
2304
2305
  },
2305
2306
  _getEv: function(element, attribute) {
2306
- var attribute = element.getAttribute(attribute);
2307
+ attribute = element.getAttribute(attribute);
2307
2308
  return attribute ? attribute.toString().slice(23, -2) : null;
2308
2309
  },
2309
2310
  _flag: function(element, attribute) {
@@ -2320,7 +2321,10 @@ else if (Prototype.Browser.IE) {
2320
2321
  };
2321
2322
 
2322
2323
  Element._attributeTranslations.write = {
2323
- names: Object.clone(Element._attributeTranslations.read.names),
2324
+ names: Object.extend({
2325
+ cellpadding: 'cellPadding',
2326
+ cellspacing: 'cellSpacing'
2327
+ }, Element._attributeTranslations.read.names),
2324
2328
  values: {
2325
2329
  checked: function(element, value) {
2326
2330
  element.checked = !!value;
@@ -2400,7 +2404,7 @@ else if (Prototype.Browser.WebKit) {
2400
2404
  };
2401
2405
 
2402
2406
  // Safari returns margins on body which is incorrect if the child is absolutely
2403
- // positioned. For performance reasons, redefine Position.cumulativeOffset for
2407
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
2404
2408
  // KHTML/WebKit only.
2405
2409
  Element.Methods.cumulativeOffset = function(element) {
2406
2410
  var valueT = 0, valueL = 0;
@@ -2440,7 +2444,7 @@ if (Prototype.Browser.IE || Prototype.Browser.Opera) {
2440
2444
  };
2441
2445
  }
2442
2446
 
2443
- if (document.createElement('div').outerHTML) {
2447
+ if ('outerHTML' in document.createElement('div')) {
2444
2448
  Element.Methods.replace = function(element, content) {
2445
2449
  element = $(element);
2446
2450
 
@@ -2478,45 +2482,25 @@ Element._returnOffset = function(l, t) {
2478
2482
 
2479
2483
  Element._getContentFromAnonymousElement = function(tagName, html) {
2480
2484
  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
2481
- div.innerHTML = t[0] + html + t[1];
2482
- t[2].times(function() { div = div.firstChild; });
2485
+ if (t) {
2486
+ div.innerHTML = t[0] + html + t[1];
2487
+ t[2].times(function() { div = div.firstChild; });
2488
+ } else div.innerHTML = html;
2483
2489
  return $A(div.childNodes);
2484
2490
  };
2485
2491
 
2486
2492
  Element._insertionTranslations = {
2487
- before: {
2488
- adjacency: 'beforeBegin',
2489
- insert: function(element, node) {
2490
- element.parentNode.insertBefore(node, element);
2491
- },
2492
- initializeRange: function(element, range) {
2493
- range.setStartBefore(element);
2494
- }
2493
+ before: function(element, node) {
2494
+ element.parentNode.insertBefore(node, element);
2495
2495
  },
2496
- top: {
2497
- adjacency: 'afterBegin',
2498
- insert: function(element, node) {
2499
- element.insertBefore(node, element.firstChild);
2500
- },
2501
- initializeRange: function(element, range) {
2502
- range.selectNodeContents(element);
2503
- range.collapse(true);
2504
- }
2496
+ top: function(element, node) {
2497
+ element.insertBefore(node, element.firstChild);
2505
2498
  },
2506
- bottom: {
2507
- adjacency: 'beforeEnd',
2508
- insert: function(element, node) {
2509
- element.appendChild(node);
2510
- }
2499
+ bottom: function(element, node) {
2500
+ element.appendChild(node);
2511
2501
  },
2512
- after: {
2513
- adjacency: 'afterEnd',
2514
- insert: function(element, node) {
2515
- element.parentNode.insertBefore(node, element.nextSibling);
2516
- },
2517
- initializeRange: function(element, range) {
2518
- range.setStartAfter(element);
2519
- }
2502
+ after: function(element, node) {
2503
+ element.parentNode.insertBefore(node, element.nextSibling);
2520
2504
  },
2521
2505
  tags: {
2522
2506
  TABLE: ['<table>', '</table>', 1],
@@ -2528,7 +2512,6 @@ Element._insertionTranslations = {
2528
2512
  };
2529
2513
 
2530
2514
  (function() {
2531
- this.bottom.initializeRange = this.top.initializeRange;
2532
2515
  Object.extend(this.tags, {
2533
2516
  THEAD: this.tags.TBODY,
2534
2517
  TFOOT: this.tags.TBODY,
@@ -2689,10 +2672,11 @@ Element.addMethods = function(methods) {
2689
2672
  document.viewport = {
2690
2673
  getDimensions: function() {
2691
2674
  var dimensions = { };
2675
+ var B = Prototype.Browser;
2692
2676
  $w('width height').each(function(d) {
2693
2677
  var D = d.capitalize();
2694
- dimensions[d] = self['inner' + D] ||
2695
- (document.documentElement['client' + D] || document.body['client' + D]);
2678
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
2679
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
2696
2680
  });
2697
2681
  return dimensions;
2698
2682
  },
@@ -2721,9 +2705,26 @@ var Selector = Class.create({
2721
2705
  this.compileMatcher();
2722
2706
  },
2723
2707
 
2708
+ shouldUseXPath: function() {
2709
+ if (!Prototype.BrowserFeatures.XPath) return false;
2710
+
2711
+ var e = this.expression;
2712
+
2713
+ // Safari 3 chokes on :*-of-type and :empty
2714
+ if (Prototype.Browser.WebKit &&
2715
+ (e.include("-of-type") || e.include(":empty")))
2716
+ return false;
2717
+
2718
+ // XPath can't do namespaced attributes, nor can it read
2719
+ // the "checked" property from DOM nodes
2720
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
2721
+ return false;
2722
+
2723
+ return true;
2724
+ },
2725
+
2724
2726
  compileMatcher: function() {
2725
- // Selectors with namespaced attributes can't use the XPath version
2726
- if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))
2727
+ if (this.shouldUseXPath())
2727
2728
  return this.compileXPathMatcher();
2728
2729
 
2729
2730
  var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
@@ -2846,8 +2847,12 @@ Object.extend(Selector, {
2846
2847
  },
2847
2848
  className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
2848
2849
  id: "[@id='#{1}']",
2849
- attrPresence: "[@#{1}]",
2850
+ attrPresence: function(m) {
2851
+ m[1] = m[1].toLowerCase();
2852
+ return new Template("[@#{1}]").evaluate(m);
2853
+ },
2850
2854
  attr: function(m) {
2855
+ m[1] = m[1].toLowerCase();
2851
2856
  m[3] = m[5] || m[6];
2852
2857
  return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
2853
2858
  },
@@ -2876,7 +2881,7 @@ Object.extend(Selector, {
2876
2881
  'enabled': "[not(@disabled)]",
2877
2882
  'not': function(m) {
2878
2883
  var e = m[6], p = Selector.patterns,
2879
- x = Selector.xpath, le, m, v;
2884
+ x = Selector.xpath, le, v;
2880
2885
 
2881
2886
  var exclusion = [];
2882
2887
  while (e && le != e && (/\S/).test(e)) {
@@ -2933,13 +2938,13 @@ Object.extend(Selector, {
2933
2938
  },
2934
2939
 
2935
2940
  criteria: {
2936
- tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
2937
- className: 'n = h.className(n, r, "#{1}", c); c = false;',
2938
- id: 'n = h.id(n, r, "#{1}", c); c = false;',
2939
- attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
2941
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
2942
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
2943
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
2944
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
2940
2945
  attr: function(m) {
2941
2946
  m[3] = (m[5] || m[6]);
2942
- return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
2947
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
2943
2948
  },
2944
2949
  pseudo: function(m) {
2945
2950
  if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
@@ -2963,7 +2968,8 @@ Object.extend(Selector, {
2963
2968
  tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
2964
2969
  id: /^#([\w\-\*]+)(\b|$)/,
2965
2970
  className: /^\.([\w\-\*]+)(\b|$)/,
2966
- pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,
2971
+ pseudo:
2972
+ /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
2967
2973
  attrPresence: /^\[([\w]+)\]/,
2968
2974
  attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
2969
2975
  },
@@ -2988,7 +2994,7 @@ Object.extend(Selector, {
2988
2994
 
2989
2995
  attr: function(element, matches) {
2990
2996
  var nodeValue = Element.readAttribute(element, matches[1]);
2991
- return Selector.operators[matches[2]](nodeValue, matches[3]);
2997
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
2992
2998
  }
2993
2999
  },
2994
3000
 
@@ -3003,14 +3009,15 @@ Object.extend(Selector, {
3003
3009
 
3004
3010
  // marks an array of nodes for counting
3005
3011
  mark: function(nodes) {
3012
+ var _true = Prototype.emptyFunction;
3006
3013
  for (var i = 0, node; node = nodes[i]; i++)
3007
- node._counted = true;
3014
+ node._countedByPrototype = _true;
3008
3015
  return nodes;
3009
3016
  },
3010
3017
 
3011
3018
  unmark: function(nodes) {
3012
3019
  for (var i = 0, node; node = nodes[i]; i++)
3013
- node._counted = undefined;
3020
+ node._countedByPrototype = undefined;
3014
3021
  return nodes;
3015
3022
  },
3016
3023
 
@@ -3018,15 +3025,15 @@ Object.extend(Selector, {
3018
3025
  // "ofType" flag indicates whether we're indexing for nth-of-type
3019
3026
  // rather than nth-child
3020
3027
  index: function(parentNode, reverse, ofType) {
3021
- parentNode._counted = true;
3028
+ parentNode._countedByPrototype = Prototype.emptyFunction;
3022
3029
  if (reverse) {
3023
3030
  for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
3024
3031
  var node = nodes[i];
3025
- if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
3032
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3026
3033
  }
3027
3034
  } else {
3028
3035
  for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
3029
- if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
3036
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3030
3037
  }
3031
3038
  },
3032
3039
 
@@ -3035,8 +3042,8 @@ Object.extend(Selector, {
3035
3042
  if (nodes.length == 0) return nodes;
3036
3043
  var results = [], n;
3037
3044
  for (var i = 0, l = nodes.length; i < l; i++)
3038
- if (!(n = nodes[i])._counted) {
3039
- n._counted = true;
3045
+ if (!(n = nodes[i])._countedByPrototype) {
3046
+ n._countedByPrototype = Prototype.emptyFunction;
3040
3047
  results.push(Element.extend(n));
3041
3048
  }
3042
3049
  return Selector.handlers.unmark(results);
@@ -3053,7 +3060,7 @@ Object.extend(Selector, {
3053
3060
  child: function(nodes) {
3054
3061
  var h = Selector.handlers;
3055
3062
  for (var i = 0, results = [], node; node = nodes[i]; i++) {
3056
- for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
3063
+ for (var j = 0, child; child = node.childNodes[j]; j++)
3057
3064
  if (child.nodeType == 1 && child.tagName != '!') results.push(child);
3058
3065
  }
3059
3066
  return results;
@@ -3088,7 +3095,7 @@ Object.extend(Selector, {
3088
3095
 
3089
3096
  // TOKEN FUNCTIONS
3090
3097
  tagName: function(nodes, root, tagName, combinator) {
3091
- tagName = tagName.toUpperCase();
3098
+ var uTagName = tagName.toUpperCase();
3092
3099
  var results = [], h = Selector.handlers;
3093
3100
  if (nodes) {
3094
3101
  if (combinator) {
@@ -3101,7 +3108,7 @@ Object.extend(Selector, {
3101
3108
  if (tagName == "*") return nodes;
3102
3109
  }
3103
3110
  for (var i = 0, node; node = nodes[i]; i++)
3104
- if (node.tagName.toUpperCase() == tagName) results.push(node);
3111
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
3105
3112
  return results;
3106
3113
  } else return root.getElementsByTagName(tagName);
3107
3114
  },
@@ -3148,16 +3155,18 @@ Object.extend(Selector, {
3148
3155
  return results;
3149
3156
  },
3150
3157
 
3151
- attrPresence: function(nodes, root, attr) {
3158
+ attrPresence: function(nodes, root, attr, combinator) {
3152
3159
  if (!nodes) nodes = root.getElementsByTagName("*");
3160
+ if (nodes && combinator) nodes = this[combinator](nodes);
3153
3161
  var results = [];
3154
3162
  for (var i = 0, node; node = nodes[i]; i++)
3155
3163
  if (Element.hasAttribute(node, attr)) results.push(node);
3156
3164
  return results;
3157
3165
  },
3158
3166
 
3159
- attr: function(nodes, root, attr, value, operator) {
3167
+ attr: function(nodes, root, attr, value, operator, combinator) {
3160
3168
  if (!nodes) nodes = root.getElementsByTagName("*");
3169
+ if (nodes && combinator) nodes = this[combinator](nodes);
3161
3170
  var handler = Selector.operators[operator], results = [];
3162
3171
  for (var i = 0, node; node = nodes[i]; i++) {
3163
3172
  var nodeValue = Element.readAttribute(node, attr);
@@ -3236,7 +3245,7 @@ Object.extend(Selector, {
3236
3245
  var h = Selector.handlers, results = [], indexed = [], m;
3237
3246
  h.mark(nodes);
3238
3247
  for (var i = 0, node; node = nodes[i]; i++) {
3239
- if (!node.parentNode._counted) {
3248
+ if (!node.parentNode._countedByPrototype) {
3240
3249
  h.index(node.parentNode, reverse, ofType);
3241
3250
  indexed.push(node.parentNode);
3242
3251
  }
@@ -3274,7 +3283,7 @@ Object.extend(Selector, {
3274
3283
  var exclusions = new Selector(selector).findElements(root);
3275
3284
  h.mark(exclusions);
3276
3285
  for (var i = 0, results = [], node; node = nodes[i]; i++)
3277
- if (!node._counted) results.push(node);
3286
+ if (!node._countedByPrototype) results.push(node);
3278
3287
  h.unmark(exclusions);
3279
3288
  return results;
3280
3289
  },
@@ -3308,11 +3317,19 @@ Object.extend(Selector, {
3308
3317
  '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
3309
3318
  },
3310
3319
 
3320
+ split: function(expression) {
3321
+ var expressions = [];
3322
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
3323
+ expressions.push(m[1].strip());
3324
+ });
3325
+ return expressions;
3326
+ },
3327
+
3311
3328
  matchElements: function(elements, expression) {
3312
- var matches = new Selector(expression).findElements(), h = Selector.handlers;
3329
+ var matches = $$(expression), h = Selector.handlers;
3313
3330
  h.mark(matches);
3314
3331
  for (var i = 0, results = [], element; element = elements[i]; i++)
3315
- if (element._counted) results.push(element);
3332
+ if (element._countedByPrototype) results.push(element);
3316
3333
  h.unmark(matches);
3317
3334
  return results;
3318
3335
  },
@@ -3325,10 +3342,7 @@ Object.extend(Selector, {
3325
3342
  },
3326
3343
 
3327
3344
  findChildElements: function(element, expressions) {
3328
- var exprs = expressions.join(','), expressions = [];
3329
- exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
3330
- expressions.push(m[1].strip());
3331
- });
3345
+ expressions = Selector.split(expressions.join(','));
3332
3346
  var results = [], h = Selector.handlers;
3333
3347
  for (var i = 0, l = expressions.length, selector; i < l; i++) {
3334
3348
  selector = new Selector(expressions[i].strip());
@@ -3338,6 +3352,25 @@ Object.extend(Selector, {
3338
3352
  }
3339
3353
  });
3340
3354
 
3355
+ if (Prototype.Browser.IE) {
3356
+ Object.extend(Selector.handlers, {
3357
+ // IE returns comment nodes on getElementsByTagName("*").
3358
+ // Filter them out.
3359
+ concat: function(a, b) {
3360
+ for (var i = 0, node; node = b[i]; i++)
3361
+ if (node.tagName !== "!") a.push(node);
3362
+ return a;
3363
+ },
3364
+
3365
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
3366
+ unmark: function(nodes) {
3367
+ for (var i = 0, node; node = nodes[i]; i++)
3368
+ node.removeAttribute('_countedByPrototype');
3369
+ return nodes;
3370
+ }
3371
+ });
3372
+ }
3373
+
3341
3374
  function $$() {
3342
3375
  return Selector.findChildElements(document, $A(arguments));
3343
3376
  }
@@ -3349,7 +3382,7 @@ var Form = {
3349
3382
 
3350
3383
  serializeElements: function(elements, options) {
3351
3384
  if (typeof options != 'object') options = { hash: !!options };
3352
- else if (options.hash === undefined) options.hash = true;
3385
+ else if (Object.isUndefined(options.hash)) options.hash = true;
3353
3386
  var key, value, submitted = false, submit = options.submit;
3354
3387
 
3355
3388
  var data = elements.inject({ }, function(result, element) {
@@ -3547,17 +3580,17 @@ Form.Element.Serializers = {
3547
3580
  },
3548
3581
 
3549
3582
  inputSelector: function(element, value) {
3550
- if (value === undefined) return element.checked ? element.value : null;
3583
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
3551
3584
  else element.checked = !!value;
3552
3585
  },
3553
3586
 
3554
3587
  textarea: function(element, value) {
3555
- if (value === undefined) return element.value;
3588
+ if (Object.isUndefined(value)) return element.value;
3556
3589
  else element.value = value;
3557
3590
  },
3558
3591
 
3559
3592
  select: function(element, index) {
3560
- if (index === undefined)
3593
+ if (Object.isUndefined(index))
3561
3594
  return this[element.type == 'select-one' ?
3562
3595
  'selectOne' : 'selectMany'](element);
3563
3596
  else {
@@ -3748,7 +3781,9 @@ Event.Methods = (function() {
3748
3781
 
3749
3782
  findElement: function(event, expression) {
3750
3783
  var element = Event.element(event);
3751
- return element.match(expression) ? element : element.up(expression);
3784
+ if (!expression) return element;
3785
+ var elements = [element].concat(element.ancestors());
3786
+ return Selector.findElement(elements, expression, 0);
3752
3787
  },
3753
3788
 
3754
3789
  pointer: function(event) {
@@ -3811,9 +3846,9 @@ Object.extend(Event, (function() {
3811
3846
  var cache = Event.cache;
3812
3847
 
3813
3848
  function getEventID(element) {
3814
- if (element._eventID) return element._eventID;
3849
+ if (element._prototypeEventID) return element._prototypeEventID[0];
3815
3850
  arguments.callee.id = arguments.callee.id || 1;
3816
- return element._eventID = ++arguments.callee.id;
3851
+ return element._prototypeEventID = [++arguments.callee.id];
3817
3852
  }
3818
3853
 
3819
3854
  function getDOMEventName(eventName) {
@@ -3923,11 +3958,12 @@ Object.extend(Event, (function() {
3923
3958
  if (element == document && document.createEvent && !element.dispatchEvent)
3924
3959
  element = document.documentElement;
3925
3960
 
3961
+ var event;
3926
3962
  if (document.createEvent) {
3927
- var event = document.createEvent("HTMLEvents");
3963
+ event = document.createEvent("HTMLEvents");
3928
3964
  event.initEvent("dataavailable", true, true);
3929
3965
  } else {
3930
- var event = document.createEventObject();
3966
+ event = document.createEventObject();
3931
3967
  event.eventType = "ondataavailable";
3932
3968
  }
3933
3969
 
@@ -3940,7 +3976,7 @@ Object.extend(Event, (function() {
3940
3976
  element.fireEvent(event.eventType, event);
3941
3977
  }
3942
3978
 
3943
- return event;
3979
+ return Event.extend(event);
3944
3980
  }
3945
3981
  };
3946
3982
  })());
@@ -3956,20 +3992,21 @@ Element.addMethods({
3956
3992
  Object.extend(document, {
3957
3993
  fire: Element.Methods.fire.methodize(),
3958
3994
  observe: Element.Methods.observe.methodize(),
3959
- stopObserving: Element.Methods.stopObserving.methodize()
3995
+ stopObserving: Element.Methods.stopObserving.methodize(),
3996
+ loaded: false
3960
3997
  });
3961
3998
 
3962
3999
  (function() {
3963
4000
  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
3964
4001
  Matthias Miller, Dean Edwards and John Resig. */
3965
4002
 
3966
- var timer, fired = false;
4003
+ var timer;
3967
4004
 
3968
4005
  function fireContentLoadedEvent() {
3969
- if (fired) return;
4006
+ if (document.loaded) return;
3970
4007
  if (timer) window.clearInterval(timer);
3971
4008
  document.fire("dom:loaded");
3972
- fired = true;
4009
+ document.loaded = true;
3973
4010
  }
3974
4011
 
3975
4012
  if (document.addEventListener) {
@@ -4183,4 +4220,4 @@ Object.extend(Element.ClassNames.prototype, Enumerable);
4183
4220
 
4184
4221
  /*--------------------------------------------------------------------------*/
4185
4222
 
4186
- Element.addMethods();
4223
+ Element.addMethods();