nitro 0.29.0 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG +410 -0
  2. data/ProjectInfo +36 -44
  3. data/README +5 -5
  4. data/doc/AUTHORS +6 -0
  5. data/doc/RELEASES +159 -2
  6. data/lib/glue/sweeper.rb +2 -2
  7. data/lib/glue/webfile.rb +14 -1
  8. data/lib/nitro.rb +6 -9
  9. data/lib/nitro/adapter/mongrel.rb +36 -43
  10. data/lib/nitro/adapter/scgi.rb +1 -1
  11. data/lib/nitro/adapter/webrick.rb +96 -24
  12. data/lib/nitro/caching/actions.rb +2 -1
  13. data/lib/nitro/caching/fragments.rb +1 -8
  14. data/lib/nitro/caching/output.rb +14 -4
  15. data/lib/nitro/cgi.rb +19 -21
  16. data/lib/nitro/cgi/cookie.rb +5 -1
  17. data/lib/nitro/cgi/request.rb +20 -4
  18. data/lib/nitro/compiler.rb +74 -28
  19. data/lib/nitro/compiler/cleanup.rb +1 -1
  20. data/lib/nitro/compiler/elements.rb +1 -2
  21. data/lib/nitro/compiler/localization.rb +1 -1
  22. data/lib/nitro/compiler/markup.rb +1 -1
  23. data/lib/nitro/compiler/script.rb +52 -44
  24. data/lib/nitro/compiler/squeeze.rb +4 -3
  25. data/lib/nitro/compiler/xslt.rb +7 -6
  26. data/lib/nitro/context.rb +39 -20
  27. data/lib/nitro/controller.rb +24 -5
  28. data/lib/nitro/dispatcher.rb +13 -5
  29. data/lib/nitro/global.rb +63 -0
  30. data/lib/nitro/helper/feed.rb +432 -0
  31. data/lib/nitro/helper/form.rb +11 -3
  32. data/lib/nitro/helper/form/builder.rb +140 -0
  33. data/lib/nitro/helper/form/controls.rb +2 -1
  34. data/lib/nitro/helper/javascript.rb +6 -0
  35. data/lib/nitro/helper/javascript/morphing.rb +13 -6
  36. data/lib/nitro/helper/xhtml.rb +42 -6
  37. data/lib/nitro/helper/xml.rb +3 -0
  38. data/lib/nitro/part.rb +2 -2
  39. data/lib/nitro/render.rb +7 -2
  40. data/lib/nitro/router.rb +57 -16
  41. data/lib/nitro/scaffolding.rb +29 -20
  42. data/lib/nitro/server.rb +4 -10
  43. data/lib/nitro/server/drb.rb +1 -1
  44. data/lib/nitro/server/runner.rb +10 -0
  45. data/lib/nitro/session.rb +31 -12
  46. data/lib/nitro/session/drb.rb +13 -1
  47. data/lib/nitro/session/file.rb +1 -1
  48. data/lib/nitro/session/memcached.rb +1 -1
  49. data/lib/nitro/session/memory.rb +1 -1
  50. data/lib/nitro/session/og.rb +1 -1
  51. data/lib/nitro/test/testcase.rb +3 -0
  52. data/proto/public/error.xhtml +5 -5
  53. data/proto/public/js/controls.js +2 -2
  54. data/proto/public/js/dragdrop.js +320 -79
  55. data/proto/public/js/effects.js +200 -152
  56. data/proto/public/js/prototype.js +284 -63
  57. data/proto/public/js/scriptaculous.js +7 -5
  58. data/proto/public/js/unittest.js +11 -0
  59. data/proto/public/scaffold/advanced_search.xhtml +30 -0
  60. data/proto/public/scaffold/list.xhtml +8 -1
  61. data/proto/public/scaffold/search.xhtml +2 -1
  62. data/proto/script/scgi_service +1 -1
  63. data/src/part/admin/controller.rb +1 -1
  64. data/src/part/admin/skin.rb +1 -1
  65. data/test/nitro/CONFIG.rb +3 -0
  66. data/test/nitro/adapter/tc_webrick.rb +1 -1
  67. data/test/nitro/cgi/tc_cookie.rb +1 -1
  68. data/test/nitro/cgi/tc_request.rb +5 -5
  69. data/test/nitro/compiler/tc_client_morpher.rb +47 -0
  70. data/test/nitro/compiler/tc_compiler.rb +2 -0
  71. data/test/nitro/helper/tc_feed.rb +138 -0
  72. data/test/nitro/helper/tc_pager.rb +1 -1
  73. data/test/nitro/helper/tc_rss.rb +1 -1
  74. data/test/nitro/helper/tc_table.rb +1 -1
  75. data/test/nitro/helper/tc_xhtml.rb +1 -1
  76. data/test/nitro/tc_caching.rb +1 -1
  77. data/test/nitro/tc_cgi.rb +1 -1
  78. data/test/nitro/tc_context.rb +1 -1
  79. data/test/nitro/tc_controller.rb +31 -3
  80. data/test/nitro/tc_controller_aspect.rb +1 -1
  81. data/test/nitro/tc_dispatcher.rb +1 -1
  82. data/test/nitro/tc_element.rb +1 -1
  83. data/test/nitro/tc_flash.rb +1 -1
  84. data/test/nitro/tc_helper.rb +1 -1
  85. data/test/nitro/tc_render.rb +6 -6
  86. data/test/nitro/tc_router.rb +8 -4
  87. data/test/nitro/tc_server.rb +1 -3
  88. data/test/nitro/tc_session.rb +1 -3
  89. metadata +107 -104
  90. data/Rakefile +0 -232
  91. data/lib/nitro/adapter/acgi.rb +0 -237
  92. data/proto/public/Makefile.acgi +0 -40
  93. data/proto/public/acgi.c +0 -138
