amrita2 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. data/README +5 -5
  2. data/Rakefile +85 -0
  3. data/lib/amrita2/gettext.rb +9 -4
  4. data/lib/amrita2/template.rb +20 -9
  5. data/lib/amrita2/testsupport.rb +25 -0
  6. data/lib/amrita2/version.rb +1 -1
  7. data/sample/depot/README +160 -0
  8. data/sample/depot/Rakefile +10 -0
  9. data/sample/depot/app/views/admin/_form.html.a2 +23 -0
  10. data/sample/depot/app/views/admin/_form.html.erb +14 -0
  11. data/sample/depot/app/views/admin/edit.html.a2 +22 -0
  12. data/sample/depot/app/views/admin/edit.html.erb +10 -0
  13. data/sample/depot/app/views/admin/list.html.a2 +34 -0
  14. data/sample/depot/app/views/admin/list.html.erb +37 -0
  15. data/sample/depot/app/views/admin/new.html.a2 +21 -0
  16. data/sample/depot/app/views/admin/new.html.erb +9 -0
  17. data/sample/depot/app/views/admin/show.html.a2 +12 -0
  18. data/sample/depot/app/views/admin/show.html.erb +13 -0
  19. data/sample/depot/app/views/info/who_bought.rhtml +14 -0
  20. data/sample/depot/app/views/info/who_bought.rxml +8 -0
  21. data/sample/depot/app/views/layouts/admin.a2html +32 -0
  22. data/sample/depot/app/views/layouts/admin.rhtml +40 -0
  23. data/sample/depot/app/views/layouts/store.a2html +37 -0
  24. data/sample/depot/app/views/layouts/store.rhtml +43 -0
  25. data/sample/depot/app/views/login/add_user.rhtml +33 -0
  26. data/sample/depot/app/views/login/index.rhtml +9 -0
  27. data/sample/depot/app/views/login/list_users.rhtml +20 -0
  28. data/sample/depot/app/views/login/login.rhtml +26 -0
  29. data/sample/depot/app/views/store/_cart.html.a2 +18 -0
  30. data/sample/depot/app/views/store/_cart.html.erb +17 -0
  31. data/sample/depot/app/views/store/_cart_item.html.a2 +16 -0
  32. data/sample/depot/app/views/store/_cart_item.html.erb +14 -0
  33. data/sample/depot/app/views/store/add_to_cart.rjs +11 -0
  34. data/sample/depot/app/views/store/checkout.html.a2 +45 -0
  35. data/sample/depot/app/views/store/checkout.html.a2.using_macro +32 -0
  36. data/sample/depot/app/views/store/checkout.html.a2.without_label +37 -0
  37. data/sample/depot/app/views/store/checkout.html.erb +41 -0
  38. data/sample/depot/app/views/store/index.html.a2 +19 -0
  39. data/sample/depot/app/views/store/index.html.erb +22 -0
  40. data/sample/depot/config/database.yml +24 -0
  41. data/sample/depot/db/create_database.sql +14 -0
  42. data/sample/depot/doc/README_FOR_APP +35 -0
  43. data/sample/depot/lib/tasks/db_schema_version.rake +6 -0
  44. data/sample/depot/log/development.log +116 -0
  45. data/sample/depot/log/test.log +347 -0
  46. data/sample/depot/public/404.html +13 -0
  47. data/sample/depot/public/500.html +13 -0
  48. data/sample/depot/public/dispatch.cgi +10 -0
  49. data/sample/depot/public/dispatch.fcgi +24 -0
  50. data/sample/depot/public/favicon.ico +0 -0
  51. data/sample/depot/public/images/auto.jpg +0 -0
  52. data/sample/depot/public/images/logo.png +0 -0
  53. data/sample/depot/public/images/rails.png +0 -0
  54. data/sample/depot/public/images/svn.jpg +0 -0
  55. data/sample/depot/public/images/utc.jpg +0 -0
  56. data/sample/depot/public/index.html +282 -0
  57. data/sample/depot/public/javascripts/application.js +2 -0
  58. data/sample/depot/public/javascripts/controls.js +832 -0
  59. data/sample/depot/public/javascripts/dragdrop.js +942 -0
  60. data/sample/depot/public/javascripts/effects.js +954 -0
  61. data/sample/depot/public/javascripts/prototype.js +2347 -0
  62. data/sample/depot/public/robots.txt +1 -0
  63. data/sample/depot/public/stylesheets/depot.css +227 -0
  64. data/sample/depot/public/stylesheets/scaffold.css +74 -0
  65. data/sample/depot/script/about +3 -0
  66. data/sample/depot/script/breakpointer +3 -0
  67. data/sample/depot/script/console +3 -0
  68. data/sample/depot/script/destroy +3 -0
  69. data/sample/depot/script/generate +3 -0
  70. data/sample/depot/script/performance/benchmarker +3 -0
  71. data/sample/depot/script/performance/profiler +3 -0
  72. data/sample/depot/script/plugin +3 -0
  73. data/sample/depot/script/process/inspector +3 -0
  74. data/sample/depot/script/process/reaper +3 -0
  75. data/sample/depot/script/process/spawner +3 -0
  76. data/sample/depot/script/runner +3 -0
  77. data/sample/depot/script/server +3 -0
  78. data/sample/depot/test/fixtures/line_items.yml +16 -0
  79. data/sample/depot/test/fixtures/orders.yml +4 -0
  80. data/sample/depot/test/fixtures/performance/products.yml +8 -0
  81. data/sample/depot/test/fixtures/products.yml +16 -0
  82. data/sample/depot/test/fixtures/users.yml +7 -0
  83. data/sample/depot/vendor/plugins/will_paginate/LICENSE +18 -0
  84. data/sample/depot/vendor/plugins/will_paginate/README +171 -0
  85. data/sample/depot/vendor/plugins/will_paginate/Rakefile +27 -0
  86. data/sample/depot/vendor/plugins/will_paginate/test/console +9 -0
  87. data/sample/depot/vendor/plugins/will_paginate/test/fixtures/companies.yml +24 -0
  88. data/sample/depot/vendor/plugins/will_paginate/test/fixtures/developers_projects.yml +13 -0
  89. data/sample/depot/vendor/plugins/will_paginate/test/fixtures/projects.yml +7 -0
  90. data/sample/depot/vendor/plugins/will_paginate/test/fixtures/replies.yml +34 -0
  91. data/sample/depot/vendor/plugins/will_paginate/test/fixtures/schema.sql +44 -0
  92. data/sample/depot/vendor/plugins/will_paginate/test/fixtures/topics.yml +30 -0
  93. data/sample/depot/vendor/plugins/will_paginate/test/fixtures/users.yml +35 -0
  94. data/sample/login_engine/README +182 -0
  95. data/sample/login_engine/Rakefile +27 -0
  96. data/sample/login_engine/app/views/layouts/user.a2html +20 -0
  97. data/sample/login_engine/app/views/layouts/user.rhtml +16 -0
  98. data/sample/login_engine/app/views/user/_edit.a2html +16 -0
  99. data/sample/login_engine/app/views/user/_edit.rhtml +11 -0
  100. data/sample/login_engine/app/views/user/_password.a2html +18 -0
  101. data/sample/login_engine/app/views/user/_password.rhtml +9 -0
  102. data/sample/login_engine/app/views/user/change_password.a2html +17 -0
  103. data/sample/login_engine/app/views/user/change_password.rhtml +17 -0
  104. data/sample/login_engine/app/views/user/edit.a2html +22 -0
  105. data/sample/login_engine/app/views/user/edit.rhtml +23 -0
  106. data/sample/login_engine/app/views/user/forgot_password.rhtml +18 -0
  107. data/sample/login_engine/app/views/user/home.a2html +12 -0
  108. data/sample/login_engine/app/views/user/home.rhtml +7 -0
  109. data/sample/login_engine/app/views/user/login.a2html +16 -0
  110. data/sample/login_engine/app/views/user/login.rhtml +17 -0
  111. data/sample/login_engine/app/views/user/logout.rhtml +8 -0
  112. data/sample/login_engine/app/views/user/signup.a2html +14 -0
  113. data/sample/login_engine/app/views/user/signup.rhtml +17 -0
  114. data/sample/login_engine/app/views/user_notify/change_password.rhtml +10 -0
  115. data/sample/login_engine/app/views/user_notify/delete.rhtml +5 -0
  116. data/sample/login_engine/app/views/user_notify/forgot_password.rhtml +11 -0
  117. data/sample/login_engine/app/views/user_notify/pending_delete.rhtml +9 -0
  118. data/sample/login_engine/app/views/user_notify/signup.rhtml +12 -0
  119. data/sample/login_engine/config/database.yml +18 -0
  120. data/sample/login_engine/db/create_database.sql +14 -0
  121. data/sample/login_engine/db/dev.sqlite3 +0 -0
  122. data/sample/login_engine/db/test.sqlite3 +0 -0
  123. data/sample/login_engine/doc/README_FOR_APP +2 -0
  124. data/sample/login_engine/locale/ja/LC_MESSAGES/login_engine.mo +0 -0
  125. data/sample/login_engine/log/development.log +330 -0
  126. data/sample/login_engine/log/test.log +19026 -0
  127. data/sample/login_engine/po/ja/login_engine.po +248 -0
  128. data/sample/login_engine/po/login_engine.pot +245 -0
  129. data/sample/login_engine/public/404.html +30 -0
  130. data/sample/login_engine/public/500.html +30 -0
  131. data/sample/login_engine/public/dispatch.cgi +10 -0
  132. data/sample/login_engine/public/dispatch.fcgi +24 -0
  133. data/sample/login_engine/public/favicon.ico +0 -0
  134. data/sample/login_engine/public/images/rails.png +0 -0
  135. data/sample/login_engine/public/index.html +277 -0
  136. data/sample/login_engine/public/javascripts/application.js +2 -0
  137. data/sample/login_engine/public/javascripts/controls.js +833 -0
  138. data/sample/login_engine/public/javascripts/dragdrop.js +942 -0
  139. data/sample/login_engine/public/javascripts/effects.js +1088 -0
  140. data/sample/login_engine/public/javascripts/prototype.js +2385 -0
  141. data/sample/login_engine/public/robots.txt +1 -0
  142. data/sample/login_engine/public/stylesheets/login_engine.css +81 -0
  143. data/sample/login_engine/script/about +3 -0
  144. data/sample/login_engine/script/breakpointer +3 -0
  145. data/sample/login_engine/script/console +3 -0
  146. data/sample/login_engine/script/destroy +3 -0
  147. data/sample/login_engine/script/generate +3 -0
  148. data/sample/login_engine/script/performance/benchmarker +3 -0
  149. data/sample/login_engine/script/performance/profiler +3 -0
  150. data/sample/login_engine/script/plugin +3 -0
  151. data/sample/login_engine/script/process/inspector +3 -0
  152. data/sample/login_engine/script/process/reaper +3 -0
  153. data/sample/login_engine/script/process/spawner +3 -0
  154. data/sample/login_engine/script/runner +3 -0
  155. data/sample/login_engine/script/server +3 -0
  156. data/sample/login_engine/test/fixtures/users.yml +41 -0
  157. data/specs/erb_cdata.rb +11 -0
  158. data/specs/filters.rb +5 -4
  159. data/specs/gettext/static_text.rb +30 -13
  160. data/specs/impl/preprocess.rb +58 -54
  161. metadata +375 -120
  162. data/sample/hello/test1.rb +0 -23
