rails 0.13.1 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (86) hide show
  1. data/CHANGELOG +105 -0
  2. data/Rakefile +39 -17
  3. data/bin/breakpointer +2 -2
  4. data/bin/console +2 -22
  5. data/bin/destroy +2 -6
  6. data/bin/generate +2 -6
  7. data/bin/performance/benchmarker +3 -0
  8. data/bin/performance/profiler +3 -0
  9. data/bin/process/reaper +3 -0
  10. data/bin/process/spawner +3 -0
  11. data/bin/process/spinner +3 -0
  12. data/bin/rails +4 -0
  13. data/bin/runner +2 -27
  14. data/bin/server +2 -48
  15. data/configs/apache.conf +8 -0
  16. data/configs/database.yml +8 -8
  17. data/environments/boot.rb +17 -0
  18. data/environments/development.rb +10 -7
  19. data/environments/environment.rb +37 -73
  20. data/environments/production.rb +15 -6
  21. data/environments/test.rb +12 -6
  22. data/fresh_rakefile +6 -198
  23. data/helpers/application.rb +2 -2
  24. data/helpers/application_helper.rb +1 -1
  25. data/helpers/test_helper.rb +6 -19
  26. data/html/javascripts/controls.js +427 -165
  27. data/html/javascripts/dragdrop.js +256 -277
  28. data/html/javascripts/effects.js +766 -277
  29. data/html/javascripts/prototype.js +903 -217
  30. data/html/javascripts/scriptaculous.js +47 -0
  31. data/html/javascripts/slider.js +258 -0
  32. data/html/robots.txt +1 -0
  33. data/lib/binding_of_caller.rb +3 -1
  34. data/lib/breakpoint.rb +5 -5
  35. data/lib/breakpoint_client.rb +1 -1
  36. data/lib/code_statistics.rb +7 -4
  37. data/lib/commands.rb +17 -0
  38. data/lib/commands/breakpointer.rb +1 -0
  39. data/lib/commands/console.rb +22 -0
  40. data/lib/commands/destroy.rb +6 -0
  41. data/lib/commands/generate.rb +6 -0
  42. data/{bin → lib/commands/ncgi}/listener +0 -0
  43. data/{bin → lib/commands/ncgi}/tracker +0 -0
  44. data/lib/commands/performance/benchmarker.rb +26 -0
  45. data/{bin/profiler → lib/commands/performance/profiler.rb} +3 -2
  46. data/lib/commands/process/reaper.rb +130 -0
  47. data/lib/commands/process/spawner.rb +52 -0
  48. data/lib/commands/process/spinner.rb +57 -0
  49. data/lib/commands/runner.rb +27 -0
  50. data/lib/commands/server.rb +59 -0
  51. data/{bin/update → lib/commands/update.rb} +1 -2
  52. data/lib/dispatcher.rb +20 -3
  53. data/lib/fcgi_handler.rb +59 -41
  54. data/lib/initializer.rb +479 -0
  55. data/lib/rails_generator/base.rb +2 -2
  56. data/lib/rails_generator/commands.rb +59 -7
  57. data/lib/rails_generator/generators/applications/app/app_generator.rb +26 -15
  58. data/lib/rails_generator/generators/components/controller/controller_generator.rb +3 -2
  59. data/lib/rails_generator/generators/components/controller/templates/view.rhtml +1 -1
  60. data/lib/rails_generator/generators/components/mailer/USAGE +2 -3
  61. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +1 -1
  62. data/lib/rails_generator/generators/components/migration/migration_generator.rb +3 -1
  63. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +32 -31
  64. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml +1 -1
  65. data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +1 -1
  66. data/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml +1 -1
  67. data/lib/rails_generator/lookup.rb +3 -3
  68. data/lib/rails_generator/options.rb +1 -0
  69. data/lib/rails_generator/scripts.rb +1 -1
  70. data/lib/rails_version.rb +9 -0
  71. data/lib/railties_path.rb +1 -0
  72. data/lib/rubyprof_ext.rb +1 -1
  73. data/lib/tasks/databases.rake +152 -0
  74. data/lib/tasks/documentation.rake +44 -0
  75. data/lib/tasks/framework.rake +33 -0
  76. data/lib/tasks/javascripts.rake +6 -0
  77. data/lib/tasks/misc.rake +15 -0
  78. data/lib/tasks/rails.rb +7 -0
  79. data/lib/tasks/statistics.rake +16 -0
  80. data/lib/tasks/testing.rake +37 -0
  81. data/lib/test_help.rb +13 -0
  82. data/lib/webrick_server.rb +31 -9
  83. metadata +121 -85
  84. data/bin/benchmarker +0 -19
  85. data/bin/breakpointer_for_gem +0 -4
  86. data/bin/console_sandbox +0 -0
@@ -1,8 +1,8 @@
1
- /* Prototype JavaScript framework, version 1.3.1
1
+ /* Prototype JavaScript framework, version 1.4.0_rc0
2
2
  * (c) 2005 Sam Stephenson <sam@conio.net>
3
3
  *
4
4
  * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
5
- * against the source tree, available from the Prototype darcs repository.
5
+ * against the source tree, available from the Prototype darcs repository.
6
6
  *
7
7
  * Prototype is freely distributable under the terms of an MIT-style license.
8
8
  *
@@ -11,13 +11,15 @@
11
11
  /*--------------------------------------------------------------------------*/
12
12
 
13
13
  var Prototype = {
14
- Version: '1.3.1',
15
- emptyFunction: function() {}
14
+ Version: '1.4.0_rc0',
15
+
16
+ emptyFunction: function() {},
17
+ K: function(x) {return x}
16
18
  }
17
19
 
