rad_common_interface 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. data/Rakefile +1 -0
  2. data/app/static/demo/images/img1.jpg +0 -0
  3. data/app/static/demo/images/img1_200.jpg +0 -0
  4. data/app/static/demo/images/img1_icon.jpg +0 -0
  5. data/app/static/demo/images/img1_thumb.jpg +0 -0
  6. data/app/static/demo/images/img2.jpg +0 -0
  7. data/app/static/demo/images/img2_200.jpg +0 -0
  8. data/app/static/demo/images/img2_icon.jpg +0 -0
  9. data/app/static/demo/images/img2_thumb.jpg +0 -0
  10. data/app/static/demo/images/img3.jpg +0 -0
  11. data/app/static/demo/images/img3_200.jpg +0 -0
  12. data/app/static/demo/images/img3_icon.jpg +0 -0
  13. data/app/static/demo/images/img3_thumb.jpg +0 -0
  14. data/app/static/demo/images/img_big.jpg +0 -0
  15. data/app/static/demo/images/img_big_icon.jpg +0 -0
  16. data/app/static/demo/images/img_big_thum.jpg +0 -0
  17. data/app/static/demo/images/video_icon.png +0 -0
  18. data/app/static/face/attachments.js +85 -0
  19. data/app/static/face/dialogs.js +189 -0
  20. data/app/static/face/discussion.js +47 -0
  21. data/app/static/face/markup.js +53 -0
  22. data/app/static/face/more.js +33 -0
  23. data/app/static/face/table.js +24 -0
  24. data/app/static/face/tabs.js +26 -0
  25. data/app/static/face.css +8 -0
  26. data/app/static/face.js +109 -0
  27. data/app/static/lib/SimpleDialog/SimpleDialog.ContextMenu.js +36 -0
  28. data/app/static/lib/SimpleDialog/SimpleDialog.Image.js +121 -0
  29. data/app/static/lib/SimpleDialog/SimpleDialog.Mask.js +76 -0
  30. data/app/static/lib/SimpleDialog/SimpleDialog.Static.js +0 -0
  31. data/app/static/lib/SimpleDialog/SimpleDialog.css +12 -0
  32. data/app/static/lib/SimpleDialog/SimpleDialog.js +158 -0
  33. data/app/static/lib/ajax_file_uploading.js +33 -0
  34. data/app/static/themes/default/reset.css +127 -0
  35. data/app/static/themes/default/style/application.less +51 -0
  36. data/app/static/themes/default/style/aspects.less +15 -0
  37. data/app/static/themes/default/style/basic.less +49 -0
  38. data/app/static/themes/default/style/forms.less +34 -0
  39. data/app/static/themes/default/style/items.less +43 -0
  40. data/app/static/themes/default/style/markup.less +16 -0
  41. data/app/static/themes/default/style/micelaneous.less +10 -0
  42. data/app/static/themes/default/style/mixins.less +72 -0
  43. data/app/static/themes/default/style/styles.less +57 -0
  44. data/app/static/themes/default/style/tools.less +15 -0
  45. data/app/static/themes/default/style/variables.less +38 -0
  46. data/app/static/themes/default/style.css +944 -0
  47. data/app/static/themes/default/style.js +127 -0
  48. data/app/static/themes/default/style.less +22 -0
  49. data/app/static/vendor/flext.js +254 -0
  50. data/app/static/vendor/formalize/formalize.css +311 -0
  51. data/app/static/vendor/formalize/mootools.formalize.js +163 -0
  52. data/app/static/vendor/formalize/reset.css +171 -0
  53. data/app/static/vendor/iFrameFormRequest.js +95 -0
  54. data/app/static/vendor/mootools-more.js +4185 -0
  55. data/app/static/vendor/purr/purr.css +43 -0
  56. data/app/static/vendor/purr/purr.js +308 -0
  57. data/app/views/face/_attachments_tag.html.haml +17 -0
  58. data/app/views/rad/face/demo/commons/aspects.html.haml +32 -0
  59. data/app/views/rad/face/demo/commons/basic.html.haml +86 -0
  60. data/app/views/rad/face/demo/commons/forms.html.haml +57 -0
  61. data/app/views/rad/face/demo/commons/items.html.haml +32 -0
  62. data/app/views/rad/face/demo/commons/style.html.erb +111 -0
  63. data/app/views/rad/face/demo/dialogs/dialog.js.haml +1 -0
  64. data/app/views/rad/face/demo/dialogs/dialog_form.html.haml +7 -0
  65. data/app/views/rad/face/demo/dialogs/dialog_form.js.erb +1 -0
  66. data/app/views/rad/face/demo/dialogs/inplace/_element.html.haml +3 -0
  67. data/app/views/rad/face/demo/dialogs/inplace/_form.html.haml +3 -0
  68. data/app/views/rad/face/demo/dialogs/inplace.js.haml +1 -0
  69. data/app/views/rad/face/demo/dialogs/inplace_form.js.haml +2 -0
  70. data/app/views/rad/face/demo/dialogs/show.html.haml +27 -0
  71. data/app/views/rad/face/demo/helps/help.html.haml +1 -0
  72. data/app/views/rad/face/demo/helps/index.html.haml +25 -0
  73. data/app/views/rad/face/demo/layout.html.haml +3 -0
  74. data/app/views/rad/face/demo/layout.js.haml +11 -0
  75. data/app/views/rad/face/demo/shared/_comments.html.haml +11 -0
  76. data/app/views/rad/face/demo/shared/_core_tools.html.haml +6 -0
  77. data/app/views/rad/face/demo/shared/_line_previews.html.haml +40 -0
  78. data/app/views/rad/face/demo/shared/_paginator.html.haml +7 -0
  79. data/app/views/rad/face/demo/shared/_tools.html.haml +25 -0
  80. data/app/views/rad/face/demo/shared/_top_navigation_bottom.html.haml +34 -0
  81. data/app/views/rad/face/demo/sites/blog.html.haml +12 -0
  82. data/app/views/rad/face/demo/sites/home.html.haml +8 -0
  83. data/app/views/rad/face/demo/sites/post.html.haml +10 -0
  84. data/app/views/rad/face/demo/sites/style.html.haml +8 -0
  85. data/app/views/themes/default/application.html.haml +25 -0
  86. data/app/views/themes/default/basic_list.html.haml +2 -0
  87. data/app/views/themes/default/basic_list_item.html.haml +5 -0
  88. data/app/views/themes/default/bottom_panel.html.haml +16 -0
  89. data/app/views/themes/default/comment.html.haml +20 -0
  90. data/app/views/themes/default/controls.html.haml +3 -0
  91. data/app/views/themes/default/demo_metadata.rb +118 -0
  92. data/app/views/themes/default/details.html.haml +6 -0
  93. data/app/views/themes/default/discussion.html.haml +7 -0
  94. data/app/views/themes/default/divider.html.haml +2 -0
  95. data/app/views/themes/default/forms/errors.html.haml +4 -0
  96. data/app/views/themes/default/forms/field.html.haml +18 -0
  97. data/app/views/themes/default/forms/form.html.haml +4 -0
  98. data/app/views/themes/default/forms/line.html.haml +8 -0
  99. data/app/views/themes/default/help.html.haml +3 -0
  100. data/app/views/themes/default/html.html.haml +1 -0
  101. data/app/views/themes/default/index.html.haml +6 -0
  102. data/app/views/themes/default/item.html.haml +12 -0
  103. data/app/views/themes/default/layout_templates/dashboard.html.haml +1 -0
  104. data/app/views/themes/default/layout_templates/default.html.haml +22 -0
  105. data/app/views/themes/default/line.html.haml +21 -0
  106. data/app/views/themes/default/message.html.haml +2 -0
  107. data/app/views/themes/default/more.html.haml +8 -0
  108. data/app/views/themes/default/narrow.html.haml +2 -0
  109. data/app/views/themes/default/navigation.html.haml +16 -0
  110. data/app/views/themes/default/paginator.html.haml +8 -0
  111. data/app/views/themes/default/shared/details.html.haml +17 -0
  112. data/app/views/themes/default/table.html.haml +9 -0
  113. data/app/views/themes/default/table_row.html.haml +4 -0
  114. data/app/views/themes/default/tabs.html.haml +27 -0
  115. data/app/views/themes/default/tag_selector.html.haml +10 -0
  116. data/app/views/themes/default/text.html.haml +4 -0
  117. data/app/views/themes/default/thumb.html.haml +10 -0
  118. data/app/views/themes/default/title.html.haml +3 -0
  119. data/app/views/themes/default/tool.html.haml +5 -0
  120. data/app/views/themes/default/toolbar.html.haml +16 -0
  121. data/app/views/themes/default/top_panel.html.haml +18 -0
  122. metadata +153 -25