@@ -0,0 +1,2385 @@
1
+ /* Prototype JavaScript framework, version 1.5.0_rc2
2
+ * (c) 2005, 2006 Sam Stephenson <sam@conio.net>
3
+ *
4
+ * Prototype is freely distributable under the terms of an MIT-style license.
5
+ * For details, see the Prototype web site: http://prototype.conio.net/
6
+ *
7
+ /*--------------------------------------------------------------------------*/
8
+
9
+ var Prototype = {
10
+ Version: '1.5.0_rc2',
11
+ BrowserFeatures: {
12
+ XPath: !!document.evaluate
13
+ },
14
+
15
+ ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
16
+ emptyFunction: function() {},
17
+ K: function(x) { return x }
18
+ }
19
+
20
+ var Class = {
21
+ create: function() {
22
+ return function() {
23
+ this.initialize.apply(this, arguments);
24
+ }
25
+ }
26
+ }
27
+
28
+ var Abstract = new Object();
29
+
30
+ Object.extend = function(destination, source) {
31
+ for (var property in source) {
32
+ destination[property] = source[property];
33
+ }
34
+ return destination;
35
+ }
36
+
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);
65
+ }
66
+ });
67
+
68
+ Function.prototype.bind = function() {
69
+ var __method = this, args = $A(arguments), object = args.shift();
70
+ return function() {
71
+ return __method.apply(object, args.concat($A(arguments)));
72
+ }
73
+ }
74
+
75
+ Function.prototype.bindAsEventListener = function(object) {
76
+ var __method = this, args = $A(arguments), object = args.shift();
77
+ return function(event) {
78
+ return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
79
+ }
80
+ }
81
+
82
+ Object.extend(Number.prototype, {
83
+ toColorPart: function() {
84
+ var digits = this.toString(16);
85
+ if (this < 16) return '0' + digits;
86
+ return digits;
87
+ },
88
+
89
+ succ: function() {
90
+ return this + 1;
91
+ },
92
+
93
+ times: function(iterator) {
94
+ $R(0, this, true).each(iterator);
95
+ return this;
96
+ }
97
+ });
98
+
99
+ var Try = {
100
+ these: function() {
101
+ var returnValue;
102
+
103
+ for (var i = 0, length = arguments.length; i < length; i++) {
104
+ var lambda = arguments[i];
105
+ try {
106
+ returnValue = lambda();
107
+ break;
108
+ } catch (e) {}
109
+ }
110
+
111
+ return returnValue;
112
+ }
113
+ }
114
+
115
+ /*--------------------------------------------------------------------------*/
116
+
117
+ var PeriodicalExecuter = Class.create();
118
+ PeriodicalExecuter.prototype = {
119
+ initialize: function(callback, frequency) {
120
+ this.callback = callback;
121
+ this.frequency = frequency;
122
+ this.currentlyExecuting = false;
123
+
124
+ this.registerCallback();
125
+ },
126
+
127
+ registerCallback: function() {
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;
135
+ },
136
+
137
+ onTimerEvent: function() {
138
+ if (!this.currentlyExecuting) {
139
+ try {
140
+ this.currentlyExecuting = true;
141
+ this.callback(this);
142
+ } finally {
143
+ this.currentlyExecuting = false;
144
+ }
145
+ }
146
+ }
147
+ }
148
+ Object.extend(String.prototype, {
149
+ gsub: function(pattern, replacement) {
150
+ var result = '', source = this, match;
151
+ replacement = arguments.callee.prepareReplacement(replacement);
152
+
153
+ while (source.length > 0) {
154
+ if (match = source.match(pattern)) {
155
+ result += source.slice(0, match.index);
156
+ result += (replacement(match) || '').toString();
157
+ source = source.slice(match.index + match[0].length);
158
+ } else {
159
+ result += source, source = '';
160
+ }
161
+ }
162
+ return result;
163
+ },
164
+
165
+ sub: function(pattern, replacement, count) {
166
+ replacement = this.gsub.prepareReplacement(replacement);
167
+ count = count === undefined ? 1 : count;
168
+
169
+ return this.gsub(pattern, function(match) {
170
+ if (--count < 0) return match[0];
171
+ return replacement(match);
172
+ });
173
+ },
174
+
175
+ scan: function(pattern, iterator) {
176
+ this.gsub(pattern, iterator);
177
+ return this;
178
+ },
179
+
180
+ truncate: function(length, truncation) {
181
+ length = length || 30;
182
+ truncation = truncation === undefined ? '...' : truncation;
183
+ return this.length > length ?
184
+ this.slice(0, length - truncation.length) + truncation : this;
185
+ },
186
+
187
+ strip: function() {
188
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
189
+ },
190
+
191
+ stripTags: function() {
192
+ return this.replace(/<\/?[^>]+>/gi, '');
193
+ },
194
+
195
+ stripScripts: function() {
196
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
197
+ },
198
+
199
+ extractScripts: function() {
200
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
201
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
202
+ return (this.match(matchAll) || []).map(function(scriptTag) {
203
+ return (scriptTag.match(matchOne) || ['', ''])[1];
204
+ });
205
+ },
206
+
207
+ evalScripts: function() {
208
+ return this.extractScripts().map(function(script) { return eval(script) });
209
+ },
210
+
211
+ escapeHTML: function() {
212
+ var div = document.createElement('div');
213
+ var text = document.createTextNode(this);
214
+ div.appendChild(text);
215
+ return div.innerHTML;
216
+ },
217
+
218
+ unescapeHTML: function() {
219
+ var div = document.createElement('div');
220
+ div.innerHTML = this.stripTags();
221
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
222
+ $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
223
+ div.childNodes[0].nodeValue) : '';
224
+ },
225
+
226
+ toQueryParams: function(separator) {
227
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
228
+ if (!match) return {};
229
+
230
+ return match[1].split(separator || '&').inject({}, function(hash, pair) {
231
+ if ((pair = pair.split('='))[0]) {
232
+ var name = decodeURIComponent(pair[0]);
233
+ var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
234
+
235
+ if (hash[name] !== undefined) {
236
+ if (hash[name].constructor != Array)
237
+ hash[name] = [hash[name]];
238
+ if (value) hash[name].push(value);
239
+ }
240
+ else hash[name] = value;
241
+ }
242
+ return hash;
243
+ });
244
+ },
245
+
246
+ toArray: function() {
247
+ return this.split('');
248
+ },
249
+
250
+ camelize: function() {
251
+ var oStringList = this.split('-');
252
+ if (oStringList.length == 1) return oStringList[0];
253
+
254
+ var camelizedString = this.indexOf('-') == 0
255
+ ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
256
+ : oStringList[0];
257
+
258
+ for (var i = 1, length = oStringList.length; i < length; i++) {
259
+ var s = oStringList[i];
260
+ camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
261
+ }
262
+
263
+ return camelizedString;
264
+ },
265
+
266
+ underscore: function() {
267
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'-').toLowerCase();
268
+ },
269
+
270
+ dasherize: function() {
271
+ return this.gsub(/_/,'-');
272
+ },
273
+
274
+ inspect: function(useDoubleQuotes) {
275
+ var escapedString = this.replace(/\\/g, '\\\\');
276
+ if (useDoubleQuotes)
277
+ return '"' + escapedString.replace(/"/g, '\\"') + '"';
278
+ else
279
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
280
+ }
281
+ });
282
+
283
+ String.prototype.gsub.prepareReplacement = function(replacement) {
284
+ if (typeof replacement == 'function') return replacement;
285
+ var template = new Template(replacement);
286
+ return function(match) { return template.evaluate(match) };
287
+ }
288
+
289
+ String.prototype.parseQuery = String.prototype.toQueryParams;
290
+
291
+ var Template = Class.create();
292
+ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
293
+ Template.prototype = {
294
+ initialize: function(template, pattern) {
295
+ this.template = template.toString();
296
+ this.pattern = pattern || Template.Pattern;
297
+ },
298
+
299
+ evaluate: function(object) {
300
+ return this.template.gsub(this.pattern, function(match) {
301
+ var before = match[1];
302
+ if (before == '\\') return match[2];
303
+ return before + (object[match[3]] || '').toString();
304
+ });
305
+ }
306
+ }
307
+
308
+ var $break = new Object();
309
+ var $continue = new Object();
310
+
311
+ var Enumerable = {
312
+ each: function(iterator) {
313
+ var index = 0;
314
+ try {
315
+ this._each(function(value) {
316
+ try {
317
+ iterator(value, index++);
318
+ } catch (e) {
319
+ if (e != $continue) throw e;
320
+ }
321
+ });
322
+ } catch (e) {
323
+ if (e != $break) throw e;
324
+ }
325
+ return this;
326
+ },
327
+
328
+ eachSlice: function(number, iterator) {
329
+ var index = -number, slices = [], array = this.toArray();
330
+ while ((index += number) < array.length)
331
+ slices.push(array.slice(index, index+number));
332
+ return slices.collect(iterator || Prototype.K);
333
+ },
334
+
335
+ all: function(iterator) {
336
+ var result = true;
337
+ this.each(function(value, index) {
338
+ result = result && !!(iterator || Prototype.K)(value, index);
339
+ if (!result) throw $break;
340
+ });
341
+ return result;
342
+ },
343
+
344
+ any: function(iterator) {
345
+ var result = false;
346
+ this.each(function(value, index) {
347
+ if (result = !!(iterator || Prototype.K)(value, index))
348
+ throw $break;
349
+ });
350
+ return result;
351
+ },
352
+
353
+ collect: function(iterator) {
354
+ var results = [];
355
+ this.each(function(value, index) {
356
+ results.push(iterator(value, index));
357
+ });
358
+ return results;
359
+ },
360
+
361
+ detect: function(iterator) {
362
+ var result;
363
+ this.each(function(value, index) {
364
+ if (iterator(value, index)) {
365
+ result = value;
366
+ throw $break;
367
+ }
368
+ });
369
+ return result;
370
+ },
371
+
372
+ findAll: function(iterator) {
373
+ var results = [];
374
+ this.each(function(value, index) {
375
+ if (iterator(value, index))
376
+ results.push(value);
377
+ });
378
+ return results;
379
+ },
380
+
381
+ grep: function(pattern, iterator) {
382
+ var results = [];
383
+ this.each(function(value, index) {
384
+ var stringValue = value.toString();
385
+ if (stringValue.match(pattern))
386
+ results.push((iterator || Prototype.K)(value, index));
387
+ })
388
+ return results;
389
+ },
390
+
391
+ include: function(object) {
392
+ var found = false;
393
+ this.each(function(value) {
394
+ if (value == object) {
395
+ found = true;
396
+ throw $break;
397
+ }
398
+ });
399
+ return found;
400
+ },
401
+
402
+ inGroupsOf: function(number, fillWith) {
403
+ fillWith = fillWith || null;
404
+ var results = this.eachSlice(number);
405
+ if (results.length > 0) (number - results.last().length).times(function() {
406
+ results.last().push(fillWith)
407
+ });
408
+ return results;
409
+ },
410
+
411
+ inject: function(memo, iterator) {
412
+ this.each(function(value, index) {
413
+ memo = iterator(memo, value, index);
414
+ });
415
+ return memo;
416
+ },
417
+
418
+ invoke: function(method) {
419
+ var args = $A(arguments).slice(1);
420
+ return this.collect(function(value) {
421
+ return value[method].apply(value, args);
422
+ });
423
+ },
424
+
425
+ max: function(iterator) {
426
+ var result;
427
+ this.each(function(value, index) {
428
+ value = (iterator || Prototype.K)(value, index);
429
+ if (result == undefined || value >= result)
430
+ result = value;
431
+ });
432
+ return result;
433
+ },
434
+
435
+ min: function(iterator) {
436
+ var result;
437
+ this.each(function(value, index) {
438
+ value = (iterator || Prototype.K)(value, index);
439
+ if (result == undefined || value < result)
440
+ result = value;
441
+ });
442
+ return result;
443
+ },
444
+
445
+ partition: function(iterator) {
446
+ var trues = [], falses = [];
447
+ this.each(function(value, index) {
448
+ ((iterator || Prototype.K)(value, index) ?
449
+ trues : falses).push(value);
450
+ });
451
+ return [trues, falses];
452
+ },
453
+
454
+ pluck: function(property) {
455
+ var results = [];
456
+ this.each(function(value, index) {
457
+ results.push(value[property]);
458
+ });
459
+ return results;
460
+ },
461
+
462
+ reject: function(iterator) {
463
+ var results = [];
464
+ this.each(function(value, index) {
465
+ if (!iterator(value, index))
466
+ results.push(value);
467
+ });
468
+ return results;
469
+ },
470
+
471
+ sortBy: function(iterator) {
472
+ return this.collect(function(value, index) {
473
+ return {value: value, criteria: iterator(value, index)};
474
+ }).sort(function(left, right) {
475
+ var a = left.criteria, b = right.criteria;
476
+ return a < b ? -1 : a > b ? 1 : 0;
477
+ }).pluck('value');
478
+ },
479
+
480
+ toArray: function() {
481
+ return this.collect(Prototype.K);
482
+ },
483
+
484
+ zip: function() {
485
+ var iterator = Prototype.K, args = $A(arguments);
486
+ if (typeof args.last() == 'function')
487
+ iterator = args.pop();
488
+
489
+ var collections = [this].concat(args).map($A);
490
+ return this.map(function(value, index) {
491
+ return iterator(collections.pluck(index));
492
+ });
493
+ },
494
+
495
+ inspect: function() {
496
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
497
+ }
498
+ }
499
+
500
+ Object.extend(Enumerable, {
501
+ map: Enumerable.collect,
502
+ find: Enumerable.detect,
503
+ select: Enumerable.findAll,
504
+ member: Enumerable.include,
505
+ entries: Enumerable.toArray
506
+ });
507
+ var $A = Array.from = function(iterable) {
508
+ if (!iterable) return [];
509
+ if (iterable.toArray) {
510
+ return iterable.toArray();
511
+ } else {
512
+ var results = [];
513
+ for (var i = 0, length = iterable.length; i < length; i++)
514
+ results.push(iterable[i]);
515
+ return results;
516
+ }
517
+ }
518
+
519
+ Object.extend(Array.prototype, Enumerable);
520
+
521
+ if (!Array.prototype._reverse)
522
+ Array.prototype._reverse = Array.prototype.reverse;
523
+
524
+ Object.extend(Array.prototype, {
525
+ _each: function(iterator) {
526
+ for (var i = 0, length = this.length; i < length; i++)
527
+ iterator(this[i]);
528
+ },
529
+
530
+ clear: function() {
531
+ this.length = 0;
532
+ return this;
533
+ },
534
+
535
+ first: function() {
536
+ return this[0];
537
+ },
538
+
539
+ last: function() {
540
+ return this[this.length - 1];
541
+ },
542
+
543
+ compact: function() {
544
+ return this.select(function(value) {
545
+ return value != undefined || value != null;
546
+ });
547
+ },
548
+
549
+ flatten: function() {
550
+ return this.inject([], function(array, value) {
551
+ return array.concat(value && value.constructor == Array ?
552
+ value.flatten() : [value]);
553
+ });
554
+ },
555
+
556
+ without: function() {
557
+ var values = $A(arguments);
558
+ return this.select(function(value) {
559
+ return !values.include(value);
560
+ });
561
+ },
562
+
563
+ indexOf: function(object) {
564
+ for (var i = 0, length = this.length; i < length; i++)
565
+ if (this[i] == object) return i;
566
+ return -1;
567
+ },
568
+
569
+ reverse: function(inline) {
570
+ return (inline !== false ? this : this.toArray())._reverse();
571
+ },
572
+
573
+ reduce: function() {
574
+ return this.length > 1 ? this : this[0];
575
+ },
576
+
577
+ uniq: function() {
578
+ return this.inject([], function(array, value) {
579
+ return array.include(value) ? array : array.concat([value]);
580
+ });
581
+ },
582
+
583
+ clone: function() {
584
+ return [].concat(this);
585
+ },
586
+
587
+ inspect: function() {
588
+ return '[' + this.map(Object.inspect).join(', ') + ']';
589
+ }
590
+ });
591
+
592
+ Array.prototype.toArray = Array.prototype.clone;
593
+
594
+ if(window.opera){
595
+ Array.prototype.concat = function(){
596
+ var array = [];
597
+ for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
598
+ for(var i = 0, length = arguments.length; i < length; i++) {
599
+ if(arguments[i].constructor == Array) {
600
+ for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
601
+ array.push(arguments[i][j]);
602
+ } else {
603
+ array.push(arguments[i]);
604
+ }
605
+ }
606
+ return array;
607
+ }
608
+ }
609
+ var Hash = {
610
+ _each: function(iterator) {
611
+ for (var key in this) {
612
+ var value = this[key];
613
+ if (typeof value == 'function') continue;
614
+
615
+ var pair = [key, value];
616
+ pair.key = key;
617
+ pair.value = value;
618
+ iterator(pair);
619
+ }
620
+ },
621
+
622
+ keys: function() {
623
+ return this.pluck('key');
624
+ },
625
+
626
+ values: function() {
627
+ return this.pluck('value');
628
+ },
629
+
630
+ merge: function(hash) {
631
+ return $H(hash).inject(this, function(mergedHash, pair) {
632
+ mergedHash[pair.key] = pair.value;
633
+ return mergedHash;
634
+ });
635
+ },
636
+
637
+ toQueryString: function() {
638
+ return this.map(function(pair) {
639
+ if (!pair.key) return null;
640
+
641
+ if (pair.value && pair.value.constructor == Array) {
642
+ pair.value = pair.value.compact();
643
+
644
+ if (pair.value.length < 2) {
645
+ pair.value = pair.value.reduce();
646
+ } else {
647
+ var key = encodeURIComponent(pair.key);
648
+ return pair.value.map(function(value) {
649
+ return key + '=' + encodeURIComponent(value);
650
+ }).join('&');
651
+ }
652
+ }
653
+
654
+ if (pair.value == undefined) pair[1] = '';
655
+ return pair.map(encodeURIComponent).join('=');
656
+ }).join('&');
657
+ },
658
+
659
+ inspect: function() {
660
+ return '#<Hash:{' + this.map(function(pair) {
661
+ return pair.map(Object.inspect).join(': ');
662
+ }).join(', ') + '}>';
663
+ }
664
+ }
665
+
666
+ function $H(object) {
667
+ var hash = Object.extend({}, object || {});
668
+ Object.extend(hash, Enumerable);
669
+ Object.extend(hash, Hash);
670
+ return hash;
671
+ }
672
+ ObjectRange = Class.create();
673
+ Object.extend(ObjectRange.prototype, Enumerable);
674
+ Object.extend(ObjectRange.prototype, {
675
+ initialize: function(start, end, exclusive) {
676
+ this.start = start;
677
+ this.end = end;
678
+ this.exclusive = exclusive;
679
+ },
680
+
681
+ _each: function(iterator) {
682
+ var value = this.start;
683
+ while (this.include(value)) {
684
+ iterator(value);
685
+ value = value.succ();
686
+ }
687
+ },
688
+
689
+ include: function(value) {
690
+ if (value < this.start)
691
+ return false;
692
+ if (this.exclusive)
693
+ return value < this.end;
694
+ return value <= this.end;
695
+ }
696
+ });
697
+
698
+ var $R = function(start, end, exclusive) {
699
+ return new ObjectRange(start, end, exclusive);
700
+ }
701
+
702
+ var Ajax = {
703
+ getTransport: function() {
704
+ return Try.these(
705
+ function() {return new XMLHttpRequest()},
706
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
707
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
708
+ ) || false;
709
+ },
710
+
711
+ activeRequestCount: 0
712
+ }
713
+
714
+ Ajax.Responders = {
715
+ responders: [],
716
+
717
+ _each: function(iterator) {
718
+ this.responders._each(iterator);
719
+ },
720
+
721
+ register: function(responder) {
722
+ if (!this.include(responder))
723
+ this.responders.push(responder);
724
+ },
725
+
726
+ unregister: function(responder) {
727
+ this.responders = this.responders.without(responder);
728
+ },
729
+
730
+ dispatch: function(callback, request, transport, json) {
731
+ this.each(function(responder) {
732
+ if (typeof responder[callback] == 'function') {
733
+ try {
734
+ responder[callback].apply(responder, [request, transport, json]);
735
+ } catch (e) {}
736
+ }
737
+ });
738
+ }
739
+ };
740
+
741
+ Object.extend(Ajax.Responders, Enumerable);
742
+
743
+ Ajax.Responders.register({
744
+ onCreate: function() {
745
+ Ajax.activeRequestCount++;
746
+ },
747
+ onComplete: function() {
748
+ Ajax.activeRequestCount--;
749
+ }
750
+ });
751
+
752
+ Ajax.Base = function() {};
753
+ Ajax.Base.prototype = {
754
+ setOptions: function(options) {
755
+ this.options = {
756
+ method: 'post',
757
+ asynchronous: true,
758
+ contentType: 'application/x-www-form-urlencoded',
759
+ encoding: 'UTF-8',
760
+ parameters: ''
761
+ }
762
+ Object.extend(this.options, options || {});
763
+
764
+ this.options.method = this.options.method.toLowerCase();
765
+ this.options.parameters = $H(typeof this.options.parameters == 'string' ?
766
+ this.options.parameters.toQueryParams() : this.options.parameters);
767
+ }
768
+ }
769
+
770
+ Ajax.Request = Class.create();
771
+ Ajax.Request.Events =
772
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
773
+
774
+ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
775
+ _complete: false,
776
+
777
+ initialize: function(url, options) {
778
+ this.transport = Ajax.getTransport();
779
+ this.setOptions(options);
780
+ this.request(url);
781
+ },
782
+
783
+ request: function(url) {
784
+ var params = this.options.parameters;
785
+ if (params.any()) params['_'] = '';
786
+
787
+ if (!['get', 'post'].include(this.options.method)) {
788
+ // simulate other verbs over post
789
+ params['_method'] = this.options.method;
790
+ this.options.method = 'post';
791
+ }
792
+
793
+ this.url = url;
794
+
795
+ // when GET, append parameters to URL
796
+ if (this.options.method == 'get' && params.any())
797
+ this.url += (this.url.indexOf('?') >= 0 ? '&' : '?') +
798
+ params.toQueryString();
799
+
800
+ try {
801
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
802
+
803
+ this.transport.open(this.options.method.toUpperCase(), this.url,
804
+ this.options.asynchronous, this.options.username,
805
+ this.options.password);
806
+
807
+ if (this.options.asynchronous)
808
+ setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
809
+
810
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
811
+ this.setRequestHeaders();
812
+
813
+ var body = this.options.method == 'post' ?
814
+ (this.options.postBody || params.toQueryString()) : null;
815
+
816
+ this.transport.send(body);
817
+
818
+ /* Force Firefox to handle ready state 4 for synchronous requests */
819
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
820
+ this.onStateChange();
821
+
822
+ }
823
+ catch (e) {
824
+ this.dispatchException(e);
825
+ }
826
+ },
827
+
828
+ onStateChange: function() {
829
+ var readyState = this.transport.readyState;
830
+ if (readyState > 1 && !((readyState == 4) && this._complete))
831
+ this.respondToReadyState(this.transport.readyState);
832
+ },
833
+
834
+ setRequestHeaders: function() {
835
+ var headers = {
836
+ 'X-Requested-With': 'XMLHttpRequest',
837
+ 'X-Prototype-Version': Prototype.Version,
838
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
839
+ };
840
+
841
+ if (this.options.method == 'post') {
842
+ headers['Content-type'] = this.options.contentType +
843
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
844
+
845
+ /* Force "Connection: close" for older Mozilla browsers to work
846
+ * around a bug where XMLHttpRequest sends an incorrect
847
+ * Content-length header. See Mozilla Bugzilla #246651.
848
+ */
849
+ if (this.transport.overrideMimeType &&
850
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
851
+ headers['Connection'] = 'close';
852
+ }
853
+
854
+ // user-defined headers
855
+ if (typeof this.options.requestHeaders == 'object') {
856
+ var extras = this.options.requestHeaders;
857
+
858
+ if (typeof extras.push == 'function')
859
+ for (var i = 0, length = extras.length; i < length; i += 2)
860
+ headers[extras[i]] = extras[i+1];
861
+ else
862
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
863
+ }
864
+
865
+ for (var name in headers)
866
+ this.transport.setRequestHeader(name, headers[name]);
867
+ },
868
+
869
+ success: function() {
870
+ return !this.transport.status
871
+ || (this.transport.status >= 200 && this.transport.status < 300);
872
+ },
873
+
874
+ respondToReadyState: function(readyState) {
875
+ var state = Ajax.Request.Events[readyState];
876
+ var transport = this.transport, json = this.evalJSON();
877
+
878
+ if (state == 'Complete') {
879
+ try {
880
+ this._complete = true;
881
+ (this.options['on' + this.transport.status]
882
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
883
+ || Prototype.emptyFunction)(transport, json);
884
+ } catch (e) {
885
+ this.dispatchException(e);
886
+ }
887
+ }
888
+
889
+ try {
890
+ (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
891
+ Ajax.Responders.dispatch('on' + state, this, transport, json);
892
+ } catch (e) {
893
+ this.dispatchException(e);
894
+ }
895
+
896
+ if (state == 'Complete') {
897
+ if ((this.getHeader('Content-type') || '').strip().
898
+ match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
899
+ this.evalResponse();
900
+
901
+ // avoid memory leak in MSIE: clean up
902
+ this.transport.onreadystatechange = Prototype.emptyFunction;
903
+ }
904
+ },
905
+
906
+ getHeader: function(name) {
907
+ try {
908
+ return this.transport.getResponseHeader(name);
909
+ } catch (e) { return null }
910
+ },
911
+
912
+ evalJSON: function() {
913
+ try {
914
+ var json = this.getHeader('X-JSON');
915
+ return json ? eval('(' + json + ')') : null;
916
+ } catch (e) { return null }
917
+ },
918
+
919
+ evalResponse: function() {
920
+ try {
921
+ return eval(this.transport.responseText);
922
+ } catch (e) {
923
+ this.dispatchException(e);
924
+ }
925
+ },
926
+
927
+ dispatchException: function(exception) {
928
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
929
+ Ajax.Responders.dispatch('onException', this, exception);
930
+ }
931
+ });
932
+
933
+ Ajax.Updater = Class.create();
934
+
935
+ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
936
+ initialize: function(container, url, options) {
937
+ this.container = {
938
+ success: (container.success || container),
939
+ failure: (container.failure || (container.success ? null : container))
940
+ }
941
+
942
+ this.transport = Ajax.getTransport();
943
+ this.setOptions(options);
944
+
945
+ var onComplete = this.options.onComplete || Prototype.emptyFunction;
946
+ this.options.onComplete = (function(transport, param) {
947
+ this.updateContent();
948
+ onComplete(transport, param);
949
+ }).bind(this);
950
+
951
+ this.request(url);
952
+ },
953
+
954
+ updateContent: function() {
955
+ var receiver = this.container[this.success() ? 'success' : 'failure'];
956
+ var response = this.transport.responseText;
957
+
958
+ if (!this.options.evalScripts) response = response.stripScripts();
959
+
960
+ if (receiver = $(receiver)) {
961
+ if (this.options.insertion)
962
+ new this.options.insertion(receiver, response);
963
+ else
964
+ receiver.update(response);
965
+ }
966
+
967
+ if (this.success()) {
968
+ if (this.onComplete)
969
+ setTimeout(this.onComplete.bind(this), 10);
970
+ }
971
+ }
972
+ });
973
+
974
+ Ajax.PeriodicalUpdater = Class.create();
975
+ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
976
+ initialize: function(container, url, options) {
977
+ this.setOptions(options);
978
+ this.onComplete = this.options.onComplete;
979
+
980
+ this.frequency = (this.options.frequency || 2);
981
+ this.decay = (this.options.decay || 1);
982
+
983
+ this.updater = {};
984
+ this.container = container;
985
+ this.url = url;
986
+
987
+ this.start();
988
+ },
989
+
990
+ start: function() {
991
+ this.options.onComplete = this.updateComplete.bind(this);
992
+ this.onTimerEvent();
993
+ },
994
+
995
+ stop: function() {
996
+ this.updater.options.onComplete = undefined;
997
+ clearTimeout(this.timer);
998
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
999
+ },
1000
+
1001
+ updateComplete: function(request) {
1002
+ if (this.options.decay) {
1003
+ this.decay = (request.responseText == this.lastText ?
1004
+ this.decay * this.options.decay : 1);
1005
+
1006
+ this.lastText = request.responseText;
1007
+ }
1008
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
1009
+ this.decay * this.frequency * 1000);
1010
+ },
1011
+
1012
+ onTimerEvent: function() {
1013
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
1014
+ }
1015
+ });
1016
+ function $(element) {
1017
+ if (arguments.length > 1) {
1018
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1019
+ elements.push($(arguments[i]));
1020
+ return elements;
1021
+ }
1022
+ if (typeof element == 'string')
1023
+ element = document.getElementById(element);
1024
+ return Element.extend(element);
1025
+ }
1026
+
1027
+ if (Prototype.BrowserFeatures.XPath) {
1028
+ document._getElementsByXPath = function(expression, parentElement) {
1029
+ var results = [];
1030
+ var query = document.evaluate(expression, $(parentElement) || document,
1031
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1032
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
1033
+ results.push(query.snapshotItem(i));
1034
+ return results;
1035
+ }
1036
+ }
1037
+
1038
+ document.getElementsByClassName = function(className, parentElement) {
1039
+ if (Prototype.BrowserFeatures.XPath) {
1040
+ var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
1041
+ return document._getElementsByXPath(q, parentElement);
1042
+ } else {
1043
+ var children = ($(parentElement) || document.body).getElementsByTagName('*');
1044
+ var elements = [], child;
1045
+ for (var i = 0, length = children.length; i < length; i++) {
1046
+ child = children[i];
1047
+ if (Element.hasClassName(child, className))
1048
+ elements.push(Element.extend(child));
1049
+ }
1050
+ return elements;
1051
+ }
1052
+ }
1053
+
1054
+ /*--------------------------------------------------------------------------*/
1055
+
1056
+ if (!window.Element)
1057
+ var Element = new Object();
1058
+
1059
+ Element.extend = function(element) {
1060
+ if (!element) return;
1061
+ if (_nativeExtensions || element.nodeType == 3) return element;
1062
+
1063
+ if (!element._extended && element.tagName && element != window) {
1064
+ var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
1065
+
1066
+ if (element.tagName == 'FORM')
1067
+ Object.extend(methods, Form.Methods);
1068
+ if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
1069
+ Object.extend(methods, Form.Element.Methods);
1070
+
1071
+ Object.extend(methods, Element.Methods.Simulated);
1072
+
1073
+ for (var property in methods) {
1074
+ var value = methods[property];
1075
+ if (typeof value == 'function' && !(property in element))
1076
+ element[property] = cache.findOrStore(value);
1077
+ }
1078
+ }
1079
+
1080
+ element._extended = true;
1081
+ return element;
1082
+ }
1083
+
1084
+ Element.extend.cache = {
1085
+ findOrStore: function(value) {
1086
+ return this[value] = this[value] || function() {
1087
+ return value.apply(null, [this].concat($A(arguments)));
1088
+ }
1089
+ }
1090
+ }
1091
+
1092
+ Element.Methods = {
1093
+ visible: function(element) {
1094
+ return $(element).style.display != 'none';
1095
+ },
1096
+
1097
+ toggle: function(element) {
1098
+ element = $(element);
1099
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
1100
+ return element;
1101
+ },
1102
+
1103
+ hide: function(element) {
1104
+ $(element).style.display = 'none';
1105
+ return element;
1106
+ },
1107
+
1108
+ show: function(element) {
1109
+ $(element).style.display = '';
1110
+ return element;
1111
+ },
1112
+
1113
+ remove: function(element) {
1114
+ element = $(element);
1115
+ element.parentNode.removeChild(element);
1116
+ return element;
1117
+ },
1118
+
1119
+ update: function(element, html) {
1120
+ html = typeof html == 'undefined' ? '' : html.toString();
1121
+ $(element).innerHTML = html.stripScripts();
1122
+ setTimeout(function() {html.evalScripts()}, 10);
1123
+ return element;
1124
+ },
1125
+
1126
+ replace: function(element, html) {
1127
+ element = $(element);
1128
+ if (element.outerHTML) {
1129
+ element.outerHTML = html.stripScripts();
1130
+ } else {
1131
+ var range = element.ownerDocument.createRange();
1132
+ range.selectNodeContents(element);
1133
+ element.parentNode.replaceChild(
1134
+ range.createContextualFragment(html.stripScripts()), element);
1135
+ }
1136
+ setTimeout(function() {html.evalScripts()}, 10);
1137
+ return element;
1138
+ },
1139
+
1140
+ inspect: function(element) {
1141
+ element = $(element);
1142
+ var result = '<' + element.tagName.toLowerCase();
1143
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1144
+ var property = pair.first(), attribute = pair.last();
1145
+ var value = (element[property] || '').toString();
1146
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
1147
+ });
1148
+ return result + '>';
1149
+ },
1150
+
1151
+ recursivelyCollect: function(element, property) {
1152
+ element = $(element);
1153
+ var elements = [];
1154
+ while (element = element[property])
1155
+ if (element.nodeType == 1)
1156
+ elements.push(Element.extend(element));
1157
+ return elements;
1158
+ },
1159
+
1160
+ ancestors: function(element) {
1161
+ return $(element).recursivelyCollect('parentNode');
1162
+ },
1163
+
1164
+ descendants: function(element) {
1165
+ element = $(element);
1166
+ return $A(element.getElementsByTagName('*'));
1167
+ },
1168
+
1169
+ immediateDescendants: function(element) {
1170
+ if (!(element = $(element).firstChild)) return [];
1171
+ while (element && element.nodeType != 1) element = element.nextSibling;
1172
+ if (element) return [element].concat($(element).nextSiblings());
1173
+ return [];
1174
+ },
1175
+
1176
+ previousSiblings: function(element) {
1177
+ return $(element).recursivelyCollect('previousSibling');
1178
+ },
1179
+
1180
+ nextSiblings: function(element) {
1181
+ return $(element).recursivelyCollect('nextSibling');
1182
+ },
1183
+
1184
+ siblings: function(element) {
1185
+ element = $(element);
1186
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
1187
+ },
1188
+
1189
+ match: function(element, selector) {
1190
+ element = $(element);
1191
+ if (typeof selector == 'string')
1192
+ selector = new Selector(selector);
1193
+ return selector.match(element);
1194
+ },
1195
+
1196
+ up: function(element, expression, index) {
1197
+ return Selector.findElement($(element).ancestors(), expression, index);
1198
+ },
1199
+
1200
+ down: function(element, expression, index) {
1201
+ return Selector.findElement($(element).descendants(), expression, index);
1202
+ },
1203
+
1204
+ previous: function(element, expression, index) {
1205
+ return Selector.findElement($(element).previousSiblings(), expression, index);
1206
+ },
1207
+
1208
+ next: function(element, expression, index) {
1209
+ return Selector.findElement($(element).nextSiblings(), expression, index);
1210
+ },
1211
+
1212
+ getElementsBySelector: function() {
1213
+ var args = $A(arguments), element = $(args.shift());
1214
+ return Selector.findChildElements(element, args);
1215
+ },
1216
+
1217
+ getElementsByClassName: function(element, className) {
1218
+ element = $(element);
1219
+ return document.getElementsByClassName(className, element);
1220
+ },
1221
+
1222
+ readAttribute: function(element, name) {
1223
+ return $(element).getAttribute(name);
1224
+ },
1225
+
1226
+ getHeight: function(element) {
1227
+ element = $(element);
1228
+ return element.offsetHeight;
1229
+ },
1230
+
1231
+ classNames: function(element) {
1232
+ return new Element.ClassNames(element);
1233
+ },
1234
+
1235
+ hasClassName: function(element, className) {
1236
+ if (!(element = $(element))) return;
1237
+ var elementClassName = element.className;
1238
+ if (elementClassName.length == 0) return false;
1239
+ if (elementClassName == className ||
1240
+ elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
1241
+ return true;
1242
+ return false;
1243
+ },
1244
+
1245
+ addClassName: function(element, className) {
1246
+ if (!(element = $(element))) return;
1247
+ Element.classNames(element).add(className);
1248
+ return element;
1249
+ },
1250
+
1251
+ removeClassName: function(element, className) {
1252
+ if (!(element = $(element))) return;
1253
+ Element.classNames(element).remove(className);
1254
+ return element;
1255
+ },
1256
+
1257
+ observe: function() {
1258
+ Event.observe.apply(Event, arguments);
1259
+ return $A(arguments).first();
1260
+ },
1261
+
1262
+ stopObserving: function() {
1263
+ Event.stopObserving.apply(Event, arguments);
1264
+ return $A(arguments).first();
1265
+ },
1266
+
1267
+ // removes whitespace-only text node children
1268
+ cleanWhitespace: function(element) {
1269
+ element = $(element);
1270
+ var node = element.firstChild;
1271
+ while (node) {
1272
+ var nextNode = node.nextSibling;
1273
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
1274
+ element.removeChild(node);
1275
+ node = nextNode;
1276
+ }
1277
+ return element;
1278
+ },
1279
+
1280
+ empty: function(element) {
1281
+ return $(element).innerHTML.match(/^\s*$/);
1282
+ },
1283
+
1284
+ childOf: function(element, ancestor) {
1285
+ element = $(element), ancestor = $(ancestor);
1286
+ while (element = element.parentNode)
1287
+ if (element == ancestor) return true;
1288
+ return false;
1289
+ },
1290
+
1291
+ scrollTo: function(element) {
1292
+ element = $(element);
1293
+ var x = element.x ? element.x : element.offsetLeft,
1294
+ y = element.y ? element.y : element.offsetTop;
1295
+ window.scrollTo(x, y);
1296
+ return element;
1297
+ },
1298
+
1299
+ getStyle: function(element, style) {
1300
+ element = $(element);
1301
+ var inline = (style == 'float' ?
1302
+ (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat') : style);
1303
+ var value = element.style[inline.camelize()];
1304
+ if (!value) {
1305
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1306
+ var css = document.defaultView.getComputedStyle(element, null);
1307
+ value = css ? css.getPropertyValue(style) : null;
1308
+ } else if (element.currentStyle) {
1309
+ value = element.currentStyle[inline.camelize()];
1310
+ }
1311
+ }
1312
+
1313
+ if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
1314
+ value = element['offset'+style.charAt(0).toUpperCase()+style.substring(1)] + 'px';
1315
+
1316
+ if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
1317
+ if (Element.getStyle(element, 'position') == 'static') value = 'auto';
1318
+
1319
+ return value == 'auto' ? null : value;
1320
+ },
1321
+
1322
+ setStyle: function(element, style) {
1323
+ element = $(element);
1324
+ for (var name in style)
1325
+ element.style[ (name == 'float' ?
1326
+ ((typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat') : name).camelize()
1327
+ ] = style[name];
1328
+ return element;
1329
+ },
1330
+
1331
+ getDimensions: function(element) {
1332
+ element = $(element);
1333
+ if (Element.getStyle(element, 'display') != 'none')
1334
+ return {width: element.offsetWidth, height: element.offsetHeight};
1335
+
1336
+ // All *Width and *Height properties give 0 on elements with display none,
1337
+ // so enable the element temporarily
1338
+ var els = element.style;
1339
+ var originalVisibility = els.visibility;
1340
+ var originalPosition = els.position;
1341
+ els.visibility = 'hidden';
1342
+ els.position = 'absolute';
1343
+ els.display = '';
1344
+ var originalWidth = element.clientWidth;
1345
+ var originalHeight = element.clientHeight;
1346
+ els.display = 'none';
1347
+ els.position = originalPosition;
1348
+ els.visibility = originalVisibility;
1349
+ return {width: originalWidth, height: originalHeight};
1350
+ },
1351
+
1352
+ makePositioned: function(element) {
1353
+ element = $(element);
1354
+ var pos = Element.getStyle(element, 'position');
1355
+ if (pos == 'static' || !pos) {
1356
+ element._madePositioned = true;
1357
+ element.style.position = 'relative';
1358
+ // Opera returns the offset relative to the positioning context, when an
1359
+ // element is position relative but top and left have not been defined
1360
+ if (window.opera) {
1361
+ element.style.top = 0;
1362
+ element.style.left = 0;
1363
+ }
1364
+ }
1365
+ return element;
1366
+ },
1367
+
1368
+ undoPositioned: function(element) {
1369
+ element = $(element);
1370
+ if (element._madePositioned) {
1371
+ element._madePositioned = undefined;
1372
+ element.style.position =
1373
+ element.style.top =
1374
+ element.style.left =
1375
+ element.style.bottom =
1376
+ element.style.right = '';
1377
+ }
1378
+ return element;
1379
+ },
1380
+
1381
+ makeClipping: function(element) {
1382
+ element = $(element);
1383
+ if (element._overflow) return element;
1384
+ element._overflow = element.style.overflow || 'auto';
1385
+ if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1386
+ element.style.overflow = 'hidden';
1387
+ return element;
1388
+ },
1389
+
1390
+ undoClipping: function(element) {
1391
+ element = $(element);
1392
+ if (!element._overflow) return element;
1393
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
1394
+ element._overflow = null;
1395
+ return element;
1396
+ }
1397
+ }
1398
+
1399
+ Element.Methods.Simulated = {
1400
+ hasAttribute: function(element, attribute) {
1401
+ return $(element).getAttributeNode(attribute).specified;
1402
+ }
1403
+ }
1404
+
1405
+ // IE is missing .innerHTML support for TABLE-related elements
1406
+ if(document.all){
1407
+ Element.Methods.update = function(element, html) {
1408
+ element = $(element);
1409
+ html = typeof html == 'undefined' ? '' : html.toString();
1410
+ var tagName = element.tagName.toUpperCase();
1411
+ if (['THEAD','TBODY','TR','TD'].include(tagName)) {
1412
+ var div = document.createElement('div');
1413
+ switch (tagName) {
1414
+ case 'THEAD':
1415
+ case 'TBODY':
1416
+ div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
1417
+ depth = 2;
1418
+ break;
1419
+ case 'TR':
1420
+ div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
1421
+ depth = 3;
1422
+ break;
1423
+ case 'TD':
1424
+ div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
1425
+ depth = 4;
1426
+ }
1427
+ $A(element.childNodes).each(function(node){
1428
+ element.removeChild(node)
1429
+ });
1430
+ depth.times(function(){ div = div.firstChild });
1431
+
1432
+ $A(div.childNodes).each(
1433
+ function(node){ element.appendChild(node) });
1434
+ } else {
1435
+ element.innerHTML = html.stripScripts();
1436
+ }
1437
+ setTimeout(function() {html.evalScripts()}, 10);
1438
+ return element;
1439
+ }
1440
+ }
1441
+
1442
+ Object.extend(Element, Element.Methods);
1443
+
1444
+ var _nativeExtensions = false;
1445
+
1446
+ if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1447
+ ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
1448
+ var className = 'HTML' + tag + 'Element';
1449
+ if(window[className]) return;
1450
+ var klass = window[className] = {};
1451
+ klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
1452
+ });
1453
+
1454
+ Element.addMethods = function(methods) {
1455
+ Object.extend(Element.Methods, methods || {});
1456
+
1457
+ function copy(methods, destination, onlyIfAbsent) {
1458
+ onlyIfAbsent = onlyIfAbsent || false;
1459
+ var cache = Element.extend.cache;
1460
+ for (var property in methods) {
1461
+ var value = methods[property];
1462
+ if (!onlyIfAbsent || !(property in destination))
1463
+ destination[property] = cache.findOrStore(value);
1464
+ }
1465
+ }
1466
+
1467
+ if (typeof HTMLElement != 'undefined') {
1468
+ copy(Element.Methods, HTMLElement.prototype);
1469
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
1470
+ copy(Form.Methods, HTMLFormElement.prototype);
1471
+ [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
1472
+ copy(Form.Element.Methods, klass.prototype);
1473
+ });
1474
+ _nativeExtensions = true;
1475
+ }
1476
+ }
1477
+
1478
+ var Toggle = new Object();
1479
+ Toggle.display = Element.toggle;
1480
+
1481
+ /*--------------------------------------------------------------------------*/
1482
+
1483
+ Abstract.Insertion = function(adjacency) {
1484
+ this.adjacency = adjacency;
1485
+ }
1486
+
1487
+ Abstract.Insertion.prototype = {
1488
+ initialize: function(element, content) {
1489
+ this.element = $(element);
1490
+ this.content = content.stripScripts();
1491
+
1492
+ if (this.adjacency && this.element.insertAdjacentHTML) {
1493
+ try {
1494
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
1495
+ } catch (e) {
1496
+ var tagName = this.element.tagName.toUpperCase();
1497
+ if (['TBODY', 'TR'].include(tagName)) {
1498
+ this.insertContent(this.contentFromAnonymousTable());
1499
+ } else {
1500
+ throw e;
1501
+ }
1502
+ }
1503
+ } else {
1504
+ this.range = this.element.ownerDocument.createRange();
1505
+ if (this.initializeRange) this.initializeRange();
1506
+ this.insertContent([this.range.createContextualFragment(this.content)]);
1507
+ }
1508
+
1509
+ setTimeout(function() {content.evalScripts()}, 10);
1510
+ },
1511
+
1512
+ contentFromAnonymousTable: function() {
1513
+ var div = document.createElement('div');
1514
+ div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1515
+ return $A(div.childNodes[0].childNodes[0].childNodes);
1516
+ }
1517
+ }
1518
+
1519
+ var Insertion = new Object();
1520
+
1521
+ Insertion.Before = Class.create();
1522
+ Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1523
+ initializeRange: function() {
1524
+ this.range.setStartBefore(this.element);
1525
+ },
1526
+
1527
+ insertContent: function(fragments) {
1528
+ fragments.each((function(fragment) {
1529
+ this.element.parentNode.insertBefore(fragment, this.element);
1530
+ }).bind(this));
1531
+ }
1532
+ });
1533
+
1534
+ Insertion.Top = Class.create();
1535
+ Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1536
+ initializeRange: function() {
1537
+ this.range.selectNodeContents(this.element);
1538
+ this.range.collapse(true);
1539
+ },
1540
+
1541
+ insertContent: function(fragments) {
1542
+ fragments.reverse(false).each((function(fragment) {
1543
+ this.element.insertBefore(fragment, this.element.firstChild);
1544
+ }).bind(this));
1545
+ }
1546
+ });
1547
+
1548
+ Insertion.Bottom = Class.create();
1549
+ Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1550
+ initializeRange: function() {
1551
+ this.range.selectNodeContents(this.element);
1552
+ this.range.collapse(this.element);
1553
+ },
1554
+
1555
+ insertContent: function(fragments) {
1556
+ fragments.each((function(fragment) {
1557
+ this.element.appendChild(fragment);
1558
+ }).bind(this));
1559
+ }
1560
+ });
1561
+
1562
+ Insertion.After = Class.create();
1563
+ Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1564
+ initializeRange: function() {
1565
+ this.range.setStartAfter(this.element);
1566
+ },
1567
+
1568
+ insertContent: function(fragments) {
1569
+ fragments.each((function(fragment) {
1570
+ this.element.parentNode.insertBefore(fragment,
1571
+ this.element.nextSibling);
1572
+ }).bind(this));
1573
+ }
1574
+ });
1575
+
1576
+ /*--------------------------------------------------------------------------*/
1577
+
1578
+ Element.ClassNames = Class.create();
1579
+ Element.ClassNames.prototype = {
1580
+ initialize: function(element) {
1581
+ this.element = $(element);
1582
+ },
1583
+
1584
+ _each: function(iterator) {
1585
+ this.element.className.split(/\s+/).select(function(name) {
1586
+ return name.length > 0;
1587
+ })._each(iterator);
1588
+ },
1589
+
1590
+ set: function(className) {
1591
+ this.element.className = className;
1592
+ },
1593
+
1594
+ add: function(classNameToAdd) {
1595
+ if (this.include(classNameToAdd)) return;
1596
+ this.set($A(this).concat(classNameToAdd).join(' '));
1597
+ },
1598
+
1599
+ remove: function(classNameToRemove) {
1600
+ if (!this.include(classNameToRemove)) return;
1601
+ this.set($A(this).without(classNameToRemove).join(' '));
1602
+ },
1603
+
1604
+ toString: function() {
1605
+ return $A(this).join(' ');
1606
+ }
1607
+ }
1608
+
1609
+ Object.extend(Element.ClassNames.prototype, Enumerable);
1610
+ var Selector = Class.create();
1611
+ Selector.prototype = {
1612
+ initialize: function(expression) {
1613
+ this.params = {classNames: []};
1614
+ this.expression = expression.toString().strip();
1615
+ this.parseExpression();
1616
+ this.compileMatcher();
1617
+ },
1618
+
1619
+ parseExpression: function() {
1620
+ function abort(message) { throw 'Parse error in selector: ' + message; }
1621
+
1622
+ if (this.expression == '') abort('empty expression');
1623
+
1624
+ var params = this.params, expr = this.expression, match, modifier, clause, rest;
1625
+ while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
1626
+ params.attributes = params.attributes || [];
1627
+ params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
1628
+ expr = match[1];
1629
+ }
1630
+
1631
+ if (expr == '*') return this.params.wildcard = true;
1632
+
1633
+ while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
1634
+ modifier = match[1], clause = match[2], rest = match[3];
1635
+ switch (modifier) {
1636
+ case '#': params.id = clause; break;
1637
+ case '.': params.classNames.push(clause); break;
1638
+ case '':
1639
+ case undefined: params.tagName = clause.toUpperCase(); break;
1640
+ default: abort(expr.inspect());
1641
+ }
1642
+ expr = rest;
1643
+ }
1644
+
1645
+ if (expr.length > 0) abort(expr.inspect());
1646
+ },
1647
+
1648
+ buildMatchExpression: function() {
1649
+ var params = this.params, conditions = [], clause;
1650
+
1651
+ if (params.wildcard)
1652
+ conditions.push('true');
1653
+ if (clause = params.id)
1654
+ conditions.push('element.id == ' + clause.inspect());
1655
+ if (clause = params.tagName)
1656
+ conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
1657
+ if ((clause = params.classNames).length > 0)
1658
+ for (var i = 0, length = clause.length; i < length; i++)
1659
+ conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
1660
+ if (clause = params.attributes) {
1661
+ clause.each(function(attribute) {
1662
+ var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
1663
+ var splitValueBy = function(delimiter) {
1664
+ return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
1665
+ }
1666
+
1667
+ switch (attribute.operator) {
1668
+ case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
1669
+ case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
1670
+ case '|=': conditions.push(
1671
+ splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
1672
+ ); break;
1673
+ case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
1674
+ case '':
1675
+ case undefined: conditions.push(value + ' != null'); break;
1676
+ default: throw 'Unknown operator ' + attribute.operator + ' in selector';
1677
+ }
1678
+ });
1679
+ }
1680
+
1681
+ return conditions.join(' && ');
1682
+ },
1683
+
1684
+ compileMatcher: function() {
1685
+ this.match = new Function('element', 'if (!element.tagName) return false; \
1686
+ return ' + this.buildMatchExpression());
1687
+ },
1688
+
1689
+ findElements: function(scope) {
1690
+ var element;
1691
+
1692
+ if (element = $(this.params.id))
1693
+ if (this.match(element))
1694
+ if (!scope || Element.childOf(element, scope))
1695
+ return [element];
1696
+
1697
+ scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
1698
+
1699
+ var results = [];
1700
+ for (var i = 0, length = scope.length; i < length; i++)
1701
+ if (this.match(element = scope[i]))
1702
+ results.push(Element.extend(element));
1703
+
1704
+ return results;
1705
+ },
1706
+
1707
+ toString: function() {
1708
+ return this.expression;
1709
+ }
1710
+ }
1711
+
1712
+ Object.extend(Selector, {
1713
+ matchElements: function(elements, expression) {
1714
+ var selector = new Selector(expression);
1715
+ return elements.select(selector.match.bind(selector)).collect(Element.extend);
1716
+ },
1717
+
1718
+ findElement: function(elements, expression, index) {
1719
+ if (typeof expression == 'number') index = expression, expression = false;
1720
+ return Selector.matchElements(elements, expression || '*')[index || 0];
1721
+ },
1722
+
1723
+ findChildElements: function(element, expressions) {
1724
+ return expressions.map(function(expression) {
1725
+ return expression.strip().split(/\s+/).inject([null], function(results, expr) {
1726
+ var selector = new Selector(expr);
1727
+ return results.inject([], function(elements, result) {
1728
+ return elements.concat(selector.findElements(result || element));
1729
+ });
1730
+ });
1731
+ }).flatten();
1732
+ }
1733
+ });
1734
+
1735
+ function $$() {
1736
+ return Selector.findChildElements(document, $A(arguments));
1737
+ }
1738
+ var Form = {
1739
+ reset: function(form) {
1740
+ $(form).reset();
1741
+ return form;
1742
+ },
1743
+
1744
+ serializeElements: function(elements) {
1745
+ return elements.inject([], function(queryComponents, element) {
1746
+ var queryComponent = Form.Element.serialize(element);
1747
+ if (queryComponent) queryComponents.push(queryComponent);
1748
+ return queryComponents;
1749
+ }).join('&');
1750
+ }
1751
+ };
1752
+
1753
+ Form.Methods = {
1754
+ serialize: function(form) {
1755
+ return Form.serializeElements($(form).getElements());
1756
+ },
1757
+
1758
+ getElements: function(form) {
1759
+ return $A($(form).getElementsByTagName('*')).inject([],
1760
+ function(elements, child) {
1761
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
1762
+ elements.push(Element.extend(child));
1763
+ return elements;
1764
+ }
1765
+ );
1766
+ },
1767
+
1768
+ getInputs: function(form, typeName, name) {
1769
+ form = $(form);
1770
+ var inputs = form.getElementsByTagName('input');
1771
+
1772
+ if (!typeName && !name)
1773
+ return inputs;
1774
+
1775
+ var matchingInputs = new Array();
1776
+ for (var i = 0, length = inputs.length; i < length; i++) {
1777
+ var input = inputs[i];
1778
+ if ((typeName && input.type != typeName) ||
1779
+ (name && input.name != name))
1780
+ continue;
1781
+ matchingInputs.push(Element.extend(input));
1782
+ }
1783
+
1784
+ return matchingInputs;
1785
+ },
1786
+
1787
+ disable: function(form) {
1788
+ form = $(form);
1789
+ form.getElements().each(function(element) {
1790
+ element.blur();
1791
+ element.disabled = 'true';
1792
+ });
1793
+ return form;
1794
+ },
1795
+
1796
+ enable: function(form) {
1797
+ form = $(form);
1798
+ form.getElements().each(function(element) {
1799
+ element.disabled = '';
1800
+ });
1801
+ return form;
1802
+ },
1803
+
1804
+ findFirstElement: function(form) {
1805
+ return $(form).getElements().find(function(element) {
1806
+ return element.type != 'hidden' && !element.disabled &&
1807
+ ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1808
+ });
1809
+ },
1810
+
1811
+ focusFirstElement: function(form) {
1812
+ form = $(form);
1813
+ form.findFirstElement().activate();
1814
+ return form;
1815
+ }
1816
+ }
1817
+
1818
+ Object.extend(Form, Form.Methods);
1819
+
1820
+ /*--------------------------------------------------------------------------*/
1821
+
1822
+ Form.Element = {
1823
+ focus: function(element) {
1824
+ $(element).focus();
1825
+ return element;
1826
+ },
1827
+
1828
+ select: function(element) {
1829
+ $(element).select();
1830
+ return element;
1831
+ }
1832
+ }
1833
+
1834
+ Form.Element.Methods = {
1835
+ serialize: function(element) {
1836
+ element = $(element);
1837
+ if (element.disabled) return '';
1838
+ var method = element.tagName.toLowerCase();
1839
+ var parameter = Form.Element.Serializers[method](element);
1840
+
1841
+ if (parameter) {
1842
+ var key = encodeURIComponent(parameter[0]);
1843
+ if (key.length == 0) return;
1844
+
1845
+ if (parameter[1].constructor != Array)
1846
+ parameter[1] = [parameter[1]];
1847
+
1848
+ return parameter[1].map(function(value) {
1849
+ return key + '=' + encodeURIComponent(value);
1850
+ }).join('&');
1851
+ }
1852
+ },
1853
+
1854
+ getValue: function(element) {
1855
+ element = $(element);
1856
+ var method = element.tagName.toLowerCase();
1857
+ var parameter = Form.Element.Serializers[method](element);
1858
+
1859
+ if (parameter)
1860
+ return parameter[1];
1861
+ },
1862
+
1863
+ clear: function(element) {
1864
+ $(element).value = '';
1865
+ return element;
1866
+ },
1867
+
1868
+ present: function(element) {
1869
+ return $(element).value != '';
1870
+ },
1871
+
1872
+ activate: function(element) {
1873
+ element = $(element);
1874
+ element.focus();
1875
+ if (element.select && ( element.tagName.toLowerCase() != 'input' ||
1876
+ !['button', 'reset', 'submit'].include(element.type) ) )
1877
+ element.select();
1878
+ return element;
1879
+ },
1880
+
1881
+ disable: function(element) {
1882
+ element = $(element);
1883
+ element.disabled = true;
1884
+ return element;
1885
+ },
1886
+
1887
+ enable: function(element) {
1888
+ element = $(element);
1889
+ element.blur();
1890
+ element.disabled = false;
1891
+ return element;
1892
+ }
1893
+ }
1894
+
1895
+ Object.extend(Form.Element, Form.Element.Methods);
1896
+ var Field = Form.Element;
1897
+
1898
+ /*--------------------------------------------------------------------------*/
1899
+
1900
+ Form.Element.Serializers = {
1901
+ input: function(element) {
1902
+ switch (element.type.toLowerCase()) {
1903
+ case 'checkbox':
1904
+ case 'radio':
1905
+ return Form.Element.Serializers.inputSelector(element);
1906
+ default:
1907
+ return Form.Element.Serializers.textarea(element);
1908
+ }
1909
+ return false;
1910
+ },
1911
+
1912
+ inputSelector: function(element) {
1913
+ if (element.checked)
1914
+ return [element.name, element.value];
1915
+ },
1916
+
1917
+ textarea: function(element) {
1918
+ return [element.name, element.value];
1919
+ },
1920
+
1921
+ select: function(element) {
1922
+ return Form.Element.Serializers[element.type == 'select-one' ?
1923
+ 'selectOne' : 'selectMany'](element);
1924
+ },
1925
+
1926
+ selectOne: function(element) {
1927
+ var value = '', opt, index = element.selectedIndex;
1928
+ if (index >= 0) {
1929
+ opt = Element.extend(element.options[index]);
1930
+ // Uses the new potential extension if hasAttribute isn't native.
1931
+ value = opt.hasAttribute('value') ? opt.value : opt.text;
1932
+ }
1933
+ return [element.name, value];
1934
+ },
1935
+
1936
+ selectMany: function(element) {
1937
+ var value = [];
1938
+ for (var i = 0, length = element.length; i < length; i++) {
1939
+ var opt = Element.extend(element.options[i]);
1940
+ if (opt.selected)
1941
+ // Uses the new potential extension if hasAttribute isn't native.
1942
+ value.push(opt.hasAttribute('value') ? opt.value : opt.text);
1943
+ }
1944
+ return [element.name, value];
1945
+ }
1946
+ }
1947
+
1948
+ /*--------------------------------------------------------------------------*/
1949
+
1950
+ var $F = Form.Element.getValue;
1951
+
1952
+ /*--------------------------------------------------------------------------*/
1953
+
1954
+ Abstract.TimedObserver = function() {}
1955
+ Abstract.TimedObserver.prototype = {
1956
+ initialize: function(element, frequency, callback) {
1957
+ this.frequency = frequency;
1958
+ this.element = $(element);
1959
+ this.callback = callback;
1960
+
1961
+ this.lastValue = this.getValue();
1962
+ this.registerCallback();
1963
+ },
1964
+
1965
+ registerCallback: function() {
1966
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
1967
+ },
1968
+
1969
+ onTimerEvent: function() {
1970
+ var value = this.getValue();
1971
+ if (this.lastValue != value) {
1972
+ this.callback(this.element, value);
1973
+ this.lastValue = value;
1974
+ }
1975
+ }
1976
+ }
1977
+
1978
+ Form.Element.Observer = Class.create();
1979
+ Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1980
+ getValue: function() {
1981
+ return Form.Element.getValue(this.element);
1982
+ }
1983
+ });
1984
+
1985
+ Form.Observer = Class.create();
1986
+ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1987
+ getValue: function() {
1988
+ return Form.serialize(this.element);
1989
+ }
1990
+ });
1991
+
1992
+ /*--------------------------------------------------------------------------*/
1993
+
1994
+ Abstract.EventObserver = function() {}
1995
+ Abstract.EventObserver.prototype = {
1996
+ initialize: function(element, callback) {
1997
+ this.element = $(element);
1998
+ this.callback = callback;
1999
+
2000
+ this.lastValue = this.getValue();
2001
+ if (this.element.tagName.toLowerCase() == 'form')
2002
+ this.registerFormCallbacks();
2003
+ else
2004
+ this.registerCallback(this.element);
2005
+ },
2006
+
2007
+ onElementEvent: function() {
2008
+ var value = this.getValue();
2009
+ if (this.lastValue != value) {
2010
+ this.callback(this.element, value);
2011
+ this.lastValue = value;
2012
+ }
2013
+ },
2014
+
2015
+ registerFormCallbacks: function() {
2016
+ Form.getElements(this.element).each(this.registerCallback.bind(this));
2017
+ },
2018
+
2019
+ registerCallback: function(element) {
2020
+ if (element.type) {
2021
+ switch (element.type.toLowerCase()) {
2022
+ case 'checkbox':
2023
+ case 'radio':
2024
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
2025
+ break;
2026
+ default:
2027
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
2028
+ break;
2029
+ }
2030
+ }
2031
+ }
2032
+ }
2033
+
2034
+ Form.Element.EventObserver = Class.create();
2035
+ Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2036
+ getValue: function() {
2037
+ return Form.Element.getValue(this.element);
2038
+ }
2039
+ });
2040
+
2041
+ Form.EventObserver = Class.create();
2042
+ Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2043
+ getValue: function() {
2044
+ return Form.serialize(this.element);
2045
+ }
2046
+ });
2047
+ if (!window.Event) {
2048
+ var Event = new Object();
2049
+ }
2050
+
2051
+ Object.extend(Event, {
2052
+ KEY_BACKSPACE: 8,
2053
+ KEY_TAB: 9,
2054
+ KEY_RETURN: 13,
2055
+ KEY_ESC: 27,
2056
+ KEY_LEFT: 37,
2057
+ KEY_UP: 38,
2058
+ KEY_RIGHT: 39,
2059
+ KEY_DOWN: 40,
2060
+ KEY_DELETE: 46,
2061
+ KEY_HOME: 36,
2062
+ KEY_END: 35,
2063
+ KEY_PAGEUP: 33,
2064
+ KEY_PAGEDOWN: 34,
2065
+
2066
+ element: function(event) {
2067
+ return event.target || event.srcElement;
2068
+ },
2069
+
2070
+ isLeftClick: function(event) {
2071
+ return (((event.which) && (event.which == 1)) ||
2072
+ ((event.button) && (event.button == 1)));
2073
+ },
2074
+
2075
+ pointerX: function(event) {
2076
+ return event.pageX || (event.clientX +
2077
+ (document.documentElement.scrollLeft || document.body.scrollLeft));
2078
+ },
2079
+
2080
+ pointerY: function(event) {
2081
+ return event.pageY || (event.clientY +
2082
+ (document.documentElement.scrollTop || document.body.scrollTop));
2083
+ },
2084
+
2085
+ stop: function(event) {
2086
+ if (event.preventDefault) {
2087
+ event.preventDefault();
2088
+ event.stopPropagation();
2089
+ } else {
2090
+ event.returnValue = false;
2091
+ event.cancelBubble = true;
2092
+ }
2093
+ },
2094
+
2095
+ // find the first node with the given tagName, starting from the
2096
+ // node the event was triggered on; traverses the DOM upwards
2097
+ findElement: function(event, tagName) {
2098
+ var element = Event.element(event);
2099
+ while (element.parentNode && (!element.tagName ||
2100
+ (element.tagName.toUpperCase() != tagName.toUpperCase())))
2101
+ element = element.parentNode;
2102
+ return element;
2103
+ },
2104
+
2105
+ observers: false,
2106
+
2107
+ _observeAndCache: function(element, name, observer, useCapture) {
2108
+ if (!this.observers) this.observers = [];
2109
+ if (element.addEventListener) {
2110
+ this.observers.push([element, name, observer, useCapture]);
2111
+ element.addEventListener(name, observer, useCapture);
2112
+ } else if (element.attachEvent) {
2113
+ this.observers.push([element, name, observer, useCapture]);
2114
+ element.attachEvent('on' + name, observer);
2115
+ }
2116
+ },
2117
+
2118
+ unloadCache: function() {
2119
+ if (!Event.observers) return;
2120
+ for (var i = 0, length = Event.observers.length; i < length; i++) {
2121
+ Event.stopObserving.apply(this, Event.observers[i]);
2122
+ Event.observers[i][0] = null;
2123
+ }
2124
+ Event.observers = false;
2125
+ },
2126
+
2127
+ observe: function(element, name, observer, useCapture) {
2128
+ element = $(element);
2129
+ useCapture = useCapture || false;
2130
+
2131
+ if (name == 'keypress' &&
2132
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
2133
+ || element.attachEvent))
2134
+ name = 'keydown';
2135
+
2136
+ Event._observeAndCache(element, name, observer, useCapture);
2137
+ },
2138
+
2139
+ stopObserving: function(element, name, observer, useCapture) {
2140
+ element = $(element);
2141
+ useCapture = useCapture || false;
2142
+
2143
+ if (name == 'keypress' &&
2144
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
2145
+ || element.detachEvent))
2146
+ name = 'keydown';
2147
+
2148
+ if (element.removeEventListener) {
2149
+ element.removeEventListener(name, observer, useCapture);
2150
+ } else if (element.detachEvent) {
2151
+ try {
2152
+ element.detachEvent('on' + name, observer);
2153
+ } catch (e) {}
2154
+ }
2155
+ }
2156
+ });
2157
+
2158
+ /* prevent memory leaks in IE */
2159
+ if (navigator.appVersion.match(/\bMSIE\b/))
2160
+ Event.observe(window, 'unload', Event.unloadCache, false);
2161
+ var Position = {
2162
+ // set to true if needed, warning: firefox performance problems
2163
+ // NOT neeeded for page scrolling, only if draggable contained in
2164
+ // scrollable elements
2165
+ includeScrollOffsets: false,
2166
+
2167
+ // must be called before calling withinIncludingScrolloffset, every time the
2168
+ // page is scrolled
2169
+ prepare: function() {
2170
+ this.deltaX = window.pageXOffset
2171
+ || document.documentElement.scrollLeft
2172
+ || document.body.scrollLeft
2173
+ || 0;
2174
+ this.deltaY = window.pageYOffset
2175
+ || document.documentElement.scrollTop
2176
+ || document.body.scrollTop
2177
+ || 0;
2178
+ },
2179
+
2180
+ realOffset: function(element) {
2181
+ var valueT = 0, valueL = 0;
2182
+ do {
2183
+ valueT += element.scrollTop || 0;
2184
+ valueL += element.scrollLeft || 0;
2185
+ element = element.parentNode;
2186
+ } while (element);
2187
+ return [valueL, valueT];
2188
+ },
2189
+
2190
+ cumulativeOffset: function(element) {
2191
+ var valueT = 0, valueL = 0;
2192
+ do {
2193
+ valueT += element.offsetTop || 0;
2194
+ valueL += element.offsetLeft || 0;
2195
+ element = element.offsetParent;
2196
+ } while (element);
2197
+ return [valueL, valueT];
2198
+ },
2199
+
2200
+ positionedOffset: function(element) {
2201
+ var valueT = 0, valueL = 0;
2202
+ do {
2203
+ valueT += element.offsetTop || 0;
2204
+ valueL += element.offsetLeft || 0;
2205
+ element = element.offsetParent;
2206
+ if (element) {
2207
+ if(element.tagName=='BODY') break;
2208
+ var p = Element.getStyle(element, 'position');
2209
+ if (p == 'relative' || p == 'absolute') break;
2210
+ }
2211
+ } while (element);
2212
+ return [valueL, valueT];
2213
+ },
2214
+
2215
+ offsetParent: function(element) {
2216
+ if (element.offsetParent) return element.offsetParent;
2217
+ if (element == document.body) return element;
2218
+
2219
+ while ((element = element.parentNode) && element != document.body)
2220
+ if (Element.getStyle(element, 'position') != 'static')
2221
+ return element;
2222
+
2223
+ return document.body;
2224
+ },
2225
+
2226
+ // caches x/y coordinate pair to use with overlap
2227
+ within: function(element, x, y) {
2228
+ if (this.includeScrollOffsets)
2229
+ return this.withinIncludingScrolloffsets(element, x, y);
2230
+ this.xcomp = x;
2231
+ this.ycomp = y;
2232
+ this.offset = this.cumulativeOffset(element);
2233
+
2234
+ return (y >= this.offset[1] &&
2235
+ y < this.offset[1] + element.offsetHeight &&
2236
+ x >= this.offset[0] &&
2237
+ x < this.offset[0] + element.offsetWidth);
2238
+ },
2239
+
2240
+ withinIncludingScrolloffsets: function(element, x, y) {
2241
+ var offsetcache = this.realOffset(element);
2242
+
2243
+ this.xcomp = x + offsetcache[0] - this.deltaX;
2244
+ this.ycomp = y + offsetcache[1] - this.deltaY;
2245
+ this.offset = this.cumulativeOffset(element);
2246
+
2247
+ return (this.ycomp >= this.offset[1] &&
2248
+ this.ycomp < this.offset[1] + element.offsetHeight &&
2249
+ this.xcomp >= this.offset[0] &&
2250
+ this.xcomp < this.offset[0] + element.offsetWidth);
2251
+ },
2252
+
2253
+ // within must be called directly before
2254
+ overlap: function(mode, element) {
2255
+ if (!mode) return 0;
2256
+ if (mode == 'vertical')
2257
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
2258
+ element.offsetHeight;
2259
+ if (mode == 'horizontal')
2260
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
2261
+ element.offsetWidth;
2262
+ },
2263
+
2264
+ page: function(forElement) {
2265
+ var valueT = 0, valueL = 0;
2266
+
2267
+ var element = forElement;
2268
+ do {
2269
+ valueT += element.offsetTop || 0;
2270
+ valueL += element.offsetLeft || 0;
2271
+
2272
+ // Safari fix
2273
+ if (element.offsetParent==document.body)
2274
+ if (Element.getStyle(element,'position')=='absolute') break;
2275
+
2276
+ } while (element = element.offsetParent);
2277
+
2278
+ element = forElement;
2279
+ do {
2280
+ if (!window.opera || element.tagName=='BODY') {
2281
+ valueT -= element.scrollTop || 0;
2282
+ valueL -= element.scrollLeft || 0;
2283
+ }
2284
+ } while (element = element.parentNode);
2285
+
2286
+ return [valueL, valueT];
2287
+ },
2288
+
2289
+ clone: function(source, target) {
2290
+ var options = Object.extend({
2291
+ setLeft: true,
2292
+ setTop: true,
2293
+ setWidth: true,
2294
+ setHeight: true,
2295
+ offsetTop: 0,
2296
+ offsetLeft: 0
2297
+ }, arguments[2] || {})
2298
+
2299
+ // find page position of source
2300
+ source = $(source);
2301
+ var p = Position.page(source);
2302
+
2303
+ // find coordinate system to use
2304
+ target = $(target);
2305
+ var delta = [0, 0];
2306
+ var parent = null;
2307
+ // delta [0,0] will do fine with position: fixed elements,
2308
+ // position:absolute needs offsetParent deltas
2309
+ if (Element.getStyle(target,'position') == 'absolute') {
2310
+ parent = Position.offsetParent(target);
2311
+ delta = Position.page(parent);
2312
+ }
2313
+
2314
+ // correct by body offsets (fixes Safari)
2315
+ if (parent == document.body) {
2316
+ delta[0] -= document.body.offsetLeft;
2317
+ delta[1] -= document.body.offsetTop;
2318
+ }
2319
+
2320
+ // set position
2321
+ if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
2322
+ if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
2323
+ if(options.setWidth) target.style.width = source.offsetWidth + 'px';
2324
+ if(options.setHeight) target.style.height = source.offsetHeight + 'px';
2325
+ },
2326
+
2327
+ absolutize: function(element) {
2328
+ element = $(element);
2329
+ if (element.style.position == 'absolute') return;
2330
+ Position.prepare();
2331
+
2332
+ var offsets = Position.positionedOffset(element);
2333
+ var top = offsets[1];
2334
+ var left = offsets[0];
2335
+ var width = element.clientWidth;
2336
+ var height = element.clientHeight;
2337
+
2338
+ element._originalLeft = left - parseFloat(element.style.left || 0);
2339
+ element._originalTop = top - parseFloat(element.style.top || 0);
2340
+ element._originalWidth = element.style.width;
2341
+ element._originalHeight = element.style.height;
2342
+
2343
+ element.style.position = 'absolute';
2344
+ element.style.top = top + 'px';;
2345
+ element.style.left = left + 'px';;
2346
+ element.style.width = width + 'px';;
2347
+ element.style.height = height + 'px';;
2348
+ },
2349
+
2350
+ relativize: function(element) {
2351
+ element = $(element);
2352
+ if (element.style.position == 'relative') return;
2353
+ Position.prepare();
2354
+
2355
+ element.style.position = 'relative';
2356
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
2357
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
2358
+
2359
+ element.style.top = top + 'px';
2360
+ element.style.left = left + 'px';
2361
+ element.style.height = element._originalHeight;
2362
+ element.style.width = element._originalWidth;
2363
+ }
2364
+ }
2365
+
2366
+ // Safari returns margins on body which is incorrect if the child is absolutely
2367
+ // positioned. For performance reasons, redefine Position.cumulativeOffset for
2368
+ // KHTML/WebKit only.
2369
+ if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
2370
+ Position.cumulativeOffset = function(element) {
2371
+ var valueT = 0, valueL = 0;
2372
+ do {
2373
+ valueT += element.offsetTop || 0;
2374
+ valueL += element.offsetLeft || 0;
2375
+ if (element.offsetParent == document.body)
2376
+ if (Element.getStyle(element, 'position') == 'absolute') break;
2377
+
2378
+ element = element.offsetParent;
2379
+ } while (element);
2380
+
2381
+ return [valueL, valueT];
2382
+ }
2383
+ }
2384
+
2385
+ Element.addMethods();