parlement 0.10 → 0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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();