18
20
  var Class = {
19
21
  create: function() {
20
- return function() {
22
+ return function() {
21
23
  this.initialize.apply(this, arguments);
22
24
  }
23
25
  }
@@ -32,29 +34,47 @@ Object.extend = function(destination, source) {
32
34
  return destination;
33
35
  }
34
36
 
35
- Object.prototype.extend = function(object) {
36
- return Object.extend.apply(this, [this, object]);
37
+ Object.inspect = function(object) {
38
+ try {
39
+ if (object == undefined) return 'undefined';
40
+ if (object == null) return 'null';
41
+ return object.inspect ? object.inspect() : object.toString();
42
+ } catch (e) {
43
+ if (e instanceof RangeError) return '...';
44
+ throw e;
45
+ }
37
46
  }
38
47
 
39
48
  Function.prototype.bind = function(object) {
40
49
  var __method = this;
41
50
  return function() {
42
- __method.apply(object, arguments);
51
+ return __method.apply(object, arguments);
43
52
  }
44
53
  }
45
54
 
46
55
  Function.prototype.bindAsEventListener = function(object) {
47
56
  var __method = this;
48
57
  return function(event) {
49
- __method.call(object, event || window.event);
58
+ return __method.call(object, event || window.event);
50
59
  }
51
60
  }
52
61
 
53
- Number.prototype.toColorPart = function() {
54
- var digits = this.toString(16);
55
- if (this < 16) return '0' + digits;
56
- return digits;
57
- }
62
+ Object.extend(Number.prototype, {
63
+ toColorPart: function() {
64
+ var digits = this.toString(16);
65
+ if (this < 16) return '0' + digits;
66
+ return digits;
67
+ },
68
+
69
+ succ: function() {
70
+ return this + 1;
71
+ },
72
+
73
+ times: function(iterator) {
74
+ $R(0, this, true).each(iterator);
75
+ return this;
76
+ }
77
+ });
58
78
 
59
79
  var Try = {
60
80
  these: function() {
@@ -90,10 +110,10 @@ PeriodicalExecuter.prototype = {
90
110
 
91
111
  onTimerEvent: function() {
92
112
  if (!this.currentlyExecuting) {
93
- try {
113
+ try {
94
114
  this.currentlyExecuting = true;
95
- this.callback();
96
- } finally {
115
+ this.callback();
116
+ } finally {
97
117
  this.currentlyExecuting = false;
98
118
  }
99
119
  }
@@ -110,7 +130,7 @@ function $() {
110
130
  if (typeof element == 'string')
111
131
  element = document.getElementById(element);
112
132
 
113
- if (arguments.length == 1)
133
+ if (arguments.length == 1)
114
134
  return element;
115
135
 
116
136
  elements.push(element);
@@ -118,36 +138,7 @@ function $() {
118
138
 
119
139
  return elements;
120
140
  }
121
-
122
- if (!Array.prototype.push) {
123
- Array.prototype.push = function() {
124
- var startLength = this.length;
125
- for (var i = 0; i < arguments.length; i++)
126
- this[startLength + i] = arguments[i];
127
- return this.length;
128
- }
129
- }
130
-
131
- if (!Function.prototype.apply) {
132
- // Based on code from http://www.youngpup.net/
133
- Function.prototype.apply = function(object, parameters) {
134
- var parameterStrings = new Array();
135
- if (!object) object = window;
136
- if (!parameters) parameters = new Array();
137
-
138
- for (var i = 0; i < parameters.length; i++)
139
- parameterStrings[i] = 'parameters[' + i + ']';
140
-
141
- object.__apply__ = this;
142
- var result = eval('object.__apply__(' +
143
- parameterStrings[i].join(', ') + ')');
144
- object.__apply__ = null;
145
-
146
- return result;
147
- }
148
- }
149
-
150
- String.prototype.extend({
141
+ Object.extend(String.prototype, {
151
142
  stripTags: function() {
152
143
  return this.replace(/<\/?[^>]+>/gi, '');
153
144
  },
@@ -162,9 +153,368 @@ String.prototype.extend({
162
153
  unescapeHTML: function() {
163
154
  var div = document.createElement('div');
164
155
  div.innerHTML = this.stripTags();
165
- return div.childNodes[0].nodeValue;
156
+ return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
157
+ },
158
+
159
+ toQueryParams: function() {
160
+ var pairs = this.match(/^\??(.*)$/)[1].split('&');
161
+ return pairs.inject({}, function(params, pairString) {
162
+ var pair = pairString.split('=');
163
+ params[pair[0]] = pair[1];
164
+ return params;
165
+ });
166
+ },
167
+
168
+ toArray: function() {
169
+ return this.split('');
170
+ },
171
+
172
+ camelize: function() {
173
+ var oStringList = this.split('-');
174
+ if (oStringList.length == 1) return oStringList[0];
175
+
176
+ var camelizedString = this.indexOf('-') == 0
177
+ ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
178
+ : oStringList[0];
179
+
180
+ for (var i = 1, len = oStringList.length; i < len; i++) {
181
+ var s = oStringList[i];
182
+ camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
183
+ }
184
+
185
+ return camelizedString;
186
+ },
187
+
188
+ inspect: function() {
189
+ return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
190
+ }
191
+ });
192
+
193
+ String.prototype.parseQuery = String.prototype.toQueryParams;
194
+
195
+ var $break = new Object();
196
+ var $continue = new Object();
197
+
198
+ var Enumerable = {
199
+ each: function(iterator) {
200
+ var index = 0;
201
+ try {
202
+ this._each(function(value) {
203
+ try {
204
+ iterator(value, index++);
205
+ } catch (e) {
206
+ if (e != $continue) throw e;
207
+ }
208
+ });
209
+ } catch (e) {
210
+ if (e != $break) throw e;
211
+ }
212
+ },
213
+
214
+ all: function(iterator) {
215
+ var result = true;
216
+ this.each(function(value, index) {
217
+ if (!(result &= (iterator || Prototype.K)(value, index)))
218
+ throw $break;
219
+ });
220
+ return result;
221
+ },
222
+
223
+ any: function(iterator) {
224
+ var result = true;
225
+ this.each(function(value, index) {
226
+ if (result &= (iterator || Prototype.K)(value, index))
227
+ throw $break;
228
+ });
229
+ return result;
230
+ },
231
+
232
+ collect: function(iterator) {
233
+ var results = [];
234
+ this.each(function(value, index) {
235
+ results.push(iterator(value, index));
236
+ });
237
+ return results;
238
+ },
239
+
240
+ detect: function (iterator) {
241
+ var result;
242
+ this.each(function(value, index) {
243
+ if (iterator(value, index)) {
244
+ result = value;
245
+ throw $break;
246
+ }
247
+ });
248
+ return result;
249
+ },
250
+
251
+ findAll: function(iterator) {
252
+ var results = [];
253
+ this.each(function(value, index) {
254
+ if (iterator(value, index))
255
+ results.push(value);
256
+ });
257
+ return results;
258
+ },
259
+
260
+ grep: function(pattern, iterator) {
261
+ var results = [];
262
+ this.each(function(value, index) {
263
+ var stringValue = value.toString();
264
+ if (stringValue.match(pattern))
265
+ results.push((iterator || Prototype.K)(value, index));
266
+ })
267
+ return results;
268
+ },
269
+
270
+ include: function(object) {
271
+ var found = false;
272
+ this.each(function(value) {
273
+ if (value == object) {
274
+ found = true;
275
+ throw $break;
276
+ }
277
+ });
278
+ return found;
279
+ },
280
+
281
+ inject: function(memo, iterator) {
282
+ this.each(function(value, index) {
283
+ memo = iterator(memo, value, index);
284
+ });
285
+ return memo;
286
+ },
287
+
288
+ invoke: function(method) {
289
+ var args = $A(arguments).slice(1);
290
+ return this.collect(function(value) {
291
+ return value[method].apply(value, args);
292
+ });
293
+ },
294
+
295
+ max: function(iterator) {
296
+ var result;
297
+ this.each(function(value, index) {
298
+ value = (iterator || Prototype.K)(value, index);
299
+ if (value >= (result || value))
300
+ result = value;
301
+ });
302
+ return result;
303
+ },
304
+
305
+ min: function(iterator) {
306
+ var result;
307
+ this.each(function(value, index) {
308
+ value = (iterator || Prototype.K)(value, index);
309
+ if (value <= (result || value))
310
+ result = value;
311
+ });
312
+ return result;
313
+ },
314
+
315
+ partition: function(iterator) {
316
+ var trues = [], falses = [];
317
+ this.each(function(value, index) {
318
+ ((iterator || Prototype.K)(value, index) ?
319
+ trues : falses).push(value);
320
+ });
321
+ return [trues, falses];
322
+ },
323
+
324
+ pluck: function(property) {
325
+ var results = [];
326
+ this.each(function(value, index) {
327
+ results.push(value[property]);
328
+ });
329
+ return results;
330
+ },
331
+
332
+ reject: function(iterator) {
333
+ var results = [];
334
+ this.each(function(value, index) {
335
+ if (!iterator(value, index))
336
+ results.push(value);
337
+ });
338
+ return results;
339
+ },
340
+
341
+ sortBy: function(iterator) {
342
+ return this.collect(function(value, index) {
343
+ return {value: value, criteria: iterator(value, index)};
344
+ }).sort(function(left, right) {
345
+ var a = left.criteria, b = right.criteria;
346
+ return a < b ? -1 : a > b ? 1 : 0;
347
+ }).pluck('value');
348
+ },
349
+
350
+ toArray: function() {
351
+ return this.collect(Prototype.K);
352
+ },
353
+
354
+ zip: function() {
355
+ var iterator = Prototype.K, args = $A(arguments);
356
+ if (typeof args.last() == 'function')
357
+ iterator = args.pop();
358
+
359
+ var collections = [this].concat(args).map($A);
360
+ return this.map(function(value, index) {
361
+ iterator(value = collections.pluck(index));
362
+ return value;
363
+ });
364
+ },
365
+
366
+ inspect: function() {
367
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
368
+ }
369
+ }
370
+
371
+ Object.extend(Enumerable, {
372
+ map: Enumerable.collect,
373
+ find: Enumerable.detect,
374
+ select: Enumerable.findAll,
375
+ member: Enumerable.include,
376
+ entries: Enumerable.toArray
377
+ });
378
+ var $A = Array.from = function(iterable) {
379
+ if (iterable.toArray) {
380
+ return iterable.toArray();
381
+ } else {
382
+ var results = [];
383
+ for (var i = 0; i < iterable.length; i++)
384
+ results.push(iterable[i]);
385
+ return results;
386
+ }
387
+ }
388
+
389
+ Object.extend(Array.prototype, Enumerable);
390
+
391
+ Object.extend(Array.prototype, {
392
+ _each: function(iterator) {
393
+ for (var i = 0; i < this.length; i++)
394
+ iterator(this[i]);
395
+ },
396
+
397
+ first: function() {
398
+ return this[0];
399
+ },
400
+
401
+ last: function() {
402
+ return this[this.length - 1];
403
+ },
404
+
405
+ compact: function() {
406
+ return this.select(function(value) {
407
+ return value != undefined || value != null;
408
+ });
409
+ },
410
+
411
+ flatten: function() {
412
+ return this.inject([], function(array, value) {
413
+ return array.concat(value.constructor == Array ?
414
+ value.flatten() : [value]);
415
+ });
416
+ },
417
+
418
+ without: function() {
419
+ var values = $A(arguments);
420
+ return this.select(function(value) {
421
+ return !values.include(value);
422
+ });
423
+ },
424
+
425
+ indexOf: function(object) {
426
+ for (var i = 0; i < this.length; i++)
427
+ if (this[i] == object) return i;
428
+ return false;
429
+ },
430
+
431
+ reverse: function() {
432
+ var result = [];
433
+ for (var i = this.length; i > 0; i--)
434
+ result.push(this[i-1]);
435
+ return result;
436
+ },
437
+
438
+ inspect: function() {
439
+ return '[' + this.map(Object.inspect).join(', ') + ']';
166
440
  }
167
441
  });
442
+ var Hash = {
443
+ _each: function(iterator) {
444
+ for (key in this) {
445
+ var value = this[key];
446
+ if (typeof value == 'function') continue;
447
+
448
+ var pair = [key, value];
449
+ pair.key = key;
450
+ pair.value = value;
451
+ iterator(pair);
452
+ }
453
+ },
454
+
455
+ keys: function() {
456
+ return this.pluck('key');
457
+ },
458
+
459
+ values: function() {
460
+ return this.pluck('value');
461
+ },
462
+
463
+ merge: function(hash) {
464
+ return $H(hash).inject($H(this), function(mergedHash, pair) {
465
+ mergedHash[pair.key] = pair.value;
466
+ return mergedHash;
467
+ });
468
+ },
469
+
470
+ toQueryString: function() {
471
+ return this.map(function(pair) {
472
+ return pair.map(encodeURIComponent).join('=');
473
+ }).join('&');
474
+ },
475
+
476
+ inspect: function() {
477
+ return '#<Hash:{' + this.map(function(pair) {
478
+ return pair.map(Object.inspect).join(': ');
479
+ }).join(', ') + '}>';
480
+ }
481
+ }
482
+
483
+ function $H(object) {
484
+ var hash = Object.extend({}, object || {});
485
+ Object.extend(hash, Enumerable);
486
+ Object.extend(hash, Hash);
487
+ return hash;
488
+ }
489
+ var Range = Class.create();
490
+ Object.extend(Range.prototype, Enumerable);
491
+ Object.extend(Range.prototype, {
492
+ initialize: function(start, end, exclusive) {
493
+ this.start = start;
494
+ this.end = end;
495
+ this.exclusive = exclusive;
496
+ },
497
+
498
+ _each: function(iterator) {
499
+ var value = this.start;
500
+ do {
501
+ iterator(value);
502
+ value = value.succ();
503
+ } while (this.include(value));
504
+ },
505
+
506
+ include: function(value) {
507
+ if (value < this.start)
508
+ return false;
509
+ if (this.exclusive)
510
+ return value < this.end;
511
+ return value <= this.end;
512
+ }
513
+ });
514
+
515
+ var $R = function(start, end, exclusive) {
516
+ return new Range(start, end, exclusive);
517
+ }
168
518
 
169
519
  var Ajax = {
170
520
  getTransport: function() {
@@ -173,9 +523,51 @@ var Ajax = {
173
523
  function() {return new ActiveXObject('Microsoft.XMLHTTP')},
174
524
  function() {return new XMLHttpRequest()}
175
525
  ) || false;
176
- }
526
+ },
527
+
528
+ activeRequestCount: 0
177
529
  }
178
530
 
531
+ Ajax.Responders = {
532
+ responders: [],
533
+
534
+ _each: function(iterator) {
535
+ this.responders._each(iterator);
536
+ },
537
+
538
+ register: function(responderToAdd) {
539
+ if (!this.include(responderToAdd))
540
+ this.responders.push(responderToAdd);
541
+ },
542
+
543
+ unregister: function(responderToRemove) {
544
+ this.responders = this.responders.without(responderToRemove);
545
+ },
546
+
547
+ dispatch: function(callback, request, transport, json) {
548
+ this.each(function(responder) {
549
+ if (responder[callback] && typeof responder[callback] == 'function') {
550
+ try {
551
+ responder[callback].apply(responder, [request, transport, json]);
552
+ } catch (e) {
553
+ }
554
+ }
555
+ });
556
+ }
557
+ };
558
+
559
+ Object.extend(Ajax.Responders, Enumerable);
560
+
561
+ Ajax.Responders.register({
562
+ onCreate: function() {
563
+ Ajax.activeRequestCount++;
564
+ },
565
+
566
+ onComplete: function() {
567
+ Ajax.activeRequestCount--;
568
+ }
569
+ });
570
+
179
571
  Ajax.Base = function() {};
180
572
  Ajax.Base.prototype = {
181
573
  setOptions: function(options) {
@@ -183,12 +575,13 @@ Ajax.Base.prototype = {
183
575
  method: 'post',
184
576
  asynchronous: true,
185
577
  parameters: ''
186
- }.extend(options || {});
578
+ }
579
+ Object.extend(this.options, options || {});
187
580
  },
188
581
 
189
582
  responseIsSuccess: function() {
190
583
  return this.transport.status == undefined
191
- || this.transport.status == 0
584
+ || this.transport.status == 0
192
585
  || (this.transport.status >= 200 && this.transport.status < 300);
193
586
  },
194
587
 
@@ -198,10 +591,10 @@ Ajax.Base.prototype = {
198
591
  }
199
592
 
200
593
  Ajax.Request = Class.create();
201
- Ajax.Request.Events =
594
+ Ajax.Request.Events =
202
595
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
203
596
 
204
- Ajax.Request.prototype = (new Ajax.Base()).extend({
597
+ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
205
598
  initialize: function(url, options) {
206
599
  this.transport = Ajax.getTransport();
207
600
  this.setOptions(options);
@@ -213,10 +606,13 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
213
606
  if (parameters.length > 0) parameters += '&_=';
214
607
 
215
608
  try {
609
+ this.url = url;
216
610
  if (this.options.method == 'get')
217
- url += '?' + parameters;
611
+ this.url += '?' + parameters;
612
+
613
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
218
614
 
219
- this.transport.open(this.options.method, url,
615
+ this.transport.open(this.options.method, this.url,
220
616
  this.options.asynchronous);
221
617
 
222
618
  if (this.options.asynchronous) {
@@ -234,17 +630,17 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
234
630
  },
235
631
 
236
632
  setRequestHeaders: function() {
237
- var requestHeaders =
633
+ var requestHeaders =
238
634
  ['X-Requested-With', 'XMLHttpRequest',
239
635
  'X-Prototype-Version', Prototype.Version];
240
636
 
241
637
  if (this.options.method == 'post') {
242
- requestHeaders.push('Content-type',
638
+ requestHeaders.push('Content-type',
243
639
  'application/x-www-form-urlencoded');
244
640
 
245
641
  /* Force "Connection: close" for Mozilla browsers to work around
246
642
  * a bug where XMLHttpReqeuest sends an incorrect Content-length
247
- * header. See Mozilla Bugzilla #246651.
643
+ * header. See Mozilla Bugzilla #246651.
248
644
  */
249
645
  if (this.transport.overrideMimeType)
250
646
  requestHeaders.push('Connection', 'close');
@@ -263,15 +659,26 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
263
659
  this.respondToReadyState(this.transport.readyState);
264
660
  },
265
661
 
662
+ evalJSON: function() {
663
+ try {
664
+ var json = this.transport.getResponseHeader('X-JSON'), object;
665
+ object = eval(json);
666
+ return object;
667
+ } catch (e) {
668
+ }
669
+ },
670
+
266
671
  respondToReadyState: function(readyState) {
267
672
  var event = Ajax.Request.Events[readyState];
673
+ var transport = this.transport, json = this.evalJSON();
268
674
 
269
675
  if (event == 'Complete')
270
676
  (this.options['on' + this.transport.status]
271
- || this.options['on' + this.responseIsSuccess() ? 'Success' : 'Failure']
272
- || Prototype.emptyFunction)(this.transport);
677
+ || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
678
+ || Prototype.emptyFunction)(transport, json);
273
679
 
274
- (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
680
+ (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
681
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
275
682
 
276
683
  /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
277
684
  if (event == 'Complete')
@@ -282,7 +689,7 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
282
689
  Ajax.Updater = Class.create();
283
690
  Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
284
691
 
285
- Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
692
+ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
286
693
  initialize: function(container, url, options) {
287
694
  this.containers = {
288
695
  success: container.success ? $(container.success) : $(container),
@@ -294,9 +701,9 @@ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
294
701
  this.setOptions(options);
295
702
 
296
703
  var onComplete = this.options.onComplete || Prototype.emptyFunction;
297
- this.options.onComplete = (function() {
704
+ this.options.onComplete = (function(transport, object) {
298
705
  this.updateContent();
299
- onComplete(this.transport);
706
+ onComplete(transport, object);
300
707
  }).bind(this);
301
708
 
302
709
  this.request(url);
@@ -320,8 +727,7 @@ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
320
727
 
321
728
  if (this.responseIsSuccess()) {
322
729
  if (this.onComplete)
323
- setTimeout((function() {this.onComplete(
324
- this.transport)}).bind(this), 10);
730
+ setTimeout(this.onComplete.bind(this), 10);
325
731
  }
326
732
 
327
733
  if (this.options.evalScripts && scripts) {
@@ -335,13 +741,13 @@ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
335
741
  });
336
742
 
337
743
  Ajax.PeriodicalUpdater = Class.create();
338
- Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
744
+ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
339
745
  initialize: function(container, url, options) {
340
746
  this.setOptions(options);
341
747
  this.onComplete = this.options.onComplete;
342
748
 
343
749
  this.frequency = (this.options.frequency || 2);
344
- this.decay = 1;
750
+ this.decay = (this.options.decay || 1);
345
751
 
346
752
  this.updater = {};
347
753
  this.container = container;
@@ -358,17 +764,17 @@ Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
358
764
  stop: function() {
359
765
  this.updater.onComplete = undefined;
360
766
  clearTimeout(this.timer);
361
- (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
767
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
362
768
  },
363
769
 
364
770
  updateComplete: function(request) {
365
771
  if (this.options.decay) {
366
- this.decay = (request.responseText == this.lastText ?
772
+ this.decay = (request.responseText == this.lastText ?
367
773
  this.decay * this.options.decay : 1);
368
774
 
369
775
  this.lastText = request.responseText;
370
776
  }
371
- this.timer = setTimeout(this.onTimerEvent.bind(this),
777
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
372
778
  this.decay * this.frequency * 1000);
373
779
  },
374
780
 
@@ -376,23 +782,13 @@ Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
376
782
  this.updater = new Ajax.Updater(this.container, this.url, this.options);
377
783
  }
378
784
  });
379
-
380
- document.getElementsByClassName = function(className) {
381
- var children = document.getElementsByTagName('*') || document.all;
382
- var elements = new Array();
383
-
384
- for (var i = 0; i < children.length; i++) {
385
- var child = children[i];
386
- var classNames = child.className.split(' ');
387
- for (var j = 0; j < classNames.length; j++) {
388
- if (classNames[j] == className) {
389
- elements.push(child);
390
- break;
391
- }
392
- }
393
- }
394
-
395
- return elements;
785
+ document.getElementsByClassName = function(className, parentElement) {
786
+ var children = (document.body || $(parentElement)).getElementsByTagName('*');
787
+ return $A(children).inject([], function(elements, child) {
788
+ if (Element.hasClassName(child, className))
789
+ elements.push(child);
790
+ return elements;
791
+ });
396
792
  }
397
793
 
398
794
  /*--------------------------------------------------------------------------*/
@@ -402,11 +798,14 @@ if (!window.Element) {
402
798
  }
403
799
 
404
800
  Object.extend(Element, {
801
+ visible: function(element) {
802
+ return $(element).style.display != 'none';
803
+ },
804
+
405
805
  toggle: function() {
406
806
  for (var i = 0; i < arguments.length; i++) {
407
807
  var element = $(arguments[i]);
408
- element.style.display =
409
- (element.style.display == 'none' ? '' : 'none');
808
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
410
809
  }
411
810
  },
412
811
 
@@ -428,54 +827,131 @@ Object.extend(Element, {
428
827
  element = $(element);
429
828
  element.parentNode.removeChild(element);
430
829
  },
431
-
830
+
432
831
  getHeight: function(element) {
433
832
  element = $(element);
434
- return element.offsetHeight;
833
+ return element.offsetHeight;
834
+ },
835
+
836
+ classNames: function(element) {
837
+ return new Element.ClassNames(element);
435
838
  },
436
839
 
437
840
  hasClassName: function(element, className) {
438
- element = $(element);
439
- if (!element)
440
- return;
441
- var a = element.className.split(' ');
442
- for (var i = 0; i < a.length; i++) {
443
- if (a[i] == className)
444
- return true;
445
- }
446
- return false;
841
+ if (!(element = $(element))) return;
842
+ return Element.classNames(element).include(className);
447
843
  },
448
844
 
449
845
  addClassName: function(element, className) {
450
- element = $(element);
451
- Element.removeClassName(element, className);
452
- element.className += ' ' + className;
846
+ if (!(element = $(element))) return;
847
+ return Element.classNames(element).add(className);
453
848
  },
454
849
 
455
850
  removeClassName: function(element, className) {
456
- element = $(element);
457
- if (!element)
458
- return;
459
- var newClassName = '';
460
- var a = element.className.split(' ');
461
- for (var i = 0; i < a.length; i++) {
462
- if (a[i] != className) {
463
- if (i > 0)
464
- newClassName += ' ';
465
- newClassName += a[i];
466
- }
467
- }
468
- element.className = newClassName;
851
+ if (!(element = $(element))) return;
852
+ return Element.classNames(element).remove(className);
469
853
  },
470
-
854
+
471
855
  // removes whitespace-only text node children
472
856
  cleanWhitespace: function(element) {
473
- var element = $(element);
857
+ element = $(element);
474
858
  for (var i = 0; i < element.childNodes.length; i++) {
475
859
  var node = element.childNodes[i];
476
- if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
860
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
477
861
  Element.remove(node);
478
862
  }
863
+ },
864
+
865
+ empty: function(element) {
866
+ return $(element).innerHTML.match(/^\s*$/);
867
+ },
868
+
869
+ scrollTo: function(element) {
870
+ element = $(element);
871
+ var x = element.x ? element.x : element.offsetLeft,
872
+ y = element.y ? element.y : element.offsetTop;
873
+ window.scrollTo(x, y);
874
+ },
875
+
876
+ getStyle: function(element, style) {
877
+ element = $(element);
878
+ var value = element.style[style.camelize()];
879
+ if (!value) {
880
+ if (document.defaultView && document.defaultView.getComputedStyle) {
881
+ var css = document.defaultView.getComputedStyle(element, null);
882
+ value = css ? css.getPropertyValue(style) : null;
883
+ } else if (element.currentStyle) {
884
+ value = element.currentStyle[style.camelize()];
885
+ }
886
+ }
887
+
888
+ if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
889
+ if (Element.getStyle(element, 'position') == 'static') value = 'auto';
890
+
891
+ return value == 'auto' ? null : value;
892
+ },
893
+
894
+ getDimensions: function(element) {
895
+ element = $(element);
896
+ if (Element.getStyle(element, 'display') != 'none')
897
+ return {width: element.offsetWidth, height: element.offsetHeight};
898
+
899
+ // All *Width and *Height properties give 0 on elements with display none,
900
+ // so enable the element temporarily
901
+ var els = element.style;
902
+ var originalVisibility = els.visibility;
903
+ var originalPosition = els.position;
904
+ els.visibility = 'hidden';
905
+ els.position = 'absolute';
906
+ els.display = '';
907
+ var originalWidth = element.clientWidth;
908
+ var originalHeight = element.clientHeight;
909
+ els.display = 'none';
910
+ els.position = originalPosition;
911
+ els.visibility = originalVisibility;
912
+ return {width: originalWidth, height: originalHeight};
913
+ },
914
+
915
+ makePositioned: function(element) {
916
+ element = $(element);
917
+ var pos = Element.getStyle(element, 'position');
918
+ if (pos == 'static' || !pos) {
919
+ element._madePositioned = true;
920
+ element.style.position = 'relative';
921
+ // Opera returns the offset relative to the positioning context, when an
922
+ // element is position relative but top and left have not been defined
923
+ if (window.opera) {
924
+ element.style.top = 0;
925
+ element.style.left = 0;
926
+ }
927
+ }
928
+ },
929
+
930
+ undoPositioned: function(element) {
931
+ element = $(element);
932
+ if (element._madePositioned) {
933
+ element._madePositioned = undefined;
934
+ element.style.position =
935
+ element.style.top =
936
+ element.style.left =
937
+ element.style.bottom =
938
+ element.style.right = '';
939
+ }
940
+ },
941
+
942
+ makeClipping: function(element) {
943
+ element = $(element);
944
+ if (element._overflow) return;
945
+ element._overflow = element.style.overflow;
946
+ if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
947
+ element.style.overflow = 'hidden';
948
+ },
949
+
950
+ undoClipping: function(element) {
951
+ element = $(element);
952
+ if (element._overflow) return;
953
+ element.style.overflow = element._overflow;
954
+ element._overflow = undefined;
479
955
  }
480
956
  });
481
957
 
@@ -492,67 +968,124 @@ Abstract.Insertion.prototype = {
492
968
  initialize: function(element, content) {
493
969
  this.element = $(element);
494
970
  this.content = content;
495
-
971
+
496
972
  if (this.adjacency && this.element.insertAdjacentHTML) {
497
- this.element.insertAdjacentHTML(this.adjacency, this.content);
973
+ try {
974
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
975
+ } catch (e) {
976
+ if (this.element.tagName.toLowerCase() == 'tbody') {
977
+ this.insertContent(this.contentFromAnonymousTable());
978
+ } else {
979
+ throw e;
980
+ }
981
+ }
498
982
  } else {
499
983
  this.range = this.element.ownerDocument.createRange();
500
984
  if (this.initializeRange) this.initializeRange();
501
- this.fragment = this.range.createContextualFragment(this.content);
502
- this.insertContent();
985
+ this.insertContent([this.range.createContextualFragment(this.content)]);
503
986
  }
987
+ },
988
+
989
+ contentFromAnonymousTable: function() {
990
+ var div = document.createElement('div');
991
+ div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
992
+ return $A(div.childNodes[0].childNodes[0].childNodes);
504
993
  }
505
994
  }
506
995
 
507
996
  var Insertion = new Object();
508
997
 
509
998
  Insertion.Before = Class.create();
510
- Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
999
+ Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
511
1000
  initializeRange: function() {
512
1001
  this.range.setStartBefore(this.element);
513
1002
  },
514
-
515
- insertContent: function() {
516
- this.element.parentNode.insertBefore(this.fragment, this.element);
1003
+
1004
+ insertContent: function(fragments) {
1005
+ fragments.each((function(fragment) {
1006
+ this.element.parentNode.insertBefore(fragment, this.element);
1007
+ }).bind(this));
517
1008
  }
518
1009
  });
519
1010
 
520
1011
  Insertion.Top = Class.create();
521
- Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
1012
+ Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
522
1013
  initializeRange: function() {
523
1014
  this.range.selectNodeContents(this.element);
524
1015
  this.range.collapse(true);
525
1016
  },
526
-
527
- insertContent: function() {
528
- this.element.insertBefore(this.fragment, this.element.firstChild);
1017
+
1018
+ insertContent: function(fragments) {
1019
+ fragments.reverse().each((function(fragment) {
1020
+ this.element.insertBefore(fragment, this.element.firstChild);
1021
+ }).bind(this));
529
1022
  }
530
1023
  });
531
1024
 
532
1025
  Insertion.Bottom = Class.create();
533
- Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
1026
+ Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
534
1027
  initializeRange: function() {
535
1028
  this.range.selectNodeContents(this.element);
536
1029
  this.range.collapse(this.element);
537
1030
  },
538
-
539
- insertContent: function() {
540
- this.element.appendChild(this.fragment);
1031
+
1032
+ insertContent: function(fragments) {
1033
+ fragments.each((function(fragment) {
1034
+ this.element.appendChild(fragment);
1035
+ }).bind(this));
541
1036
  }
542
1037
  });
543
1038
 
544
1039
  Insertion.After = Class.create();
545
- Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
1040
+ Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
546
1041
  initializeRange: function() {
547
1042
  this.range.setStartAfter(this.element);
548
1043
  },
549
-
550
- insertContent: function() {
551
- this.element.parentNode.insertBefore(this.fragment,
552
- this.element.nextSibling);
1044
+
1045
+ insertContent: function(fragments) {
1046
+ fragments.each((function(fragment) {
1047
+ this.element.parentNode.insertBefore(fragment,
1048
+ this.element.nextSibling);
1049
+ }).bind(this));
553
1050
  }
554
1051
  });
555
1052
 
1053
+ /*--------------------------------------------------------------------------*/
1054
+
1055
+ Element.ClassNames = Class.create();
1056
+ Element.ClassNames.prototype = {
1057
+ initialize: function(element) {
1058
+ this.element = $(element);
1059
+ },
1060
+
1061
+ _each: function(iterator) {
1062
+ this.element.className.split(/\s+/).select(function(name) {
1063
+ return name.length > 0;
1064
+ })._each(iterator);
1065
+ },
1066
+
1067
+ set: function(className) {
1068
+ this.element.className = className;
1069
+ },
1070
+
1071
+ add: function(classNameToAdd) {
1072
+ if (this.include(classNameToAdd)) return;
1073
+ this.set(this.toArray().concat(classNameToAdd).join(' '));
1074
+ },
1075
+
1076
+ remove: function(classNameToRemove) {
1077
+ if (!this.include(classNameToRemove)) return;
1078
+ this.set(this.select(function(className) {
1079
+ return className != classNameToRemove;
1080
+ }));
1081
+ },
1082
+
1083
+ toString: function() {
1084
+ return this.toArray().join(' ');
1085
+ }
1086
+ }
1087
+
1088
+ Object.extend(Element.ClassNames.prototype, Enumerable);
556
1089
  var Field = {
557
1090
  clear: function() {
558
1091
  for (var i = 0; i < arguments.length; i++)
@@ -562,17 +1095,17 @@ var Field = {
562
1095
  focus: function(element) {
563
1096
  $(element).focus();
564
1097
  },
565
-
1098
+
566
1099
  present: function() {
567
1100
  for (var i = 0; i < arguments.length; i++)
568
1101
  if ($(arguments[i]).value == '') return false;
569
1102
  return true;
570
1103
  },
571
-
1104
+
572
1105
  select: function(element) {
573
1106
  $(element).select();
574
1107
  },
575
-
1108
+
576
1109
  activate: function(element) {
577
1110
  $(element).focus();
578
1111
  $(element).select();
@@ -585,16 +1118,16 @@ var Form = {
585
1118
  serialize: function(form) {
586
1119
  var elements = Form.getElements($(form));
587
1120
  var queryComponents = new Array();
588
-
1121
+
589
1122
  for (var i = 0; i < elements.length; i++) {
590
1123
  var queryComponent = Form.Element.serialize(elements[i]);
591
1124
  if (queryComponent)
592
1125
  queryComponents.push(queryComponent);
593
1126
  }
594
-
1127
+
595
1128
  return queryComponents.join('&');
596
1129
  },
597
-
1130
+
598
1131
  getElements: function(form) {
599
1132
  var form = $(form);
600
1133
  var elements = new Array();
@@ -606,19 +1139,19 @@ var Form = {
606
1139
  }
607
1140
  return elements;
608
1141
  },
609
-
1142
+
610
1143
  getInputs: function(form, typeName, name) {
611
1144
  var form = $(form);
612
1145
  var inputs = form.getElementsByTagName('input');
613
-
1146
+
614
1147
  if (!typeName && !name)
615
1148
  return inputs;
616
-
1149
+
617
1150
  var matchingInputs = new Array();
618
1151
  for (var i = 0; i < inputs.length; i++) {
619
1152
  var input = inputs[i];
620
1153
  if ((typeName && input.type != typeName) ||
621
- (name && input.name != name))
1154
+ (name && input.name != name))
622
1155
  continue;
623
1156
  matchingInputs.push(input);
624
1157
  }
@@ -665,18 +1198,18 @@ Form.Element = {
665
1198
  var element = $(element);
666
1199
  var method = element.tagName.toLowerCase();
667
1200
  var parameter = Form.Element.Serializers[method](element);
668
-
1201
+
669
1202
  if (parameter)
670
- return encodeURIComponent(parameter[0]) + '=' +
671
- encodeURIComponent(parameter[1]);
1203
+ return encodeURIComponent(parameter[0]) + '=' +
1204
+ encodeURIComponent(parameter[1]);
672
1205
  },
673
-
1206
+
674
1207
  getValue: function(element) {
675
1208
  var element = $(element);
676
1209
  var method = element.tagName.toLowerCase();
677
1210
  var parameter = Form.Element.Serializers[method](element);
678
-
679
- if (parameter)
1211
+
1212
+ if (parameter)
680
1213
  return parameter[1];
681
1214
  }
682
1215
  }
@@ -689,7 +1222,7 @@ Form.Element.Serializers = {
689
1222
  case 'password':
690
1223
  case 'text':
691
1224
  return Form.Element.Serializers.textarea(element);
692
- case 'checkbox':
1225
+ case 'checkbox':
693
1226
  case 'radio':
694
1227
  return Form.Element.Serializers.inputSelector(element);
695
1228
  }
@@ -706,17 +1239,30 @@ Form.Element.Serializers = {
706
1239
  },
707
1240
 
708
1241
  select: function(element) {
709
- var value = '';
710
- if (element.type == 'select-one') {
711
- var index = element.selectedIndex;
712
- if (index >= 0)
713
- value = element.options[index].value || element.options[index].text;
714
- } else {
715
- value = new Array();
716
- for (var i = 0; i < element.length; i++) {
717
- var opt = element.options[i];
718
- if (opt.selected)
719
- value.push(opt.value || opt.text);
1242
+ return Form.Element.Serializers[element.type == 'select-one' ?
1243
+ 'selectOne' : 'selectMany'](element);
1244
+ },
1245
+
1246
+ selectOne: function(element) {
1247
+ var value = '', opt, index = element.selectedIndex;
1248
+ if (index >= 0) {
1249
+ opt = element.options[index];
1250
+ value = opt.value;
1251
+ if (!value && !('value' in opt))
1252
+ value = opt.text;
1253
+ }
1254
+ return [element.name, value];
1255
+ },
1256
+
1257
+ selectMany: function(element) {
1258
+ var value = new Array();
1259
+ for (var i = 0; i < element.length; i++) {
1260
+ var opt = element.options[i];
1261
+ if (opt.selected) {
1262
+ var optValue = opt.value;
1263
+ if (!optValue && !('value' in opt))
1264
+ optValue = opt.text;
1265
+ value.push(optValue);
720
1266
  }
721
1267
  }
722
1268
  return [element.name, value];
@@ -735,15 +1281,15 @@ Abstract.TimedObserver.prototype = {
735
1281
  this.frequency = frequency;
736
1282
  this.element = $(element);
737
1283
  this.callback = callback;
738
-
1284
+
739
1285
  this.lastValue = this.getValue();
740
1286
  this.registerCallback();
741
1287
  },
742
-
1288
+
743
1289
  registerCallback: function() {
744
1290
  setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
745
1291
  },
746
-
1292
+
747
1293
  onTimerEvent: function() {
748
1294
  var value = this.getValue();
749
1295
  if (this.lastValue != value) {
@@ -754,14 +1300,14 @@ Abstract.TimedObserver.prototype = {
754
1300
  }
755
1301
 
756
1302
  Form.Element.Observer = Class.create();
757
- Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
1303
+ Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
758
1304
  getValue: function() {
759
1305
  return Form.Element.getValue(this.element);
760
1306
  }
761
1307
  });
762
1308
 
763
1309
  Form.Observer = Class.create();
764
- Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
1310
+ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
765
1311
  getValue: function() {
766
1312
  return Form.serialize(this.element);
767
1313
  }
@@ -774,14 +1320,14 @@ Abstract.EventObserver.prototype = {
774
1320
  initialize: function(element, callback) {
775
1321
  this.element = $(element);
776
1322
  this.callback = callback;
777
-
1323
+
778
1324
  this.lastValue = this.getValue();
779
1325
  if (this.element.tagName.toLowerCase() == 'form')
780
1326
  this.registerFormCallbacks();
781
1327
  else
782
1328
  this.registerCallback(this.element);
783
1329
  },
784
-
1330
+
785
1331
  onElementEvent: function() {
786
1332
  var value = this.getValue();
787
1333
  if (this.lastValue != value) {
@@ -789,22 +1335,22 @@ Abstract.EventObserver.prototype = {
789
1335
  this.lastValue = value;
790
1336
  }
791
1337
  },
792
-
1338
+
793
1339
  registerFormCallbacks: function() {
794
1340
  var elements = Form.getElements(this.element);
795
1341
  for (var i = 0; i < elements.length; i++)
796
1342
  this.registerCallback(elements[i]);
797
1343
  },
798
-
1344
+
799
1345
  registerCallback: function(element) {
800
1346
  if (element.type) {
801
1347
  switch (element.type.toLowerCase()) {
802
- case 'checkbox':
1348
+ case 'checkbox':
803
1349
  case 'radio':
804
1350
  element.target = this;
805
1351
  element.prev_onclick = element.onclick || Prototype.emptyFunction;
806
1352
  element.onclick = function() {
807
- this.prev_onclick();
1353
+ this.prev_onclick();
808
1354
  this.target.onElementEvent();
809
1355
  }
810
1356
  break;
@@ -816,30 +1362,28 @@ Abstract.EventObserver.prototype = {
816
1362
  element.target = this;
817
1363
  element.prev_onchange = element.onchange || Prototype.emptyFunction;
818
1364
  element.onchange = function() {
819
- this.prev_onchange();
1365
+ this.prev_onchange();
820
1366
  this.target.onElementEvent();
821
1367
  }
822
1368
  break;
823
1369
  }
824
- }
1370
+ }
825
1371
  }
826
1372
  }
827
1373
 
828
1374
  Form.Element.EventObserver = Class.create();
829
- Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
1375
+ Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
830
1376
  getValue: function() {
831
1377
  return Form.Element.getValue(this.element);
832
1378
  }
833
1379
  });
834
1380
 
835
1381
  Form.EventObserver = Class.create();
836
- Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
1382
+ Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
837
1383
  getValue: function() {
838
1384
  return Form.serialize(this.element);
839
1385
  }
840
1386
  });
841
-
842
-
843
1387
  if (!window.Event) {
844
1388
  var Event = new Object();
845
1389
  }
@@ -865,21 +1409,22 @@ Object.extend(Event, {
865
1409
  },
866
1410
 
867
1411
  pointerX: function(event) {
868
- return event.pageX || (event.clientX +
1412
+ return event.pageX || (event.clientX +
869
1413
  (document.documentElement.scrollLeft || document.body.scrollLeft));
870
1414
  },
871
1415
 
872
1416
  pointerY: function(event) {
873
- return event.pageY || (event.clientY +
1417
+ return event.pageY || (event.clientY +
874
1418
  (document.documentElement.scrollTop || document.body.scrollTop));
875
1419
  },
876
1420
 
877
1421
  stop: function(event) {
878
- if (event.preventDefault) {
879
- event.preventDefault();
880
- event.stopPropagation();
1422
+ if (event.preventDefault) {
1423
+ event.preventDefault();
1424
+ event.stopPropagation();
881
1425
  } else {
882
1426
  event.returnValue = false;
1427
+ event.cancelBubble = true;
883
1428
  }
884
1429
  },
885
1430
 
@@ -894,7 +1439,7 @@ Object.extend(Event, {
894
1439
  },
895
1440
 
896
1441
  observers: false,
897
-
1442
+
898
1443
  _observeAndCache: function(element, name, observer, useCapture) {
899
1444
  if (!this.observers) this.observers = [];
900
1445
  if (element.addEventListener) {
@@ -905,7 +1450,7 @@ Object.extend(Event, {
905
1450
  element.attachEvent('on' + name, observer);
906
1451
  }
907
1452
  },
908
-
1453
+
909
1454
  unloadCache: function() {
910
1455
  if (!Event.observers) return;
911
1456
  for (var i = 0; i < Event.observers.length; i++) {
@@ -918,24 +1463,24 @@ Object.extend(Event, {
918
1463
  observe: function(element, name, observer, useCapture) {
919
1464
  var element = $(element);
920
1465
  useCapture = useCapture || false;
921
-
1466
+
922
1467
  if (name == 'keypress' &&
923
- ((navigator.appVersion.indexOf('AppleWebKit') > 0)
1468
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
924
1469
  || element.attachEvent))
925
1470
  name = 'keydown';
926
-
1471
+
927
1472
  this._observeAndCache(element, name, observer, useCapture);
928
1473
  },
929
1474
 
930
1475
  stopObserving: function(element, name, observer, useCapture) {
931
1476
  var element = $(element);
932
1477
  useCapture = useCapture || false;
933
-
1478
+
934
1479
  if (name == 'keypress' &&
935
- ((navigator.appVersion.indexOf('AppleWebKit') > 0)
1480
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
936
1481
  || element.detachEvent))
937
1482
  name = 'keydown';
938
-
1483
+
939
1484
  if (element.removeEventListener) {
940
1485
  element.removeEventListener(name, observer, useCapture);
941
1486
  } else if (element.detachEvent) {
@@ -946,24 +1491,22 @@ Object.extend(Event, {
946
1491
 
947
1492
  /* prevent memory leaks in IE */
948
1493
  Event.observe(window, 'unload', Event.unloadCache, false);
949
-
950
1494
  var Position = {
951
-
952
1495
  // set to true if needed, warning: firefox performance problems
953
1496
  // NOT neeeded for page scrolling, only if draggable contained in
954
1497
  // scrollable elements
955
- includeScrollOffsets: false,
1498
+ includeScrollOffsets: false,
956
1499
 
957
1500
  // must be called before calling withinIncludingScrolloffset, every time the
958
1501
  // page is scrolled
959
1502
  prepare: function() {
960
- this.deltaX = window.pageXOffset
961
- || document.documentElement.scrollLeft
962
- || document.body.scrollLeft
1503
+ this.deltaX = window.pageXOffset
1504
+ || document.documentElement.scrollLeft
1505
+ || document.body.scrollLeft
963
1506
  || 0;
964
- this.deltaY = window.pageYOffset
965
- || document.documentElement.scrollTop
966
- || document.body.scrollTop
1507
+ this.deltaY = window.pageYOffset
1508
+ || document.documentElement.scrollTop
1509
+ || document.body.scrollTop
967
1510
  || 0;
968
1511
  },
969
1512
 
@@ -971,7 +1514,7 @@ var Position = {
971
1514
  var valueT = 0, valueL = 0;
972
1515
  do {
973
1516
  valueT += element.scrollTop || 0;
974
- valueL += element.scrollLeft || 0;
1517
+ valueL += element.scrollLeft || 0;
975
1518
  element = element.parentNode;
976
1519
  } while (element);
977
1520
  return [valueL, valueT];
@@ -987,6 +1530,31 @@ var Position = {
987
1530
  return [valueL, valueT];
988
1531
  },
989
1532
 
1533
+ positionedOffset: function(element) {
1534
+ var valueT = 0, valueL = 0;
1535
+ do {
1536
+ valueT += element.offsetTop || 0;
1537
+ valueL += element.offsetLeft || 0;
1538
+ element = element.offsetParent;
1539
+ if (element) {
1540
+ p = Element.getStyle(element, 'position');
1541
+ if (p == 'relative' || p == 'absolute') break;
1542
+ }
1543
+ } while (element);
1544
+ return [valueL, valueT];
1545
+ },
1546
+
1547
+ offsetParent: function(element) {
1548
+ if (element.offsetParent) return element.offsetParent;
1549
+ if (element == document.body) return element;
1550
+
1551
+ while ((element = element.parentNode) && element != document.body)
1552
+ if (Element.getStyle(element, 'position') != 'static')
1553
+ return element;
1554
+
1555
+ return document.body;
1556
+ },
1557
+
990
1558
  // caches x/y coordinate pair to use with overlap
991
1559
  within: function(element, x, y) {
992
1560
  if (this.includeScrollOffsets)
@@ -997,7 +1565,7 @@ var Position = {
997
1565
 
998
1566
  return (y >= this.offset[1] &&
999
1567
  y < this.offset[1] + element.offsetHeight &&
1000
- x >= this.offset[0] &&
1568
+ x >= this.offset[0] &&
1001
1569
  x < this.offset[0] + element.offsetWidth);
1002
1570
  },
1003
1571
 
@@ -1010,18 +1578,18 @@ var Position = {
1010
1578
 
1011
1579
  return (this.ycomp >= this.offset[1] &&
1012
1580
  this.ycomp < this.offset[1] + element.offsetHeight &&
1013
- this.xcomp >= this.offset[0] &&
1581
+ this.xcomp >= this.offset[0] &&
1014
1582
  this.xcomp < this.offset[0] + element.offsetWidth);
1015
1583
  },
1016
1584
 
1017
1585
  // within must be called directly before
1018
- overlap: function(mode, element) {
1019
- if (!mode) return 0;
1020
- if (mode == 'vertical')
1021
- return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1586
+ overlap: function(mode, element) {
1587
+ if (!mode) return 0;
1588
+ if (mode == 'vertical')
1589
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1022
1590
  element.offsetHeight;
1023
1591
  if (mode == 'horizontal')
1024
- return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1592
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1025
1593
  element.offsetWidth;
1026
1594
  },
1027
1595
 
@@ -1034,5 +1602,123 @@ var Position = {
1034
1602
  target.style.left = offsets[0] + 'px';
1035
1603
  target.style.width = source.offsetWidth + 'px';
1036
1604
  target.style.height = source.offsetHeight + 'px';
1605
+ },
1606
+
1607
+ page: function(forElement) {
1608
+ var valueT = 0, valueL = 0;
1609
+
1610
+ var element = forElement;
1611
+ do {
1612
+ valueT += element.offsetTop || 0;
1613
+ valueL += element.offsetLeft || 0;
1614
+
1615
+ // Safari fix
1616
+ if (element.offsetParent==document.body)
1617
+ if (Element.getStyle(element,'position')=='absolute') break;
1618
+
1619
+ } while (element = element.offsetParent);
1620
+
1621
+ element = forElement;
1622
+ do {
1623
+ valueT -= element.scrollTop || 0;
1624
+ valueL -= element.scrollLeft || 0;
1625
+ } while (element = element.parentNode);
1626
+
1627
+ return [valueL, valueT];
1628
+ },
1629
+
1630
+ clone: function(source, target) {
1631
+ var options = Object.extend({
1632
+ setLeft: true,
1633
+ setTop: true,
1634
+ setWidth: true,
1635
+ setHeight: true,
1636
+ offsetTop: 0,
1637
+ offsetLeft: 0
1638
+ }, arguments[2] || {})
1639
+
1640
+ // find page position of source
1641
+ source = $(source);
1642
+ var p = Position.page(source);
1643
+
1644
+ // find coordinate system to use
1645
+ target = $(target);
1646
+ var delta = [0, 0];
1647
+ var parent = null;
1648
+ // delta [0,0] will do fine with position: fixed elements,
1649
+ // position:absolute needs offsetParent deltas
1650
+ if (Element.getStyle(target,'position') == 'absolute') {
1651
+ parent = Position.offsetParent(target);
1652
+ delta = Position.page(parent);
1653
+ }
1654
+
1655
+ // correct by body offsets (fixes Safari)
1656
+ if (parent == document.body) {
1657
+ delta[0] -= document.body.offsetLeft;
1658
+ delta[1] -= document.body.offsetTop;
1659
+ }
1660
+
1661
+ // set position
1662
+ if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
1663
+ if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
1664
+ if(options.setWidth) target.style.width = source.offsetWidth + 'px';
1665
+ if(options.setHeight) target.style.height = source.offsetHeight + 'px';
1666
+ },
1667
+
1668
+ absolutize: function(element) {
1669
+ element = $(element);
1670
+ if (element.style.position == 'absolute') return;
1671
+ Position.prepare();
1672
+
1673
+ var offsets = Position.positionedOffset(element);
1674
+ var top = offsets[1];
1675
+ var left = offsets[0];
1676
+ var width = element.clientWidth;
1677
+ var height = element.clientHeight;
1678
+
1679
+ element._originalLeft = left - parseFloat(element.style.left || 0);
1680
+ element._originalTop = top - parseFloat(element.style.top || 0);
1681
+ element._originalWidth = element.style.width;
1682
+ element._originalHeight = element.style.height;
1683
+
1684
+ element.style.position = 'absolute';
1685
+ element.style.top = top + 'px';;
1686
+ element.style.left = left + 'px';;
1687
+ element.style.width = width + 'px';;
1688
+ element.style.height = height + 'px';;
1689
+ },
1690
+
1691
+ relativize: function(element) {
1692
+ element = $(element);
1693
+ if (element.style.position == 'relative') return;
1694
+ Position.prepare();
1695
+
1696
+ element.style.position = 'relative';
1697
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
1698
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1699
+
1700
+ element.style.top = top + 'px';
1701
+ element.style.left = left + 'px';
1702
+ element.style.height = element._originalHeight;
1703
+ element.style.width = element._originalWidth;
1037
1704
  }
1038
1705
  }
1706
+
1707
+ // Safari returns margins on body which is incorrect if the child is absolutely
1708
+ // positioned. For performance reasons, redefine Position.cumulativeOffset for
1709
+ // KHTML/WebKit only.
1710
+ if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1711
+ Position.cumulativeOffset = function(element) {
1712
+ var valueT = 0, valueL = 0;
1713
+ do {
1714
+ valueT += element.offsetTop || 0;
1715
+ valueL += element.offsetLeft || 0;
1716
+ if (element.offsetParent == document.body)
1717
+ if (Element.getStyle(element, 'position') == 'absolute') break;
1718
+
1719
+ element = element.offsetParent;
1720
+ } while (element);
1721
+
1722
+ return [valueL, valueT];
1723
+ }
1724
+ }