parlement 0.10 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/CHANGES +11 -0
  2. data/MEMORY +9 -1
  3. data/README +5 -4
  4. data/app/controllers/account_controller.rb +10 -13
  5. data/app/controllers/application.rb +4 -5
  6. data/app/controllers/elt_controller.rb +9 -7
  7. data/app/controllers/person_controller.rb +1 -3
  8. data/app/controllers/subscriber_controller.rb +10 -10
  9. data/app/helpers/elt_helper.rb +2 -0
  10. data/app/models/elt.rb +28 -19
  11. data/app/models/mail.rb +26 -14
  12. data/app/models/mail_notify.rb +5 -4
  13. data/app/models/person.rb +11 -2
  14. data/app/views/account/_login.rhtml +3 -3
  15. data/app/views/account/_show.rhtml +12 -14
  16. data/app/views/elt/_choice.rhtml +3 -3
  17. data/app/views/elt/_elt.rhtml +4 -4
  18. data/app/views/elt/_list.rhtml +2 -2
  19. data/app/views/elt/_listByDate.rhtml +1 -1
  20. data/app/views/elt/_listByVote.rhtml +1 -1
  21. data/app/views/elt/new.rhtml +3 -3
  22. data/app/views/elt/show.rhtml +2 -2
  23. data/app/views/layouts/top.rhtml +6 -0
  24. data/app/views/mail_notify/publish.text.html.rhtml +1 -1
  25. data/app/views/person/_listElts.rhtml +5 -3
  26. data/app/views/person/show.rhtml +1 -2
  27. data/config/boot.rb +5 -4
  28. data/config/environment.rb +6 -4
  29. data/config/routes.rb +3 -2
  30. data/db/development_structure.sql +15 -4
  31. data/db/migrate/006_last_activity.rb +10 -0
  32. data/db/schema.rb +67 -49
  33. data/public/dispatch.fcgi +1 -0
  34. data/public/javascripts/controls.js +41 -23
  35. data/public/javascripts/dragdrop.js +317 -99
  36. data/public/javascripts/effects.js +301 -166
  37. data/public/javascripts/prototype.js +932 -402
  38. data/public/stylesheets/default.css +3 -2
  39. data/test/unit/elt_test.rb +13 -0
  40. data/test/unit/mail_test.rb +3 -1
  41. data/vendor/plugins/engines/CHANGELOG +203 -99
  42. data/vendor/plugins/engines/MIT-LICENSE +1 -1
  43. data/vendor/plugins/engines/README +32 -384
  44. data/vendor/plugins/engines/Rakefile +14 -0
  45. data/vendor/plugins/engines/UPGRADING +93 -0
  46. data/vendor/plugins/engines/about.yml +7 -0
  47. data/vendor/plugins/engines/generators/plugin_migration/USAGE +45 -0
  48. data/vendor/plugins/engines/generators/plugin_migration/plugin_migration_generator.rb +79 -0
  49. data/vendor/plugins/engines/generators/plugin_migration/templates/plugin_migration.erb +13 -0
  50. data/vendor/plugins/engines/init.rb +34 -47
  51. data/vendor/plugins/engines/install.rb +32 -0
  52. data/vendor/plugins/engines/lib/engines/{ruby_extensions.rb → deprecated_config_support.rb} +135 -113
  53. data/vendor/plugins/engines/lib/engines/plugin.rb +214 -0
  54. data/vendor/plugins/engines/lib/engines/plugin_list.rb +31 -0
  55. data/vendor/plugins/engines/lib/engines/plugin_migrator.rb +60 -0
  56. data/vendor/plugins/engines/lib/engines/rails_extensions/active_record.rb +19 -0
  57. data/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb +143 -0
  58. data/vendor/plugins/engines/lib/engines/rails_extensions/migrations.rb +155 -0
  59. data/vendor/plugins/engines/lib/engines/rails_extensions/public_asset_helpers.rb +116 -0
  60. data/vendor/plugins/engines/lib/engines/rails_extensions/rails.rb +20 -0
  61. data/vendor/plugins/engines/lib/engines/rails_extensions/rails_initializer.rb +86 -0
  62. data/vendor/plugins/engines/lib/engines/rails_extensions/routing.rb +77 -0
  63. data/vendor/plugins/engines/lib/engines/rails_extensions/templates.rb +140 -0
  64. data/vendor/plugins/engines/lib/engines/rails_extensions.rb +6 -0
  65. data/vendor/plugins/engines/lib/engines/testing.rb +88 -0
  66. data/vendor/plugins/engines/lib/engines.rb +281 -425
  67. data/vendor/plugins/engines/tasks/engines.rake +108 -137
  68. metadata +218 -250
  69. data/db/ROOT/perso.txt +0 -214
  70. data/public/images/indicator.gif +0 -0
  71. data/public/images/orange_by_darren_Hester_350o.jpg +0 -0
  72. data/public/images/smile.png +0 -0
  73. data/vendor/plugins/engines/generators/engine/USAGE +0 -26
  74. data/vendor/plugins/engines/generators/engine/engine_generator.rb +0 -199
  75. data/vendor/plugins/engines/generators/engine/templates/README +0 -85
  76. data/vendor/plugins/engines/generators/engine/templates/init_engine.erb +0 -15
  77. data/vendor/plugins/engines/generators/engine/templates/install.erb +0 -4
  78. data/vendor/plugins/engines/generators/engine/templates/lib/engine.erb +0 -6
  79. data/vendor/plugins/engines/generators/engine/templates/licenses/GPL +0 -18
  80. data/vendor/plugins/engines/generators/engine/templates/licenses/LGPL +0 -19
  81. data/vendor/plugins/engines/generators/engine/templates/licenses/MIT +0 -22
  82. data/vendor/plugins/engines/generators/engine/templates/licenses/None +0 -1
  83. data/vendor/plugins/engines/generators/engine/templates/public/javascripts/engine.js +0 -0
  84. data/vendor/plugins/engines/generators/engine/templates/public/stylesheets/engine.css +0 -0
  85. data/vendor/plugins/engines/generators/engine/templates/tasks/engine.rake +0 -0
  86. data/vendor/plugins/engines/generators/engine/templates/test/test_helper.erb +0 -17
  87. data/vendor/plugins/engines/lib/bundles/require_resource.rb +0 -124
  88. data/vendor/plugins/engines/lib/bundles.rb +0 -77
  89. data/vendor/plugins/engines/lib/engines/action_mailer_extensions.rb +0 -140
  90. data/vendor/plugins/engines/lib/engines/action_view_extensions.rb +0 -141
  91. data/vendor/plugins/engines/lib/engines/active_record_extensions.rb +0 -21
  92. data/vendor/plugins/engines/lib/engines/dependencies_extensions.rb +0 -129
  93. data/vendor/plugins/engines/lib/engines/migration_extensions.rb +0 -53
  94. data/vendor/plugins/engines/lib/engines/routing_extensions.rb +0 -28
  95. data/vendor/plugins/engines/lib/engines/testing_extensions.rb +0 -327
  96. data/vendor/plugins/engines/tasks/deprecated_engines.rake +0 -7
  97. data/vendor/plugins/engines/test/action_view_extensions_test.rb +0 -9
  98. data/vendor/plugins/engines/test/ruby_extensions_test.rb +0 -115
  99. data/vendor/plugins/guid/README.TXT +0 -29
  100. data/vendor/plugins/guid/init.rb +0 -30
  101. data/vendor/plugins/guid/lib/usesguid.rb +0 -37
  102. data/vendor/plugins/guid/lib/uuid22.rb +0 -43
  103. data/vendor/plugins/guid/lib/uuidtools.rb +0 -572
  104. data/vendor/plugins/responds_to_parent/MIT-LICENSE +0 -20
  105. data/vendor/plugins/responds_to_parent/README +0 -42
  106. data/vendor/plugins/responds_to_parent/Rakefile +0 -22
  107. data/vendor/plugins/responds_to_parent/init.rb +0 -1
  108. data/vendor/plugins/responds_to_parent/lib/responds_to_parent.rb +0 -46
  109. data/vendor/plugins/responds_to_parent/test/responds_to_parent_test.rb +0 -115
@@ -1,5 +1,5 @@
1
- /* Prototype JavaScript framework, version 1.5.0_pre1
2
- * (c) 2005 Sam Stephenson <sam@conio.net>
1
+ /* Prototype JavaScript framework, version 1.5.0
2
+ * (c) 2005-2007 Sam Stephenson
3
3
  *
4
4
  * Prototype is freely distributable under the terms of an MIT-style license.
5
5
  * For details, see the Prototype web site: http://prototype.conio.net/
@@ -7,11 +7,14 @@
7
7
  /*--------------------------------------------------------------------------*/
8
8
 
9
9
  var Prototype = {
10
- Version: '1.5.0_pre1',
11
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
10
+ Version: '1.5.0',
11
+ BrowserFeatures: {
12
+ XPath: !!document.evaluate
13
+ },
12
14
 
15
+ ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
13
16
  emptyFunction: function() {},
14
- K: function(x) {return x}
17
+ K: function(x) { return x }
15
18
  }
16
19
 