@@ -0,0 +1,4185 @@
1
+ // MooTools: the javascript framework.
2
+ // Load this file's selection again by visiting: http://mootools.net/more/40cf67ff29e768d172446f7fcd18a5f3
3
+ // Or build this file again with packager using: packager build More/More More/Events.Pseudos More/Class.Refactor More/Class.Binds More/Class.Occlude More/Array.Extras More/Number.Format More/Object.Extras More/String.Extras More/String.QueryString More/Hash More/Hash.Extras More/Elements.From More/Element.Event.Pseudos More/Element.Event.Pseudos.Keys More/Element.Delegation More/Element.Measure More/Element.Position More/Element.Shortcuts More/Drag More/Drag.Move More/Sortables More/Request.JSONP More/Request.Periodical More/Assets More/IframeShim More/Keyboard More/Keyboard.Extras More/Mask More/Tips More/Spinner More/Locale
4
+ /*
5
+ ---
6
+
7
+ script: More.js
8
+
9
+ name: More
10
+
11
+ description: MooTools More
12
+
13
+ license: MIT-style license
14
+
15
+ authors:
16
+ - Guillermo Rauch
17
+ - Thomas Aylott
18
+ - Scott Kyle
19
+ - Arian Stolwijk
20
+ - Tim Wienk
21
+ - Christoph Pojer
22
+ - Aaron Newton
23
+ - Jacob Thornton
24
+
25
+ requires:
26
+ - Core/MooTools
27
+
28
+ provides: [MooTools.More]
29
+
30
+ ...
31
+ */
32
+
33
+ MooTools.More = {
34
+ 'version': '1.3.2.1',
35
+ 'build': 'e586bcd2496e9b22acfde32e12f84d49ce09e59d'
36
+ };
37
+
38
+
39
+ /*
40
+ ---
41
+
42
+ name: Events.Pseudos
43
+
44
+ description: Adds the functionality to add pseudo events
45
+
46
+ license: MIT-style license
47
+
48
+ authors:
49
+ - Arian Stolwijk
50
+
51
+ requires: [Core/Class.Extras, Core/Slick.Parser, More/MooTools.More]
52
+
53
+ provides: [Events.Pseudos]
54
+
55
+ ...
56
+ */
57
+
58
+ Events.Pseudos = function(pseudos, addEvent, removeEvent){
59
+
60
+ var storeKey = 'monitorEvents:';
61
+
62
+ var storageOf = function(object){
63
+ return {
64
+ store: object.store ? function(key, value){
65
+ object.store(storeKey + key, value);
66
+ } : function(key, value){
67
+ (object.$monitorEvents || (object.$monitorEvents = {}))[key] = value;
68
+ },
69
+ retrieve: object.retrieve ? function(key, dflt){
70
+ return object.retrieve(storeKey + key, dflt);
71
+ } : function(key, dflt){
72
+ if (!object.$monitorEvents) return dflt;
73
+ return object.$monitorEvents[key] || dflt;
74
+ }
75
+ };
76
+ };
77
+
78
+ var splitType = function(type){
79
+ if (type.indexOf(':') == -1 || !pseudos) return null;
80
+
81
+ var parsed = Slick.parse(type).expressions[0][0],
82
+ parsedPseudos = parsed.pseudos,
83
+ l = parsedPseudos.length,
84
+ splits = [];
85
+
86
+ while (l--) if (pseudos[parsedPseudos[l].key]){
87
+ splits.push({
88
+ event: parsed.tag,
89
+ value: parsedPseudos[l].value,
90
+ pseudo: parsedPseudos[l].key,
91
+ original: type
92
+ });
93
+ }
94
+
95
+ return splits.length ? splits : null;
96
+ };
97
+
98
+ var mergePseudoOptions = function(split){
99
+ return Object.merge.apply(this, split.map(function(item){
100
+ return pseudos[item.pseudo].options || {};
101
+ }));
102
+ };
103
+
104
+ return {
105
+
106
+ addEvent: function(type, fn, internal){
107
+ var split = splitType(type);
108
+ if (!split) return addEvent.call(this, type, fn, internal);
109
+
110
+ var storage = storageOf(this),
111
+ events = storage.retrieve(type, []),
112
+ eventType = split[0].event,
113
+ options = mergePseudoOptions(split),
114
+ stack = fn,
115
+ eventOptions = options[eventType] || {},
116
+ args = Array.slice(arguments, 2),
117
+ self = this,
118
+ monitor;
119
+
120
+ if (eventOptions.args) args.append(Array.from(eventOptions.args));
121
+ if (eventOptions.base) eventType = eventOptions.base;
122
+ if (eventOptions.onAdd) eventOptions.onAdd(this);
123
+
124
+ split.each(function(item){
125
+ var stackFn = stack;
126
+ stack = function(){
127
+ (eventOptions.listener || pseudos[item.pseudo].listener).call(self, item, stackFn, arguments, monitor, options);
128
+ };
129
+ });
130
+ monitor = stack.bind(this);
131
+
132
+ events.include({event: fn, monitor: monitor});
133
+ storage.store(type, events);
134
+
135
+ addEvent.apply(this, [type, fn].concat(args));
136
+ return addEvent.apply(this, [eventType, monitor].concat(args));
137
+ },
138
+
139
+ removeEvent: function(type, fn){
140
+ var split = splitType(type);
141
+ if (!split) return removeEvent.call(this, type, fn);
142
+
143
+ var storage = storageOf(this),
144
+ events = storage.retrieve(type);
145
+ if (!events) return this;
146
+
147
+ var eventType = split[0].event,
148
+ options = mergePseudoOptions(split),
149
+ eventOptions = options[eventType] || {},
150
+ args = Array.slice(arguments, 2);
151
+
152
+ if (eventOptions.args) args.append(Array.from(eventOptions.args));
153
+ if (eventOptions.base) eventType = eventOptions.base;
154
+ if (eventOptions.onRemove) eventOptions.onRemove(this);
155
+
156
+ removeEvent.apply(this, [type, fn].concat(args));
157
+ events.each(function(monitor, i){
158
+ if (!fn || monitor.event == fn) removeEvent.apply(this, [eventType, monitor.monitor].concat(args));
159
+ delete events[i];
160
+ }, this);
161
+
162
+ storage.store(type, events);
163
+ return this;
164
+ }
165
+
166
+ };
167
+
168
+ };
169
+
170
+ (function(){
171
+
172
+ var pseudos = {
173
+
174
+ once: {
175
+ listener: function(split, fn, args, monitor){
176
+ fn.apply(this, args);
177
+ this.removeEvent(split.event, monitor)
178
+ .removeEvent(split.original, fn);
179
+ }
180
+ },
181
+
182
+ throttle: {
183
+ listener: function(split, fn, args){
184
+ if (!fn._throttled){
185
+ fn.apply(this, args);
186
+ fn._throttled = setTimeout(function(){
187
+ fn._throttled = false;
188
+ }, split.value || 250);
189
+ }
190
+ }
191
+ },
192
+
193
+ pause: {
194
+ listener: function(split, fn, args){
195
+ clearTimeout(fn._pause);
196
+ fn._pause = fn.delay(split.value || 250, this, args);
197
+ }
198
+ }
199
+
200
+ };
201
+
202
+ Events.definePseudo = function(key, listener){
203
+ pseudos[key] = Type.isFunction(listener) ? {listener: listener} : listener;
204
+ return this;
205
+ };
206
+
207
+ Events.lookupPseudo = function(key){
208
+ return pseudos[key];
209
+ };
210
+
211
+ var proto = Events.prototype;
212
+ Events.implement(Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent));
213
+
214
+ ['Request', 'Fx'].each(function(klass){
215
+ if (this[klass]) this[klass].implement(Events.prototype);
216
+ });
217
+
218
+ })();
219
+
220
+
221
+ /*
222
+ ---
223
+
224
+ script: Class.Refactor.js
225
+
226
+ name: Class.Refactor
227
+
228
+ description: Extends a class onto itself with new property, preserving any items attached to the class's namespace.
229
+
230
+ license: MIT-style license
231
+
232
+ authors:
233
+ - Aaron Newton
234
+
235
+ requires:
236
+ - Core/Class
237
+ - /MooTools.More
238
+
239
+ # Some modules declare themselves dependent on Class.Refactor
240
+ provides: [Class.refactor, Class.Refactor]
241
+
242
+ ...
243
+ */
244
+
245
+ Class.refactor = function(original, refactors){
246
+
247
+ Object.each(refactors, function(item, name){
248
+ var origin = original.prototype[name];
249
+ origin = (origin && origin.$origin) || origin || function(){};
250
+ original.implement(name, (typeof item == 'function') ? function(){
251
+ var old = this.previous;
252
+ this.previous = origin;
253
+ var value = item.apply(this, arguments);
254
+ this.previous = old;
255
+ return value;
256
+ } : item);
257
+ });
258
+
259
+ return original;
260
+
261
+ };
262
+
263
+
264
+ /*
265
+ ---
266
+
267
+ script: Class.Binds.js
268
+
269
+ name: Class.Binds
270
+
271
+ description: Automagically binds specified methods in a class to the instance of the class.
272
+
273
+ license: MIT-style license
274
+
275
+ authors:
276
+ - Aaron Newton
277
+
278
+ requires:
279
+ - Core/Class
280
+ - /MooTools.More
281
+
282
+ provides: [Class.Binds]
283
+
284
+ ...
285
+ */
286
+
287
+ Class.Mutators.Binds = function(binds){
288
+ if (!this.prototype.initialize) this.implement('initialize', function(){});
289
+ return Array.from(binds).concat(this.prototype.Binds || []);
290
+ };
291
+
292
+ Class.Mutators.initialize = function(initialize){
293
+ return function(){
294
+ Array.from(this.Binds).each(function(name){
295
+ var original = this[name];
296
+ if (original) this[name] = original.bind(this);
297
+ }, this);
298
+ return initialize.apply(this, arguments);
299
+ };
300
+ };
301
+
302
+
303
+ /*
304
+ ---
305
+
306
+ script: Class.Occlude.js
307
+
308
+ name: Class.Occlude
309
+
310
+ description: Prevents a class from being applied to a DOM element twice.
311
+
312
+ license: MIT-style license.
313
+
314
+ authors:
315
+ - Aaron Newton
316
+
317
+ requires:
318
+ - Core/Class
319
+ - Core/Element
320
+ - /MooTools.More
321
+
322
+ provides: [Class.Occlude]
323
+
324
+ ...
325
+ */
326
+
327
+ Class.Occlude = new Class({
328
+
329
+ occlude: function(property, element){
330
+ element = document.id(element || this.element);
331
+ var instance = element.retrieve(property || this.property);
332
+ if (instance && !this.occluded)
333
+ return (this.occluded = instance);
334
+
335
+ this.occluded = false;
336
+ element.store(property || this.property, this);
337
+ return this.occluded;
338
+ }
339
+
340
+ });
341
+
342
+
343
+ /*
344
+ ---
345
+
346
+ script: Array.Extras.js
347
+
348
+ name: Array.Extras
349
+
350
+ description: Extends the Array native object to include useful methods to work with arrays.
351
+
352
+ license: MIT-style license
353
+
354
+ authors:
355
+ - Christoph Pojer
356
+ - Sebastian Markbåge
357
+
358
+ requires:
359
+ - Core/Array
360
+ - MooTools.More
361
+
362
+ provides: [Array.Extras]
363
+
364
+ ...
365
+ */
366
+
367
+ (function(nil){
368
+
369
+ Array.implement({
370
+
371
+ min: function(){
372
+ return Math.min.apply(null, this);
373
+ },
374
+
375
+ max: function(){
376
+ return Math.max.apply(null, this);
377
+ },
378
+
379
+ average: function(){
380
+ return this.length ? this.sum() / this.length : 0;
381
+ },
382
+
383
+ sum: function(){
384
+ var result = 0, l = this.length;
385
+ if (l){
386
+ while (l--) result += this[l];
387
+ }
388
+ return result;
389
+ },
390
+
391
+ unique: function(){
392
+ return [].combine(this);
393
+ },
394
+
395
+ shuffle: function(){
396
+ for (var i = this.length; i && --i;){
397
+ var temp = this[i], r = Math.floor(Math.random() * ( i + 1 ));
398
+ this[i] = this[r];
399
+ this[r] = temp;
400
+ }
401
+ return this;
402
+ },
403
+
404
+ reduce: function(fn, value){
405
+ for (var i = 0, l = this.length; i < l; i++){
406
+ if (i in this) value = value === nil ? this[i] : fn.call(null, value, this[i], i, this);
407
+ }
408
+ return value;
409
+ },
410
+
411
+ reduceRight: function(fn, value){
412
+ var i = this.length;
413
+ while (i--){
414
+ if (i in this) value = value === nil ? this[i] : fn.call(null, value, this[i], i, this);
415
+ }
416
+ return value;
417
+ }
418
+
419
+ });
420
+
421
+ })();
422
+
423
+
424
+ /*
425
+ ---
426
+
427
+ script: Object.Extras.js
428
+
429
+ name: Object.Extras
430
+
431
+ description: Extra Object generics, like getFromPath which allows a path notation to child elements.
432
+
433
+ license: MIT-style license
434
+
435
+ authors:
436
+ - Aaron Newton
437
+
438
+ requires:
439
+ - Core/Object
440
+ - /MooTools.More
441
+
442
+ provides: [Object.Extras]
443
+
444
+ ...
445
+ */
446
+
447
+ (function(){
448
+
449
+ var defined = function(value){
450
+ return value != null;
451
+ };
452
+
453
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
454
+
455
+ Object.extend({
456
+
457
+ getFromPath: function(source, parts){
458
+ if (typeof parts == 'string') parts = parts.split('.');
459
+ for (var i = 0, l = parts.length; i < l; i++){
460
+ if (hasOwnProperty.call(source, parts[i])) source = source[parts[i]];
461
+ else return null;
462
+ }
463
+ return source;
464
+ },
465
+
466
+ cleanValues: function(object, method){
467
+ method = method || defined;
468
+ for (var key in object) if (!method(object[key])){
469
+ delete object[key];
470
+ }
471
+ return object;
472
+ },
473
+
474
+ erase: function(object, key){
475
+ if (hasOwnProperty.call(object, key)) delete object[key];
476
+ return object;
477
+ },
478
+
479
+ run: function(object){
480
+ var args = Array.slice(arguments, 1);
481
+ for (var key in object) if (object[key].apply){
482
+ object[key].apply(object, args);
483
+ }
484
+ return object;
485
+ }
486
+
487
+ });
488
+
489
+ })();
490
+
491
+
492
+ /*
493
+ ---
494
+
495
+ script: Locale.js
496
+
497
+ name: Locale
498
+
499
+ description: Provides methods for localization.
500
+
501
+ license: MIT-style license
502
+
503
+ authors:
504
+ - Aaron Newton
505
+ - Arian Stolwijk
506
+
507
+ requires:
508
+ - Core/Events
509
+ - /Object.Extras
510
+ - /MooTools.More
511
+
512
+ provides: [Locale, Lang]
513
+
514
+ ...
515
+ */
516
+
517
+ (function(){
518
+
519
+ var current = null,
520
+ locales = {},
521
+ inherits = {};
522
+
523
+ var getSet = function(set){
524
+ if (instanceOf(set, Locale.Set)) return set;
525
+ else return locales[set];
526
+ };
527
+
528
+ var Locale = this.Locale = {
529
+
530
+ define: function(locale, set, key, value){
531
+ var name;
532
+ if (instanceOf(locale, Locale.Set)){
533
+ name = locale.name;
534
+ if (name) locales[name] = locale;
535
+ } else {
536
+ name = locale;
537
+ if (!locales[name]) locales[name] = new Locale.Set(name);
538
+ locale = locales[name];
539
+ }
540
+
541
+ if (set) locale.define(set, key, value);
542
+
543
+ /*<1.2compat>*/
544
+ if (set == 'cascade') return Locale.inherit(name, key);
545
+ /*</1.2compat>*/
546
+
547
+ if (!current) current = locale;
548
+
549
+ return locale;
550
+ },
551
+
552
+ use: function(locale){
553
+ locale = getSet(locale);
554
+
555
+ if (locale){
556
+ current = locale;
557
+
558
+ this.fireEvent('change', locale);
559
+
560
+ /*<1.2compat>*/
561
+ this.fireEvent('langChange', locale.name);
562
+ /*</1.2compat>*/
563
+ }
564
+
565
+ return this;
566
+ },
567
+
568
+ getCurrent: function(){
569
+ return current;
570
+ },
571
+
572
+ get: function(key, args){
573
+ return (current) ? current.get(key, args) : '';
574
+ },
575
+
576
+ inherit: function(locale, inherits, set){
577
+ locale = getSet(locale);
578
+
579
+ if (locale) locale.inherit(inherits, set);
580
+ return this;
581
+ },
582
+
583
+ list: function(){
584
+ return Object.keys(locales);
585
+ }
586
+
587
+ };
588
+
589
+ Object.append(Locale, new Events);
590
+
591
+ Locale.Set = new Class({
592
+
593
+ sets: {},
594
+
595
+ inherits: {
596
+ locales: [],
597
+ sets: {}
598
+ },
599
+
600
+ initialize: function(name){
601
+ this.name = name || '';
602
+ },
603
+
604
+ define: function(set, key, value){
605
+ var defineData = this.sets[set];
606
+ if (!defineData) defineData = {};
607
+
608
+ if (key){
609
+ if (typeOf(key) == 'object') defineData = Object.merge(defineData, key);
610
+ else defineData[key] = value;
611
+ }
612
+ this.sets[set] = defineData;
613
+
614
+ return this;
615
+ },
616
+
617
+ get: function(key, args, _base){
618
+ var value = Object.getFromPath(this.sets, key);
619
+ if (value != null){
620
+ var type = typeOf(value);
621
+ if (type == 'function') value = value.apply(null, Array.from(args));
622
+ else if (type == 'object') value = Object.clone(value);
623
+ return value;
624
+ }
625
+
626
+ // get value of inherited locales
627
+ var index = key.indexOf('.'),
628
+ set = index < 0 ? key : key.substr(0, index),
629
+ names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include('en-US');
630
+ if (!_base) _base = [];
631
+
632
+ for (var i = 0, l = names.length; i < l; i++){
633
+ if (_base.contains(names[i])) continue;
634
+ _base.include(names[i]);
635
+
636
+ var locale = locales[names[i]];
637
+ if (!locale) continue;
638
+
639
+ value = locale.get(key, args, _base);
640
+ if (value != null) return value;
641
+ }
642
+
643
+ return '';
644
+ },
645
+
646
+ inherit: function(names, set){
647
+ names = Array.from(names);
648
+
649
+ if (set && !this.inherits.sets[set]) this.inherits.sets[set] = [];
650
+
651
+ var l = names.length;
652
+ while (l--) (set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]);
653
+
654
+ return this;
655
+ }
656
+
657
+ });
658
+
659
+ /*<1.2compat>*/
660
+ var lang = MooTools.lang = {};
661
+
662
+ Object.append(lang, Locale, {
663
+ setLanguage: Locale.use,
664
+ getCurrentLanguage: function(){
665
+ var current = Locale.getCurrent();
666
+ return (current) ? current.name : null;
667
+ },
668
+ set: function(){
669
+ Locale.define.apply(this, arguments);
670
+ return this;
671
+ },
672
+ get: function(set, key, args){
673
+ if (key) set += '.' + key;
674
+ return Locale.get(set, args);
675
+ }
676
+ });
677
+ /*</1.2compat>*/
678
+
679
+ })();
680
+
681
+
682
+ /*
683
+ ---
684
+
685
+ name: Locale.en-US.Number
686
+
687
+ description: Number messages for US English.
688
+
689
+ license: MIT-style license
690
+
691
+ authors:
692
+ - Arian Stolwijk
693
+
694
+ requires:
695
+ - /Locale
696
+
697
+ provides: [Locale.en-US.Number]
698
+
699
+ ...
700
+ */
701
+
702
+ Locale.define('en-US', 'Number', {
703
+
704
+ decimal: '.',
705
+ group: ',',
706
+
707
+ /* Commented properties are the defaults for Number.format
708
+ decimals: 0,
709
+ precision: 0,
710
+ scientific: null,
711
+
712
+ prefix: null,
713
+ suffic: null,
714
+
715
+ // Negative/Currency/percentage will mixin Number
716
+ negative: {
717
+ prefix: '-'
718
+ },*/
719
+
720
+ currency: {
721
+ // decimals: 2,
722
+ prefix: '$ '
723
+ }/*,
724
+
725
+ percentage: {
726
+ decimals: 2,
727
+ suffix: '%'
728
+ }*/
729
+
730
+ });
731
+
732
+
733
+
734
+
735
+ /*
736
+ ---
737
+ name: Number.Format
738
+ description: Extends the Number Type object to include a number formatting method.
739
+ license: MIT-style license
740
+ authors: [Arian Stolwijk]
741
+ requires: [Core/Number, Locale.en-US.Number]
742
+ # Number.Extras is for compatibility
743
+ provides: [Number.Format, Number.Extras]
744
+ ...
745
+ */
746
+
747
+
748
+ Number.implement({
749
+
750
+ format: function(options){
751
+ // Thanks dojo and YUI for some inspiration
752
+ var value = this;
753
+ options = options ? Object.clone(options) : {};
754
+ var getOption = function(key){
755
+ if (options[key] != null) return options[key];
756
+ return Locale.get('Number.' + key);
757
+ };
758
+
759
+ var negative = value < 0,
760
+ decimal = getOption('decimal'),
761
+ precision = getOption('precision'),
762
+ group = getOption('group'),
763
+ decimals = getOption('decimals');
764
+
765
+ if (negative){
766
+ var negativeLocale = getOption('negative') || {};
767
+ if (negativeLocale.prefix == null && negativeLocale.suffix == null) negativeLocale.prefix = '-';
768
+ ['prefix', 'suffix'].each(function(key){
769
+ if (negativeLocale[key]) options[key] = getOption(key) + negativeLocale[key];
770
+ });
771
+
772
+ value = -value;
773
+ }
774
+
775
+ var prefix = getOption('prefix'),
776
+ suffix = getOption('suffix');
777
+
778
+ if (decimals !== '' && decimals >= 0 && decimals <= 20) value = value.toFixed(decimals);
779
+ if (precision >= 1 && precision <= 21) value = (+value).toPrecision(precision);
780
+
781
+ value += '';
782
+ var index;
783
+ if (getOption('scientific') === false && value.indexOf('e') > -1){
784
+ var match = value.split('e'),
785
+ zeros = +match[1];
786
+ value = match[0].replace('.', '');
787
+
788
+ if (zeros < 0){
789
+ zeros = -zeros - 1;
790
+ index = match[0].indexOf('.');
791
+ if (index > -1) zeros -= index - 1;
792
+ while (zeros--) value = '0' + value;
793
+ value = '0.' + value;
794
+ } else {
795
+ index = match[0].lastIndexOf('.');
796
+ if (index > -1) zeros -= match[0].length - index - 1;
797
+ while (zeros--) value += '0';
798
+ }
799
+ }
800
+
801
+ if (decimal != '.') value = value.replace('.', decimal);
802
+
803
+ if (group){
804
+ index = value.lastIndexOf(decimal);
805
+ index = (index > -1) ? index : value.length;
806
+ var newOutput = value.substring(index),
807
+ i = index;
808
+
809
+ while (i--){
810
+ if ((index - i - 1) % 3 == 0 && i != (index - 1)) newOutput = group + newOutput;
811
+ newOutput = value.charAt(i) + newOutput;
812
+ }
813
+
814
+ value = newOutput;
815
+ }
816
+
817
+ if (prefix) value = prefix + value;
818
+ if (suffix) value += suffix;
819
+
820
+ return value;
821
+ },
822
+
823
+ formatCurrency: function(){
824
+ var locale = Locale.get('Number.currency') || {};
825
+ if (locale.scientific == null) locale.scientific = false;
826
+ if (locale.decimals == null) locale.decimals = 2;
827
+
828
+ return this.format(locale);
829
+ },
830
+
831
+ formatPercentage: function(){
832
+ var locale = Locale.get('Number.percentage') || {};
833
+ if (locale.suffix == null) locale.suffix = '%';
834
+ if (locale.decimals == null) locale.decimals = 2;
835
+
836
+ return this.format(locale);
837
+ }
838
+
839
+ });
840
+
841
+
842
+ /*
843
+ ---
844
+
845
+ script: String.Extras.js
846
+
847
+ name: String.Extras
848
+
849
+ description: Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc).
850
+
851
+ license: MIT-style license
852
+
853
+ authors:
854
+ - Aaron Newton
855
+ - Guillermo Rauch
856
+ - Christopher Pitt
857
+
858
+ requires:
859
+ - Core/String
860
+ - Core/Array
861
+ - MooTools.More
862
+
863
+ provides: [String.Extras]
864
+
865
+ ...
866
+ */
867
+
868
+ (function(){
869
+
870
+ var special = {
871
+ 'a': /[àáâãäåăą]/g,
872
+ 'A': /[ÀÁÂÃÄÅĂĄ]/g,
873
+ 'c': /[ćčç]/g,
874
+ 'C': /[ĆČÇ]/g,
875
+ 'd': /[ďđ]/g,
876
+ 'D': /[ĎÐ]/g,
877
+ 'e': /[èéêëěę]/g,
878
+ 'E': /[ÈÉÊËĚĘ]/g,
879
+ 'g': /[ğ]/g,
880
+ 'G': /[Ğ]/g,
881
+ 'i': /[ìíîï]/g,
882
+ 'I': /[ÌÍÎÏ]/g,
883
+ 'l': /[ĺľł]/g,
884
+ 'L': /[ĹĽŁ]/g,
885
+ 'n': /[ñňń]/g,
886
+ 'N': /[ÑŇŃ]/g,
887
+ 'o': /[òóôõöøő]/g,
888
+ 'O': /[ÒÓÔÕÖØ]/g,
889
+ 'r': /[řŕ]/g,
890
+ 'R': /[ŘŔ]/g,
891
+ 's': /[ššş]/g,
892
+ 'S': /[ŠŞŚ]/g,
893
+ 't': /[ťţ]/g,
894
+ 'T': /[ŤŢ]/g,
895
+ 'ue': /[ü]/g,
896
+ 'UE': /[Ü]/g,
897
+ 'u': /[ùúûůµ]/g,
898
+ 'U': /[ÙÚÛŮ]/g,
899
+ 'y': /[ÿý]/g,
900
+ 'Y': /[ŸÝ]/g,
901
+ 'z': /[žźż]/g,
902
+ 'Z': /[ŽŹŻ]/g,
903
+ 'th': /[þ]/g,
904
+ 'TH': /[Þ]/g,
905
+ 'dh': /[ð]/g,
906
+ 'DH': /[Ð]/g,
907
+ 'ss': /[ß]/g,
908
+ 'oe': /[œ]/g,
909
+ 'OE': /[Œ]/g,
910
+ 'ae': /[æ]/g,
911
+ 'AE': /[Æ]/g
912
+ },
913
+
914
+ tidy = {
915
+ ' ': /[\xa0\u2002\u2003\u2009]/g,
916
+ '*': /[\xb7]/g,
917
+ '\'': /[\u2018\u2019]/g,
918
+ '"': /[\u201c\u201d]/g,
919
+ '...': /[\u2026]/g,
920
+ '-': /[\u2013]/g,
921
+ // '--': /[\u2014]/g,
922
+ '&raquo;': /[\uFFFD]/g
923
+ };
924
+
925
+ var walk = function(string, replacements){
926
+ var result = string, key;
927
+ for (key in replacements) result = result.replace(replacements[key], key);
928
+ return result;
929
+ };
930
+
931
+ var getRegexForTag = function(tag, contents){
932
+ tag = tag || '';
933
+ var regstr = contents ? "<" + tag + "(?!\\w)[^>]*>([\\s\\S]*?)<\/" + tag + "(?!\\w)>" : "<\/?" + tag + "([^>]+)?>",
934
+ reg = new RegExp(regstr, "gi");
935
+ return reg;
936
+ };
937
+
938
+ String.implement({
939
+
940
+ standardize: function(){
941
+ return walk(this, special);
942
+ },
943
+
944
+ repeat: function(times){
945
+ return new Array(times + 1).join(this);
946
+ },
947
+
948
+ pad: function(length, str, direction){
949
+ if (this.length >= length) return this;
950
+
951
+ var pad = (str == null ? ' ' : '' + str)
952
+ .repeat(length - this.length)
953
+ .substr(0, length - this.length);
954
+
955
+ if (!direction || direction == 'right') return this + pad;
956
+ if (direction == 'left') return pad + this;
957
+
958
+ return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil());
959
+ },
960
+
961
+ getTags: function(tag, contents){
962
+ return this.match(getRegexForTag(tag, contents)) || [];
963
+ },
964
+
965
+ stripTags: function(tag, contents){
966
+ return this.replace(getRegexForTag(tag, contents), '');
967
+ },
968
+
969
+ tidy: function(){
970
+ return walk(this, tidy);
971
+ },
972
+
973
+ truncate: function(max, trail, atChar){
974
+ var string = this;
975
+ if (trail == null && arguments.length == 1) trail = '…';
976
+ if (string.length > max){
977
+ string = string.substring(0, max);
978
+ if (atChar){
979
+ var index = string.lastIndexOf(atChar);
980
+ if (index != -1) string = string.substr(0, index);
981
+ }
982
+ if (trail) string += trail;
983
+ }
984
+ return string;
985
+ }
986
+
987
+ });
988
+
989
+ })();
990
+
991
+
992
+ /*
993
+ ---
994
+
995
+ script: String.QueryString.js
996
+
997
+ name: String.QueryString
998
+
999
+ description: Methods for dealing with URI query strings.
1000
+
1001
+ license: MIT-style license
1002
+
1003
+ authors:
1004
+ - Sebastian Markbåge
1005
+ - Aaron Newton
1006
+ - Lennart Pilon
1007
+ - Valerio Proietti
1008
+
1009
+ requires:
1010
+ - Core/Array
1011
+ - Core/String
1012
+ - /MooTools.More
1013
+
1014
+ provides: [String.QueryString]
1015
+
1016
+ ...
1017
+ */
1018
+
1019
+ String.implement({
1020
+
1021
+ parseQueryString: function(decodeKeys, decodeValues){
1022
+ if (decodeKeys == null) decodeKeys = true;
1023
+ if (decodeValues == null) decodeValues = true;
1024
+
1025
+ var vars = this.split(/[&;]/),
1026
+ object = {};
1027
+ if (!vars.length) return object;
1028
+
1029
+ vars.each(function(val){
1030
+ var index = val.indexOf('=') + 1,
1031
+ value = index ? val.substr(index) : '',
1032
+ keys = index ? val.substr(0, index - 1).match(/([^\]\[]+|(\B)(?=\]))/g) : [val],
1033
+ obj = object;
1034
+ if (!keys) return;
1035
+ if (decodeValues) value = decodeURIComponent(value);
1036
+ keys.each(function(key, i){
1037
+ if (decodeKeys) key = decodeURIComponent(key);
1038
+ var current = obj[key];
1039
+
1040
+ if (i < keys.length - 1) obj = obj[key] = current || {};
1041
+ else if (typeOf(current) == 'array') current.push(value);
1042
+ else obj[key] = current != null ? [current, value] : value;
1043
+ });
1044
+ });
1045
+
1046
+ return object;
1047
+ },
1048
+
1049
+ cleanQueryString: function(method){
1050
+ return this.split('&').filter(function(val){
1051
+ var index = val.indexOf('='),
1052
+ key = index < 0 ? '' : val.substr(0, index),
1053
+ value = val.substr(index + 1);
1054
+
1055
+ return method ? method.call(null, key, value) : (value || value === 0);
1056
+ }).join('&');
1057
+ }
1058
+
1059
+ });
1060
+
1061
+
1062
+ /*
1063
+ ---
1064
+
1065
+ name: Hash
1066
+
1067
+ description: Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
1068
+
1069
+ license: MIT-style license.
1070
+
1071
+ requires:
1072
+ - Core/Object
1073
+ - /MooTools.More
1074
+
1075
+ provides: [Hash]
1076
+
1077
+ ...
1078
+ */
1079
+
1080
+ (function(){
1081
+
1082
+ if (this.Hash) return;
1083
+
1084
+ var Hash = this.Hash = new Type('Hash', function(object){
1085
+ if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
1086
+ for (var key in object) this[key] = object[key];
1087
+ return this;
1088
+ });
1089
+
1090
+ this.$H = function(object){
1091
+ return new Hash(object);
1092
+ };
1093
+
1094
+ Hash.implement({
1095
+
1096
+ forEach: function(fn, bind){
1097
+ Object.forEach(this, fn, bind);
1098
+ },
1099
+
1100
+ getClean: function(){
1101
+ var clean = {};
1102
+ for (var key in this){
1103
+ if (this.hasOwnProperty(key)) clean[key] = this[key];
1104
+ }
1105
+ return clean;
1106
+ },
1107
+
1108
+ getLength: function(){
1109
+ var length = 0;
1110
+ for (var key in this){
1111
+ if (this.hasOwnProperty(key)) length++;
1112
+ }
1113
+ return length;
1114
+ }
1115
+
1116
+ });
1117
+
1118
+ Hash.alias('each', 'forEach');
1119
+
1120
+ Hash.implement({
1121
+
1122
+ has: Object.prototype.hasOwnProperty,
1123
+
1124
+ keyOf: function(value){
1125
+ return Object.keyOf(this, value);
1126
+ },
1127
+
1128
+ hasValue: function(value){
1129
+ return Object.contains(this, value);
1130
+ },
1131
+
1132
+ extend: function(properties){
1133
+ Hash.each(properties || {}, function(value, key){
1134
+ Hash.set(this, key, value);
1135
+ }, this);
1136
+ return this;
1137
+ },
1138
+
1139
+ combine: function(properties){
1140
+ Hash.each(properties || {}, function(value, key){
1141
+ Hash.include(this, key, value);
1142
+ }, this);
1143
+ return this;
1144
+ },
1145
+
1146
+ erase: function(key){
1147
+ if (this.hasOwnProperty(key)) delete this[key];
1148
+ return this;
1149
+ },
1150
+
1151
+ get: function(key){
1152
+ return (this.hasOwnProperty(key)) ? this[key] : null;
1153
+ },
1154
+
1155
+ set: function(key, value){
1156
+ if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
1157
+ return this;
1158
+ },
1159
+
1160
+ empty: function(){
1161
+ Hash.each(this, function(value, key){
1162
+ delete this[key];
1163
+ }, this);
1164
+ return this;
1165
+ },
1166
+
1167
+ include: function(key, value){
1168
+ if (this[key] == undefined) this[key] = value;
1169
+ return this;
1170
+ },
1171
+
1172
+ map: function(fn, bind){
1173
+ return new Hash(Object.map(this, fn, bind));
1174
+ },
1175
+
1176
+ filter: function(fn, bind){
1177
+ return new Hash(Object.filter(this, fn, bind));
1178
+ },
1179
+
1180
+ every: function(fn, bind){
1181
+ return Object.every(this, fn, bind);
1182
+ },
1183
+
1184
+ some: function(fn, bind){
1185
+ return Object.some(this, fn, bind);
1186
+ },
1187
+
1188
+ getKeys: function(){
1189
+ return Object.keys(this);
1190
+ },
1191
+
1192
+ getValues: function(){
1193
+ return Object.values(this);
1194
+ },
1195
+
1196
+ toQueryString: function(base){
1197
+ return Object.toQueryString(this, base);
1198
+ }
1199
+
1200
+ });
1201
+
1202
+ Hash.alias({indexOf: 'keyOf', contains: 'hasValue'});
1203
+
1204
+
1205
+ })();
1206
+
1207
+
1208
+
1209
+ /*
1210
+ ---
1211
+
1212
+ script: Hash.Extras.js
1213
+
1214
+ name: Hash.Extras
1215
+
1216
+ description: Extends the Hash Type to include getFromPath which allows a path notation to child elements.
1217
+
1218
+ license: MIT-style license
1219
+
1220
+ authors:
1221
+ - Aaron Newton
1222
+
1223
+ requires:
1224
+ - /Hash
1225
+ - /Object.Extras
1226
+
1227
+ provides: [Hash.Extras]
1228
+
1229
+ ...
1230
+ */
1231
+
1232
+ Hash.implement({
1233
+
1234
+ getFromPath: function(notation){
1235
+ return Object.getFromPath(this, notation);
1236
+ },
1237
+
1238
+ cleanValues: function(method){
1239
+ return new Hash(Object.cleanValues(this, method));
1240
+ },
1241
+
1242
+ run: function(){
1243
+ Object.run(arguments);
1244
+ }
1245
+
1246
+ });
1247
+
1248
+
1249
+ /*
1250
+ ---
1251
+
1252
+ script: Elements.From.js
1253
+
1254
+ name: Elements.From
1255
+
1256
+ description: Returns a collection of elements from a string of html.
1257
+
1258
+ license: MIT-style license
1259
+
1260
+ authors:
1261
+ - Aaron Newton
1262
+
1263
+ requires:
1264
+ - Core/String
1265
+ - Core/Element
1266
+ - /MooTools.More
1267
+
1268
+ provides: [Elements.from, Elements.From]
1269
+
1270
+ ...
1271
+ */
1272
+
1273
+ Elements.from = function(text, excludeScripts){
1274
+ if (excludeScripts || excludeScripts == null) text = text.stripScripts();
1275
+
1276
+ var container, match = text.match(/^\s*<(t[dhr]|tbody|tfoot|thead)/i);
1277
+
1278
+ if (match){
1279
+ container = new Element('table');
1280
+ var tag = match[1].toLowerCase();
1281
+ if (['td', 'th', 'tr'].contains(tag)){
1282
+ container = new Element('tbody').inject(container);
1283
+ if (tag != 'tr') container = new Element('tr').inject(container);
1284
+ }
1285
+ }
1286
+
1287
+ return (container || new Element('div')).set('html', text).getChildren();
1288
+ };
1289
+
1290
+
1291
+ /*
1292
+ ---
1293
+
1294
+ name: Element.Event.Pseudos
1295
+
1296
+ description: Adds the functionality to add pseudo events for Elements
1297
+
1298
+ license: MIT-style license
1299
+
1300
+ authors:
1301
+ - Arian Stolwijk
1302
+
1303
+ requires: [Core/Element.Event, Events.Pseudos]
1304
+
1305
+ provides: [Element.Event.Pseudos]
1306
+
1307
+ ...
1308
+ */
1309
+
1310
+ (function(){
1311
+
1312
+ var pseudos = {},
1313
+ copyFromEvents = ['once', 'throttle', 'pause'],
1314
+ count = copyFromEvents.length;
1315
+
1316
+ while (count--) pseudos[copyFromEvents[count]] = Events.lookupPseudo(copyFromEvents[count]);
1317
+
1318
+ Event.definePseudo = function(key, listener){
1319
+ pseudos[key] = Type.isFunction(listener) ? {listener: listener} : listener;
1320
+ return this;
1321
+ };
1322
+
1323
+ var proto = Element.prototype;
1324
+ [Element, Window, Document].invoke('implement', Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent));
1325
+
1326
+ })();
1327
+
1328
+
1329
+ /*
1330
+ ---
1331
+
1332
+ name: Element.Event.Pseudos.Keys
1333
+
1334
+ description: Adds functionality fire events if certain keycombinations are pressed
1335
+
1336
+ license: MIT-style license
1337
+
1338
+ authors:
1339
+ - Arian Stolwijk
1340
+
1341
+ requires: [Element.Event.Pseudos]
1342
+
1343
+ provides: [Element.Event.Pseudos.Keys]
1344
+
1345
+ ...
1346
+ */
1347
+
1348
+ (function(){
1349
+
1350
+ var keysStoreKey = '$moo:keys-pressed',
1351
+ keysKeyupStoreKey = '$moo:keys-keyup';
1352
+
1353
+
1354
+ Event.definePseudo('keys', function(split, fn, args){
1355
+
1356
+ var event = args[0],
1357
+ keys = [],
1358
+ pressed = this.retrieve(keysStoreKey, []);
1359
+
1360
+ keys.append(split.value.replace('++', function(){
1361
+ keys.push('+'); // shift++ and shift+++a
1362
+ return '';
1363
+ }).split('+'));
1364
+
1365
+ pressed.include(event.key);
1366
+
1367
+ if (keys.every(function(key){
1368
+ return pressed.contains(key);
1369
+ })) fn.apply(this, args);
1370
+
1371
+ this.store(keysStoreKey, pressed);
1372
+
1373
+ if (!this.retrieve(keysKeyupStoreKey)){
1374
+ var keyup = function(event){
1375
+ (function(){
1376
+ pressed = this.retrieve(keysStoreKey, []).erase(event.key);
1377
+ this.store(keysStoreKey, pressed);
1378
+ }).delay(0, this); // Fix for IE
1379
+ };
1380
+ this.store(keysKeyupStoreKey, keyup).addEvent('keyup', keyup);
1381
+ }
1382
+
1383
+ });
1384
+
1385
+ Object.append(Event.Keys, {
1386
+ 'shift': 16,
1387
+ 'control': 17,
1388
+ 'alt': 18,
1389
+ 'capslock': 20,
1390
+ 'pageup': 33,
1391
+ 'pagedown': 34,
1392
+ 'end': 35,
1393
+ 'home': 36,
1394
+ 'numlock': 144,
1395
+ 'scrolllock': 145,
1396
+ ';': 186,
1397
+ '=': 187,
1398
+ ',': 188,
1399
+ '-': Browser.firefox ? 109 : 189,
1400
+ '.': 190,
1401
+ '/': 191,
1402
+ '`': 192,
1403
+ '[': 219,
1404
+ '\\': 220,
1405
+ ']': 221,
1406
+ "'": 222,
1407
+ '+': 107
1408
+ });
1409
+
1410
+ })();
1411
+
1412
+
1413
+ /*
1414
+ ---
1415
+
1416
+ script: Element.Delegation.js
1417
+
1418
+ name: Element.Delegation
1419
+
1420
+ description: Extends the Element native object to include the delegate method for more efficient event management.
1421
+
1422
+ credits:
1423
+ - "Event checking based on the work of Daniel Steigerwald. License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
1424
+
1425
+ license: MIT-style license
1426
+
1427
+ authors:
1428
+ - Aaron Newton
1429
+ - Daniel Steigerwald
1430
+
1431
+ requires: [/MooTools.More, Element.Event.Pseudos]
1432
+
1433
+ provides: [Element.Delegation]
1434
+
1435
+ ...
1436
+ */
1437
+
1438
+ (function(){
1439
+
1440
+ var eventListenerSupport = !(window.attachEvent && !window.addEventListener),
1441
+ nativeEvents = Element.NativeEvents;
1442
+
1443
+ nativeEvents.focusin = 2;
1444
+ nativeEvents.focusout = 2;
1445
+
1446
+ var check = function(split, target, event){
1447
+ var elementEvent = Element.Events[split.event], condition;
1448
+ if (elementEvent) condition = elementEvent.condition;
1449
+ return Slick.match(target, split.value) && (!condition || condition.call(target, event));
1450
+ };
1451
+
1452
+ var bubbleUp = function(split, event, fn){
1453
+ for (var target = event.target; target && target != this; target = document.id(target.parentNode)){
1454
+ if (target && check(split, target, event)) return fn.call(target, event, target);
1455
+ }
1456
+ };
1457
+
1458
+ var formObserver = function(eventName){
1459
+
1460
+ var $delegationKey = '$delegation:';
1461
+
1462
+ return {
1463
+ base: 'focusin',
1464
+
1465
+ onRemove: function(element){
1466
+ element.retrieve($delegationKey + 'forms', []).each(function(el){
1467
+ el.retrieve($delegationKey + 'listeners', []).each(function(listener){
1468
+ el.removeEvent(eventName, listener);
1469
+ });
1470
+ el.eliminate($delegationKey + eventName + 'listeners')
1471
+ .eliminate($delegationKey + eventName + 'originalFn');
1472
+ });
1473
+ },
1474
+
1475
+ listener: function(split, fn, args, monitor, options){
1476
+ var event = args[0],
1477
+ forms = this.retrieve($delegationKey + 'forms', []),
1478
+ target = event.target,
1479
+ form = (target.get('tag') == 'form') ? target : event.target.getParent('form');
1480
+
1481
+ if (!form) return;
1482
+
1483
+ var formEvents = form.retrieve($delegationKey + 'originalFn', []),
1484
+ formListeners = form.retrieve($delegationKey + 'listeners', []),
1485
+ self = this;
1486
+
1487
+ forms.include(form);
1488
+ this.store($delegationKey + 'forms', forms);
1489
+
1490
+ if (!formEvents.contains(fn)){
1491
+ var formListener = function(event){
1492
+ bubbleUp.call(self, split, event, fn);
1493
+ };
1494
+ form.addEvent(eventName, formListener);
1495
+
1496
+ formEvents.push(fn);
1497
+ formListeners.push(formListener);
1498
+
1499
+ form.store($delegationKey + eventName + 'originalFn', formEvents)
1500
+ .store($delegationKey + eventName + 'listeners', formListeners);
1501
+ }
1502
+ }
1503
+ };
1504
+ };
1505
+
1506
+ var inputObserver = function(eventName){
1507
+ return {
1508
+ base: 'focusin',
1509
+ listener: function(split, fn, args){
1510
+ var events = {blur: function(){
1511
+ this.removeEvents(events);
1512
+ }}, self = this;
1513
+ events[eventName] = function(event){
1514
+ bubbleUp.call(self, split, event, fn);
1515
+ };
1516
+ args[0].target.addEvents(events);
1517
+ }
1518
+ };
1519
+ };
1520
+
1521
+ var eventOptions = {
1522
+ mouseenter: {
1523
+ base: 'mouseover'
1524
+ },
1525
+ mouseleave: {
1526
+ base: 'mouseout'
1527
+ },
1528
+ focus: {
1529
+ base: 'focus' + (eventListenerSupport ? '' : 'in'),
1530
+ args: [true]
1531
+ },
1532
+ blur: {
1533
+ base: eventListenerSupport ? 'blur' : 'focusout',
1534
+ args: [true]
1535
+ }
1536
+ };
1537
+
1538
+ if (!eventListenerSupport) Object.append(eventOptions, {
1539
+ submit: formObserver('submit'),
1540
+ reset: formObserver('reset'),
1541
+ change: inputObserver('change'),
1542
+ select: inputObserver('select')
1543
+ });
1544
+
1545
+ Event.definePseudo('relay', {
1546
+ listener: function(split, fn, args){
1547
+ bubbleUp.call(this, split, args[0], fn);
1548
+ },
1549
+ options: eventOptions
1550
+ });
1551
+
1552
+ })();
1553
+
1554
+
1555
+ /*
1556
+ ---
1557
+
1558
+ script: Element.Measure.js
1559
+
1560
+ name: Element.Measure
1561
+
1562
+ description: Extends the Element native object to include methods useful in measuring dimensions.
1563
+
1564
+ credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
1565
+
1566
+ license: MIT-style license
1567
+
1568
+ authors:
1569
+ - Aaron Newton
1570
+
1571
+ requires:
1572
+ - Core/Element.Style
1573
+ - Core/Element.Dimensions
1574
+ - /MooTools.More
1575
+
1576
+ provides: [Element.Measure]
1577
+
1578
+ ...
1579
+ */
1580
+
1581
+ (function(){
1582
+
1583
+ var getStylesList = function(styles, planes){
1584
+ var list = [];
1585
+ Object.each(planes, function(directions){
1586
+ Object.each(directions, function(edge){
1587
+ styles.each(function(style){
1588
+ list.push(style + '-' + edge + (style == 'border' ? '-width' : ''));
1589
+ });
1590
+ });
1591
+ });
1592
+ return list;
1593
+ };
1594
+
1595
+ var calculateEdgeSize = function(edge, styles){
1596
+ var total = 0;
1597
+ Object.each(styles, function(value, style){
1598
+ if (style.test(edge)) total = total + value.toInt();
1599
+ });
1600
+ return total;
1601
+ };
1602
+
1603
+ var isVisible = function(el){
1604
+ return !!(!el || el.offsetHeight || el.offsetWidth);
1605
+ };
1606
+
1607
+
1608
+ Element.implement({
1609
+
1610
+ measure: function(fn){
1611
+ if (isVisible(this)) return fn.call(this);
1612
+ var parent = this.getParent(),
1613
+ toMeasure = [];
1614
+ while (!isVisible(parent) && parent != document.body){
1615
+ toMeasure.push(parent.expose());
1616
+ parent = parent.getParent();
1617
+ }
1618
+ var restore = this.expose(),
1619
+ result = fn.call(this);
1620
+ restore();
1621
+ toMeasure.each(function(restore){
1622
+ restore();
1623
+ });
1624
+ return result;
1625
+ },
1626
+
1627
+ expose: function(){
1628
+ if (this.getStyle('display') != 'none') return function(){};
1629
+ var before = this.style.cssText;
1630
+ this.setStyles({
1631
+ display: 'block',
1632
+ position: 'absolute',
1633
+ visibility: 'hidden'
1634
+ });
1635
+ return function(){
1636
+ this.style.cssText = before;
1637
+ }.bind(this);
1638
+ },
1639
+
1640
+ getDimensions: function(options){
1641
+ options = Object.merge({computeSize: false}, options);
1642
+ var dim = {x: 0, y: 0};
1643
+
1644
+ var getSize = function(el, options){
1645
+ return (options.computeSize) ? el.getComputedSize(options) : el.getSize();
1646
+ };
1647
+
1648
+ var parent = this.getParent('body');
1649
+
1650
+ if (parent && this.getStyle('display') == 'none'){
1651
+ dim = this.measure(function(){
1652
+ return getSize(this, options);
1653
+ });
1654
+ } else if (parent){
1655
+ try { //safari sometimes crashes here, so catch it
1656
+ dim = getSize(this, options);
1657
+ }catch(e){}
1658
+ }
1659
+
1660
+ return Object.append(dim, (dim.x || dim.x === 0) ? {
1661
+ width: dim.x,
1662
+ height: dim.y
1663
+ } : {
1664
+ x: dim.width,
1665
+ y: dim.height
1666
+ }
1667
+ );
1668
+ },
1669
+
1670
+ getComputedSize: function(options){
1671
+ //<1.2compat>
1672
+ //legacy support for my stupid spelling error
1673
+ if (options && options.plains) options.planes = options.plains;
1674
+ //</1.2compat>
1675
+
1676
+ options = Object.merge({
1677
+ styles: ['padding','border'],
1678
+ planes: {
1679
+ height: ['top','bottom'],
1680
+ width: ['left','right']
1681
+ },
1682
+ mode: 'both'
1683
+ }, options);
1684
+
1685
+ var styles = {},
1686
+ size = {width: 0, height: 0},
1687
+ dimensions;
1688
+
1689
+ if (options.mode == 'vertical'){
1690
+ delete size.width;
1691
+ delete options.planes.width;
1692
+ } else if (options.mode == 'horizontal'){
1693
+ delete size.height;
1694
+ delete options.planes.height;
1695
+ }
1696
+
1697
+ getStylesList(options.styles, options.planes).each(function(style){
1698
+ styles[style] = this.getStyle(style).toInt();
1699
+ }, this);
1700
+
1701
+ Object.each(options.planes, function(edges, plane){
1702
+
1703
+ var capitalized = plane.capitalize(),
1704
+ style = this.getStyle(plane);
1705
+
1706
+ if (style == 'auto' && !dimensions) dimensions = this.getDimensions();
1707
+
1708
+ style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt();
1709
+ size['total' + capitalized] = style;
1710
+
1711
+ edges.each(function(edge){
1712
+ var edgesize = calculateEdgeSize(edge, styles);
1713
+ size['computed' + edge.capitalize()] = edgesize;
1714
+ size['total' + capitalized] += edgesize;
1715
+ });
1716
+
1717
+ }, this);
1718
+
1719
+ return Object.append(size, styles);
1720
+ }
1721
+
1722
+ });
1723
+
1724
+ })();
1725
+
1726
+
1727
+ /*
1728
+ ---
1729
+
1730
+ script: Element.Position.js
1731
+
1732
+ name: Element.Position
1733
+
1734
+ description: Extends the Element native object to include methods useful positioning elements relative to others.
1735
+
1736
+ license: MIT-style license
1737
+
1738
+ authors:
1739
+ - Aaron Newton
1740
+ - Jacob Thornton
1741
+
1742
+ requires:
1743
+ - Core/Options
1744
+ - Core/Element.Dimensions
1745
+ - Element.Measure
1746
+
1747
+ provides: [Element.Position]
1748
+
1749
+ ...
1750
+ */
1751
+
1752
+ (function(original){
1753
+
1754
+ var local = Element.Position = {
1755
+
1756
+ options: {/*
1757
+ edge: false,
1758
+ returnPos: false,
1759
+ minimum: {x: 0, y: 0},
1760
+ maximum: {x: 0, y: 0},
1761
+ relFixedPosition: false,
1762
+ ignoreMargins: false,
1763
+ ignoreScroll: false,
1764
+ allowNegative: false,*/
1765
+ relativeTo: document.body,
1766
+ position: {
1767
+ x: 'center', //left, center, right
1768
+ y: 'center' //top, center, bottom
1769
+ },
1770
+ offset: {x: 0, y: 0}
1771
+ },
1772
+
1773
+ getOptions: function(element, options){
1774
+ options = Object.merge({}, local.options, options);
1775
+ local.setPositionOption(options);
1776
+ local.setEdgeOption(options);
1777
+ local.setOffsetOption(element, options);
1778
+ local.setDimensionsOption(element, options);
1779
+ return options;
1780
+ },
1781
+
1782
+ setPositionOption: function(options){
1783
+ options.position = local.getCoordinateFromValue(options.position);
1784
+ },
1785
+
1786
+ setEdgeOption: function(options){
1787
+ var edgeOption = local.getCoordinateFromValue(options.edge);
1788
+ options.edge = edgeOption ? edgeOption :
1789
+ (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} :
1790
+ {x: 'left', y: 'top'};
1791
+ },
1792
+
1793
+ setOffsetOption: function(element, options){
1794
+ var parentOffset = {x: 0, y: 0},
1795
+ offsetParent = element.measure(function(){
1796
+ return document.id(this.getOffsetParent());
1797
+ }),
1798
+ parentScroll = offsetParent.getScroll();
1799
+
1800
+ if (!offsetParent || offsetParent == element.getDocument().body) return;
1801
+ parentOffset = offsetParent.measure(function(){
1802
+ var position = this.getPosition();
1803
+ if (this.getStyle('position') == 'fixed'){
1804
+ var scroll = window.getScroll();
1805
+ position.x += scroll.x;
1806
+ position.y += scroll.y;
1807
+ }
1808
+ return position;
1809
+ });
1810
+
1811
+ options.offset = {
1812
+ parentPositioned: offsetParent != document.id(options.relativeTo),
1813
+ x: options.offset.x - parentOffset.x + parentScroll.x,
1814
+ y: options.offset.y - parentOffset.y + parentScroll.y
1815
+ };
1816
+ },
1817
+
1818
+ setDimensionsOption: function(element, options){
1819
+ options.dimensions = element.getDimensions({
1820
+ computeSize: true,
1821
+ styles: ['padding', 'border', 'margin']
1822
+ });
1823
+ },
1824
+
1825
+ getPosition: function(element, options){
1826
+ var position = {};
1827
+ options = local.getOptions(element, options);
1828
+ var relativeTo = document.id(options.relativeTo) || document.body;
1829
+
1830
+ local.setPositionCoordinates(options, position, relativeTo);
1831
+ if (options.edge) local.toEdge(position, options);
1832
+
1833
+ var offset = options.offset;
1834
+ position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt();
1835
+ position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt();
1836
+
1837
+ local.toMinMax(position, options);
1838
+
1839
+ if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position);
1840
+ if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position);
1841
+ if (options.ignoreMargins) local.toIgnoreMargins(position, options);
1842
+
1843
+ position.left = Math.ceil(position.left);
1844
+ position.top = Math.ceil(position.top);
1845
+ delete position.x;
1846
+ delete position.y;
1847
+
1848
+ return position;
1849
+ },
1850
+
1851
+ setPositionCoordinates: function(options, position, relativeTo){
1852
+ var offsetY = options.offset.y,
1853
+ offsetX = options.offset.x,
1854
+ calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(),
1855
+ top = calc.y,
1856
+ left = calc.x,
1857
+ winSize = window.getSize();
1858
+
1859
+ switch(options.position.x){
1860
+ case 'left': position.x = left + offsetX; break;
1861
+ case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break;
1862
+ default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break;
1863
+ }
1864
+
1865
+ switch(options.position.y){
1866
+ case 'top': position.y = top + offsetY; break;
1867
+ case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break;
1868
+ default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break;
1869
+ }
1870
+ },
1871
+
1872
+ toMinMax: function(position, options){
1873
+ var xy = {left: 'x', top: 'y'}, value;
1874
+ ['minimum', 'maximum'].each(function(minmax){
1875
+ ['left', 'top'].each(function(lr){
1876
+ value = options[minmax] ? options[minmax][xy[lr]] : null;
1877
+ if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value;
1878
+ });
1879
+ });
1880
+ },
1881
+
1882
+ toRelFixedPosition: function(relativeTo, position){
1883
+ var winScroll = window.getScroll();
1884
+ position.top += winScroll.y;
1885
+ position.left += winScroll.x;
1886
+ },
1887
+
1888
+ toIgnoreScroll: function(relativeTo, position){
1889
+ var relScroll = relativeTo.getScroll();
1890
+ position.top -= relScroll.y;
1891
+ position.left -= relScroll.x;
1892
+ },
1893
+
1894
+ toIgnoreMargins: function(position, options){
1895
+ position.left += options.edge.x == 'right'
1896
+ ? options.dimensions['margin-right']
1897
+ : (options.edge.x != 'center'
1898
+ ? -options.dimensions['margin-left']
1899
+ : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2));
1900
+
1901
+ position.top += options.edge.y == 'bottom'
1902
+ ? options.dimensions['margin-bottom']
1903
+ : (options.edge.y != 'center'
1904
+ ? -options.dimensions['margin-top']
1905
+ : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2));
1906
+ },
1907
+
1908
+ toEdge: function(position, options){
1909
+ var edgeOffset = {},
1910
+ dimensions = options.dimensions,
1911
+ edge = options.edge;
1912
+
1913
+ switch(edge.x){
1914
+ case 'left': edgeOffset.x = 0; break;
1915
+ case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break;
1916
+ // center
1917
+ default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break;
1918
+ }
1919
+
1920
+ switch(edge.y){
1921
+ case 'top': edgeOffset.y = 0; break;
1922
+ case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break;
1923
+ // center
1924
+ default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break;
1925
+ }
1926
+
1927
+ position.x += edgeOffset.x;
1928
+ position.y += edgeOffset.y;
1929
+ },
1930
+
1931
+ getCoordinateFromValue: function(option){
1932
+ if (typeOf(option) != 'string') return option;
1933
+ option = option.toLowerCase();
1934
+
1935
+ return {
1936
+ x: option.test('left') ? 'left'
1937
+ : (option.test('right') ? 'right' : 'center'),
1938
+ y: option.test(/upper|top/) ? 'top'
1939
+ : (option.test('bottom') ? 'bottom' : 'center')
1940
+ };
1941
+ }
1942
+
1943
+ };
1944
+
1945
+ Element.implement({
1946
+
1947
+ position: function(options){
1948
+ if (options && (options.x != null || options.y != null)) {
1949
+ return (original ? original.apply(this, arguments) : this);
1950
+ }
1951
+ var position = this.setStyle('position', 'absolute').calculatePosition(options);
1952
+ return (options && options.returnPos) ? position : this.setStyles(position);
1953
+ },
1954
+
1955
+ calculatePosition: function(options){
1956
+ return local.getPosition(this, options);
1957
+ }
1958
+
1959
+ });
1960
+
1961
+ })(Element.prototype.position);
1962
+
1963
+
1964
+ /*
1965
+ ---
1966
+
1967
+ script: Element.Shortcuts.js
1968
+
1969
+ name: Element.Shortcuts
1970
+
1971
+ description: Extends the Element native object to include some shortcut methods.
1972
+
1973
+ license: MIT-style license
1974
+
1975
+ authors:
1976
+ - Aaron Newton
1977
+
1978
+ requires:
1979
+ - Core/Element.Style
1980
+ - /MooTools.More
1981
+
1982
+ provides: [Element.Shortcuts]
1983
+
1984
+ ...
1985
+ */
1986
+
1987
+ Element.implement({
1988
+
1989
+ isDisplayed: function(){
1990
+ return this.getStyle('display') != 'none';
1991
+ },
1992
+
1993
+ isVisible: function(){
1994
+ var w = this.offsetWidth,
1995
+ h = this.offsetHeight;
1996
+ return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.style.display != 'none';
1997
+ },
1998
+
1999
+ toggle: function(){
2000
+ return this[this.isDisplayed() ? 'hide' : 'show']();
2001
+ },
2002
+
2003
+ hide: function(){
2004
+ var d;
2005
+ try {
2006
+ //IE fails here if the element is not in the dom
2007
+ d = this.getStyle('display');
2008
+ } catch(e){}
2009
+ if (d == 'none') return this;
2010
+ return this.store('element:_originalDisplay', d || '').setStyle('display', 'none');
2011
+ },
2012
+
2013
+ show: function(display){
2014
+ if (!display && this.isDisplayed()) return this;
2015
+ display = display || this.retrieve('element:_originalDisplay') || 'block';
2016
+ return this.setStyle('display', (display == 'none') ? 'block' : display);
2017
+ },
2018
+
2019
+ swapClass: function(remove, add){
2020
+ return this.removeClass(remove).addClass(add);
2021
+ }
2022
+
2023
+ });
2024
+
2025
+ Document.implement({
2026
+
2027
+ clearSelection: function(){
2028
+ if (window.getSelection){
2029
+ var selection = window.getSelection();
2030
+ if (selection && selection.removeAllRanges) selection.removeAllRanges();
2031
+ } else if (document.selection && document.selection.empty){
2032
+ try {
2033
+ //IE fails here if selected element is not in dom
2034
+ document.selection.empty();
2035
+ } catch(e){}
2036
+ }
2037
+ }
2038
+
2039
+ });
2040
+
2041
+
2042
+ /*
2043
+ ---
2044
+
2045
+ script: Drag.js
2046
+
2047
+ name: Drag
2048
+
2049
+ description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
2050
+
2051
+ license: MIT-style license
2052
+
2053
+ authors:
2054
+ - Valerio Proietti
2055
+ - Tom Occhinno
2056
+ - Jan Kassens
2057
+
2058
+ requires:
2059
+ - Core/Events
2060
+ - Core/Options
2061
+ - Core/Element.Event
2062
+ - Core/Element.Style
2063
+ - Core/Element.Dimensions
2064
+ - /MooTools.More
2065
+
2066
+ provides: [Drag]
2067
+ ...
2068
+
2069
+ */
2070
+
2071
+ var Drag = new Class({
2072
+
2073
+ Implements: [Events, Options],
2074
+
2075
+ options: {/*
2076
+ onBeforeStart: function(thisElement){},
2077
+ onStart: function(thisElement, event){},
2078
+ onSnap: function(thisElement){},
2079
+ onDrag: function(thisElement, event){},
2080
+ onCancel: function(thisElement){},
2081
+ onComplete: function(thisElement, event){},*/
2082
+ snap: 6,
2083
+ unit: 'px',
2084
+ grid: false,
2085
+ style: true,
2086
+ limit: false,
2087
+ handle: false,
2088
+ invert: false,
2089
+ preventDefault: false,
2090
+ stopPropagation: false,
2091
+ modifiers: {x: 'left', y: 'top'}
2092
+ },
2093
+
2094
+ initialize: function(){
2095
+ var params = Array.link(arguments, {
2096
+ 'options': Type.isObject,
2097
+ 'element': function(obj){
2098
+ return obj != null;
2099
+ }
2100
+ });
2101
+
2102
+ this.element = document.id(params.element);
2103
+ this.document = this.element.getDocument();
2104
+ this.setOptions(params.options || {});
2105
+ var htype = typeOf(this.options.handle);
2106
+ this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
2107
+ this.mouse = {'now': {}, 'pos': {}};
2108
+ this.value = {'start': {}, 'now': {}};
2109
+
2110
+ this.selection = (Browser.ie) ? 'selectstart' : 'mousedown';
2111
+
2112
+
2113
+ if (Browser.ie && !Drag.ondragstartFixed){
2114
+ document.ondragstart = Function.from(false);
2115
+ Drag.ondragstartFixed = true;
2116
+ }
2117
+
2118
+ this.bound = {
2119
+ start: this.start.bind(this),
2120
+ check: this.check.bind(this),
2121
+ drag: this.drag.bind(this),
2122
+ stop: this.stop.bind(this),
2123
+ cancel: this.cancel.bind(this),
2124
+ eventStop: Function.from(false)
2125
+ };
2126
+ this.attach();
2127
+ },
2128
+
2129
+ attach: function(){
2130
+ this.handles.addEvent('mousedown', this.bound.start);
2131
+ return this;
2132
+ },
2133
+
2134
+ detach: function(){
2135
+ this.handles.removeEvent('mousedown', this.bound.start);
2136
+ return this;
2137
+ },
2138
+
2139
+ start: function(event){
2140
+ var options = this.options;
2141
+
2142
+ if (event.rightClick) return;
2143
+
2144
+ if (options.preventDefault) event.preventDefault();
2145
+ if (options.stopPropagation) event.stopPropagation();
2146
+ this.mouse.start = event.page;
2147
+
2148
+ this.fireEvent('beforeStart', this.element);
2149
+
2150
+ var limit = options.limit;
2151
+ this.limit = {x: [], y: []};
2152
+
2153
+ var z, coordinates;
2154
+ for (z in options.modifiers){
2155
+ if (!options.modifiers[z]) continue;
2156
+
2157
+ var style = this.element.getStyle(options.modifiers[z]);
2158
+
2159
+ // Some browsers (IE and Opera) don't always return pixels.
2160
+ if (style && !style.match(/px$/)){
2161
+ if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent());
2162
+ style = coordinates[options.modifiers[z]];
2163
+ }
2164
+
2165
+ if (options.style) this.value.now[z] = (style || 0).toInt();
2166
+ else this.value.now[z] = this.element[options.modifiers[z]];
2167
+
2168
+ if (options.invert) this.value.now[z] *= -1;
2169
+
2170
+ this.mouse.pos[z] = event.page[z] - this.value.now[z];
2171
+
2172
+ if (limit && limit[z]){
2173
+ var i = 2;
2174
+ while (i--){
2175
+ var limitZI = limit[z][i];
2176
+ if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI;
2177
+ }
2178
+ }
2179
+ }
2180
+
2181
+ if (typeOf(this.options.grid) == 'number') this.options.grid = {
2182
+ x: this.options.grid,
2183
+ y: this.options.grid
2184
+ };
2185
+
2186
+ var events = {
2187
+ mousemove: this.bound.check,
2188
+ mouseup: this.bound.cancel
2189
+ };
2190
+ events[this.selection] = this.bound.eventStop;
2191
+ this.document.addEvents(events);
2192
+ },
2193
+
2194
+ check: function(event){
2195
+ if (this.options.preventDefault) event.preventDefault();
2196
+ var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
2197
+ if (distance > this.options.snap){
2198
+ this.cancel();
2199
+ this.document.addEvents({
2200
+ mousemove: this.bound.drag,
2201
+ mouseup: this.bound.stop
2202
+ });
2203
+ this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
2204
+ }
2205
+ },
2206
+
2207
+ drag: function(event){
2208
+ var options = this.options;
2209
+
2210
+ if (options.preventDefault) event.preventDefault();
2211
+ this.mouse.now = event.page;
2212
+
2213
+ for (var z in options.modifiers){
2214
+ if (!options.modifiers[z]) continue;
2215
+ this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
2216
+
2217
+ if (options.invert) this.value.now[z] *= -1;
2218
+
2219
+ if (options.limit && this.limit[z]){
2220
+ if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){
2221
+ this.value.now[z] = this.limit[z][1];
2222
+ } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){
2223
+ this.value.now[z] = this.limit[z][0];
2224
+ }
2225
+ }
2226
+
2227
+ if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]);
2228
+
2229
+ if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit);
2230
+ else this.element[options.modifiers[z]] = this.value.now[z];
2231
+ }
2232
+
2233
+ this.fireEvent('drag', [this.element, event]);
2234
+ },
2235
+
2236
+ cancel: function(event){
2237
+ this.document.removeEvents({
2238
+ mousemove: this.bound.check,
2239
+ mouseup: this.bound.cancel
2240
+ });
2241
+ if (event){
2242
+ this.document.removeEvent(this.selection, this.bound.eventStop);
2243
+ this.fireEvent('cancel', this.element);
2244
+ }
2245
+ },
2246
+
2247
+ stop: function(event){
2248
+ var events = {
2249
+ mousemove: this.bound.drag,
2250
+ mouseup: this.bound.stop
2251
+ };
2252
+ events[this.selection] = this.bound.eventStop;
2253
+ this.document.removeEvents(events);
2254
+ if (event) this.fireEvent('complete', [this.element, event]);
2255
+ }
2256
+
2257
+ });
2258
+
2259
+ Element.implement({
2260
+
2261
+ makeResizable: function(options){
2262
+ var drag = new Drag(this, Object.merge({
2263
+ modifiers: {
2264
+ x: 'width',
2265
+ y: 'height'
2266
+ }
2267
+ }, options));
2268
+
2269
+ this.store('resizer', drag);
2270
+ return drag.addEvent('drag', function(){
2271
+ this.fireEvent('resize', drag);
2272
+ }.bind(this));
2273
+ }
2274
+
2275
+ });
2276
+
2277
+
2278
+ /*
2279
+ ---
2280
+
2281
+ script: Drag.Move.js
2282
+
2283
+ name: Drag.Move
2284
+
2285
+ description: A Drag extension that provides support for the constraining of draggables to containers and droppables.
2286
+
2287
+ license: MIT-style license
2288
+
2289
+ authors:
2290
+ - Valerio Proietti
2291
+ - Tom Occhinno
2292
+ - Jan Kassens
2293
+ - Aaron Newton
2294
+ - Scott Kyle
2295
+
2296
+ requires:
2297
+ - Core/Element.Dimensions
2298
+ - /Drag
2299
+
2300
+ provides: [Drag.Move]
2301
+
2302
+ ...
2303
+ */
2304
+
2305
+ Drag.Move = new Class({
2306
+
2307
+ Extends: Drag,
2308
+
2309
+ options: {/*
2310
+ onEnter: function(thisElement, overed){},
2311
+ onLeave: function(thisElement, overed){},
2312
+ onDrop: function(thisElement, overed, event){},*/
2313
+ droppables: [],
2314
+ container: false,
2315
+ precalculate: false,
2316
+ includeMargins: true,
2317
+ checkDroppables: true
2318
+ },
2319
+
2320
+ initialize: function(element, options){
2321
+ this.parent(element, options);
2322
+ element = this.element;
2323
+
2324
+ this.droppables = $$(this.options.droppables);
2325
+ this.container = document.id(this.options.container);
2326
+
2327
+ if (this.container && typeOf(this.container) != 'element')
2328
+ this.container = document.id(this.container.getDocument().body);
2329
+
2330
+ if (this.options.style){
2331
+ if (this.options.modifiers.x == 'left' && this.options.modifiers.y == 'top'){
2332
+ var parent = element.getOffsetParent(),
2333
+ styles = element.getStyles('left', 'top');
2334
+ if (parent && (styles.left == 'auto' || styles.top == 'auto')){
2335
+ element.setPosition(element.getPosition(parent));
2336
+ }
2337
+ }
2338
+
2339
+ if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute');
2340
+ }
2341
+
2342
+ this.addEvent('start', this.checkDroppables, true);
2343
+ this.overed = null;
2344
+ },
2345
+
2346
+ start: function(event){
2347
+ if (this.container) this.options.limit = this.calculateLimit();
2348
+
2349
+ if (this.options.precalculate){
2350
+ this.positions = this.droppables.map(function(el){
2351
+ return el.getCoordinates();
2352
+ });
2353
+ }
2354
+
2355
+ this.parent(event);
2356
+ },
2357
+
2358
+ calculateLimit: function(){
2359
+ var element = this.element,
2360
+ container = this.container,
2361
+
2362
+ offsetParent = document.id(element.getOffsetParent()) || document.body,
2363
+ containerCoordinates = container.getCoordinates(offsetParent),
2364
+ elementMargin = {},
2365
+ elementBorder = {},
2366
+ containerMargin = {},
2367
+ containerBorder = {},
2368
+ offsetParentPadding = {};
2369
+
2370
+ ['top', 'right', 'bottom', 'left'].each(function(pad){
2371
+ elementMargin[pad] = element.getStyle('margin-' + pad).toInt();
2372
+ elementBorder[pad] = element.getStyle('border-' + pad).toInt();
2373
+ containerMargin[pad] = container.getStyle('margin-' + pad).toInt();
2374
+ containerBorder[pad] = container.getStyle('border-' + pad).toInt();
2375
+ offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt();
2376
+ }, this);
2377
+
2378
+ var width = element.offsetWidth + elementMargin.left + elementMargin.right,
2379
+ height = element.offsetHeight + elementMargin.top + elementMargin.bottom,
2380
+ left = 0,
2381
+ top = 0,
2382
+ right = containerCoordinates.right - containerBorder.right - width,
2383
+ bottom = containerCoordinates.bottom - containerBorder.bottom - height;
2384
+
2385
+ if (this.options.includeMargins){
2386
+ left += elementMargin.left;
2387
+ top += elementMargin.top;
2388
+ } else {
2389
+ right += elementMargin.right;
2390
+ bottom += elementMargin.bottom;
2391
+ }
2392
+
2393
+ if (element.getStyle('position') == 'relative'){
2394
+ var coords = element.getCoordinates(offsetParent);
2395
+ coords.left -= element.getStyle('left').toInt();
2396
+ coords.top -= element.getStyle('top').toInt();
2397
+
2398
+ left -= coords.left;
2399
+ top -= coords.top;
2400
+ if (container.getStyle('position') != 'relative'){
2401
+ left += containerBorder.left;
2402
+ top += containerBorder.top;
2403
+ }
2404
+ right += elementMargin.left - coords.left;
2405
+ bottom += elementMargin.top - coords.top;
2406
+
2407
+ if (container != offsetParent){
2408
+ left += containerMargin.left + offsetParentPadding.left;
2409
+ top += ((Browser.ie6 || Browser.ie7) ? 0 : containerMargin.top) + offsetParentPadding.top;
2410
+ }
2411
+ } else {
2412
+ left -= elementMargin.left;
2413
+ top -= elementMargin.top;
2414
+ if (container != offsetParent){
2415
+ left += containerCoordinates.left + containerBorder.left;
2416
+ top += containerCoordinates.top + containerBorder.top;
2417
+ }
2418
+ }
2419
+
2420
+ return {
2421
+ x: [left, right],
2422
+ y: [top, bottom]
2423
+ };
2424
+ },
2425
+
2426
+ getDroppableCoordinates: function(element){
2427
+ var position = element.getCoordinates();
2428
+ if (element.getStyle('position') == 'fixed'){
2429
+ var scroll = window.getScroll();
2430
+ position.left += scroll.x;
2431
+ position.right += scroll.x;
2432
+ position.top += scroll.y;
2433
+ position.bottom += scroll.y;
2434
+ }
2435
+ return position;
2436
+ },
2437
+
2438
+ checkDroppables: function(){
2439
+ var overed = this.droppables.filter(function(el, i){
2440
+ el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el);
2441
+ var now = this.mouse.now;
2442
+ return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
2443
+ }, this).getLast();
2444
+
2445
+ if (this.overed != overed){
2446
+ if (this.overed) this.fireEvent('leave', [this.element, this.overed]);
2447
+ if (overed) this.fireEvent('enter', [this.element, overed]);
2448
+ this.overed = overed;
2449
+ }
2450
+ },
2451
+
2452
+ drag: function(event){
2453
+ this.parent(event);
2454
+ if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
2455
+ },
2456
+
2457
+ stop: function(event){
2458
+ this.checkDroppables();
2459
+ this.fireEvent('drop', [this.element, this.overed, event]);
2460
+ this.overed = null;
2461
+ return this.parent(event);
2462
+ }
2463
+
2464
+ });
2465
+
2466
+ Element.implement({
2467
+
2468
+ makeDraggable: function(options){
2469
+ var drag = new Drag.Move(this, options);
2470
+ this.store('dragger', drag);
2471
+ return drag;
2472
+ }
2473
+
2474
+ });
2475
+
2476
+
2477
+ /*
2478
+ ---
2479
+
2480
+ script: Sortables.js
2481
+
2482
+ name: Sortables
2483
+
2484
+ description: Class for creating a drag and drop sorting interface for lists of items.
2485
+
2486
+ license: MIT-style license
2487
+
2488
+ authors:
2489
+ - Tom Occhino
2490
+
2491
+ requires:
2492
+ - Core/Fx.Morph
2493
+ - /Drag.Move
2494
+
2495
+ provides: [Sortables]
2496
+
2497
+ ...
2498
+ */
2499
+
2500
+ var Sortables = new Class({
2501
+
2502
+ Implements: [Events, Options],
2503
+
2504
+ options: {/*
2505
+ onSort: function(element, clone){},
2506
+ onStart: function(element, clone){},
2507
+ onComplete: function(element){},*/
2508
+ opacity: 1,
2509
+ clone: false,
2510
+ revert: false,
2511
+ handle: false,
2512
+ dragOptions: {}/*<1.2compat>*/,
2513
+ snap: 4,
2514
+ constrain: false,
2515
+ preventDefault: false
2516
+ /*</1.2compat>*/
2517
+ },
2518
+
2519
+ initialize: function(lists, options){
2520
+ this.setOptions(options);
2521
+
2522
+ this.elements = [];
2523
+ this.lists = [];
2524
+ this.idle = true;
2525
+
2526
+ this.addLists($$(document.id(lists) || lists));
2527
+
2528
+ if (!this.options.clone) this.options.revert = false;
2529
+ if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({
2530
+ duration: 250,
2531
+ link: 'cancel'
2532
+ }, this.options.revert));
2533
+ },
2534
+
2535
+ attach: function(){
2536
+ this.addLists(this.lists);
2537
+ return this;
2538
+ },
2539
+
2540
+ detach: function(){
2541
+ this.lists = this.removeLists(this.lists);
2542
+ return this;
2543
+ },
2544
+
2545
+ addItems: function(){
2546
+ Array.flatten(arguments).each(function(element){
2547
+ this.elements.push(element);
2548
+ var start = element.retrieve('sortables:start', function(event){
2549
+ this.start.call(this, event, element);
2550
+ }.bind(this));
2551
+ (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start);
2552
+ }, this);
2553
+ return this;
2554
+ },
2555
+
2556
+ addLists: function(){
2557
+ Array.flatten(arguments).each(function(list){
2558
+ this.lists.include(list);
2559
+ this.addItems(list.getChildren());
2560
+ }, this);
2561
+ return this;
2562
+ },
2563
+
2564
+ removeItems: function(){
2565
+ return $$(Array.flatten(arguments).map(function(element){
2566
+ this.elements.erase(element);
2567
+ var start = element.retrieve('sortables:start');
2568
+ (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
2569
+
2570
+ return element;
2571
+ }, this));
2572
+ },
2573
+
2574
+ removeLists: function(){
2575
+ return $$(Array.flatten(arguments).map(function(list){
2576
+ this.lists.erase(list);
2577
+ this.removeItems(list.getChildren());
2578
+
2579
+ return list;
2580
+ }, this));
2581
+ },
2582
+
2583
+ getClone: function(event, element){
2584
+ if (!this.options.clone) return new Element(element.tagName).inject(document.body);
2585
+ if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list);
2586
+ var clone = element.clone(true).setStyles({
2587
+ margin: 0,
2588
+ position: 'absolute',
2589
+ visibility: 'hidden',
2590
+ width: element.getStyle('width')
2591
+ }).addEvent('mousedown', function(event){
2592
+ element.fireEvent('mousedown', event);
2593
+ });
2594
+ //prevent the duplicated radio inputs from unchecking the real one
2595
+ if (clone.get('html').test('radio')){
2596
+ clone.getElements('input[type=radio]').each(function(input, i){
2597
+ input.set('name', 'clone_' + i);
2598
+ if (input.get('checked')) element.getElements('input[type=radio]')[i].set('checked', true);
2599
+ });
2600
+ }
2601
+
2602
+ return clone.inject(this.list).setPosition(element.getPosition(element.getOffsetParent()));
2603
+ },
2604
+
2605
+ getDroppables: function(){
2606
+ var droppables = this.list.getChildren().erase(this.clone).erase(this.element);
2607
+ if (!this.options.constrain) droppables.append(this.lists).erase(this.list);
2608
+ return droppables;
2609
+ },
2610
+
2611
+ insert: function(dragging, element){
2612
+ var where = 'inside';
2613
+ if (this.lists.contains(element)){
2614
+ this.list = element;
2615
+ this.drag.droppables = this.getDroppables();
2616
+ } else {
2617
+ where = this.element.getAllPrevious().contains(element) ? 'before' : 'after';
2618
+ }
2619
+ this.element.inject(element, where);
2620
+ this.fireEvent('sort', [this.element, this.clone]);
2621
+ },
2622
+
2623
+ start: function(event, element){
2624
+ if (
2625
+ !this.idle ||
2626
+ event.rightClick ||
2627
+ ['button', 'input', 'a'].contains(event.target.get('tag'))
2628
+ ) return;
2629
+
2630
+ this.idle = false;
2631
+ this.element = element;
2632
+ this.opacity = element.get('opacity');
2633
+ this.list = element.getParent();
2634
+ this.clone = this.getClone(event, element);
2635
+
2636
+ this.drag = new Drag.Move(this.clone, Object.merge({
2637
+ /*<1.2compat>*/
2638
+ preventDefault: this.options.preventDefault,
2639
+ snap: this.options.snap,
2640
+ container: this.options.constrain && this.element.getParent(),
2641
+ /*</1.2compat>*/
2642
+ droppables: this.getDroppables()
2643
+ }, this.options.dragOptions)).addEvents({
2644
+ onSnap: function(){
2645
+ event.stop();
2646
+ this.clone.setStyle('visibility', 'visible');
2647
+ this.element.set('opacity', this.options.opacity || 0);
2648
+ this.fireEvent('start', [this.element, this.clone]);
2649
+ }.bind(this),
2650
+ onEnter: this.insert.bind(this),
2651
+ onCancel: this.end.bind(this),
2652
+ onComplete: this.end.bind(this)
2653
+ });
2654
+
2655
+ this.clone.inject(this.element, 'before');
2656
+ this.drag.start(event);
2657
+ },
2658
+
2659
+ end: function(){
2660
+ this.drag.detach();
2661
+ this.element.set('opacity', this.opacity);
2662
+ if (this.effect){
2663
+ var dim = this.element.getStyles('width', 'height'),
2664
+ clone = this.clone,
2665
+ pos = clone.computePosition(this.element.getPosition(this.clone.getOffsetParent()));
2666
+
2667
+ var destroy = function(){
2668
+ this.removeEvent('cancel', destroy);
2669
+ clone.destroy();
2670
+ };
2671
+
2672
+ this.effect.element = clone;
2673
+ this.effect.start({
2674
+ top: pos.top,
2675
+ left: pos.left,
2676
+ width: dim.width,
2677
+ height: dim.height,
2678
+ opacity: 0.25
2679
+ }).addEvent('cancel', destroy).chain(destroy);
2680
+ } else {
2681
+ this.clone.destroy();
2682
+ }
2683
+ this.reset();
2684
+ },
2685
+
2686
+ reset: function(){
2687
+ this.idle = true;
2688
+ this.fireEvent('complete', this.element);
2689
+ },
2690
+
2691
+ serialize: function(){
2692
+ var params = Array.link(arguments, {
2693
+ modifier: Type.isFunction,
2694
+ index: function(obj){
2695
+ return obj != null;
2696
+ }
2697
+ });
2698
+ var serial = this.lists.map(function(list){
2699
+ return list.getChildren().map(params.modifier || function(element){
2700
+ return element.get('id');
2701
+ }, this);
2702
+ }, this);
2703
+
2704
+ var index = params.index;
2705
+ if (this.lists.length == 1) index = 0;
2706
+ return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial;
2707
+ }
2708
+
2709
+ });
2710
+
2711
+
2712
+ /*
2713
+ ---
2714
+
2715
+ script: Request.JSONP.js
2716
+
2717
+ name: Request.JSONP
2718
+
2719
+ description: Defines Request.JSONP, a class for cross domain javascript via script injection.
2720
+
2721
+ license: MIT-style license
2722
+
2723
+ authors:
2724
+ - Aaron Newton
2725
+ - Guillermo Rauch
2726
+ - Arian Stolwijk
2727
+
2728
+ requires:
2729
+ - Core/Element
2730
+ - Core/Request
2731
+ - MooTools.More
2732
+
2733
+ provides: [Request.JSONP]
2734
+
2735
+ ...
2736
+ */
2737
+
2738
+ Request.JSONP = new Class({
2739
+
2740
+ Implements: [Chain, Events, Options],
2741
+
2742
+ options: {/*
2743
+ onRequest: function(src, scriptElement){},
2744
+ onComplete: function(data){},
2745
+ onSuccess: function(data){},
2746
+ onCancel: function(){},
2747
+ onTimeout: function(){},
2748
+ onError: function(){}, */
2749
+ onRequest: function(src){
2750
+ if (this.options.log && window.console && console.log){
2751
+ console.log('JSONP retrieving script with url:' + src);
2752
+ }
2753
+ },
2754
+ onError: function(src){
2755
+ if (this.options.log && window.console && console.warn){
2756
+ console.warn('JSONP '+ src +' will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs');
2757
+ }
2758
+ },
2759
+ url: '',
2760
+ callbackKey: 'callback',
2761
+ injectScript: document.head,
2762
+ data: '',
2763
+ link: 'ignore',
2764
+ timeout: 0,
2765
+ log: false
2766
+ },
2767
+
2768
+ initialize: function(options){
2769
+ this.setOptions(options);
2770
+ },
2771
+
2772
+ send: function(options){
2773
+ if (!Request.prototype.check.call(this, options)) return this;
2774
+ this.running = true;
2775
+
2776
+ var type = typeOf(options);
2777
+ if (type == 'string' || type == 'element') options = {data: options};
2778
+ options = Object.merge(this.options, options || {});
2779
+
2780
+ var data = options.data;
2781
+ switch (typeOf(data)){
2782
+ case 'element': data = document.id(data).toQueryString(); break;
2783
+ case 'object': case 'hash': data = Object.toQueryString(data);
2784
+ }
2785
+
2786
+ var index = this.index = Request.JSONP.counter++;
2787
+
2788
+ var src = options.url +
2789
+ (options.url.test('\\?') ? '&' :'?') +
2790
+ (options.callbackKey) +
2791
+ '=Request.JSONP.request_map.request_'+ index +
2792
+ (data ? '&' + data : '');
2793
+
2794
+ if (src.length > 2083) this.fireEvent('error', src);
2795
+
2796
+ Request.JSONP.request_map['request_' + index] = function(){
2797
+ this.success(arguments, index);
2798
+ }.bind(this);
2799
+
2800
+ var script = this.getScript(src).inject(options.injectScript);
2801
+ this.fireEvent('request', [src, script]);
2802
+
2803
+ if (options.timeout) this.timeout.delay(options.timeout, this);
2804
+
2805
+ return this;
2806
+ },
2807
+
2808
+ getScript: function(src){
2809
+ if (!this.script) this.script = new Element('script', {
2810
+ type: 'text/javascript',
2811
+ async: true,
2812
+ src: src
2813
+ });
2814
+ return this.script;
2815
+ },
2816
+
2817
+ success: function(args, index){
2818
+ if (!this.running) return;
2819
+ this.clear()
2820
+ .fireEvent('complete', args).fireEvent('success', args)
2821
+ .callChain();
2822
+ },
2823
+
2824
+ cancel: function(){
2825
+ if (this.running) this.clear().fireEvent('cancel');
2826
+ return this;
2827
+ },
2828
+
2829
+ isRunning: function(){
2830
+ return !!this.running;
2831
+ },
2832
+
2833
+ clear: function(){
2834
+ this.running = false;
2835
+ if (this.script){
2836
+ this.script.destroy();
2837
+ this.script = null;
2838
+ }
2839
+ return this;
2840
+ },
2841
+
2842
+ timeout: function(){
2843
+ if (this.running){
2844
+ this.running = false;
2845
+ this.fireEvent('timeout', [this.script.get('src'), this.script]).fireEvent('failure').cancel();
2846
+ }
2847
+ return this;
2848
+ }
2849
+
2850
+ });
2851
+
2852
+ Request.JSONP.counter = 0;
2853
+ Request.JSONP.request_map = {};
2854
+
2855
+
2856
+ /*
2857
+ ---
2858
+
2859
+ script: Request.Periodical.js
2860
+
2861
+ name: Request.Periodical
2862
+
2863
+ description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load
2864
+
2865
+ license: MIT-style license
2866
+
2867
+ authors:
2868
+ - Christoph Pojer
2869
+
2870
+ requires:
2871
+ - Core/Request
2872
+ - /MooTools.More
2873
+
2874
+ provides: [Request.Periodical]
2875
+
2876
+ ...
2877
+ */
2878
+
2879
+ Request.implement({
2880
+
2881
+ options: {
2882
+ initialDelay: 5000,
2883
+ delay: 5000,
2884
+ limit: 60000
2885
+ },
2886
+
2887
+ startTimer: function(data){
2888
+ var fn = function(){
2889
+ if (!this.running) this.send({data: data});
2890
+ };
2891
+ this.lastDelay = this.options.initialDelay;
2892
+ this.timer = fn.delay(this.lastDelay, this);
2893
+ this.completeCheck = function(response){
2894
+ clearTimeout(this.timer);
2895
+ this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit);
2896
+ this.timer = fn.delay(this.lastDelay, this);
2897
+ };
2898
+ return this.addEvent('complete', this.completeCheck);
2899
+ },
2900
+
2901
+ stopTimer: function(){
2902
+ clearTimeout(this.timer);
2903
+ return this.removeEvent('complete', this.completeCheck);
2904
+ }
2905
+
2906
+ });
2907
+
2908
+
2909
+ /*
2910
+ ---
2911
+
2912
+ script: Assets.js
2913
+
2914
+ name: Assets
2915
+
2916
+ description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
2917
+
2918
+ license: MIT-style license
2919
+
2920
+ authors:
2921
+ - Valerio Proietti
2922
+
2923
+ requires:
2924
+ - Core/Element.Event
2925
+ - /MooTools.More
2926
+
2927
+ provides: [Assets]
2928
+
2929
+ ...
2930
+ */
2931
+
2932
+ var Asset = {
2933
+
2934
+ javascript: function(source, properties){
2935
+ if (!properties) properties = {};
2936
+
2937
+ var script = new Element('script', {src: source, type: 'text/javascript'}),
2938
+ doc = properties.document || document,
2939
+ loaded = 0,
2940
+ loadEvent = properties.onload || properties.onLoad;
2941
+
2942
+ var load = loadEvent ? function(){ // make sure we only call the event once
2943
+ if (++loaded == 1) loadEvent.call(this);
2944
+ } : function(){};
2945
+
2946
+ delete properties.onload;
2947
+ delete properties.onLoad;
2948
+ delete properties.document;
2949
+
2950
+ return script.addEvents({
2951
+ load: load,
2952
+ readystatechange: function(){
2953
+ if (['loaded', 'complete'].contains(this.readyState)) load.call(this);
2954
+ }
2955
+ }).set(properties).inject(doc.head);
2956
+ },
2957
+
2958
+ css: function(source, properties){
2959
+ if (!properties) properties = {};
2960
+
2961
+ var link = new Element('link', {
2962
+ rel: 'stylesheet',
2963
+ media: 'screen',
2964
+ type: 'text/css',
2965
+ href: source
2966
+ });
2967
+
2968
+ var load = properties.onload || properties.onLoad,
2969
+ doc = properties.document || document;
2970
+
2971
+ delete properties.onload;
2972
+ delete properties.onLoad;
2973
+ delete properties.document;
2974
+
2975
+ if (load) link.addEvent('load', load);
2976
+ return link.set(properties).inject(doc.head);
2977
+ },
2978
+
2979
+ image: function(source, properties){
2980
+ if (!properties) properties = {};
2981
+
2982
+ var image = new Image(),
2983
+ element = document.id(image) || new Element('img');
2984
+
2985
+ ['load', 'abort', 'error'].each(function(name){
2986
+ var type = 'on' + name,
2987
+ cap = 'on' + name.capitalize(),
2988
+ event = properties[type] || properties[cap] || function(){};
2989
+
2990
+ delete properties[cap];
2991
+ delete properties[type];
2992
+
2993
+ image[type] = function(){
2994
+ if (!image) return;
2995
+ if (!element.parentNode){
2996
+ element.width = image.width;
2997
+ element.height = image.height;
2998
+ }
2999
+ image = image.onload = image.onabort = image.onerror = null;
3000
+ event.delay(1, element, element);
3001
+ element.fireEvent(name, element, 1);
3002
+ };
3003
+ });
3004
+
3005
+ image.src = element.src = source;
3006
+ if (image && image.complete) image.onload.delay(1);
3007
+ return element.set(properties);
3008
+ },
3009
+
3010
+ images: function(sources, options){
3011
+ sources = Array.from(sources);
3012
+
3013
+ var fn = function(){},
3014
+ counter = 0;
3015
+
3016
+ options = Object.merge({
3017
+ onComplete: fn,
3018
+ onProgress: fn,
3019
+ onError: fn,
3020
+ properties: {}
3021
+ }, options);
3022
+
3023
+ return new Elements(sources.map(function(source, index){
3024
+ return Asset.image(source, Object.append(options.properties, {
3025
+ onload: function(){
3026
+ counter++;
3027
+ options.onProgress.call(this, counter, index, source);
3028
+ if (counter == sources.length) options.onComplete();
3029
+ },
3030
+ onerror: function(){
3031
+ counter++;
3032
+ options.onError.call(this, counter, index, source);
3033
+ if (counter == sources.length) options.onComplete();
3034
+ }
3035
+ }));
3036
+ }));
3037
+ }
3038
+
3039
+ };
3040
+
3041
+
3042
+ /*
3043
+ ---
3044
+
3045
+ script: IframeShim.js
3046
+
3047
+ name: IframeShim
3048
+
3049
+ description: Defines IframeShim, a class for obscuring select lists and flash objects in IE.
3050
+
3051
+ license: MIT-style license
3052
+
3053
+ authors:
3054
+ - Aaron Newton
3055
+
3056
+ requires:
3057
+ - Core/Element.Event
3058
+ - Core/Element.Style
3059
+ - Core/Options
3060
+ - Core/Events
3061
+ - /Element.Position
3062
+ - /Class.Occlude
3063
+
3064
+ provides: [IframeShim]
3065
+
3066
+ ...
3067
+ */
3068
+
3069
+ var IframeShim = new Class({
3070
+
3071
+ Implements: [Options, Events, Class.Occlude],
3072
+
3073
+ options: {
3074
+ className: 'iframeShim',
3075
+ src: 'javascript:false;document.write("");',
3076
+ display: false,
3077
+ zIndex: null,
3078
+ margin: 0,
3079
+ offset: {x: 0, y: 0},
3080
+ browsers: (Browser.ie6 || (Browser.firefox && Browser.version < 3 && Browser.Platform.mac))
3081
+ },
3082
+
3083
+ property: 'IframeShim',
3084
+
3085
+ initialize: function(element, options){
3086
+ this.element = document.id(element);
3087
+ if (this.occlude()) return this.occluded;
3088
+ this.setOptions(options);
3089
+ this.makeShim();
3090
+ return this;
3091
+ },
3092
+
3093
+ makeShim: function(){
3094
+ if (this.options.browsers){
3095
+ var zIndex = this.element.getStyle('zIndex').toInt();
3096
+
3097
+ if (!zIndex){
3098
+ zIndex = 1;
3099
+ var pos = this.element.getStyle('position');
3100
+ if (pos == 'static' || !pos) this.element.setStyle('position', 'relative');
3101
+ this.element.setStyle('zIndex', zIndex);
3102
+ }
3103
+ zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1;
3104
+ if (zIndex < 0) zIndex = 1;
3105
+ this.shim = new Element('iframe', {
3106
+ src: this.options.src,
3107
+ scrolling: 'no',
3108
+ frameborder: 0,
3109
+ styles: {
3110
+ zIndex: zIndex,
3111
+ position: 'absolute',
3112
+ border: 'none',
3113
+ filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
3114
+ },
3115
+ 'class': this.options.className
3116
+ }).store('IframeShim', this);
3117
+ var inject = (function(){
3118
+ this.shim.inject(this.element, 'after');
3119
+ this[this.options.display ? 'show' : 'hide']();
3120
+ this.fireEvent('inject');
3121
+ }).bind(this);
3122
+ if (!IframeShim.ready) window.addEvent('load', inject);
3123
+ else inject();
3124
+ } else {
3125
+ this.position = this.hide = this.show = this.dispose = Function.from(this);
3126
+ }
3127
+ },
3128
+
3129
+ position: function(){
3130
+ if (!IframeShim.ready || !this.shim) return this;
3131
+ var size = this.element.measure(function(){
3132
+ return this.getSize();
3133
+ });
3134
+ if (this.options.margin != undefined){
3135
+ size.x = size.x - (this.options.margin * 2);
3136
+ size.y = size.y - (this.options.margin * 2);
3137
+ this.options.offset.x += this.options.margin;
3138
+ this.options.offset.y += this.options.margin;
3139
+ }
3140
+ this.shim.set({width: size.x, height: size.y}).position({
3141
+ relativeTo: this.element,
3142
+ offset: this.options.offset
3143
+ });
3144
+ return this;
3145
+ },
3146
+
3147
+ hide: function(){
3148
+ if (this.shim) this.shim.setStyle('display', 'none');
3149
+ return this;
3150
+ },
3151
+
3152
+ show: function(){
3153
+ if (this.shim) this.shim.setStyle('display', 'block');
3154
+ return this.position();
3155
+ },
3156
+
3157
+ dispose: function(){
3158
+ if (this.shim) this.shim.dispose();
3159
+ return this;
3160
+ },
3161
+
3162
+ destroy: function(){
3163
+ if (this.shim) this.shim.destroy();
3164
+ return this;
3165
+ }
3166
+
3167
+ });
3168
+
3169
+ window.addEvent('load', function(){
3170
+ IframeShim.ready = true;
3171
+ });
3172
+
3173
+
3174
+ /*
3175
+ ---
3176
+
3177
+ script: Keyboard.js
3178
+
3179
+ name: Keyboard
3180
+
3181
+ description: KeyboardEvents used to intercept events on a class for keyboard and format modifiers in a specific order so as to make alt+shift+c the same as shift+alt+c.
3182
+
3183
+ license: MIT-style license
3184
+
3185
+ authors:
3186
+ - Perrin Westrich
3187
+ - Aaron Newton
3188
+ - Scott Kyle
3189
+
3190
+ requires:
3191
+ - Core/Events
3192
+ - Core/Options
3193
+ - Core/Element.Event
3194
+ - Element.Event.Pseudos.Keys
3195
+
3196
+ provides: [Keyboard]
3197
+
3198
+ ...
3199
+ */
3200
+
3201
+ (function(){
3202
+
3203
+ var Keyboard = this.Keyboard = new Class({
3204
+
3205
+ Extends: Events,
3206
+
3207
+ Implements: [Options],
3208
+
3209
+ options: {/*
3210
+ onActivate: function(){},
3211
+ onDeactivate: function(){},*/
3212
+ defaultEventType: 'keydown',
3213
+ active: false,
3214
+ manager: null,
3215
+ events: {},
3216
+ nonParsedEvents: ['activate', 'deactivate', 'onactivate', 'ondeactivate', 'changed', 'onchanged']
3217
+ },
3218
+
3219
+ initialize: function(options){
3220
+ if (options && options.manager){
3221
+ this._manager = options.manager;
3222
+ delete options.manager;
3223
+ }
3224
+ this.setOptions(options);
3225
+ this._setup();
3226
+ },
3227
+
3228
+ addEvent: function(type, fn, internal){
3229
+ return this.parent(Keyboard.parse(type, this.options.defaultEventType, this.options.nonParsedEvents), fn, internal);
3230
+ },
3231
+
3232
+ removeEvent: function(type, fn){
3233
+ return this.parent(Keyboard.parse(type, this.options.defaultEventType, this.options.nonParsedEvents), fn);
3234
+ },
3235
+
3236
+ toggleActive: function(){
3237
+ return this[this.isActive() ? 'deactivate' : 'activate']();
3238
+ },
3239
+
3240
+ activate: function(instance){
3241
+ if (instance){
3242
+ if (instance.isActive()) return this;
3243
+ //if we're stealing focus, store the last keyboard to have it so the relinquish command works
3244
+ if (this._activeKB && instance != this._activeKB){
3245
+ this.previous = this._activeKB;
3246
+ this.previous.fireEvent('deactivate');
3247
+ }
3248
+ //if we're enabling a child, assign it so that events are now passed to it
3249
+ this._activeKB = instance.fireEvent('activate');
3250
+ Keyboard.manager.fireEvent('changed');
3251
+ } else if (this._manager){
3252
+ //else we're enabling ourselves, we must ask our parent to do it for us
3253
+ this._manager.activate(this);
3254
+ }
3255
+ return this;
3256
+ },
3257
+
3258
+ isActive: function(){
3259
+ return this._manager ? (this._manager._activeKB == this) : (Keyboard.manager == this);
3260
+ },
3261
+
3262
+ deactivate: function(instance){
3263
+ if (instance){
3264
+ if (instance === this._activeKB){
3265
+ this._activeKB = null;
3266
+ instance.fireEvent('deactivate');
3267
+ Keyboard.manager.fireEvent('changed');
3268
+ }
3269
+ } else if (this._manager){
3270
+ this._manager.deactivate(this);
3271
+ }
3272
+ return this;
3273
+ },
3274
+
3275
+ relinquish: function(){
3276
+ if (this.isActive() && this._manager && this._manager.previous) this._manager.activate(this._manager.previous);
3277
+ else this.deactivate();
3278
+ return this;
3279
+ },
3280
+
3281
+ //management logic
3282
+ manage: function(instance){
3283
+ if (instance._manager) instance._manager.drop(instance);
3284
+ this._instances.push(instance);
3285
+ instance._manager = this;
3286
+ if (!this._activeKB) this.activate(instance);
3287
+ return this;
3288
+ },
3289
+
3290
+ drop: function(instance){
3291
+ instance.relinquish();
3292
+ this._instances.erase(instance);
3293
+ if (this._activeKB == instance){
3294
+ if (this.previous && this._instances.contains(this.previous)) this.activate(this.previous);
3295
+ else this._activeKB = this._instances[0];
3296
+ }
3297
+ return this;
3298
+ },
3299
+
3300
+ trace: function(){
3301
+ Keyboard.trace(this);
3302
+ },
3303
+
3304
+ each: function(fn){
3305
+ Keyboard.each(this, fn);
3306
+ },
3307
+
3308
+ /*
3309
+ PRIVATE METHODS
3310
+ */
3311
+
3312
+ _instances: [],
3313
+
3314
+ _disable: function(instance){
3315
+ if (this._activeKB == instance) this._activeKB = null;
3316
+ },
3317
+
3318
+ _setup: function(){
3319
+ this.addEvents(this.options.events);
3320
+ //if this is the root manager, nothing manages it
3321
+ if (Keyboard.manager && !this._manager) Keyboard.manager.manage(this);
3322
+ if (this.options.active) this.activate();
3323
+ else this.relinquish();
3324
+ },
3325
+
3326
+ _handle: function(event, type){
3327
+ //Keyboard.stop(event) prevents key propagation
3328
+ if (event.preventKeyboardPropagation) return;
3329
+
3330
+ var bubbles = !!this._manager;
3331
+ if (bubbles && this._activeKB){
3332
+ this._activeKB._handle(event, type);
3333
+ if (event.preventKeyboardPropagation) return;
3334
+ }
3335
+ this.fireEvent(type, event);
3336
+
3337
+ if (!bubbles && this._activeKB) this._activeKB._handle(event, type);
3338
+ }
3339
+
3340
+ });
3341
+
3342
+ var parsed = {};
3343
+ var modifiers = ['shift', 'control', 'alt', 'meta'];
3344
+ var regex = /^(?:shift|control|ctrl|alt|meta)$/;
3345
+
3346
+ Keyboard.parse = function(type, eventType, ignore){
3347
+ if (ignore && ignore.contains(type.toLowerCase())) return type;
3348
+
3349
+ type = type.toLowerCase().replace(/^(keyup|keydown):/, function($0, $1){
3350
+ eventType = $1;
3351
+ return '';
3352
+ });
3353
+
3354
+ if (!parsed[type]){
3355
+ var key, mods = {};
3356
+ type.split('+').each(function(part){
3357
+ if (regex.test(part)) mods[part] = true;
3358
+ else key = part;
3359
+ });
3360
+
3361
+ mods.control = mods.control || mods.ctrl; // allow both control and ctrl
3362
+
3363
+ var keys = [];
3364
+ modifiers.each(function(mod){
3365
+ if (mods[mod]) keys.push(mod);
3366
+ });
3367
+
3368
+ if (key) keys.push(key);
3369
+ parsed[type] = keys.join('+');
3370
+ }
3371
+
3372
+ return eventType + ':keys(' + parsed[type] + ')';
3373
+ };
3374
+
3375
+ Keyboard.each = function(keyboard, fn){
3376
+ var current = keyboard || Keyboard.manager;
3377
+ while (current){
3378
+ fn.run(current);
3379
+ current = current._activeKB;
3380
+ }
3381
+ };
3382
+
3383
+ Keyboard.stop = function(event){
3384
+ event.preventKeyboardPropagation = true;
3385
+ };
3386
+
3387
+ Keyboard.manager = new Keyboard({
3388
+ active: true
3389
+ });
3390
+
3391
+ Keyboard.trace = function(keyboard){
3392
+ keyboard = keyboard || Keyboard.manager;
3393
+ var hasConsole = window.console && console.log;
3394
+ if (hasConsole) console.log('the following items have focus: ');
3395
+ Keyboard.each(keyboard, function(current){
3396
+ if (hasConsole) console.log(document.id(current.widget) || current.wiget || current);
3397
+ });
3398
+ };
3399
+
3400
+ var handler = function(event){
3401
+ var keys = [];
3402
+ modifiers.each(function(mod){
3403
+ if (event[mod]) keys.push(mod);
3404
+ });
3405
+
3406
+ if (!regex.test(event.key)) keys.push(event.key);
3407
+ Keyboard.manager._handle(event, event.type + ':keys(' + keys.join('+') + ')');
3408
+ };
3409
+
3410
+ document.addEvents({
3411
+ 'keyup': handler,
3412
+ 'keydown': handler
3413
+ });
3414
+
3415
+ })();
3416
+
3417
+
3418
+ /*
3419
+ ---
3420
+
3421
+ script: Keyboard.Extras.js
3422
+
3423
+ name: Keyboard.Extras
3424
+
3425
+ description: Enhances Keyboard by adding the ability to name and describe keyboard shortcuts, and the ability to grab shortcuts by name and bind the shortcut to different keys.
3426
+
3427
+ license: MIT-style license
3428
+
3429
+ authors:
3430
+ - Perrin Westrich
3431
+
3432
+ requires:
3433
+ - /Keyboard
3434
+ - /MooTools.More
3435
+
3436
+ provides: [Keyboard.Extras]
3437
+
3438
+ ...
3439
+ */
3440
+ Keyboard.prototype.options.nonParsedEvents.combine(['rebound', 'onrebound']);
3441
+
3442
+ Keyboard.implement({
3443
+
3444
+ /*
3445
+ shortcut should be in the format of:
3446
+ {
3447
+ 'keys': 'shift+s', // the default to add as an event.
3448
+ 'description': 'blah blah blah', // a brief description of the functionality.
3449
+ 'handler': function(){} // the event handler to run when keys are pressed.
3450
+ }
3451
+ */
3452
+ addShortcut: function(name, shortcut){
3453
+ this._shortcuts = this._shortcuts || [];
3454
+ this._shortcutIndex = this._shortcutIndex || {};
3455
+
3456
+ shortcut.getKeyboard = Function.from(this);
3457
+ shortcut.name = name;
3458
+ this._shortcutIndex[name] = shortcut;
3459
+ this._shortcuts.push(shortcut);
3460
+ if (shortcut.keys) this.addEvent(shortcut.keys, shortcut.handler);
3461
+ return this;
3462
+ },
3463
+
3464
+ addShortcuts: function(obj){
3465
+ for (var name in obj) this.addShortcut(name, obj[name]);
3466
+ return this;
3467
+ },
3468
+
3469
+ removeShortcut: function(name){
3470
+ var shortcut = this.getShortcut(name);
3471
+ if (shortcut && shortcut.keys){
3472
+ this.removeEvent(shortcut.keys, shortcut.handler);
3473
+ delete this._shortcutIndex[name];
3474
+ this._shortcuts.erase(shortcut);
3475
+ }
3476
+ return this;
3477
+ },
3478
+
3479
+ removeShortcuts: function(names){
3480
+ names.each(this.removeShortcut, this);
3481
+ return this;
3482
+ },
3483
+
3484
+ getShortcuts: function(){
3485
+ return this._shortcuts || [];
3486
+ },
3487
+
3488
+ getShortcut: function(name){
3489
+ return (this._shortcutIndex || {})[name];
3490
+ }
3491
+
3492
+ });
3493
+
3494
+ Keyboard.rebind = function(newKeys, shortcuts){
3495
+ Array.from(shortcuts).each(function(shortcut){
3496
+ shortcut.getKeyboard().removeEvent(shortcut.keys, shortcut.handler);
3497
+ shortcut.getKeyboard().addEvent(newKeys, shortcut.handler);
3498
+ shortcut.keys = newKeys;
3499
+ shortcut.getKeyboard().fireEvent('rebound');
3500
+ });
3501
+ };
3502
+
3503
+
3504
+ Keyboard.getActiveShortcuts = function(keyboard){
3505
+ var activeKBS = [], activeSCS = [];
3506
+ Keyboard.each(keyboard, [].push.bind(activeKBS));
3507
+ activeKBS.each(function(kb){ activeSCS.extend(kb.getShortcuts()); });
3508
+ return activeSCS;
3509
+ };
3510
+
3511
+ Keyboard.getShortcut = function(name, keyboard, opts){
3512
+ opts = opts || {};
3513
+ var shortcuts = opts.many ? [] : null,
3514
+ set = opts.many ? function(kb){
3515
+ var shortcut = kb.getShortcut(name);
3516
+ if (shortcut) shortcuts.push(shortcut);
3517
+ } : function(kb){
3518
+ if (!shortcuts) shortcuts = kb.getShortcut(name);
3519
+ };
3520
+ Keyboard.each(keyboard, set);
3521
+ return shortcuts;
3522
+ };
3523
+
3524
+ Keyboard.getShortcuts = function(name, keyboard){
3525
+ return Keyboard.getShortcut(name, keyboard, { many: true });
3526
+ };
3527
+
3528
+
3529
+ /*
3530
+ ---
3531
+
3532
+ script: Mask.js
3533
+
3534
+ name: Mask
3535
+
3536
+ description: Creates a mask element to cover another.
3537
+
3538
+ license: MIT-style license
3539
+
3540
+ authors:
3541
+ - Aaron Newton
3542
+
3543
+ requires:
3544
+ - Core/Options
3545
+ - Core/Events
3546
+ - Core/Element.Event
3547
+ - /Class.Binds
3548
+ - /Element.Position
3549
+ - /IframeShim
3550
+
3551
+ provides: [Mask]
3552
+
3553
+ ...
3554
+ */
3555
+
3556
+ var Mask = new Class({
3557
+
3558
+ Implements: [Options, Events],
3559
+
3560
+ Binds: ['position'],
3561
+
3562
+ options: {/*
3563
+ onShow: function(){},
3564
+ onHide: function(){},
3565
+ onDestroy: function(){},
3566
+ onClick: function(event){},
3567
+ inject: {
3568
+ where: 'after',
3569
+ target: null,
3570
+ },
3571
+ hideOnClick: false,
3572
+ id: null,
3573
+ destroyOnHide: false,*/
3574
+ style: {},
3575
+ 'class': 'mask',
3576
+ maskMargins: false,
3577
+ useIframeShim: true,
3578
+ iframeShimOptions: {}
3579
+ },
3580
+
3581
+ initialize: function(target, options){
3582
+ this.target = document.id(target) || document.id(document.body);
3583
+ this.target.store('mask', this);
3584
+ this.setOptions(options);
3585
+ this.render();
3586
+ this.inject();
3587
+ },
3588
+
3589
+ render: function(){
3590
+ this.element = new Element('div', {
3591
+ 'class': this.options['class'],
3592
+ id: this.options.id || 'mask-' + String.uniqueID(),
3593
+ styles: Object.merge({}, this.options.style, {
3594
+ display: 'none'
3595
+ }),
3596
+ events: {
3597
+ click: function(event){
3598
+ this.fireEvent('click', event);
3599
+ if (this.options.hideOnClick) this.hide();
3600
+ }.bind(this)
3601
+ }
3602
+ });
3603
+
3604
+ this.hidden = true;
3605
+ },
3606
+
3607
+ toElement: function(){
3608
+ return this.element;
3609
+ },
3610
+
3611
+ inject: function(target, where){
3612
+ where = where || (this.options.inject ? this.options.inject.where : '') || this.target == document.body ? 'inside' : 'after';
3613
+ target = target || (this.options.inject && this.options.inject.target) || this.target;
3614
+
3615
+ this.element.inject(target, where);
3616
+
3617
+ if (this.options.useIframeShim){
3618
+ this.shim = new IframeShim(this.element, this.options.iframeShimOptions);
3619
+
3620
+ this.addEvents({
3621
+ show: this.shim.show.bind(this.shim),
3622
+ hide: this.shim.hide.bind(this.shim),
3623
+ destroy: this.shim.destroy.bind(this.shim)
3624
+ });
3625
+ }
3626
+ },
3627
+
3628
+ position: function(){
3629
+ this.resize(this.options.width, this.options.height);
3630
+
3631
+ this.element.position({
3632
+ relativeTo: this.target,
3633
+ position: 'topLeft',
3634
+ ignoreMargins: !this.options.maskMargins,
3635
+ ignoreScroll: this.target == document.body
3636
+ });
3637
+
3638
+ return this;
3639
+ },
3640
+
3641
+ resize: function(x, y){
3642
+ var opt = {
3643
+ styles: ['padding', 'border']
3644
+ };
3645
+ if (this.options.maskMargins) opt.styles.push('margin');
3646
+
3647
+ var dim = this.target.getComputedSize(opt);
3648
+ if (this.target == document.body){
3649
+ this.element.setStyles({width: 0, height: 0});
3650
+ var win = window.getScrollSize();
3651
+ if (dim.totalHeight < win.y) dim.totalHeight = win.y;
3652
+ if (dim.totalWidth < win.x) dim.totalWidth = win.x;
3653
+ }
3654
+ this.element.setStyles({
3655
+ width: Array.pick([x, dim.totalWidth, dim.x]),
3656
+ height: Array.pick([y, dim.totalHeight, dim.y])
3657
+ });
3658
+
3659
+ return this;
3660
+ },
3661
+
3662
+ show: function(){
3663
+ if (!this.hidden) return this;
3664
+
3665
+ window.addEvent('resize', this.position);
3666
+ this.position();
3667
+ this.showMask.apply(this, arguments);
3668
+
3669
+ return this;
3670
+ },
3671
+
3672
+ showMask: function(){
3673
+ this.element.setStyle('display', 'block');
3674
+ this.hidden = false;
3675
+ this.fireEvent('show');
3676
+ },
3677
+
3678
+ hide: function(){
3679
+ if (this.hidden) return this;
3680
+
3681
+ window.removeEvent('resize', this.position);
3682
+ this.hideMask.apply(this, arguments);
3683
+ if (this.options.destroyOnHide) return this.destroy();
3684
+
3685
+ return this;
3686
+ },
3687
+
3688
+ hideMask: function(){
3689
+ this.element.setStyle('display', 'none');
3690
+ this.hidden = true;
3691
+ this.fireEvent('hide');
3692
+ },
3693
+
3694
+ toggle: function(){
3695
+ this[this.hidden ? 'show' : 'hide']();
3696
+ },
3697
+
3698
+ destroy: function(){
3699
+ this.hide();
3700
+ this.element.destroy();
3701
+ this.fireEvent('destroy');
3702
+ this.target.eliminate('mask');
3703
+ }
3704
+
3705
+ });
3706
+
3707
+ Element.Properties.mask = {
3708
+
3709
+ set: function(options){
3710
+ var mask = this.retrieve('mask');
3711
+ if (mask) mask.destroy();
3712
+ return this.eliminate('mask').store('mask:options', options);
3713
+ },
3714
+
3715
+ get: function(){
3716
+ var mask = this.retrieve('mask');
3717
+ if (!mask){
3718
+ mask = new Mask(this, this.retrieve('mask:options'));
3719
+ this.store('mask', mask);
3720
+ }
3721
+ return mask;
3722
+ }
3723
+
3724
+ };
3725
+
3726
+ Element.implement({
3727
+
3728
+ mask: function(options){
3729
+ if (options) this.set('mask', options);
3730
+ this.get('mask').show();
3731
+ return this;
3732
+ },
3733
+
3734
+ unmask: function(){
3735
+ this.get('mask').hide();
3736
+ return this;
3737
+ }
3738
+
3739
+ });
3740
+
3741
+
3742
+ /*
3743
+ ---
3744
+
3745
+ script: Tips.js
3746
+
3747
+ name: Tips
3748
+
3749
+ description: Class for creating nice tips that follow the mouse cursor when hovering an element.
3750
+
3751
+ license: MIT-style license
3752
+
3753
+ authors:
3754
+ - Valerio Proietti
3755
+ - Christoph Pojer
3756
+ - Luis Merino
3757
+
3758
+ requires:
3759
+ - Core/Options
3760
+ - Core/Events
3761
+ - Core/Element.Event
3762
+ - Core/Element.Style
3763
+ - Core/Element.Dimensions
3764
+ - /MooTools.More
3765
+
3766
+ provides: [Tips]
3767
+
3768
+ ...
3769
+ */
3770
+
3771
+ (function(){
3772
+
3773
+ var read = function(option, element){
3774
+ return (option) ? (typeOf(option) == 'function' ? option(element) : element.get(option)) : '';
3775
+ };
3776
+
3777
+ this.Tips = new Class({
3778
+
3779
+ Implements: [Events, Options],
3780
+
3781
+ options: {/*
3782
+ onAttach: function(element){},
3783
+ onDetach: function(element){},
3784
+ onBound: function(coords){},*/
3785
+ onShow: function(){
3786
+ this.tip.setStyle('display', 'block');
3787
+ },
3788
+ onHide: function(){
3789
+ this.tip.setStyle('display', 'none');
3790
+ },
3791
+ title: 'title',
3792
+ text: function(element){
3793
+ return element.get('rel') || element.get('href');
3794
+ },
3795
+ showDelay: 100,
3796
+ hideDelay: 100,
3797
+ className: 'tip-wrap',
3798
+ offset: {x: 16, y: 16},
3799
+ windowPadding: {x:0, y:0},
3800
+ fixed: false
3801
+ },
3802
+
3803
+ initialize: function(){
3804
+ var params = Array.link(arguments, {
3805
+ options: Type.isObject,
3806
+ elements: function(obj){
3807
+ return obj != null;
3808
+ }
3809
+ });
3810
+ this.setOptions(params.options);
3811
+ if (params.elements) this.attach(params.elements);
3812
+ this.container = new Element('div', {'class': 'tip'});
3813
+ },
3814
+
3815
+ toElement: function(){
3816
+ if (this.tip) return this.tip;
3817
+
3818
+ this.tip = new Element('div', {
3819
+ 'class': this.options.className,
3820
+ styles: {
3821
+ position: 'absolute',
3822
+ top: 0,
3823
+ left: 0
3824
+ }
3825
+ }).adopt(
3826
+ new Element('div', {'class': 'tip-top'}),
3827
+ this.container,
3828
+ new Element('div', {'class': 'tip-bottom'})
3829
+ );
3830
+
3831
+ return this.tip;
3832
+ },
3833
+
3834
+ attach: function(elements){
3835
+ $$(elements).each(function(element){
3836
+ var title = read(this.options.title, element),
3837
+ text = read(this.options.text, element);
3838
+
3839
+ element.set('title', '').store('tip:native', title).retrieve('tip:title', title);
3840
+ element.retrieve('tip:text', text);
3841
+ this.fireEvent('attach', [element]);
3842
+
3843
+ var events = ['enter', 'leave'];
3844
+ if (!this.options.fixed) events.push('move');
3845
+
3846
+ events.each(function(value){
3847
+ var event = element.retrieve('tip:' + value);
3848
+ if (!event) event = function(event){
3849
+ this['element' + value.capitalize()].apply(this, [event, element]);
3850
+ }.bind(this);
3851
+
3852
+ element.store('tip:' + value, event).addEvent('mouse' + value, event);
3853
+ }, this);
3854
+ }, this);
3855
+
3856
+ return this;
3857
+ },
3858
+
3859
+ detach: function(elements){
3860
+ $$(elements).each(function(element){
3861
+ ['enter', 'leave', 'move'].each(function(value){
3862
+ element.removeEvent('mouse' + value, element.retrieve('tip:' + value)).eliminate('tip:' + value);
3863
+ });
3864
+
3865
+ this.fireEvent('detach', [element]);
3866
+
3867
+ if (this.options.title == 'title'){ // This is necessary to check if we can revert the title
3868
+ var original = element.retrieve('tip:native');
3869
+ if (original) element.set('title', original);
3870
+ }
3871
+ }, this);
3872
+
3873
+ return this;
3874
+ },
3875
+
3876
+ elementEnter: function(event, element){
3877
+ clearTimeout(this.timer);
3878
+ this.timer = (function(){
3879
+ this.container.empty();
3880
+
3881
+ ['title', 'text'].each(function(value){
3882
+ var content = element.retrieve('tip:' + value);
3883
+ var div = this['_' + value + 'Element'] = new Element('div', {
3884
+ 'class': 'tip-' + value
3885
+ }).inject(this.container);
3886
+ if (content) this.fill(div, content);
3887
+ }, this);
3888
+ this.show(element);
3889
+ this.position((this.options.fixed) ? {page: element.getPosition()} : event);
3890
+ }).delay(this.options.showDelay, this);
3891
+ },
3892
+
3893
+ elementLeave: function(event, element){
3894
+ clearTimeout(this.timer);
3895
+ this.timer = this.hide.delay(this.options.hideDelay, this, element);
3896
+ this.fireForParent(event, element);
3897
+ },
3898
+
3899
+ setTitle: function(title){
3900
+ if (this._titleElement){
3901
+ this._titleElement.empty();
3902
+ this.fill(this._titleElement, title);
3903
+ }
3904
+ return this;
3905
+ },
3906
+
3907
+ setText: function(text){
3908
+ if (this._textElement){
3909
+ this._textElement.empty();
3910
+ this.fill(this._textElement, text);
3911
+ }
3912
+ return this;
3913
+ },
3914
+
3915
+ fireForParent: function(event, element){
3916
+ element = element.getParent();
3917
+ if (!element || element == document.body) return;
3918
+ if (element.retrieve('tip:enter')) element.fireEvent('mouseenter', event);
3919
+ else this.fireForParent(event, element);
3920
+ },
3921
+
3922
+ elementMove: function(event, element){
3923
+ this.position(event);
3924
+ },
3925
+
3926
+ position: function(event){
3927
+ if (!this.tip) document.id(this);
3928
+
3929
+ var size = window.getSize(), scroll = window.getScroll(),
3930
+ tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
3931
+ props = {x: 'left', y: 'top'},
3932
+ bounds = {y: false, x2: false, y2: false, x: false},
3933
+ obj = {};
3934
+
3935
+ for (var z in props){
3936
+ obj[props[z]] = event.page[z] + this.options.offset[z];
3937
+ if (obj[props[z]] < 0) bounds[z] = true;
3938
+ if ((obj[props[z]] + tip[z] - scroll[z]) > size[z] - this.options.windowPadding[z]){
3939
+ obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
3940
+ bounds[z+'2'] = true;
3941
+ }
3942
+ }
3943
+
3944
+ this.fireEvent('bound', bounds);
3945
+ this.tip.setStyles(obj);
3946
+ },
3947
+
3948
+ fill: function(element, contents){
3949
+ if (typeof contents == 'string') element.set('html', contents);
3950
+ else element.adopt(contents);
3951
+ },
3952
+
3953
+ show: function(element){
3954
+ if (!this.tip) document.id(this);
3955
+ if (!this.tip.getParent()) this.tip.inject(document.body);
3956
+ this.fireEvent('show', [this.tip, element]);
3957
+ },
3958
+
3959
+ hide: function(element){
3960
+ if (!this.tip) document.id(this);
3961
+ this.fireEvent('hide', [this.tip, element]);
3962
+ }
3963
+
3964
+ });
3965
+
3966
+ })();
3967
+
3968
+
3969
+ /*
3970
+ ---
3971
+
3972
+ script: Spinner.js
3973
+
3974
+ name: Spinner
3975
+
3976
+ description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon.
3977
+
3978
+ license: MIT-style license
3979
+
3980
+ authors:
3981
+ - Aaron Newton
3982
+
3983
+ requires:
3984
+ - Core/Fx.Tween
3985
+ - Core/Request
3986
+ - /Class.refactor
3987
+ - /Mask
3988
+
3989
+ provides: [Spinner]
3990
+
3991
+ ...
3992
+ */
3993
+
3994
+ var Spinner = new Class({
3995
+
3996
+ Extends: Mask,
3997
+
3998
+ Implements: Chain,
3999
+
4000
+ options: {/*
4001
+ message: false,*/
4002
+ 'class': 'spinner',
4003
+ containerPosition: {},
4004
+ content: {
4005
+ 'class': 'spinner-content'
4006
+ },
4007
+ messageContainer: {
4008
+ 'class': 'spinner-msg'
4009
+ },
4010
+ img: {
4011
+ 'class': 'spinner-img'
4012
+ },
4013
+ fxOptions: {
4014
+ link: 'chain'
4015
+ }
4016
+ },
4017
+
4018
+ initialize: function(target, options){
4019
+ this.target = document.id(target) || document.id(document.body);
4020
+ this.target.store('spinner', this);
4021
+ this.setOptions(options);
4022
+ this.render();
4023
+ this.inject();
4024
+
4025
+ // Add this to events for when noFx is true; parent methods handle hide/show.
4026
+ var deactivate = function(){ this.active = false; }.bind(this);
4027
+ this.addEvents({
4028
+ hide: deactivate,
4029
+ show: deactivate
4030
+ });
4031
+ },
4032
+
4033
+ render: function(){
4034
+ this.parent();
4035
+
4036
+ this.element.set('id', this.options.id || 'spinner-' + String.uniqueID());
4037
+
4038
+ this.content = document.id(this.options.content) || new Element('div', this.options.content);
4039
+ this.content.inject(this.element);
4040
+
4041
+ if (this.options.message){
4042
+ this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message);
4043
+ this.msg.inject(this.content);
4044
+ }
4045
+
4046
+ if (this.options.img){
4047
+ this.img = document.id(this.options.img) || new Element('div', this.options.img);
4048
+ this.img.inject(this.content);
4049
+ }
4050
+
4051
+ this.element.set('tween', this.options.fxOptions);
4052
+ },
4053
+
4054
+ show: function(noFx){
4055
+ if (this.active) return this.chain(this.show.bind(this));
4056
+ if (!this.hidden){
4057
+ this.callChain.delay(20, this);
4058
+ return this;
4059
+ }
4060
+
4061
+ this.active = true;
4062
+
4063
+ return this.parent(noFx);
4064
+ },
4065
+
4066
+ showMask: function(noFx){
4067
+ var pos = function(){
4068
+ this.content.position(Object.merge({
4069
+ relativeTo: this.element
4070
+ }, this.options.containerPosition));
4071
+ }.bind(this);
4072
+
4073
+ if (noFx){
4074
+ this.parent();
4075
+ pos();
4076
+ } else {
4077
+ if (!this.options.style.opacity) this.options.style.opacity = this.element.getStyle('opacity').toFloat();
4078
+ this.element.setStyles({
4079
+ display: 'block',
4080
+ opacity: 0
4081
+ }).tween('opacity', this.options.style.opacity);
4082
+ pos();
4083
+ this.hidden = false;
4084
+ this.fireEvent('show');
4085
+ this.callChain();
4086
+ }
4087
+ },
4088
+
4089
+ hide: function(noFx){
4090
+ if (this.active) return this.chain(this.hide.bind(this));
4091
+ if (this.hidden){
4092
+ this.callChain.delay(20, this);
4093
+ return this;
4094
+ }
4095
+ this.active = true;
4096
+ return this.parent(noFx);
4097
+ },
4098
+
4099
+ hideMask: function(noFx){
4100
+ if (noFx) return this.parent();
4101
+ this.element.tween('opacity', 0).get('tween').chain(function(){
4102
+ this.element.setStyle('display', 'none');
4103
+ this.hidden = true;
4104
+ this.fireEvent('hide');
4105
+ this.callChain();
4106
+ }.bind(this));
4107
+ },
4108
+
4109
+ destroy: function(){
4110
+ this.content.destroy();
4111
+ this.parent();
4112
+ this.target.eliminate('spinner');
4113
+ }
4114
+
4115
+ });
4116
+
4117
+ Request = Class.refactor(Request, {
4118
+
4119
+ options: {
4120
+ useSpinner: false,
4121
+ spinnerOptions: {},
4122
+ spinnerTarget: false
4123
+ },
4124
+
4125
+ initialize: function(options){
4126
+ this._send = this.send;
4127
+ this.send = function(options){
4128
+ var spinner = this.getSpinner();
4129
+ if (spinner) spinner.chain(this._send.pass(options, this)).show();
4130
+ else this._send(options);
4131
+ return this;
4132
+ };
4133
+ this.previous(options);
4134
+ },
4135
+
4136
+ getSpinner: function(){
4137
+ if (!this.spinner){
4138
+ var update = document.id(this.options.spinnerTarget) || document.id(this.options.update);
4139
+ if (this.options.useSpinner && update){
4140
+ update.set('spinner', this.options.spinnerOptions);
4141
+ var spinner = this.spinner = update.get('spinner');
4142
+ ['complete', 'exception', 'cancel'].each(function(event){
4143
+ this.addEvent(event, spinner.hide.bind(spinner));
4144
+ }, this);
4145
+ }
4146
+ }
4147
+ return this.spinner;
4148
+ }
4149
+
4150
+ });
4151
+
4152
+ Element.Properties.spinner = {
4153
+
4154
+ set: function(options){
4155
+ var spinner = this.retrieve('spinner');
4156
+ if (spinner) spinner.destroy();
4157
+ return this.eliminate('spinner').store('spinner:options', options);
4158
+ },
4159
+
4160
+ get: function(){
4161
+ var spinner = this.retrieve('spinner');
4162
+ if (!spinner){
4163
+ spinner = new Spinner(this, this.retrieve('spinner:options'));
4164
+ this.store('spinner', spinner);
4165
+ }
4166
+ return spinner;
4167
+ }
4168
+
4169
+ };
4170
+
4171
+ Element.implement({
4172
+
4173
+ spin: function(options){
4174
+ if (options) this.set('spinner', options);
4175
+ this.get('spinner').show();
4176
+ return this;
4177
+ },
4178
+
4179
+ unspin: function(){
4180
+ this.get('spinner').hide();
4181
+ return this;
4182
+ }
4183
+
4184
+ });
4185
+