@@ -1,17 +1,13 @@
1
- /* Prototype JavaScript framework, version 1.4.0
1
+ /* Prototype JavaScript framework, version 1.5.0_rc0
2
2
  * (c) 2005 Sam Stephenson <sam@conio.net>
3
3
  *
4
- * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
5
- * against the source tree, available from the Prototype darcs repository.
6
- *
7
4
  * Prototype is freely distributable under the terms of an MIT-style license.
8
- *
9
5
  * For details, see the Prototype web site: http://prototype.conio.net/
10
6
  *
11
7
  /*--------------------------------------------------------------------------*/
12
8
 
13
9
  var Prototype = {
14
- Version: '1.4.0',
10
+ Version: '1.5.0_rc0',
15
11
  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
16
12
 
17
13
  emptyFunction: function() {},
@@ -29,7 +25,7 @@ var Class = {
29
25
  var Abstract = new Object();
30
26
 
31
27
  Object.extend = function(destination, source) {
32
- for (property in source) {
28
+ for (var property in source) {
33
29
  destination[property] = source[property];
34
30
  }
35
31
  return destination;
@@ -120,26 +116,49 @@ PeriodicalExecuter.prototype = {
120
116
  }
121
117
  }
122
118
  }
119
+ Object.extend(String.prototype, {
120
+ gsub: function(pattern, replacement) {
121
+ var result = '', source = this, match;
122
+ replacement = arguments.callee.prepareReplacement(replacement);
123
+
124
+ while (source.length > 0) {
125
+ if (match = source.match(pattern)) {
126
+ result += source.slice(0, match.index);
127
+ result += (replacement(match) || '').toString();
128
+ source = source.slice(match.index + match[0].length);
129
+ } else {
130
+ result += source, source = '';
131
+ }
132
+ }
133
+ return result;
134
+ },
123
135
 
124
- /*--------------------------------------------------------------------------*/
136
+ sub: function(pattern, replacement, count) {
137
+ replacement = this.gsub.prepareReplacement(replacement);
138
+ count = count === undefined ? 1 : count;
125
139
 
126
- function $() {
127
- var elements = new Array();
140
+ return this.gsub(pattern, function(match) {
141
+ if (--count < 0) return match[0];
142
+ return replacement(match);
143
+ });
144
+ },
128
145
 
129
- for (var i = 0; i < arguments.length; i++) {
130
- var element = arguments[i];
131
- if (typeof element == 'string')
132
- element = document.getElementById(element);
146
+ scan: function(pattern, iterator) {
147
+ this.gsub(pattern, iterator);
148
+ return this;
149
+ },
133
150
 
134
- if (arguments.length == 1)
135
- return element;
151
+ truncate: function(length, truncation) {
152
+ length = length || 30;
153
+ truncation = truncation === undefined ? '...' : truncation;
154
+ return this.length > length ?
155
+ this.slice(0, length - truncation.length) + truncation : this;
156
+ },
136
157
 
137
- elements.push(element);
138
- }
158
+ strip: function() {
159
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
160
+ },
139
161
 
140
- return elements;
141
- }
142
- Object.extend(String.prototype, {
143
162
  stripTags: function() {
144
163
  return this.replace(/<\/?[^>]+>/gi, '');
145
164
  },
@@ -157,7 +176,7 @@ Object.extend(String.prototype, {
157
176
  },
158
177
 
159
178
  evalScripts: function() {
160
- return this.extractScripts().map(eval);
179
+ return this.extractScripts().map(function(script) { return eval(script) });
161
180
  },
162
181
 
163
182
  escapeHTML: function() {
@@ -203,12 +222,35 @@ Object.extend(String.prototype, {
203
222
  },
204
223
 
205
224
  inspect: function() {
206
- return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
225
+ return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
207
226
  }
208
227
  });
209
228
 
229
+ String.prototype.gsub.prepareReplacement = function(replacement) {
230
+ if (typeof replacement == 'function') return replacement;
231
+ var template = new Template(replacement);
232
+ return function(match) { return template.evaluate(match) };
233
+ }
234
+
210
235
  String.prototype.parseQuery = String.prototype.toQueryParams;
211
236
 
237
+ var Template = Class.create();
238
+ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
239
+ Template.prototype = {
240
+ initialize: function(template, pattern) {
241
+ this.template = template.toString();
242
+ this.pattern = pattern || Template.Pattern;
243
+ },
244
+
245
+ evaluate: function(object) {
246
+ return this.template.gsub(this.pattern, function(match) {
247
+ var before = match[1];
248
+ if (before == '\\') return match[2];
249
+ return before + (object[match[3]] || '').toString();
250
+ });
251
+ }
252
+ }
253
+
212
254
  var $break = new Object();
213
255
  var $continue = new Object();
214
256
 
@@ -313,7 +355,7 @@ var Enumerable = {
313
355
  var result;
314
356
  this.each(function(value, index) {
315
357
  value = (iterator || Prototype.K)(value, index);
316
- if (value >= (result || value))
358
+ if (result == undefined || value >= result)
317
359
  result = value;
318
360
  });
319
361
  return result;
@@ -323,7 +365,7 @@ var Enumerable = {
323
365
  var result;
324
366
  this.each(function(value, index) {
325
367
  value = (iterator || Prototype.K)(value, index);
326
- if (value <= (result || value))
368
+ if (result == undefined || value < result)
327
369
  result = value;
328
370
  });
329
371
  return result;
@@ -375,8 +417,7 @@ var Enumerable = {
375
417
 
376
418
  var collections = [this].concat(args).map($A);
377
419
  return this.map(function(value, index) {
378
- iterator(value = collections.pluck(index));
379
- return value;
420
+ return iterator(collections.pluck(index));
380
421
  });
381
422
  },
382
423
 
@@ -406,7 +447,8 @@ var $A = Array.from = function(iterable) {
406
447
 
407
448
  Object.extend(Array.prototype, Enumerable);
408
449
 
409
- Array.prototype._reverse = Array.prototype.reverse;
450
+ if (!Array.prototype._reverse)
451
+ Array.prototype._reverse = Array.prototype.reverse;
410
452
 
411
453
  Object.extend(Array.prototype, {
412
454
  _each: function(iterator) {
@@ -435,7 +477,7 @@ Object.extend(Array.prototype, {
435
477
 
436
478
  flatten: function() {
437
479
  return this.inject([], function(array, value) {
438
- return array.concat(value.constructor == Array ?
480
+ return array.concat(value && value.constructor == Array ?
439
481
  value.flatten() : [value]);
440
482
  });
441
483
  },
@@ -457,21 +499,13 @@ Object.extend(Array.prototype, {
457
499
  return (inline !== false ? this : this.toArray())._reverse();
458
500
  },
459
501
 
460
- shift: function() {
461
- var result = this[0];
462
- for (var i = 0; i < this.length - 1; i++)
463
- this[i] = this[i + 1];
464
- this.length--;
465
- return result;
466
- },
467
-
468
502
  inspect: function() {
469
503
  return '[' + this.map(Object.inspect).join(', ') + ']';
470
504
  }
471
505
  });
472
506
  var Hash = {
473
507
  _each: function(iterator) {
474
- for (key in this) {
508
+ for (var key in this) {
475
509
  var value = this[key];
476
510
  if (typeof value == 'function') continue;
477
511
 
@@ -549,9 +583,9 @@ var $R = function(start, end, exclusive) {
549
583
  var Ajax = {
550
584
  getTransport: function() {
551
585
  return Try.these(
586
+ function() {return new XMLHttpRequest()},
552
587
  function() {return new ActiveXObject('Msxml2.XMLHTTP')},
553
- function() {return new ActiveXObject('Microsoft.XMLHTTP')},
554
- function() {return new XMLHttpRequest()}
588
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
555
589
  ) || false;
556
590
  },
557
591
 
@@ -603,6 +637,7 @@ Ajax.Base.prototype = {
603
637
  this.options = {
604
638
  method: 'post',
605
639
  asynchronous: true,
640
+ contentType: 'application/x-www-form-urlencoded',
606
641
  parameters: ''
607
642
  }
608
643
  Object.extend(this.options, options || {});
@@ -662,11 +697,11 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
662
697
  setRequestHeaders: function() {
663
698
  var requestHeaders =
664
699
  ['X-Requested-With', 'XMLHttpRequest',
665
- 'X-Prototype-Version', Prototype.Version];
700
+ 'X-Prototype-Version', Prototype.Version,
701
+ 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
666
702
 
667
703
  if (this.options.method == 'post') {
668
- requestHeaders.push('Content-type',
669
- 'application/x-www-form-urlencoded');
704
+ requestHeaders.push('Content-type', this.options.contentType);
670
705
 
671
706
  /* Force "Connection: close" for Mozilla browsers to work around
672
707
  * a bug where XMLHttpReqeuest sends an incorrect Content-length
@@ -697,7 +732,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
697
732
 
698
733
  evalJSON: function() {
699
734
  try {
700
- return eval(this.header('X-JSON'));
735
+ return eval('(' + this.header('X-JSON') + ')');
701
736
  } catch (e) {}
702
737
  },
703
738
 
@@ -831,22 +866,57 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
831
866
  this.updater = new Ajax.Updater(this.container, this.url, this.options);
832
867
  }
833
868
  });
869
+ function $() {
870
+ var results = [], element;
871
+ for (var i = 0; i < arguments.length; i++) {
872
+ element = arguments[i];
873
+ if (typeof element == 'string')
874
+ element = document.getElementById(element);
875
+ results.push(Element.extend(element));
876
+ }
877
+ return results.length < 2 ? results[0] : results;
878
+ }
879
+
834
880
  document.getElementsByClassName = function(className, parentElement) {
835
881
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
836
882
  return $A(children).inject([], function(elements, child) {
837
883
  if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
838
- elements.push(child);
884
+ elements.push(Element.extend(child));
839
885
  return elements;
840
886
  });
841
887
  }
842
888
 
843
889
  /*--------------------------------------------------------------------------*/
844
890
 
845
- if (!window.Element) {
891
+ if (!window.Element)
846
892
  var Element = new Object();
893
+
894
+ Element.extend = function(element) {
895
+ if (!element) return;
896
+ if (_nativeExtensions) return element;
897
+
898
+ if (!element._extended && element.tagName && element != window) {
899
+ var methods = Element.Methods, cache = Element.extend.cache;
900
+ for (property in methods) {
901
+ var value = methods[property];
902
+ if (typeof value == 'function')
903
+ element[property] = cache.findOrStore(value);
904
+ }
905
+ }
906
+
907
+ element._extended = true;
908
+ return element;
847
909
  }
848
910
 
849
- Object.extend(Element, {
911
+ Element.extend.cache = {
912
+ findOrStore: function(value) {
913
+ return this[value] = this[value] || function() {
914
+ return value.apply(null, [this].concat($A(arguments)));
915
+ }
916
+ }
917
+ }
918
+
919
+ Element.Methods = {
850
920
  visible: function(element) {
851
921
  return $(element).style.display != 'none';
852
922
  },
@@ -882,6 +952,19 @@ Object.extend(Element, {
882
952
  setTimeout(function() {html.evalScripts()}, 10);
883
953
  },
884
954
 
955
+ replace: function(element, html) {
956
+ element = $(element);
957
+ if (element.outerHTML) {
958
+ element.outerHTML = html.stripScripts();
959
+ } else {
960
+ var range = element.ownerDocument.createRange();
961
+ range.selectNodeContents(element);
962
+ element.parentNode.replaceChild(
963
+ range.createContextualFragment(html.stripScripts()), element);
964
+ }
965
+ setTimeout(function() {html.evalScripts()}, 10);
966
+ },
967
+
885
968
  getHeight: function(element) {
886
969
  element = $(element);
887
970
  return element.offsetHeight;
@@ -920,6 +1003,13 @@ Object.extend(Element, {
920
1003
  return $(element).innerHTML.match(/^\s*$/);
921
1004
  },
922
1005
 
1006
+ childOf: function(element, ancestor) {
1007
+ element = $(element), ancestor = $(ancestor);
1008
+ while (element = element.parentNode)
1009
+ if (element == ancestor) return true;
1010
+ return false;
1011
+ },
1012
+
923
1013
  scrollTo: function(element) {
924
1014
  element = $(element);
925
1015
  var x = element.x ? element.x : element.offsetLeft,
@@ -947,7 +1037,7 @@ Object.extend(Element, {
947
1037
 
948
1038
  setStyle: function(element, style) {
949
1039
  element = $(element);
950
- for (name in style)
1040
+ for (var name in style)
951
1041
  element.style[name.camelize()] = style[name];
952
1042
  },
953
1043
 
@@ -1013,7 +1103,32 @@ Object.extend(Element, {
1013
1103
  element.style.overflow = element._overflow;
1014
1104
  element._overflow = undefined;
1015
1105
  }
1016
- });
1106
+ }
1107
+
1108
+ Object.extend(Element, Element.Methods);
1109
+
1110
+ var _nativeExtensions = false;
1111
+
1112
+ if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1113
+ var HTMLElement = {}
1114
+ HTMLElement.prototype = document.createElement('div').__proto__;
1115
+ }
1116
+
1117
+ Element.addMethods = function(methods) {
1118
+ Object.extend(Element.Methods, methods || {});
1119
+
1120
+ if(typeof HTMLElement != 'undefined') {
1121
+ var methods = Element.Methods, cache = Element.extend.cache;
1122
+ for (property in methods) {
1123
+ var value = methods[property];
1124
+ if (typeof value == 'function')
1125
+ HTMLElement.prototype[property] = cache.findOrStore(value);
1126
+ }
1127
+ _nativeExtensions = true;
1128
+ }
1129
+ }
1130
+
1131
+ Element.addMethods();
1017
1132
 
1018
1133
  var Toggle = new Object();
1019
1134
  Toggle.display = Element.toggle;
@@ -1033,7 +1148,8 @@ Abstract.Insertion.prototype = {
1033
1148
  try {
1034
1149
  this.element.insertAdjacentHTML(this.adjacency, this.content);
1035
1150
  } catch (e) {
1036
- if (this.element.tagName.toLowerCase() == 'tbody') {
1151
+ var tagName = this.element.tagName.toLowerCase();
1152
+ if (tagName == 'tbody' || tagName == 'tr') {
1037
1153
  this.insertContent(this.contentFromAnonymousTable());
1038
1154
  } else {
1039
1155
  throw e;
@@ -1148,6 +1264,116 @@ Element.ClassNames.prototype = {
1148
1264
  }
1149
1265
 
1150
1266
  Object.extend(Element.ClassNames.prototype, Enumerable);
1267
+ var Selector = Class.create();
1268
+ Selector.prototype = {
1269
+ initialize: function(expression) {
1270
+ this.params = {classNames: []};
1271
+ this.expression = expression.toString().strip();
1272
+ this.parseExpression();
1273
+ this.compileMatcher();
1274
+ },
1275
+
1276
+ parseExpression: function() {
1277
+ function abort(message) { throw 'Parse error in selector: ' + message; }
1278
+
1279
+ if (this.expression == '') abort('empty expression');
1280
+
1281
+ var params = this.params, expr = this.expression, match, modifier, clause, rest;
1282
+ while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
1283
+ params.attributes = params.attributes || [];
1284
+ params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
1285
+ expr = match[1];
1286
+ }
1287
+
1288
+ if (expr == '*') return this.params.wildcard = true;
1289
+
1290
+ while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
1291
+ modifier = match[1], clause = match[2], rest = match[3];
1292
+ switch (modifier) {
1293
+ case '#': params.id = clause; break;
1294
+ case '.': params.classNames.push(clause); break;
1295
+ case '':
1296
+ case undefined: params.tagName = clause.toUpperCase(); break;
1297
+ default: abort(expr.inspect());
1298
+ }
1299
+ expr = rest;
1300
+ }
1301
+
1302
+ if (expr.length > 0) abort(expr.inspect());
1303
+ },
1304
+
1305
+ buildMatchExpression: function() {
1306
+ var params = this.params, conditions = [], clause;
1307
+
1308
+ if (params.wildcard)
1309
+ conditions.push('true');
1310
+ if (clause = params.id)
1311
+ conditions.push('element.id == ' + clause.inspect());
1312
+ if (clause = params.tagName)
1313
+ conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
1314
+ if ((clause = params.classNames).length > 0)
1315
+ for (var i = 0; i < clause.length; i++)
1316
+ conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
1317
+ if (clause = params.attributes) {
1318
+ clause.each(function(attribute) {
1319
+ var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
1320
+ var splitValueBy = function(delimiter) {
1321
+ return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
1322
+ }
1323
+
1324
+ switch (attribute.operator) {
1325
+ case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
1326
+ case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
1327
+ case '|=': conditions.push(
1328
+ splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
1329
+ ); break;
1330
+ case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
1331
+ case '':
1332
+ case undefined: conditions.push(value + ' != null'); break;
1333
+ default: throw 'Unknown operator ' + attribute.operator + ' in selector';
1334
+ }
1335
+ });
1336
+ }
1337
+
1338
+ return conditions.join(' && ');
1339
+ },
1340
+
1341
+ compileMatcher: function() {
1342
+ this.match = new Function('element', 'if (!element.tagName) return false; \
1343
+ return ' + this.buildMatchExpression());
1344
+ },
1345
+
1346
+ findElements: function(scope) {
1347
+ var element;
1348
+
1349
+ if (element = $(this.params.id))
1350
+ if (this.match(element))
1351
+ if (!scope || Element.childOf(element, scope))
1352
+ return [element];
1353
+
1354
+ scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
1355
+
1356
+ var results = [];
1357
+ for (var i = 0; i < scope.length; i++)
1358
+ if (this.match(element = scope[i]))
1359
+ results.push(Element.extend(element));
1360
+
1361
+ return results;
1362
+ },
1363
+
1364
+ toString: function() {
1365
+ return this.expression;
1366
+ }
1367
+ }
1368
+
1369
+ function $$() {
1370
+ return $A(arguments).map(function(expression) {
1371
+ return expression.strip().split(/\s+/).inject([null], function(results, expr) {
1372
+ var selector = new Selector(expr);
1373
+ return results.map(selector.findElements.bind(selector)).flatten();
1374
+ });
1375
+ }).flatten();
1376
+ }
1151
1377
  var Field = {
1152
1378
  clear: function() {
1153
1379
  for (var i = 0; i < arguments.length; i++)
@@ -1196,7 +1422,7 @@ var Form = {
1196
1422
  form = $(form);
1197
1423
  var elements = new Array();
1198
1424
 
1199
- for (tagName in Form.Element.Serializers) {
1425
+ for (var tagName in Form.Element.Serializers) {
1200
1426
  var tagElements = form.getElementsByTagName(tagName);
1201
1427
  for (var j = 0; j < tagElements.length; j++)
1202
1428
  elements.push(tagElements[j]);
@@ -1318,23 +1544,17 @@ Form.Element.Serializers = {
1318
1544
  var value = '', opt, index = element.selectedIndex;
1319
1545
  if (index >= 0) {
1320
1546
  opt = element.options[index];
1321
- value = opt.value;
1322
- if (!value && !('value' in opt))
1323
- value = opt.text;
1547
+ value = opt.value || opt.text;
1324
1548
  }
1325
1549
  return [element.name, value];
1326
1550
  },
1327
1551
 
1328
1552
  selectMany: function(element) {
1329
- var value = new Array();
1553
+ var value = [];
1330
1554
  for (var i = 0; i < element.length; i++) {
1331
1555
  var opt = element.options[i];
1332
- if (opt.selected) {
1333
- var optValue = opt.value;
1334
- if (!optValue && !('value' in opt))
1335
- optValue = opt.text;
1336
- value.push(optValue);
1337
- }
1556
+ if (opt.selected)
1557
+ value.push(opt.value || opt.text);
1338
1558
  }
1339
1559
  return [element.name, value];
1340
1560
  }
@@ -1551,7 +1771,8 @@ Object.extend(Event, {
1551
1771
  });
1552
1772
 
1553
1773
  /* prevent memory leaks in IE */
1554
- Event.observe(window, 'unload', Event.unloadCache, false);
1774
+ if (navigator.appVersion.match(/\bMSIE\b/))
1775
+ Event.observe(window, 'unload', Event.unloadCache, false);
1555
1776
  var Position = {
1556
1777
  // set to true if needed, warning: firefox performance problems
1557
1778
  // NOT neeeded for page scrolling, only if draggable contained in
@@ -1782,4 +2003,4 @@ if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1782
2003
 
1783
2004
  return [valueL, valueT];
1784
2005
  }
1785
- }
2006
+ }