17
20
  var Class = {
@@ -25,22 +28,42 @@ var Class = {
25
28
  var Abstract = new Object();
26
29
 
27
30
  Object.extend = function(destination, source) {
28
- for (property in source) {
31
+ for (var property in source) {
29
32
  destination[property] = source[property];
30
33
  }
31
34
  return destination;
32
35
  }
33
36
 
34
- Object.inspect = function(object) {
35
- try {
36
- if (object == undefined) return 'undefined';
37
- if (object == null) return 'null';
38
- return object.inspect ? object.inspect() : object.toString();
39
- } catch (e) {
40
- if (e instanceof RangeError) return '...';
41
- throw e;
37
+ Object.extend(Object, {
38
+ inspect: function(object) {
39
+ try {
40
+ if (object === undefined) return 'undefined';
41
+ if (object === null) return 'null';
42
+ return object.inspect ? object.inspect() : object.toString();
43
+ } catch (e) {
44
+ if (e instanceof RangeError) return '...';
45
+ throw e;
46
+ }
47
+ },
48
+
49
+ keys: function(object) {
50
+ var keys = [];
51
+ for (var property in object)
52
+ keys.push(property);
53
+ return keys;
54
+ },
55
+
56
+ values: function(object) {
57
+ var values = [];
58
+ for (var property in object)
59
+ values.push(object[property]);
60
+ return values;
61
+ },
62
+
63
+ clone: function(object) {
64
+ return Object.extend({}, object);
42
65
  }
43
- }
66
+ });
44
67
 
45
68
  Function.prototype.bind = function() {
46
69
  var __method = this, args = $A(arguments), object = args.shift();
@@ -50,9 +73,9 @@ Function.prototype.bind = function() {
50
73
  }
51
74
 
52
75
  Function.prototype.bindAsEventListener = function(object) {
53
- var __method = this;
76
+ var __method = this, args = $A(arguments), object = args.shift();
54
77
  return function(event) {
55
- return __method.call(object, event || window.event);
78
+ return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
56
79
  }
57
80
  }
58
81
 
@@ -77,7 +100,7 @@ var Try = {
77
100
  these: function() {
78
101
  var returnValue;
79
102
 
80
- for (var i = 0; i < arguments.length; i++) {
103
+ for (var i = 0, length = arguments.length; i < length; i++) {
81
104
  var lambda = arguments[i];
82
105
  try {
83
106
  returnValue = lambda();
@@ -102,20 +125,30 @@ PeriodicalExecuter.prototype = {
102
125
  },
103
126
 
104
127
  registerCallback: function() {
105
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
128
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
129
+ },
130
+
131
+ stop: function() {
132
+ if (!this.timer) return;
133
+ clearInterval(this.timer);
134
+ this.timer = null;
106
135
  },
107
136
 
108
137
  onTimerEvent: function() {
109
138
  if (!this.currentlyExecuting) {
110
139
  try {
111
140
  this.currentlyExecuting = true;
112
- this.callback();
141
+ this.callback(this);
113
142
  } finally {
114
143
  this.currentlyExecuting = false;
115
144
  }
116
145
  }
117
146
  }
118
147
  }
148
+ String.interpret = function(value){
149
+ return value == null ? '' : String(value);
150
+ }
151
+
119
152
  Object.extend(String.prototype, {
120
153
  gsub: function(pattern, replacement) {
121
154
  var result = '', source = this, match;
@@ -124,7 +157,7 @@ Object.extend(String.prototype, {
124
157
  while (source.length > 0) {
125
158
  if (match = source.match(pattern)) {
126
159
  result += source.slice(0, match.index);
127
- result += (replacement(match) || '').toString();
160
+ result += String.interpret(replacement(match));
128
161
  source = source.slice(match.index + match[0].length);
129
162
  } else {
130
163
  result += source, source = '';
@@ -176,7 +209,7 @@ Object.extend(String.prototype, {
176
209
  },
177
210
 
178
211
  evalScripts: function() {
179
- return this.extractScripts().map(eval);
212
+ return this.extractScripts().map(function(script) { return eval(script) });
180
213
  },
181
214
 
182
215
  escapeHTML: function() {
@@ -189,15 +222,28 @@ Object.extend(String.prototype, {
189
222
  unescapeHTML: function() {
190
223
  var div = document.createElement('div');
191
224
  div.innerHTML = this.stripTags();
192
- return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
225
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
226
+ $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
227
+ div.childNodes[0].nodeValue) : '';
193
228
  },
194
229
 
195
- toQueryParams: function() {
196
- var pairs = this.match(/^\??(.*)$/)[1].split('&');
197
- return pairs.inject({}, function(params, pairString) {
198
- var pair = pairString.split('=');
199
- params[pair[0]] = pair[1];
200
- return params;
230
+ toQueryParams: function(separator) {
231
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
232
+ if (!match) return {};
233
+
234
+ return match[1].split(separator || '&').inject({}, function(hash, pair) {
235
+ if ((pair = pair.split('='))[0]) {
236
+ var name = decodeURIComponent(pair[0]);
237
+ var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
238
+
239
+ if (hash[name] !== undefined) {
240
+ if (hash[name].constructor != Array)
241
+ hash[name] = [hash[name]];
242
+ if (value) hash[name].push(value);
243
+ }
244
+ else hash[name] = value;
245
+ }
246
+ return hash;
201
247
  });
202
248
  },
203
249
 
@@ -205,24 +251,43 @@ Object.extend(String.prototype, {
205
251
  return this.split('');
206
252
  },
207
253
 
254
+ succ: function() {
255
+ return this.slice(0, this.length - 1) +
256
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
257
+ },
258
+
208
259
  camelize: function() {
209
- var oStringList = this.split('-');
210
- if (oStringList.length == 1) return oStringList[0];
260
+ var parts = this.split('-'), len = parts.length;
261
+ if (len == 1) return parts[0];
211
262
 
212
- var camelizedString = this.indexOf('-') == 0
213
- ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
214
- : oStringList[0];
263
+ var camelized = this.charAt(0) == '-'
264
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
265
+ : parts[0];
215
266
 
216
- for (var i = 1, len = oStringList.length; i < len; i++) {
217
- var s = oStringList[i];
218
- camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
219
- }
267
+ for (var i = 1; i < len; i++)
268
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
220
269
 
221
- return camelizedString;
270
+ return camelized;
222
271
  },
223
272
 
224
- inspect: function() {
225
- return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
273
+ capitalize: function(){
274
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
275
+ },
276
+
277
+ underscore: function() {
278
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
279
+ },
280
+
281
+ dasherize: function() {
282
+ return this.gsub(/_/,'-');
283
+ },
284
+
285
+ inspect: function(useDoubleQuotes) {
286
+ var escapedString = this.replace(/\\/g, '\\\\');
287
+ if (useDoubleQuotes)
288
+ return '"' + escapedString.replace(/"/g, '\\"') + '"';
289
+ else
290
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
226
291
  }
227
292
  });
228
293
 
@@ -246,7 +311,7 @@ Template.prototype = {
246
311
  return this.template.gsub(this.pattern, function(match) {
247
312
  var before = match[1];
248
313
  if (before == '\\') return match[2];
249
- return before + (object[match[3]] || '').toString();
314
+ return before + String.interpret(object[match[3]]);
250
315
  });
251
316
  }
252
317
  }
@@ -268,6 +333,14 @@ var Enumerable = {
268
333
  } catch (e) {
269
334
  if (e != $break) throw e;
270
335
  }
336
+ return this;
337
+ },
338
+
339
+ eachSlice: function(number, iterator) {
340
+ var index = -number, slices = [], array = this.toArray();
341
+ while ((index += number) < array.length)
342
+ slices.push(array.slice(index, index+number));
343
+ return slices.map(iterator);
271
344
  },
272
345
 
273
346
  all: function(iterator) {
@@ -280,7 +353,7 @@ var Enumerable = {
280
353
  },
281
354
 
282
355
  any: function(iterator) {
283
- var result = true;
356
+ var result = false;
284
357
  this.each(function(value, index) {
285
358
  if (result = !!(iterator || Prototype.K)(value, index))
286
359
  throw $break;
@@ -291,12 +364,12 @@ var Enumerable = {
291
364
  collect: function(iterator) {
292
365
  var results = [];
293
366
  this.each(function(value, index) {
294
- results.push(iterator(value, index));
367
+ results.push((iterator || Prototype.K)(value, index));
295
368
  });
296
369
  return results;
297
370
  },
298
371
 
299
- detect: function (iterator) {
372
+ detect: function(iterator) {
300
373
  var result;
301
374
  this.each(function(value, index) {
302
375
  if (iterator(value, index)) {
@@ -337,6 +410,14 @@ var Enumerable = {
337
410
  return found;
338
411
  },
339
412
 
413
+ inGroupsOf: function(number, fillWith) {
414
+ fillWith = fillWith === undefined ? null : fillWith;
415
+ return this.eachSlice(number, function(slice) {
416
+ while(slice.length < number) slice.push(fillWith);
417
+ return slice;
418
+ });
419
+ },
420
+
340
421
  inject: function(memo, iterator) {
341
422
  this.each(function(value, index) {
342
423
  memo = iterator(memo, value, index);
@@ -346,7 +427,7 @@ var Enumerable = {
346
427
 
347
428
  invoke: function(method) {
348
429
  var args = $A(arguments).slice(1);
349
- return this.collect(function(value) {
430
+ return this.map(function(value) {
350
431
  return value[method].apply(value, args);
351
432
  });
352
433
  },
@@ -355,7 +436,7 @@ var Enumerable = {
355
436
  var result;
356
437
  this.each(function(value, index) {
357
438
  value = (iterator || Prototype.K)(value, index);
358
- if (value >= (result || value))
439
+ if (result == undefined || value >= result)
359
440
  result = value;
360
441
  });
361
442
  return result;
@@ -365,7 +446,7 @@ var Enumerable = {
365
446
  var result;
366
447
  this.each(function(value, index) {
367
448
  value = (iterator || Prototype.K)(value, index);
368
- if (value <= (result || value))
449
+ if (result == undefined || value < result)
369
450
  result = value;
370
451
  });
371
452
  return result;
@@ -398,7 +479,7 @@ var Enumerable = {
398
479
  },
399
480
 
400
481
  sortBy: function(iterator) {
401
- return this.collect(function(value, index) {
482
+ return this.map(function(value, index) {
402
483
  return {value: value, criteria: iterator(value, index)};
403
484
  }).sort(function(left, right) {
404
485
  var a = left.criteria, b = right.criteria;
@@ -407,7 +488,7 @@ var Enumerable = {
407
488
  },
408
489
 
409
490
  toArray: function() {
410
- return this.collect(Prototype.K);
491
+ return this.map();
411
492
  },
412
493
 
413
494
  zip: function() {
@@ -421,6 +502,10 @@ var Enumerable = {
421
502
  });
422
503
  },
423
504
 
505
+ size: function() {
506
+ return this.toArray().length;
507
+ },
508
+
424
509
  inspect: function() {
425
510
  return '#<Enumerable:' + this.toArray().inspect() + '>';
426
511
  }
@@ -439,7 +524,7 @@ var $A = Array.from = function(iterable) {
439
524
  return iterable.toArray();
440
525
  } else {
441
526
  var results = [];
442
- for (var i = 0; i < iterable.length; i++)
527
+ for (var i = 0, length = iterable.length; i < length; i++)
443
528
  results.push(iterable[i]);
444
529
  return results;
445
530
  }
@@ -447,11 +532,12 @@ var $A = Array.from = function(iterable) {
447
532
 
448
533
  Object.extend(Array.prototype, Enumerable);
449
534
 
450
- Array.prototype._reverse = Array.prototype.reverse;
535
+ if (!Array.prototype._reverse)
536
+ Array.prototype._reverse = Array.prototype.reverse;
451
537
 
452
538
  Object.extend(Array.prototype, {
453
539
  _each: function(iterator) {
454
- for (var i = 0; i < this.length; i++)
540
+ for (var i = 0, length = this.length; i < length; i++)
455
541
  iterator(this[i]);
456
542
  },
457
543
 
@@ -470,13 +556,13 @@ Object.extend(Array.prototype, {
470
556
 
471
557
  compact: function() {
472
558
  return this.select(function(value) {
473
- return value != undefined || value != null;
559
+ return value != null;
474
560
  });
475
561
  },
476
562
 
477
563
  flatten: function() {
478
564
  return this.inject([], function(array, value) {
479
- return array.concat(value.constructor == Array ?
565
+ return array.concat(value && value.constructor == Array ?
480
566
  value.flatten() : [value]);
481
567
  });
482
568
  },
@@ -489,7 +575,7 @@ Object.extend(Array.prototype, {
489
575
  },
490
576
 
491
577
  indexOf: function(object) {
492
- for (var i = 0; i < this.length; i++)
578
+ for (var i = 0, length = this.length; i < length; i++)
493
579
  if (this[i] == object) return i;
494
580
  return -1;
495
581
  },
@@ -498,23 +584,88 @@ Object.extend(Array.prototype, {
498
584
  return (inline !== false ? this : this.toArray())._reverse();
499
585
  },
500
586
 
501
- shift: function() {
502
- var result = this[0];
503
- for (var i = 0; i < this.length - 1; i++)
504
- this[i] = this[i + 1];
505
- this.length--;
506
- return result;
587
+ reduce: function() {
588
+ return this.length > 1 ? this : this[0];
589
+ },
590
+
591
+ uniq: function() {
592
+ return this.inject([], function(array, value) {
593
+ return array.include(value) ? array : array.concat([value]);
594
+ });
595
+ },
596
+
597
+ clone: function() {
598
+ return [].concat(this);
599
+ },
600
+
601
+ size: function() {
602
+ return this.length;
507
603
  },
508
604
 
509
605
  inspect: function() {
510
606
  return '[' + this.map(Object.inspect).join(', ') + ']';
511
607
  }
512
608
  });
513
- var Hash = {
609
+
610
+ Array.prototype.toArray = Array.prototype.clone;
611
+
612
+ function $w(string){
613
+ string = string.strip();
614
+ return string ? string.split(/\s+/) : [];
615
+ }
616
+
617
+ if(window.opera){
618
+ Array.prototype.concat = function(){
619
+ var array = [];
620
+ for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
621
+ for(var i = 0, length = arguments.length; i < length; i++) {
622
+ if(arguments[i].constructor == Array) {
623
+ for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
624
+ array.push(arguments[i][j]);
625
+ } else {
626
+ array.push(arguments[i]);
627
+ }
628
+ }
629
+ return array;
630
+ }
631
+ }
632
+ var Hash = function(obj) {
633
+ Object.extend(this, obj || {});
634
+ };
635
+
636
+ Object.extend(Hash, {
637
+ toQueryString: function(obj) {
638
+ var parts = [];
639
+
640
+ this.prototype._each.call(obj, function(pair) {
641
+ if (!pair.key) return;
642
+
643
+ if (pair.value && pair.value.constructor == Array) {
644
+ var values = pair.value.compact();
645
+ if (values.length < 2) pair.value = values.reduce();
646
+ else {
647
+ key = encodeURIComponent(pair.key);
648
+ values.each(function(value) {
649
+ value = value != undefined ? encodeURIComponent(value) : '';
650
+ parts.push(key + '=' + encodeURIComponent(value));
651
+ });
652
+ return;
653
+ }
654
+ }
655
+ if (pair.value == undefined) pair[1] = '';
656
+ parts.push(pair.map(encodeURIComponent).join('='));
657
+ });
658
+
659
+ return parts.join('&');
660
+ }
661
+ });
662
+
663
+ Object.extend(Hash.prototype, Enumerable);
664
+ Object.extend(Hash.prototype, {
514
665
  _each: function(iterator) {
515
- for (key in this) {
666
+ for (var key in this) {
516
667
  var value = this[key];
517
- if (typeof value == 'function') continue;
668
+ if (value && value == Hash.prototype[key]) continue;
518
669
 
519
670
  var pair = [key, value];
520
671
  pair.key = key;
@@ -532,16 +683,30 @@ var Hash = {
532
683
  },
533
684
 
534
685
  merge: function(hash) {
535
- return $H(hash).inject($H(this), function(mergedHash, pair) {
686
+ return $H(hash).inject(this, function(mergedHash, pair) {
536
687
  mergedHash[pair.key] = pair.value;
537
688
  return mergedHash;
538
689
  });
539
690
  },
540
691
 
692
+ remove: function() {
693
+ var result;
694
+ for(var i = 0, length = arguments.length; i < length; i++) {
695
+ var value = this[arguments[i]];
696
+ if (value !== undefined){
697
+ if (result === undefined) result = value;
698
+ else {
699
+ if (result.constructor != Array) result = [result];
700
+ result.push(value)
701
+ }
702
+ }
703
+ delete this[arguments[i]];
704
+ }
705
+ return result;
706
+ },
707
+
541
708
  toQueryString: function() {
542
- return this.map(function(pair) {
543
- return pair.map(encodeURIComponent).join('=');
544
- }).join('&');
709
+ return Hash.toQueryString(this);
545
710
  },
546
711
 
547
712
  inspect: function() {
@@ -549,14 +714,12 @@ var Hash = {
549
714
  return pair.map(Object.inspect).join(': ');
550
715
  }).join(', ') + '}>';
551
716
  }
552
- }
717
+ });
553
718
 
554
719
  function $H(object) {
555
- var hash = Object.extend({}, object || {});
556
- Object.extend(hash, Enumerable);
557
- Object.extend(hash, Hash);
558
- return hash;
559
- }
720
+ if (object && object.constructor == Hash) return object;
721
+ return new Hash(object);
722
+ };
560
723
  ObjectRange = Class.create();
561
724
  Object.extend(ObjectRange.prototype, Enumerable);
562
725
  Object.extend(ObjectRange.prototype, {
@@ -568,10 +731,10 @@ Object.extend(ObjectRange.prototype, {
568
731
 
569
732
  _each: function(iterator) {
570
733
  var value = this.start;
571
- do {
734
+ while (this.include(value)) {
572
735
  iterator(value);
573
736
  value = value.succ();
574
- } while (this.include(value));
737
+ }
575
738
  },
576
739
 
577
740
  include: function(value) {
@@ -590,9 +753,9 @@ var $R = function(start, end, exclusive) {
590
753
  var Ajax = {
591
754
  getTransport: function() {
592
755
  return Try.these(
756
+ function() {return new XMLHttpRequest()},
593
757
  function() {return new ActiveXObject('Msxml2.XMLHTTP')},
594
- function() {return new ActiveXObject('Microsoft.XMLHTTP')},
595
- function() {return new XMLHttpRequest()}
758
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
596
759
  ) || false;
597
760
  },
598
761
 
@@ -606,18 +769,18 @@ Ajax.Responders = {
606
769
  this.responders._each(iterator);
607
770
  },
608
771
 
609
- register: function(responderToAdd) {
610
- if (!this.include(responderToAdd))
611
- this.responders.push(responderToAdd);
772
+ register: function(responder) {
773
+ if (!this.include(responder))
774
+ this.responders.push(responder);
612
775
  },
613
776
 
614
- unregister: function(responderToRemove) {
615
- this.responders = this.responders.without(responderToRemove);
777
+ unregister: function(responder) {
778
+ this.responders = this.responders.without(responder);
616
779
  },
617
780
 
618
781
  dispatch: function(callback, request, transport, json) {
619
782
  this.each(function(responder) {
620
- if (responder[callback] && typeof responder[callback] == 'function') {
783
+ if (typeof responder[callback] == 'function') {
621
784
  try {
622
785
  responder[callback].apply(responder, [request, transport, json]);
623
786
  } catch (e) {}
@@ -632,7 +795,6 @@ Ajax.Responders.register({
632
795
  onCreate: function() {
633
796
  Ajax.activeRequestCount++;
634
797
  },
635
-
636
798
  onComplete: function() {
637
799
  Ajax.activeRequestCount--;
638
800
  }
@@ -644,19 +806,15 @@ Ajax.Base.prototype = {
644
806
  this.options = {
645
807
  method: 'post',
646
808
  asynchronous: true,
809
+ contentType: 'application/x-www-form-urlencoded',
810
+ encoding: 'UTF-8',
647
811
  parameters: ''
648
812
  }
649
813
  Object.extend(this.options, options || {});
650
- },
651
814
 
652
- responseIsSuccess: function() {
653
- return this.transport.status == undefined
654
- || this.transport.status == 0
655
- || (this.transport.status >= 200 && this.transport.status < 300);
656
- },
657
-
658
- responseIsFailure: function() {
659
- return !this.responseIsSuccess();
815
+ this.options.method = this.options.method.toLowerCase();
816
+ if (typeof this.options.parameters == 'string')
817
+ this.options.parameters = this.options.parameters.toQueryParams();
660
818
  }
661
819
  }
662
820
 
@@ -665,6 +823,8 @@ Ajax.Request.Events =
665
823
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
666
824
 
667
825
  Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
826
+ _complete: false,
827
+
668
828
  initialize: function(url, options) {
669
829
  this.transport = Ajax.getTransport();
670
830
  this.setOptions(options);
@@ -672,112 +832,146 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
672
832
  },
673
833
 
674
834
  request: function(url) {
675
- var parameters = this.options.parameters || '';
676
- if (parameters.length > 0) parameters += '&_=';
835
+ this.url = url;
836
+ this.method = this.options.method;
837
+ var params = this.options.parameters;
677
838
 
678
- try {
679
- this.url = url;
680
- if (this.options.method == 'get' && parameters.length > 0)
681
- this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
839
+ if (!['get', 'post'].include(this.method)) {
840
+ // simulate other verbs over post
841
+ params['_method'] = this.method;
842
+ this.method = 'post';
843
+ }
682
844
 
845
+ params = Hash.toQueryString(params);
846
+ if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='
847
+
848
+ // when GET, append parameters to URL
849
+ if (this.method == 'get' && params)
850
+ this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;
851
+
852
+ try {
683
853
  Ajax.Responders.dispatch('onCreate', this, this.transport);
684
854
 
685
- this.transport.open(this.options.method, this.url,
855
+ this.transport.open(this.method.toUpperCase(), this.url,
686
856
  this.options.asynchronous);
687
857
 
688
- if (this.options.asynchronous) {
689
- this.transport.onreadystatechange = this.onStateChange.bind(this);
690
- setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
691
- }
858
+ if (this.options.asynchronous)
859
+ setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
692
860
 
861
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
693
862
  this.setRequestHeaders();
694
863
 
695
- var body = this.options.postBody ? this.options.postBody : parameters;
696
- this.transport.send(this.options.method == 'post' ? body : null);
864
+ var body = this.method == 'post' ? (this.options.postBody || params) : null;
697
865
 
698
- } catch (e) {
699
- this.dispatchException(e);
700
- }
701
- },
866
+ this.transport.send(body);
702
867
 
703
- setRequestHeaders: function() {
704
- var requestHeaders =
705
- ['X-Requested-With', 'XMLHttpRequest',
706
- 'X-Prototype-Version', Prototype.Version,
707
- 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
708
-
709
- if (this.options.method == 'post') {
710
- requestHeaders.push('Content-type',
711
- 'application/x-www-form-urlencoded');
712
-
713
- /* Force "Connection: close" for Mozilla browsers to work around
714
- * a bug where XMLHttpReqeuest sends an incorrect Content-length
715
- * header. See Mozilla Bugzilla #246651.
716
- */
717
- if (this.transport.overrideMimeType)
718
- requestHeaders.push('Connection', 'close');
719
- }
720
-
721
- if (this.options.requestHeaders)
722
- requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
868
+ /* Force Firefox to handle ready state 4 for synchronous requests */
869
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
870
+ this.onStateChange();
723
871
 
724
- for (var i = 0; i < requestHeaders.length; i += 2)
725
- this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
872
+ }
873
+ catch (e) {
874
+ this.dispatchException(e);
875
+ }
726
876
  },
727
877
 
728
878
  onStateChange: function() {
729
879
  var readyState = this.transport.readyState;
730
- if (readyState != 1)
880
+ if (readyState > 1 && !((readyState == 4) && this._complete))
731
881
  this.respondToReadyState(this.transport.readyState);
732
882
  },
733
883
 
734
- header: function(name) {
735
- try {
736
- return this.transport.getResponseHeader(name);
737
- } catch (e) {}
738
- },
884
+ setRequestHeaders: function() {
885
+ var headers = {
886
+ 'X-Requested-With': 'XMLHttpRequest',
887
+ 'X-Prototype-Version': Prototype.Version,
888
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
889
+ };
890
+
891
+ if (this.method == 'post') {
892
+ headers['Content-type'] = this.options.contentType +
893
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
894
+
895
+ /* Force "Connection: close" for older Mozilla browsers to work
896
+ * around a bug where XMLHttpRequest sends an incorrect
897
+ * Content-length header. See Mozilla Bugzilla #246651.
898
+ */
899
+ if (this.transport.overrideMimeType &&
900
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
901
+ headers['Connection'] = 'close';
902
+ }
739
903
 
740
- evalJSON: function() {
741
- try {
742
- return eval(this.header('X-JSON'));
743
- } catch (e) {}
744
- },
904
+ // user-defined headers
905
+ if (typeof this.options.requestHeaders == 'object') {
906
+ var extras = this.options.requestHeaders;
745
907
 
746
- evalResponse: function() {
747
- try {
748
- return eval(this.transport.responseText);
749
- } catch (e) {
750
- this.dispatchException(e);
908
+ if (typeof extras.push == 'function')
909
+ for (var i = 0, length = extras.length; i < length; i += 2)
910
+ headers[extras[i]] = extras[i+1];
911
+ else
912
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
751
913
  }
914
+
915
+ for (var name in headers)
916
+ this.transport.setRequestHeader(name, headers[name]);
917
+ },
918
+
919
+ success: function() {
920
+ return !this.transport.status
921
+ || (this.transport.status >= 200 && this.transport.status < 300);
752
922
  },
753
923
 
754
924
  respondToReadyState: function(readyState) {
755
- var event = Ajax.Request.Events[readyState];
925
+ var state = Ajax.Request.Events[readyState];
756
926
  var transport = this.transport, json = this.evalJSON();
757
927
 
758
- if (event == 'Complete') {
928
+ if (state == 'Complete') {
759
929
  try {
930
+ this._complete = true;
760
931
  (this.options['on' + this.transport.status]
761
- || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
932
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
762
933
  || Prototype.emptyFunction)(transport, json);
763
934
  } catch (e) {
764
935
  this.dispatchException(e);
765
936
  }
766
937
 
767
- if ((this.header('Content-type') || '').match(/^text\/javascript/i))
768
- this.evalResponse();
938
+ if ((this.getHeader('Content-type') || 'text/javascript').strip().
939
+ match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
940
+ this.evalResponse();
769
941
  }
770
942
 
771
943
  try {
772
- (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
773
- Ajax.Responders.dispatch('on' + event, this, transport, json);
944
+ (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
945
+ Ajax.Responders.dispatch('on' + state, this, transport, json);
774
946
  } catch (e) {
775
947
  this.dispatchException(e);
776
948
  }
777
949
 
778
- /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
779
- if (event == 'Complete')
950
+ if (state == 'Complete') {
951
+ // avoid memory leak in MSIE: clean up
780
952
  this.transport.onreadystatechange = Prototype.emptyFunction;
953
+ }
954
+ },
955
+
956
+ getHeader: function(name) {
957
+ try {
958
+ return this.transport.getResponseHeader(name);
959
+ } catch (e) { return null }
960
+ },
961
+
962
+ evalJSON: function() {
963
+ try {
964
+ var json = this.getHeader('X-JSON');
965
+ return json ? eval('(' + json + ')') : null;
966
+ } catch (e) { return null }
967
+ },
968
+
969
+ evalResponse: function() {
970
+ try {
971
+ return eval(this.transport.responseText);
972
+ } catch (e) {
973
+ this.dispatchException(e);
974
+ }
781
975
  },
782
976
 
783
977
  dispatchException: function(exception) {
@@ -790,41 +984,37 @@ Ajax.Updater = Class.create();
790
984
 
791
985
  Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
792
986
  initialize: function(container, url, options) {
793
- this.containers = {
794
- success: container.success ? $(container.success) : $(container),
795
- failure: container.failure ? $(container.failure) :
796
- (container.success ? null : $(container))
987
+ this.container = {
988
+ success: (container.success || container),
989
+ failure: (container.failure || (container.success ? null : container))
797
990
  }
798
991
 
799
992
  this.transport = Ajax.getTransport();
800
993
  this.setOptions(options);
801
994
 
802
995
  var onComplete = this.options.onComplete || Prototype.emptyFunction;
803
- this.options.onComplete = (function(transport, object) {
996
+ this.options.onComplete = (function(transport, param) {
804
997
  this.updateContent();
805
- onComplete(transport, object);
998
+ onComplete(transport, param);
806
999
  }).bind(this);
807
1000
 
808
1001
  this.request(url);
809
1002
  },
810
1003
 
811
1004
  updateContent: function() {
812
- var receiver = this.responseIsSuccess() ?
813
- this.containers.success : this.containers.failure;
1005
+ var receiver = this.container[this.success() ? 'success' : 'failure'];
814
1006
  var response = this.transport.responseText;
815
1007
 
816
- if (!this.options.evalScripts)
817
- response = response.stripScripts();
1008
+ if (!this.options.evalScripts) response = response.stripScripts();
818
1009
 
819
- if (receiver) {
820
- if (this.options.insertion) {
1010
+ if (receiver = $(receiver)) {
1011
+ if (this.options.insertion)
821
1012
  new this.options.insertion(receiver, response);
822
- } else {
823
- Element.update(receiver, response);
824
- }
1013
+ else
1014
+ receiver.update(response);
825
1015
  }
826
1016
 
827
- if (this.responseIsSuccess()) {
1017
+ if (this.success()) {
828
1018
  if (this.onComplete)
829
1019
  setTimeout(this.onComplete.bind(this), 10);
830
1020
  }
@@ -853,7 +1043,7 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
853
1043
  },
854
1044
 
855
1045
  stop: function() {
856
- this.updater.onComplete = undefined;
1046
+ this.updater.options.onComplete = undefined;
857
1047
  clearTimeout(this.timer);
858
1048
  (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
859
1049
  },
@@ -873,25 +1063,43 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
873
1063
  this.updater = new Ajax.Updater(this.container, this.url, this.options);
874
1064
  }
875
1065
  });
876
- function $() {
877
- var results = [], element;
878
- for (var i = 0; i < arguments.length; i++) {
879
- element = arguments[i];
880
- if (typeof element == 'string')
881
- element = document.getElementById(element);
882
- results.push(Element.extend(element));
1066
+ function $(element) {
1067
+ if (arguments.length > 1) {
1068
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1069
+ elements.push($(arguments[i]));
1070
+ return elements;
883
1071
  }
884
- return results.length < 2 ? results[0] : results;
1072
+ if (typeof element == 'string')
1073
+ element = document.getElementById(element);
1074
+ return Element.extend(element);
1075
+ }
1076
+
1077
+ if (Prototype.BrowserFeatures.XPath) {
1078
+ document._getElementsByXPath = function(expression, parentElement) {
1079
+ var results = [];
1080
+ var query = document.evaluate(expression, $(parentElement) || document,
1081
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1082
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
1083
+ results.push(query.snapshotItem(i));
1084
+ return results;
1085
+ };
885
1086
  }
886
1087
 
887
1088
  document.getElementsByClassName = function(className, parentElement) {
888
- var children = ($(parentElement) || document.body).getElementsByTagName('*');
889
- return $A(children).inject([], function(elements, child) {
890
- if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
891
- elements.push(Element.extend(child));
1089
+ if (Prototype.BrowserFeatures.XPath) {
1090
+ var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
1091
+ return document._getElementsByXPath(q, parentElement);
1092
+ } else {
1093
+ var children = ($(parentElement) || document.body).getElementsByTagName('*');
1094
+ var elements = [], child;
1095
+ for (var i = 0, length = children.length; i < length; i++) {
1096
+ child = children[i];
1097
+ if (Element.hasClassName(child, className))
1098
+ elements.push(Element.extend(child));
1099
+ }
892
1100
  return elements;
893
- });
894
- }
1101
+ }
1102
+ };
895
1103
 
896
1104
  /*--------------------------------------------------------------------------*/
897
1105
 
@@ -899,59 +1107,74 @@ if (!window.Element)
899
1107
  var Element = new Object();
900
1108
 
901
1109
  Element.extend = function(element) {
902
- if (!element) return;
1110
+ if (!element || _nativeExtensions || element.nodeType == 3) return element;
903
1111
 
904
1112
  if (!element._extended && element.tagName && element != window) {
905
- var methods = Element.Methods;
906
- for (property in methods) {
1113
+ var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
1114
+
1115
+ if (element.tagName == 'FORM')
1116
+ Object.extend(methods, Form.Methods);
1117
+ if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
1118
+ Object.extend(methods, Form.Element.Methods);
1119
+
1120
+ Object.extend(methods, Element.Methods.Simulated);
1121
+
1122
+ for (var property in methods) {
907
1123
  var value = methods[property];
908
- if (typeof value == 'function')
909
- element[property] = value.bind(null, element);
1124
+ if (typeof value == 'function' && !(property in element))
1125
+ element[property] = cache.findOrStore(value);
910
1126
  }
911
1127
  }
912
1128
 
913
1129
  element._extended = true;
914
1130
  return element;
915
- }
1131
+ };
1132
+
1133
+ Element.extend.cache = {
1134
+ findOrStore: function(value) {
1135
+ return this[value] = this[value] || function() {
1136
+ return value.apply(null, [this].concat($A(arguments)));
1137
+ }
1138
+ }
1139
+ };
916
1140
 
917
1141
  Element.Methods = {
918
1142
  visible: function(element) {
919
1143
  return $(element).style.display != 'none';
920
1144
  },
921
1145
 
922
- toggle: function() {
923
- for (var i = 0; i < arguments.length; i++) {
924
- var element = $(arguments[i]);
925
- Element[Element.visible(element) ? 'hide' : 'show'](element);
926
- }
1146
+ toggle: function(element) {
1147
+ element = $(element);
1148
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
1149
+ return element;
927
1150
  },
928
1151
 
929
- hide: function() {
930
- for (var i = 0; i < arguments.length; i++) {
931
- var element = $(arguments[i]);
932
- element.style.display = 'none';
933
- }
1152
+ hide: function(element) {
1153
+ $(element).style.display = 'none';
1154
+ return element;
934
1155
  },
935
1156
 
936
- show: function() {
937
- for (var i = 0; i < arguments.length; i++) {
938
- var element = $(arguments[i]);
939
- element.style.display = '';
940
- }
1157
+ show: function(element) {
1158
+ $(element).style.display = '';
1159
+ return element;
941
1160
  },
942
1161
 
943
1162
  remove: function(element) {
944
1163
  element = $(element);
945
1164
  element.parentNode.removeChild(element);
1165
+ return element;
946
1166
  },
947
1167
 
948
1168
  update: function(element, html) {
1169
+ html = typeof html == 'undefined' ? '' : html.toString();
949
1170
  $(element).innerHTML = html.stripScripts();
950
1171
  setTimeout(function() {html.evalScripts()}, 10);
1172
+ return element;
951
1173
  },
952
1174
 
953
1175
  replace: function(element, html) {
954
1176
  element = $(element);
1177
+ html = typeof html == 'undefined' ? '' : html.toString();
955
1178
  if (element.outerHTML) {
956
1179
  element.outerHTML = html.stripScripts();
957
1180
  } else {
@@ -961,11 +1184,106 @@ Element.Methods = {
961
1184
  range.createContextualFragment(html.stripScripts()), element);
962
1185
  }
963
1186
  setTimeout(function() {html.evalScripts()}, 10);
1187
+ return element;
964
1188
  },
965
1189
 
966
- getHeight: function(element) {
1190
+ inspect: function(element) {
967
1191
  element = $(element);
968
- return element.offsetHeight;
1192
+ var result = '<' + element.tagName.toLowerCase();
1193
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1194
+ var property = pair.first(), attribute = pair.last();
1195
+ var value = (element[property] || '').toString();
1196
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
1197
+ });
1198
+ return result + '>';
1199
+ },
1200
+
1201
+ recursivelyCollect: function(element, property) {
1202
+ element = $(element);
1203
+ var elements = [];
1204
+ while (element = element[property])
1205
+ if (element.nodeType == 1)
1206
+ elements.push(Element.extend(element));
1207
+ return elements;
1208
+ },
1209
+
1210
+ ancestors: function(element) {
1211
+ return $(element).recursivelyCollect('parentNode');
1212
+ },
1213
+
1214
+ descendants: function(element) {
1215
+ return $A($(element).getElementsByTagName('*'));
1216
+ },
1217
+
1218
+ immediateDescendants: function(element) {
1219
+ if (!(element = $(element).firstChild)) return [];
1220
+ while (element && element.nodeType != 1) element = element.nextSibling;
1221
+ if (element) return [element].concat($(element).nextSiblings());
1222
+ return [];
1223
+ },
1224
+
1225
+ previousSiblings: function(element) {
1226
+ return $(element).recursivelyCollect('previousSibling');
1227
+ },
1228
+
1229
+ nextSiblings: function(element) {
1230
+ return $(element).recursivelyCollect('nextSibling');
1231
+ },
1232
+
1233
+ siblings: function(element) {
1234
+ element = $(element);
1235
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
1236
+ },
1237
+
1238
+ match: function(element, selector) {
1239
+ if (typeof selector == 'string')
1240
+ selector = new Selector(selector);
1241
+ return selector.match($(element));
1242
+ },
1243
+
1244
+ up: function(element, expression, index) {
1245
+ return Selector.findElement($(element).ancestors(), expression, index);
1246
+ },
1247
+
1248
+ down: function(element, expression, index) {
1249
+ return Selector.findElement($(element).descendants(), expression, index);
1250
+ },
1251
+
1252
+ previous: function(element, expression, index) {
1253
+ return Selector.findElement($(element).previousSiblings(), expression, index);
1254
+ },
1255
+
1256
+ next: function(element, expression, index) {
1257
+ return Selector.findElement($(element).nextSiblings(), expression, index);
1258
+ },
1259
+
1260
+ getElementsBySelector: function() {
1261
+ var args = $A(arguments), element = $(args.shift());
1262
+ return Selector.findChildElements(element, args);
1263
+ },
1264
+
1265
+ getElementsByClassName: function(element, className) {
1266
+ return document.getElementsByClassName(className, element);
1267
+ },
1268
+
1269
+ readAttribute: function(element, name) {
1270
+ element = $(element);
1271
+ if (document.all && !window.opera) {
1272
+ var t = Element._attributeTranslations;
1273
+ if (t.values[name]) return t.values[name](element, name);
1274
+ if (t.names[name]) name = t.names[name];
1275
+ var attribute = element.attributes[name];
1276
+ if(attribute) return attribute.nodeValue;
1277
+ }
1278
+ return element.getAttribute(name);
1279
+ },
1280
+
1281
+ getHeight: function(element) {
1282
+ return $(element).getDimensions().height;
1283
+ },
1284
+
1285
+ getWidth: function(element) {
1286
+ return $(element).getDimensions().width;
969
1287
  },
970
1288
 
971
1289
  classNames: function(element) {
@@ -974,34 +1292,60 @@ Element.Methods = {
974
1292
 
975
1293
  hasClassName: function(element, className) {
976
1294
  if (!(element = $(element))) return;
977
- return Element.classNames(element).include(className);
1295
+ var elementClassName = element.className;
1296
+ if (elementClassName.length == 0) return false;
1297
+ if (elementClassName == className ||
1298
+ elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
1299
+ return true;
1300
+ return false;
978
1301
  },
979
1302
 
980
1303
  addClassName: function(element, className) {
981
1304
  if (!(element = $(element))) return;
982
- return Element.classNames(element).add(className);
1305
+ Element.classNames(element).add(className);
1306
+ return element;
983
1307
  },
984
1308
 
985
1309
  removeClassName: function(element, className) {
986
1310
  if (!(element = $(element))) return;
987
- return Element.classNames(element).remove(className);
1311
+ Element.classNames(element).remove(className);
1312
+ return element;
1313
+ },
1314
+
1315
+ toggleClassName: function(element, className) {
1316
+ if (!(element = $(element))) return;
1317
+ Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
1318
+ return element;
1319
+ },
1320
+
1321
+ observe: function() {
1322
+ Event.observe.apply(Event, arguments);
1323
+ return $A(arguments).first();
1324
+ },
1325
+
1326
+ stopObserving: function() {
1327
+ Event.stopObserving.apply(Event, arguments);
1328
+ return $A(arguments).first();
988
1329
  },
989
1330
 
990
1331
  // removes whitespace-only text node children
991
1332
  cleanWhitespace: function(element) {
992
1333
  element = $(element);
993
- for (var i = 0; i < element.childNodes.length; i++) {
994
- var node = element.childNodes[i];
1334
+ var node = element.firstChild;
1335
+ while (node) {
1336
+ var nextNode = node.nextSibling;
995
1337
  if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
996
- Element.remove(node);
1338
+ element.removeChild(node);
1339
+ node = nextNode;
997
1340
  }
1341
+ return element;
998
1342
  },
999
1343
 
1000
1344
  empty: function(element) {
1001
1345
  return $(element).innerHTML.match(/^\s*$/);
1002
1346
  },
1003
1347
 
1004
- childOf: function(element, ancestor) {
1348
+ descendantOf: function(element, ancestor) {
1005
1349
  element = $(element), ancestor = $(ancestor);
1006
1350
  while (element = element.parentNode)
1007
1351
  if (element == ancestor) return true;
@@ -1010,38 +1354,69 @@ Element.Methods = {
1010
1354
 
1011
1355
  scrollTo: function(element) {
1012
1356
  element = $(element);
1013
- var x = element.x ? element.x : element.offsetLeft,
1014
- y = element.y ? element.y : element.offsetTop;
1015
- window.scrollTo(x, y);
1357
+ var pos = Position.cumulativeOffset(element);
1358
+ window.scrollTo(pos[0], pos[1]);
1359
+ return element;
1016
1360
  },
1017
1361
 
1018
1362
  getStyle: function(element, style) {
1019
1363
  element = $(element);
1020
- var value = element.style[style.camelize()];
1364
+ if (['float','cssFloat'].include(style))
1365
+ style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
1366
+ style = style.camelize();
1367
+ var value = element.style[style];
1021
1368
  if (!value) {
1022
1369
  if (document.defaultView && document.defaultView.getComputedStyle) {
1023
1370
  var css = document.defaultView.getComputedStyle(element, null);
1024
- value = css ? css.getPropertyValue(style) : null;
1371
+ value = css ? css[style] : null;
1025
1372
  } else if (element.currentStyle) {
1026
- value = element.currentStyle[style.camelize()];
1373
+ value = element.currentStyle[style];
1027
1374
  }
1028
1375
  }
1029
1376
 
1377
+ if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
1378
+ value = element['offset'+style.capitalize()] + 'px';
1379
+
1030
1380
  if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
1031
1381
  if (Element.getStyle(element, 'position') == 'static') value = 'auto';
1032
-
1382
+ if(style == 'opacity') {
1383
+ if(value) return parseFloat(value);
1384
+ if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
1385
+ if(value[1]) return parseFloat(value[1]) / 100;
1386
+ return 1.0;
1387
+ }
1033
1388
  return value == 'auto' ? null : value;
1034
1389
  },
1035
1390
 
1036
1391
  setStyle: function(element, style) {
1037
1392
  element = $(element);
1038
- for (name in style)
1039
- element.style[name.camelize()] = style[name];
1393
+ for (var name in style) {
1394
+ var value = style[name];
1395
+ if(name == 'opacity') {
1396
+ if (value == 1) {
1397
+ value = (/Gecko/.test(navigator.userAgent) &&
1398
+ !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
1399
+ if(/MSIE/.test(navigator.userAgent) && !window.opera)
1400
+ element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
1401
+ } else if(value == '') {
1402
+ if(/MSIE/.test(navigator.userAgent) && !window.opera)
1403
+ element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
1404
+ } else {
1405
+ if(value < 0.00001) value = 0;
1406
+ if(/MSIE/.test(navigator.userAgent) && !window.opera)
1407
+ element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
1408
+ 'alpha(opacity='+value*100+')';
1409
+ }
1410
+ } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
1411
+ element.style[name.camelize()] = value;
1412
+ }
1413
+ return element;
1040
1414
  },
1041
1415
 
1042
1416
  getDimensions: function(element) {
1043
1417
  element = $(element);
1044
- if (Element.getStyle(element, 'display') != 'none')
1418
+ var display = $(element).getStyle('display');
1419
+ if (display != 'none' && display != null) // Safari bug
1045
1420
  return {width: element.offsetWidth, height: element.offsetHeight};
1046
1421
 
1047
1422
  // All *Width and *Height properties give 0 on elements with display none,
@@ -1049,12 +1424,13 @@ Element.Methods = {
1049
1424
  var els = element.style;
1050
1425
  var originalVisibility = els.visibility;
1051
1426
  var originalPosition = els.position;
1427
+ var originalDisplay = els.display;
1052
1428
  els.visibility = 'hidden';
1053
1429
  els.position = 'absolute';
1054
- els.display = '';
1430
+ els.display = 'block';
1055
1431
  var originalWidth = element.clientWidth;
1056
1432
  var originalHeight = element.clientHeight;
1057
- els.display = 'none';
1433
+ els.display = originalDisplay;
1058
1434
  els.position = originalPosition;
1059
1435
  els.visibility = originalVisibility;
1060
1436
  return {width: originalWidth, height: originalHeight};
@@ -1073,6 +1449,7 @@ Element.Methods = {
1073
1449
  element.style.left = 0;
1074
1450
  }
1075
1451
  }
1452
+ return element;
1076
1453
  },
1077
1454
 
1078
1455
  undoPositioned: function(element) {
@@ -1085,26 +1462,153 @@ Element.Methods = {
1085
1462
  element.style.bottom =
1086
1463
  element.style.right = '';
1087
1464
  }
1465
+ return element;
1088
1466
  },
1089
1467
 
1090
1468
  makeClipping: function(element) {
1091
1469
  element = $(element);
1092
- if (element._overflow) return;
1093
- element._overflow = element.style.overflow;
1470
+ if (element._overflow) return element;
1471
+ element._overflow = element.style.overflow || 'auto';
1094
1472
  if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1095
1473
  element.style.overflow = 'hidden';
1474
+ return element;
1096
1475
  },
1097
1476
 
1098
1477
  undoClipping: function(element) {
1099
1478
  element = $(element);
1100
- if (element._overflow) return;
1101
- element.style.overflow = element._overflow;
1102
- element._overflow = undefined;
1479
+ if (!element._overflow) return element;
1480
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
1481
+ element._overflow = null;
1482
+ return element;
1103
1483
  }
1104
- }
1484
+ };
1485
+
1486
+ Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
1487
+
1488
+ Element._attributeTranslations = {};
1489
+
1490
+ Element._attributeTranslations.names = {
1491
+ colspan: "colSpan",
1492
+ rowspan: "rowSpan",
1493
+ valign: "vAlign",
1494
+ datetime: "dateTime",
1495
+ accesskey: "accessKey",
1496
+ tabindex: "tabIndex",
1497
+ enctype: "encType",
1498
+ maxlength: "maxLength",
1499
+ readonly: "readOnly",
1500
+ longdesc: "longDesc"
1501
+ };
1502
+
1503
+ Element._attributeTranslations.values = {
1504
+ _getAttr: function(element, attribute) {
1505
+ return element.getAttribute(attribute, 2);
1506
+ },
1507
+
1508
+ _flag: function(element, attribute) {
1509
+ return $(element).hasAttribute(attribute) ? attribute : null;
1510
+ },
1511
+
1512
+ style: function(element) {
1513
+ return element.style.cssText.toLowerCase();
1514
+ },
1515
+
1516
+ title: function(element) {
1517
+ var node = element.getAttributeNode('title');
1518
+ return node.specified ? node.nodeValue : null;
1519
+ }
1520
+ };
1521
+
1522
+ Object.extend(Element._attributeTranslations.values, {
1523
+ href: Element._attributeTranslations.values._getAttr,
1524
+ src: Element._attributeTranslations.values._getAttr,
1525
+ disabled: Element._attributeTranslations.values._flag,
1526
+ checked: Element._attributeTranslations.values._flag,
1527
+ readonly: Element._attributeTranslations.values._flag,
1528
+ multiple: Element._attributeTranslations.values._flag
1529
+ });
1530
+
1531
+ Element.Methods.Simulated = {
1532
+ hasAttribute: function(element, attribute) {
1533
+ var t = Element._attributeTranslations;
1534
+ attribute = t.names[attribute] || attribute;
1535
+ return $(element).getAttributeNode(attribute).specified;
1536
+ }
1537
+ };
1538
+
1539
+ // IE is missing .innerHTML support for TABLE-related elements
1540
+ if (document.all && !window.opera){
1541
+ Element.Methods.update = function(element, html) {
1542
+ element = $(element);
1543
+ html = typeof html == 'undefined' ? '' : html.toString();
1544
+ var tagName = element.tagName.toUpperCase();
1545
+ if (['THEAD','TBODY','TR','TD'].include(tagName)) {
1546
+ var div = document.createElement('div');
1547
+ switch (tagName) {
1548
+ case 'THEAD':
1549
+ case 'TBODY':
1550
+ div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
1551
+ depth = 2;
1552
+ break;
1553
+ case 'TR':
1554
+ div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
1555
+ depth = 3;
1556
+ break;
1557
+ case 'TD':
1558
+ div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
1559
+ depth = 4;
1560
+ }
1561
+ $A(element.childNodes).each(function(node){
1562
+ element.removeChild(node)
1563
+ });
1564
+ depth.times(function(){ div = div.firstChild });
1565
+
1566
+ $A(div.childNodes).each(
1567
+ function(node){ element.appendChild(node) });
1568
+ } else {
1569
+ element.innerHTML = html.stripScripts();
1570
+ }
1571
+ setTimeout(function() {html.evalScripts()}, 10);
1572
+ return element;
1573
+ }
1574
+ };
1105
1575
 
1106
1576
  Object.extend(Element, Element.Methods);
1107
1577
 
1578
+ var _nativeExtensions = false;
1579
+
1580
+ if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1581
+ ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
1582
+ var className = 'HTML' + tag + 'Element';
1583
+ if(window[className]) return;
1584
+ var klass = window[className] = {};
1585
+ klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
1586
+ });
1587
+
1588
+ Element.addMethods = function(methods) {
1589
+ Object.extend(Element.Methods, methods || {});
1590
+
1591
+ function copy(methods, destination, onlyIfAbsent) {
1592
+ onlyIfAbsent = onlyIfAbsent || false;
1593
+ var cache = Element.extend.cache;
1594
+ for (var property in methods) {
1595
+ var value = methods[property];
1596
+ if (!onlyIfAbsent || !(property in destination))
1597
+ destination[property] = cache.findOrStore(value);
1598
+ }
1599
+ }
1600
+
1601
+ if (typeof HTMLElement != 'undefined') {
1602
+ copy(Element.Methods, HTMLElement.prototype);
1603
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
1604
+ copy(Form.Methods, HTMLFormElement.prototype);
1605
+ [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
1606
+ copy(Form.Element.Methods, klass.prototype);
1607
+ });
1608
+ _nativeExtensions = true;
1609
+ }
1610
+ }
1611
+
1108
1612
  var Toggle = new Object();
1109
1613
  Toggle.display = Element.toggle;
1110
1614
 
@@ -1123,7 +1627,8 @@ Abstract.Insertion.prototype = {
1123
1627
  try {
1124
1628
  this.element.insertAdjacentHTML(this.adjacency, this.content);
1125
1629
  } catch (e) {
1126
- if (this.element.tagName.toLowerCase() == 'tbody') {
1630
+ var tagName = this.element.tagName.toUpperCase();
1631
+ if (['TBODY', 'TR'].include(tagName)) {
1127
1632
  this.insertContent(this.contentFromAnonymousTable());
1128
1633
  } else {
1129
1634
  throw e;
@@ -1222,20 +1727,18 @@ Element.ClassNames.prototype = {
1222
1727
 
1223
1728
  add: function(classNameToAdd) {
1224
1729
  if (this.include(classNameToAdd)) return;
1225
- this.set(this.toArray().concat(classNameToAdd).join(' '));
1730
+ this.set($A(this).concat(classNameToAdd).join(' '));
1226
1731
  },
1227
1732
 
1228
1733
  remove: function(classNameToRemove) {
1229
1734
  if (!this.include(classNameToRemove)) return;
1230
- this.set(this.select(function(className) {
1231
- return className != classNameToRemove;
1232
- }).join(' '));
1735
+ this.set($A(this).without(classNameToRemove).join(' '));
1233
1736
  },
1234
1737
 
1235
1738
  toString: function() {
1236
- return this.toArray().join(' ');
1739
+ return $A(this).join(' ');
1237
1740
  }
1238
- }
1741
+ };
1239
1742
 
1240
1743
  Object.extend(Element.ClassNames.prototype, Enumerable);
1241
1744
  var Selector = Class.create();
@@ -1282,15 +1785,15 @@ Selector.prototype = {
1282
1785
  if (params.wildcard)
1283
1786
  conditions.push('true');
1284
1787
  if (clause = params.id)
1285
- conditions.push('element.id == ' + clause.inspect());
1788
+ conditions.push('element.readAttribute("id") == ' + clause.inspect());
1286
1789
  if (clause = params.tagName)
1287
1790
  conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
1288
1791
  if ((clause = params.classNames).length > 0)
1289
- for (var i = 0; i < clause.length; i++)
1290
- conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
1792
+ for (var i = 0, length = clause.length; i < length; i++)
1793
+ conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
1291
1794
  if (clause = params.attributes) {
1292
1795
  clause.each(function(attribute) {
1293
- var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
1796
+ var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
1294
1797
  var splitValueBy = function(delimiter) {
1295
1798
  return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
1296
1799
  }
@@ -1303,7 +1806,7 @@ Selector.prototype = {
1303
1806
  ); break;
1304
1807
  case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
1305
1808
  case '':
1306
- case undefined: conditions.push(value + ' != null'); break;
1809
+ case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
1307
1810
  default: throw 'Unknown operator ' + attribute.operator + ' in selector';
1308
1811
  }
1309
1812
  });
@@ -1314,6 +1817,7 @@ Selector.prototype = {
1314
1817
 
1315
1818
  compileMatcher: function() {
1316
1819
  this.match = new Function('element', 'if (!element.tagName) return false; \
1820
+ element = $(element); \
1317
1821
  return ' + this.buildMatchExpression());
1318
1822
  },
1319
1823
 
@@ -1328,7 +1832,7 @@ Selector.prototype = {
1328
1832
  scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
1329
1833
 
1330
1834
  var results = [];
1331
- for (var i = 0; i < scope.length; i++)
1835
+ for (var i = 0, length = scope.length; i < length; i++)
1332
1836
  if (this.match(element = scope[i]))
1333
1837
  results.push(Element.extend(element));
1334
1838
 
@@ -1340,212 +1844,241 @@ Selector.prototype = {
1340
1844
  }
1341
1845
  }
1342
1846
 
1343
- function $$() {
1344
- return $A(arguments).map(function(expression) {
1345
- return expression.strip().split(/\s+/).inject([null], function(results, expr) {
1346
- var selector = new Selector(expr);
1347
- return results.map(selector.findElements.bind(selector)).flatten();
1348
- });
1349
- }).flatten();
1350
- }
1351
- var Field = {
1352
- clear: function() {
1353
- for (var i = 0; i < arguments.length; i++)
1354
- $(arguments[i]).value = '';
1355
- },
1356
-
1357
- focus: function(element) {
1358
- $(element).focus();
1359
- },
1360
-
1361
- present: function() {
1362
- for (var i = 0; i < arguments.length; i++)
1363
- if ($(arguments[i]).value == '') return false;
1364
- return true;
1847
+ Object.extend(Selector, {
1848
+ matchElements: function(elements, expression) {
1849
+ var selector = new Selector(expression);
1850
+ return elements.select(selector.match.bind(selector)).map(Element.extend);
1365
1851
  },
1366
1852
 
1367
- select: function(element) {
1368
- $(element).select();
1853
+ findElement: function(elements, expression, index) {
1854
+ if (typeof expression == 'number') index = expression, expression = false;
1855
+ return Selector.matchElements(elements, expression || '*')[index || 0];
1369
1856
  },
1370
1857
 
1371
- activate: function(element) {
1372
- element = $(element);
1373
- element.focus();
1374
- if (element.select)
1375
- element.select();
1858
+ findChildElements: function(element, expressions) {
1859
+ return expressions.map(function(expression) {
1860
+ return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
1861
+ var selector = new Selector(expr);
1862
+ return results.inject([], function(elements, result) {
1863
+ return elements.concat(selector.findElements(result || element));
1864
+ });
1865
+ });
1866
+ }).flatten();
1376
1867
  }
1377
- }
1378
-
1379
- /*--------------------------------------------------------------------------*/
1868
+ });
1380
1869
 
1870
+ function $$() {
1871
+ return Selector.findChildElements(document, $A(arguments));
1872
+ }
1381
1873
  var Form = {
1382
- serialize: function(form) {
1383
- var elements = Form.getElements($(form));
1384
- var queryComponents = new Array();
1385
-
1386
- for (var i = 0; i < elements.length; i++) {
1387
- var queryComponent = Form.Element.serialize(elements[i]);
1388
- if (queryComponent)
1389
- queryComponents.push(queryComponent);
1390
- }
1874
+ reset: function(form) {
1875
+ $(form).reset();
1876
+ return form;
1877
+ },
1878
+
1879
+ serializeElements: function(elements, getHash) {
1880
+ var data = elements.inject({}, function(result, element) {
1881
+ if (!element.disabled && element.name) {
1882
+ var key = element.name, value = $(element).getValue();
1883
+ if (value != undefined) {
1884
+ if (result[key]) {
1885
+ if (result[key].constructor != Array) result[key] = [result[key]];
1886
+ result[key].push(value);
1887
+ }
1888
+ else result[key] = value;
1889
+ }
1890
+ }
1891
+ return result;
1892
+ });
1893
+
1894
+ return getHash ? data : Hash.toQueryString(data);
1895
+ }
1896
+ };
1391
1897
 
1392
- return queryComponents.join('&');
1898
+ Form.Methods = {
1899
+ serialize: function(form, getHash) {
1900
+ return Form.serializeElements(Form.getElements(form), getHash);
1393
1901
  },
1394
1902
 
1395
1903
  getElements: function(form) {
1396
- form = $(form);
1397
- var elements = new Array();
1398
-
1399
- for (tagName in Form.Element.Serializers) {
1400
- var tagElements = form.getElementsByTagName(tagName);
1401
- for (var j = 0; j < tagElements.length; j++)
1402
- elements.push(tagElements[j]);
1403
- }
1404
- return elements;
1904
+ return $A($(form).getElementsByTagName('*')).inject([],
1905
+ function(elements, child) {
1906
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
1907
+ elements.push(Element.extend(child));
1908
+ return elements;
1909
+ }
1910
+ );
1405
1911
  },
1406
1912
 
1407
1913
  getInputs: function(form, typeName, name) {
1408
1914
  form = $(form);
1409
1915
  var inputs = form.getElementsByTagName('input');
1410
1916
 
1411
- if (!typeName && !name)
1412
- return inputs;
1917
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
1413
1918
 
1414
- var matchingInputs = new Array();
1415
- for (var i = 0; i < inputs.length; i++) {
1919
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
1416
1920
  var input = inputs[i];
1417
- if ((typeName && input.type != typeName) ||
1418
- (name && input.name != name))
1921
+ if ((typeName && input.type != typeName) || (name && input.name != name))
1419
1922
  continue;
1420
- matchingInputs.push(input);
1923
+ matchingInputs.push(Element.extend(input));
1421
1924
  }
1422
1925
 
1423
1926
  return matchingInputs;
1424
1927
  },
1425
1928
 
1426
1929
  disable: function(form) {
1427
- var elements = Form.getElements(form);
1428
- for (var i = 0; i < elements.length; i++) {
1429
- var element = elements[i];
1930
+ form = $(form);
1931
+ form.getElements().each(function(element) {
1430
1932
  element.blur();
1431
1933
  element.disabled = 'true';
1432
- }
1934
+ });
1935
+ return form;
1433
1936
  },
1434
1937
 
1435
1938
  enable: function(form) {
1436
- var elements = Form.getElements(form);
1437
- for (var i = 0; i < elements.length; i++) {
1438
- var element = elements[i];
1939
+ form = $(form);
1940
+ form.getElements().each(function(element) {
1439
1941
  element.disabled = '';
1440
- }
1942
+ });
1943
+ return form;
1441
1944
  },
1442
1945
 
1443
1946
  findFirstElement: function(form) {
1444
- return Form.getElements(form).find(function(element) {
1947
+ return $(form).getElements().find(function(element) {
1445
1948
  return element.type != 'hidden' && !element.disabled &&
1446
1949
  ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1447
1950
  });
1448
1951
  },
1449
1952
 
1450
1953
  focusFirstElement: function(form) {
1451
- Field.activate(Form.findFirstElement(form));
1954
+ form = $(form);
1955
+ form.findFirstElement().activate();
1956
+ return form;
1957
+ }
1958
+ }
1959
+
1960
+ Object.extend(Form, Form.Methods);
1961
+
1962
+ /*--------------------------------------------------------------------------*/
1963
+
1964
+ Form.Element = {
1965
+ focus: function(element) {
1966
+ $(element).focus();
1967
+ return element;
1452
1968
  },
1453
1969
 
1454
- reset: function(form) {
1455
- $(form).reset();
1970
+ select: function(element) {
1971
+ $(element).select();
1972
+ return element;
1456
1973
  }
1457
1974
  }
1458
1975
 
1459
- Form.Element = {
1976
+ Form.Element.Methods = {
1460
1977
  serialize: function(element) {
1978
+ element = $(element);
1979
+ if (!element.disabled && element.name) {
1980
+ var value = element.getValue();
1981
+ if (value != undefined) {
1982
+ var pair = {};
1983
+ pair[element.name] = value;
1984
+ return Hash.toQueryString(pair);
1985
+ }
1986
+ }
1987
+ return '';
1988
+ },
1989
+
1990
+ getValue: function(element) {
1461
1991
  element = $(element);
1462
1992
  var method = element.tagName.toLowerCase();
1463
- var parameter = Form.Element.Serializers[method](element);
1993
+ return Form.Element.Serializers[method](element);
1994
+ },
1464
1995
 
1465
- if (parameter) {
1466
- var key = encodeURIComponent(parameter[0]);
1467
- if (key.length == 0) return;
1996
+ clear: function(element) {
1997
+ $(element).value = '';
1998
+ return element;
1999
+ },
1468
2000
 
1469
- if (parameter[1].constructor != Array)
1470
- parameter[1] = [parameter[1]];
2001
+ present: function(element) {
2002
+ return $(element).value != '';
2003
+ },
1471
2004
 
1472
- return parameter[1].map(function(value) {
1473
- return key + '=' + encodeURIComponent(value);
1474
- }).join('&');
1475
- }
2005
+ activate: function(element) {
2006
+ element = $(element);
2007
+ element.focus();
2008
+ if (element.select && ( element.tagName.toLowerCase() != 'input' ||
2009
+ !['button', 'reset', 'submit'].include(element.type) ) )
2010
+ element.select();
2011
+ return element;
1476
2012
  },
1477
2013
 
1478
- getValue: function(element) {
2014
+ disable: function(element) {
1479
2015
  element = $(element);
1480
- var method = element.tagName.toLowerCase();
1481
- var parameter = Form.Element.Serializers[method](element);
2016
+ element.disabled = true;
2017
+ return element;
2018
+ },
1482
2019
 
1483
- if (parameter)
1484
- return parameter[1];
2020
+ enable: function(element) {
2021
+ element = $(element);
2022
+ element.blur();
2023
+ element.disabled = false;
2024
+ return element;
1485
2025
  }
1486
2026
  }
1487
2027
 
2028
+ Object.extend(Form.Element, Form.Element.Methods);
2029
+ var Field = Form.Element;
2030
+ var $F = Form.Element.getValue;
2031
+
2032
+ /*--------------------------------------------------------------------------*/
2033
+
1488
2034
  Form.Element.Serializers = {
1489
2035
  input: function(element) {
1490
2036
  switch (element.type.toLowerCase()) {
1491
- case 'submit':
1492
- case 'hidden':
1493
- case 'password':
1494
- case 'text':
1495
- return Form.Element.Serializers.textarea(element);
1496
2037
  case 'checkbox':
1497
2038
  case 'radio':
1498
2039
  return Form.Element.Serializers.inputSelector(element);
2040
+ default:
2041
+ return Form.Element.Serializers.textarea(element);
1499
2042
  }
1500
- return false;
1501
2043
  },
1502
2044
 
1503
2045
  inputSelector: function(element) {
1504
- if (element.checked)
1505
- return [element.name, element.value];
2046
+ return element.checked ? element.value : null;
1506
2047
  },
1507
2048
 
1508
2049
  textarea: function(element) {
1509
- return [element.name, element.value];
2050
+ return element.value;
1510
2051
  },
1511
2052
 
1512
2053
  select: function(element) {
1513
- return Form.Element.Serializers[element.type == 'select-one' ?
2054
+ return this[element.type == 'select-one' ?
1514
2055
  'selectOne' : 'selectMany'](element);
1515
2056
  },
1516
2057
 
1517
2058
  selectOne: function(element) {
1518
- var value = '', opt, index = element.selectedIndex;
1519
- if (index >= 0) {
1520
- opt = element.options[index];
1521
- value = opt.value;
1522
- if (!value && !('value' in opt))
1523
- value = opt.text;
1524
- }
1525
- return [element.name, value];
2059
+ var index = element.selectedIndex;
2060
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
1526
2061
  },
1527
2062
 
1528
2063
  selectMany: function(element) {
1529
- var value = new Array();
1530
- for (var i = 0; i < element.length; i++) {
2064
+ var values, length = element.length;
2065
+ if (!length) return null;
2066
+
2067
+ for (var i = 0, values = []; i < length; i++) {
1531
2068
  var opt = element.options[i];
1532
- if (opt.selected) {
1533
- var optValue = opt.value;
1534
- if (!optValue && !('value' in opt))
1535
- optValue = opt.text;
1536
- value.push(optValue);
1537
- }
2069
+ if (opt.selected) values.push(this.optionValue(opt));
1538
2070
  }
1539
- return [element.name, value];
2071
+ return values;
2072
+ },
2073
+
2074
+ optionValue: function(opt) {
2075
+ // extend element because hasAttribute may not be native
2076
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
1540
2077
  }
1541
2078
  }
1542
2079
 
1543
2080
  /*--------------------------------------------------------------------------*/
1544
2081
 
1545
- var $F = Form.Element.getValue;
1546
-
1547
- /*--------------------------------------------------------------------------*/
1548
-
1549
2082
  Abstract.TimedObserver = function() {}
1550
2083
  Abstract.TimedObserver.prototype = {
1551
2084
  initialize: function(element, frequency, callback) {
@@ -1563,7 +2096,9 @@ Abstract.TimedObserver.prototype = {
1563
2096
 
1564
2097
  onTimerEvent: function() {
1565
2098
  var value = this.getValue();
1566
- if (this.lastValue != value) {
2099
+ var changed = ('string' == typeof this.lastValue && 'string' == typeof value
2100
+ ? this.lastValue != value : String(this.lastValue) != String(value));
2101
+ if (changed) {
1567
2102
  this.callback(this.element, value);
1568
2103
  this.lastValue = value;
1569
2104
  }
@@ -1608,9 +2143,7 @@ Abstract.EventObserver.prototype = {
1608
2143
  },
1609
2144
 
1610
2145
  registerFormCallbacks: function() {
1611
- var elements = Form.getElements(this.element);
1612
- for (var i = 0; i < elements.length; i++)
1613
- this.registerCallback(elements[i]);
2146
+ Form.getElements(this.element).each(this.registerCallback.bind(this));
1614
2147
  },
1615
2148
 
1616
2149
  registerCallback: function(element) {
@@ -1620,11 +2153,7 @@ Abstract.EventObserver.prototype = {
1620
2153
  case 'radio':
1621
2154
  Event.observe(element, 'click', this.onElementEvent.bind(this));
1622
2155
  break;
1623
- case 'password':
1624
- case 'text':
1625
- case 'textarea':
1626
- case 'select-one':
1627
- case 'select-multiple':
2156
+ default:
1628
2157
  Event.observe(element, 'change', this.onElementEvent.bind(this));
1629
2158
  break;
1630
2159
  }
@@ -1659,6 +2188,10 @@ Object.extend(Event, {
1659
2188
  KEY_RIGHT: 39,
1660
2189
  KEY_DOWN: 40,
1661
2190
  KEY_DELETE: 46,
2191
+ KEY_HOME: 36,
2192
+ KEY_END: 35,
2193
+ KEY_PAGEUP: 33,
2194
+ KEY_PAGEDOWN: 34,
1662
2195
 
1663
2196
  element: function(event) {
1664
2197
  return event.target || event.srcElement;
@@ -1714,7 +2247,7 @@ Object.extend(Event, {
1714
2247
 
1715
2248
  unloadCache: function() {
1716
2249
  if (!Event.observers) return;
1717
- for (var i = 0; i < Event.observers.length; i++) {
2250
+ for (var i = 0, length = Event.observers.length; i < length; i++) {
1718
2251
  Event.stopObserving.apply(this, Event.observers[i]);
1719
2252
  Event.observers[i][0] = null;
1720
2253
  }
@@ -1722,7 +2255,7 @@ Object.extend(Event, {
1722
2255
  },
1723
2256
 
1724
2257
  observe: function(element, name, observer, useCapture) {
1725
- var element = $(element);
2258
+ element = $(element);
1726
2259
  useCapture = useCapture || false;
1727
2260
 
1728
2261
  if (name == 'keypress' &&
@@ -1730,11 +2263,11 @@ Object.extend(Event, {
1730
2263
  || element.attachEvent))
1731
2264
  name = 'keydown';
1732
2265
 
1733
- this._observeAndCache(element, name, observer, useCapture);
2266
+ Event._observeAndCache(element, name, observer, useCapture);
1734
2267
  },
1735
2268
 
1736
2269
  stopObserving: function(element, name, observer, useCapture) {
1737
- var element = $(element);
2270
+ element = $(element);
1738
2271
  useCapture = useCapture || false;
1739
2272
 
1740
2273
  if (name == 'keypress' &&
@@ -1745,13 +2278,16 @@ Object.extend(Event, {
1745
2278
  if (element.removeEventListener) {
1746
2279
  element.removeEventListener(name, observer, useCapture);
1747
2280
  } else if (element.detachEvent) {
1748
- element.detachEvent('on' + name, observer);
2281
+ try {
2282
+ element.detachEvent('on' + name, observer);
2283
+ } catch (e) {}
1749
2284
  }
1750
2285
  }
1751
2286
  });
1752
2287
 
1753
2288
  /* prevent memory leaks in IE */
1754
- Event.observe(window, 'unload', Event.unloadCache, false);
2289
+ if (navigator.appVersion.match(/\bMSIE\b/))
2290
+ Event.observe(window, 'unload', Event.unloadCache, false);
1755
2291
  var Position = {
1756
2292
  // set to true if needed, warning: firefox performance problems
1757
2293
  // NOT neeeded for page scrolling, only if draggable contained in
@@ -1798,7 +2334,8 @@ var Position = {
1798
2334
  valueL += element.offsetLeft || 0;
1799
2335
  element = element.offsetParent;
1800
2336
  if (element) {
1801
- p = Element.getStyle(element, 'position');
2337
+ if(element.tagName=='BODY') break;
2338
+ var p = Element.getStyle(element, 'position');
1802
2339
  if (p == 'relative' || p == 'absolute') break;
1803
2340
  }
1804
2341
  } while (element);
@@ -1854,17 +2391,6 @@ var Position = {
1854
2391
  element.offsetWidth;
1855
2392
  },
1856
2393
 
1857
- clone: function(source, target) {
1858
- source = $(source);
1859
- target = $(target);
1860
- target.style.position = 'absolute';
1861
- var offsets = this.cumulativeOffset(source);
1862
- target.style.top = offsets[1] + 'px';
1863
- target.style.left = offsets[0] + 'px';
1864
- target.style.width = source.offsetWidth + 'px';
1865
- target.style.height = source.offsetHeight + 'px';
1866
- },
1867
-
1868
2394
  page: function(forElement) {
1869
2395
  var valueT = 0, valueL = 0;
1870
2396
 
@@ -1881,8 +2407,10 @@ var Position = {
1881
2407
 
1882
2408
  element = forElement;
1883
2409
  do {
1884
- valueT -= element.scrollTop || 0;
1885
- valueL -= element.scrollLeft || 0;
2410
+ if (!window.opera || element.tagName=='BODY') {
2411
+ valueT -= element.scrollTop || 0;
2412
+ valueL -= element.scrollLeft || 0;
2413
+ }
1886
2414
  } while (element = element.parentNode);
1887
2415
 
1888
2416
  return [valueL, valueT];
@@ -1943,10 +2471,10 @@ var Position = {
1943
2471
  element._originalHeight = element.style.height;
1944
2472
 
1945
2473
  element.style.position = 'absolute';
1946
- element.style.top = top + 'px';;
1947
- element.style.left = left + 'px';;
1948
- element.style.width = width + 'px';;
1949
- element.style.height = height + 'px';;
2474
+ element.style.top = top + 'px';
2475
+ element.style.left = left + 'px';
2476
+ element.style.width = width + 'px';
2477
+ element.style.height = height + 'px';
1950
2478
  },
1951
2479
 
1952
2480
  relativize: function(element) {
@@ -1982,4 +2510,6 @@ if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1982
2510
 
1983
2511
  return [valueL, valueT];
1984
2512
  }
1985
- }
2513
+ }
2514
+
2515
+ Element.addMethods();