bhf 0.7.7 → 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2561 @@
1
+ /*
2
+ ---
3
+ MooTools: the javascript framework
4
+
5
+ web build:
6
+ - http://mootools.net/more/335fff3ee615958016e5569b21c1d4cf
7
+
8
+ packager build:
9
+ - packager build More/Date More/String.Extras More/Sortables More/Assets More/IframeShim More/Locale More/Locale.en-US.Date More/Locale.de-DE.Date
10
+
11
+ ...
12
+ */
13
+
14
+ /*
15
+ ---
16
+
17
+ script: More.js
18
+
19
+ name: More
20
+
21
+ description: MooTools More
22
+
23
+ license: MIT-style license
24
+
25
+ authors:
26
+ - Guillermo Rauch
27
+ - Thomas Aylott
28
+ - Scott Kyle
29
+ - Arian Stolwijk
30
+ - Tim Wienk
31
+ - Christoph Pojer
32
+ - Aaron Newton
33
+ - Jacob Thornton
34
+
35
+ requires:
36
+ - Core/MooTools
37
+
38
+ provides: [MooTools.More]
39
+
40
+ ...
41
+ */
42
+
43
+ MooTools.More = {
44
+ version: '1.5.0',
45
+ build: '73db5e24e6e9c5c87b3a27aebef2248053f7db37'
46
+ };
47
+
48
+
49
+ /*
50
+ ---
51
+
52
+ script: Object.Extras.js
53
+
54
+ name: Object.Extras
55
+
56
+ description: Extra Object generics, like getFromPath which allows a path notation to child elements.
57
+
58
+ license: MIT-style license
59
+
60
+ authors:
61
+ - Aaron Newton
62
+
63
+ requires:
64
+ - Core/Object
65
+ - MooTools.More
66
+
67
+ provides: [Object.Extras]
68
+
69
+ ...
70
+ */
71
+
72
+ (function(){
73
+
74
+ var defined = function(value){
75
+ return value != null;
76
+ };
77
+
78
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
79
+
80
+ Object.extend({
81
+
82
+ getFromPath: function(source, parts){
83
+ if (typeof parts == 'string') parts = parts.split('.');
84
+ for (var i = 0, l = parts.length; i < l; i++){
85
+ if (hasOwnProperty.call(source, parts[i])) source = source[parts[i]];
86
+ else return null;
87
+ }
88
+ return source;
89
+ },
90
+
91
+ cleanValues: function(object, method){
92
+ method = method || defined;
93
+ for (var key in object) if (!method(object[key])){
94
+ delete object[key];
95
+ }
96
+ return object;
97
+ },
98
+
99
+ erase: function(object, key){
100
+ if (hasOwnProperty.call(object, key)) delete object[key];
101
+ return object;
102
+ },
103
+
104
+ run: function(object){
105
+ var args = Array.slice(arguments, 1);
106
+ for (var key in object) if (object[key].apply){
107
+ object[key].apply(object, args);
108
+ }
109
+ return object;
110
+ }
111
+
112
+ });
113
+
114
+ })();
115
+
116
+
117
+ /*
118
+ ---
119
+
120
+ script: Locale.js
121
+
122
+ name: Locale
123
+
124
+ description: Provides methods for localization.
125
+
126
+ license: MIT-style license
127
+
128
+ authors:
129
+ - Aaron Newton
130
+ - Arian Stolwijk
131
+
132
+ requires:
133
+ - Core/Events
134
+ - Object.Extras
135
+ - MooTools.More
136
+
137
+ provides: [Locale, Lang]
138
+
139
+ ...
140
+ */
141
+
142
+ (function(){
143
+
144
+ var current = null,
145
+ locales = {},
146
+ inherits = {};
147
+
148
+ var getSet = function(set){
149
+ if (instanceOf(set, Locale.Set)) return set;
150
+ else return locales[set];
151
+ };
152
+
153
+ var Locale = this.Locale = {
154
+
155
+ define: function(locale, set, key, value){
156
+ var name;
157
+ if (instanceOf(locale, Locale.Set)){
158
+ name = locale.name;
159
+ if (name) locales[name] = locale;
160
+ } else {
161
+ name = locale;
162
+ if (!locales[name]) locales[name] = new Locale.Set(name);
163
+ locale = locales[name];
164
+ }
165
+
166
+ if (set) locale.define(set, key, value);
167
+
168
+
169
+
170
+ if (!current) current = locale;
171
+
172
+ return locale;
173
+ },
174
+
175
+ use: function(locale){
176
+ locale = getSet(locale);
177
+
178
+ if (locale){
179
+ current = locale;
180
+
181
+ this.fireEvent('change', locale);
182
+
183
+
184
+ }
185
+
186
+ return this;
187
+ },
188
+
189
+ getCurrent: function(){
190
+ return current;
191
+ },
192
+
193
+ get: function(key, args){
194
+ return (current) ? current.get(key, args) : '';
195
+ },
196
+
197
+ inherit: function(locale, inherits, set){
198
+ locale = getSet(locale);
199
+
200
+ if (locale) locale.inherit(inherits, set);
201
+ return this;
202
+ },
203
+
204
+ list: function(){
205
+ return Object.keys(locales);
206
+ }
207
+
208
+ };
209
+
210
+ Object.append(Locale, new Events);
211
+
212
+ Locale.Set = new Class({
213
+
214
+ sets: {},
215
+
216
+ inherits: {
217
+ locales: [],
218
+ sets: {}
219
+ },
220
+
221
+ initialize: function(name){
222
+ this.name = name || '';
223
+ },
224
+
225
+ define: function(set, key, value){
226
+ var defineData = this.sets[set];
227
+ if (!defineData) defineData = {};
228
+
229
+ if (key){
230
+ if (typeOf(key) == 'object') defineData = Object.merge(defineData, key);
231
+ else defineData[key] = value;
232
+ }
233
+ this.sets[set] = defineData;
234
+
235
+ return this;
236
+ },
237
+
238
+ get: function(key, args, _base){
239
+ var value = Object.getFromPath(this.sets, key);
240
+ if (value != null){
241
+ var type = typeOf(value);
242
+ if (type == 'function') value = value.apply(null, Array.from(args));
243
+ else if (type == 'object') value = Object.clone(value);
244
+ return value;
245
+ }
246
+
247
+ // get value of inherited locales
248
+ var index = key.indexOf('.'),
249
+ set = index < 0 ? key : key.substr(0, index),
250
+ names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include('en-US');
251
+ if (!_base) _base = [];
252
+
253
+ for (var i = 0, l = names.length; i < l; i++){
254
+ if (_base.contains(names[i])) continue;
255
+ _base.include(names[i]);
256
+
257
+ var locale = locales[names[i]];
258
+ if (!locale) continue;
259
+
260
+ value = locale.get(key, args, _base);
261
+ if (value != null) return value;
262
+ }
263
+
264
+ return '';
265
+ },
266
+
267
+ inherit: function(names, set){
268
+ names = Array.from(names);
269
+
270
+ if (set && !this.inherits.sets[set]) this.inherits.sets[set] = [];
271
+
272
+ var l = names.length;
273
+ while (l--) (set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]);
274
+
275
+ return this;
276
+ }
277
+
278
+ });
279
+
280
+
281
+
282
+ })();
283
+
284
+
285
+ /*
286
+ ---
287
+
288
+ name: Locale.en-US.Date
289
+
290
+ description: Date messages for US English.
291
+
292
+ license: MIT-style license
293
+
294
+ authors:
295
+ - Aaron Newton
296
+
297
+ requires:
298
+ - Locale
299
+
300
+ provides: [Locale.en-US.Date]
301
+
302
+ ...
303
+ */
304
+
305
+ Locale.define('en-US', 'Date', {
306
+
307
+ months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
308
+ months_abbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
309
+ days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
310
+ days_abbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
311
+
312
+ // Culture's date order: MM/DD/YYYY
313
+ dateOrder: ['month', 'date', 'year'],
314
+ shortDate: '%m/%d/%Y',
315
+ shortTime: '%I:%M%p',
316
+ AM: 'AM',
317
+ PM: 'PM',
318
+ firstDayOfWeek: 0,
319
+
320
+ // Date.Extras
321
+ ordinal: function(dayOfMonth){
322
+ // 1st, 2nd, 3rd, etc.
323
+ return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
324
+ },
325
+
326
+ lessThanMinuteAgo: 'less than a minute ago',
327
+ minuteAgo: 'about a minute ago',
328
+ minutesAgo: '{delta} minutes ago',
329
+ hourAgo: 'about an hour ago',
330
+ hoursAgo: 'about {delta} hours ago',
331
+ dayAgo: '1 day ago',
332
+ daysAgo: '{delta} days ago',
333
+ weekAgo: '1 week ago',
334
+ weeksAgo: '{delta} weeks ago',
335
+ monthAgo: '1 month ago',
336
+ monthsAgo: '{delta} months ago',
337
+ yearAgo: '1 year ago',
338
+ yearsAgo: '{delta} years ago',
339
+
340
+ lessThanMinuteUntil: 'less than a minute from now',
341
+ minuteUntil: 'about a minute from now',
342
+ minutesUntil: '{delta} minutes from now',
343
+ hourUntil: 'about an hour from now',
344
+ hoursUntil: 'about {delta} hours from now',
345
+ dayUntil: '1 day from now',
346
+ daysUntil: '{delta} days from now',
347
+ weekUntil: '1 week from now',
348
+ weeksUntil: '{delta} weeks from now',
349
+ monthUntil: '1 month from now',
350
+ monthsUntil: '{delta} months from now',
351
+ yearUntil: '1 year from now',
352
+ yearsUntil: '{delta} years from now'
353
+
354
+ });
355
+
356
+
357
+ /*
358
+ ---
359
+
360
+ script: Date.js
361
+
362
+ name: Date
363
+
364
+ description: Extends the Date native object to include methods useful in managing dates.
365
+
366
+ license: MIT-style license
367
+
368
+ authors:
369
+ - Aaron Newton
370
+ - Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/
371
+ - Harald Kirshner - mail [at] digitarald.de; http://digitarald.de
372
+ - Scott Kyle - scott [at] appden.com; http://appden.com
373
+
374
+ requires:
375
+ - Core/Array
376
+ - Core/String
377
+ - Core/Number
378
+ - MooTools.More
379
+ - Locale
380
+ - Locale.en-US.Date
381
+
382
+ provides: [Date]
383
+
384
+ ...
385
+ */
386
+
387
+ (function(){
388
+
389
+ var Date = this.Date;
390
+
391
+ var DateMethods = Date.Methods = {
392
+ ms: 'Milliseconds',
393
+ year: 'FullYear',
394
+ min: 'Minutes',
395
+ mo: 'Month',
396
+ sec: 'Seconds',
397
+ hr: 'Hours'
398
+ };
399
+
400
+ ['Date', 'Day', 'FullYear', 'Hours', 'Milliseconds', 'Minutes', 'Month', 'Seconds', 'Time', 'TimezoneOffset',
401
+ 'Week', 'Timezone', 'GMTOffset', 'DayOfYear', 'LastMonth', 'LastDayOfMonth', 'UTCDate', 'UTCDay', 'UTCFullYear',
402
+ 'AMPM', 'Ordinal', 'UTCHours', 'UTCMilliseconds', 'UTCMinutes', 'UTCMonth', 'UTCSeconds', 'UTCMilliseconds'].each(function(method){
403
+ Date.Methods[method.toLowerCase()] = method;
404
+ });
405
+
406
+ var pad = function(n, digits, string){
407
+ if (digits == 1) return n;
408
+ return n < Math.pow(10, digits - 1) ? (string || '0') + pad(n, digits - 1, string) : n;
409
+ };
410
+
411
+ Date.implement({
412
+
413
+ set: function(prop, value){
414
+ prop = prop.toLowerCase();
415
+ var method = DateMethods[prop] && 'set' + DateMethods[prop];
416
+ if (method && this[method]) this[method](value);
417
+ return this;
418
+ }.overloadSetter(),
419
+
420
+ get: function(prop){
421
+ prop = prop.toLowerCase();
422
+ var method = DateMethods[prop] && 'get' + DateMethods[prop];
423
+ if (method && this[method]) return this[method]();
424
+ return null;
425
+ }.overloadGetter(),
426
+
427
+ clone: function(){
428
+ return new Date(this.get('time'));
429
+ },
430
+
431
+ increment: function(interval, times){
432
+ interval = interval || 'day';
433
+ times = times != null ? times : 1;
434
+
435
+ switch (interval){
436
+ case 'year':
437
+ return this.increment('month', times * 12);
438
+ case 'month':
439
+ var d = this.get('date');
440
+ this.set('date', 1).set('mo', this.get('mo') + times);
441
+ return this.set('date', d.min(this.get('lastdayofmonth')));
442
+ case 'week':
443
+ return this.increment('day', times * 7);
444
+ case 'day':
445
+ return this.set('date', this.get('date') + times);
446
+ }
447
+
448
+ if (!Date.units[interval]) throw new Error(interval + ' is not a supported interval');
449
+
450
+ return this.set('time', this.get('time') + times * Date.units[interval]());
451
+ },
452
+
453
+ decrement: function(interval, times){
454
+ return this.increment(interval, -1 * (times != null ? times : 1));
455
+ },
456
+
457
+ isLeapYear: function(){
458
+ return Date.isLeapYear(this.get('year'));
459
+ },
460
+
461
+ clearTime: function(){
462
+ return this.set({hr: 0, min: 0, sec: 0, ms: 0});
463
+ },
464
+
465
+ diff: function(date, resolution){
466
+ if (typeOf(date) == 'string') date = Date.parse(date);
467
+
468
+ return ((date - this) / Date.units[resolution || 'day'](3, 3)).round(); // non-leap year, 30-day month
469
+ },
470
+
471
+ getLastDayOfMonth: function(){
472
+ return Date.daysInMonth(this.get('mo'), this.get('year'));
473
+ },
474
+
475
+ getDayOfYear: function(){
476
+ return (Date.UTC(this.get('year'), this.get('mo'), this.get('date') + 1)
477
+ - Date.UTC(this.get('year'), 0, 1)) / Date.units.day();
478
+ },
479
+
480
+ setDay: function(day, firstDayOfWeek){
481
+ if (firstDayOfWeek == null){
482
+ firstDayOfWeek = Date.getMsg('firstDayOfWeek');
483
+ if (firstDayOfWeek === '') firstDayOfWeek = 1;
484
+ }
485
+
486
+ day = (7 + Date.parseDay(day, true) - firstDayOfWeek) % 7;
487
+ var currentDay = (7 + this.get('day') - firstDayOfWeek) % 7;
488
+
489
+ return this.increment('day', day - currentDay);
490
+ },
491
+
492
+ getWeek: function(firstDayOfWeek){
493
+ if (firstDayOfWeek == null){
494
+ firstDayOfWeek = Date.getMsg('firstDayOfWeek');
495
+ if (firstDayOfWeek === '') firstDayOfWeek = 1;
496
+ }
497
+
498
+ var date = this,
499
+ dayOfWeek = (7 + date.get('day') - firstDayOfWeek) % 7,
500
+ dividend = 0,
501
+ firstDayOfYear;
502
+
503
+ if (firstDayOfWeek == 1){
504
+ // ISO-8601, week belongs to year that has the most days of the week (i.e. has the thursday of the week)
505
+ var month = date.get('month'),
506
+ startOfWeek = date.get('date') - dayOfWeek;
507
+
508
+ if (month == 11 && startOfWeek > 28) return 1; // Week 1 of next year
509
+
510
+ if (month == 0 && startOfWeek < -2){
511
+ // Use a date from last year to determine the week
512
+ date = new Date(date).decrement('day', dayOfWeek);
513
+ dayOfWeek = 0;
514
+ }
515
+
516
+ firstDayOfYear = new Date(date.get('year'), 0, 1).get('day') || 7;
517
+ if (firstDayOfYear > 4) dividend = -7; // First week of the year is not week 1
518
+ } else {
519
+ // In other cultures the first week of the year is always week 1 and the last week always 53 or 54.
520
+ // Days in the same week can have a different weeknumber if the week spreads across two years.
521
+ firstDayOfYear = new Date(date.get('year'), 0, 1).get('day');
522
+ }
523
+
524
+ dividend += date.get('dayofyear');
525
+ dividend += 6 - dayOfWeek; // Add days so we calculate the current date's week as a full week
526
+ dividend += (7 + firstDayOfYear - firstDayOfWeek) % 7; // Make up for first week of the year not being a full week
527
+
528
+ return (dividend / 7);
529
+ },
530
+
531
+ getOrdinal: function(day){
532
+ return Date.getMsg('ordinal', day || this.get('date'));
533
+ },
534
+
535
+ getTimezone: function(){
536
+ return this.toString()
537
+ .replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/, '$1')
538
+ .replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, '$1$2$3');
539
+ },
540
+
541
+ getGMTOffset: function(){
542
+ var off = this.get('timezoneOffset');
543
+ return ((off > 0) ? '-' : '+') + pad((off.abs() / 60).floor(), 2) + pad(off % 60, 2);
544
+ },
545
+
546
+ setAMPM: function(ampm){
547
+ ampm = ampm.toUpperCase();
548
+ var hr = this.get('hr');
549
+ if (hr > 11 && ampm == 'AM') return this.decrement('hour', 12);
550
+ else if (hr < 12 && ampm == 'PM') return this.increment('hour', 12);
551
+ return this;
552
+ },
553
+
554
+ getAMPM: function(){
555
+ return (this.get('hr') < 12) ? 'AM' : 'PM';
556
+ },
557
+
558
+ parse: function(str){
559
+ this.set('time', Date.parse(str));
560
+ return this;
561
+ },
562
+
563
+ isValid: function(date){
564
+ if (!date) date = this;
565
+ return typeOf(date) == 'date' && !isNaN(date.valueOf());
566
+ },
567
+
568
+ format: function(format){
569
+ if (!this.isValid()) return 'invalid date';
570
+
571
+ if (!format) format = '%x %X';
572
+ if (typeof format == 'string') format = formats[format.toLowerCase()] || format;
573
+ if (typeof format == 'function') return format(this);
574
+
575
+ var d = this;
576
+ return format.replace(/%([a-z%])/gi,
577
+ function($0, $1){
578
+ switch ($1){
579
+ case 'a': return Date.getMsg('days_abbr')[d.get('day')];
580
+ case 'A': return Date.getMsg('days')[d.get('day')];
581
+ case 'b': return Date.getMsg('months_abbr')[d.get('month')];
582
+ case 'B': return Date.getMsg('months')[d.get('month')];
583
+ case 'c': return d.format('%a %b %d %H:%M:%S %Y');
584
+ case 'd': return pad(d.get('date'), 2);
585
+ case 'e': return pad(d.get('date'), 2, ' ');
586
+ case 'H': return pad(d.get('hr'), 2);
587
+ case 'I': return pad((d.get('hr') % 12) || 12, 2);
588
+ case 'j': return pad(d.get('dayofyear'), 3);
589
+ case 'k': return pad(d.get('hr'), 2, ' ');
590
+ case 'l': return pad((d.get('hr') % 12) || 12, 2, ' ');
591
+ case 'L': return pad(d.get('ms'), 3);
592
+ case 'm': return pad((d.get('mo') + 1), 2);
593
+ case 'M': return pad(d.get('min'), 2);
594
+ case 'o': return d.get('ordinal');
595
+ case 'p': return Date.getMsg(d.get('ampm'));
596
+ case 's': return Math.round(d / 1000);
597
+ case 'S': return pad(d.get('seconds'), 2);
598
+ case 'T': return d.format('%H:%M:%S');
599
+ case 'U': return pad(d.get('week'), 2);
600
+ case 'w': return d.get('day');
601
+ case 'x': return d.format(Date.getMsg('shortDate'));
602
+ case 'X': return d.format(Date.getMsg('shortTime'));
603
+ case 'y': return d.get('year').toString().substr(2);
604
+ case 'Y': return d.get('year');
605
+ case 'z': return d.get('GMTOffset');
606
+ case 'Z': return d.get('Timezone');
607
+ }
608
+ return $1;
609
+ }
610
+ );
611
+ },
612
+
613
+ toISOString: function(){
614
+ return this.format('iso8601');
615
+ }
616
+
617
+ }).alias({
618
+ toJSON: 'toISOString',
619
+ compare: 'diff',
620
+ strftime: 'format'
621
+ });
622
+
623
+ // The day and month abbreviations are standardized, so we cannot use simply %a and %b because they will get localized
624
+ var rfcDayAbbr = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
625
+ rfcMonthAbbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
626
+
627
+ var formats = {
628
+ db: '%Y-%m-%d %H:%M:%S',
629
+ compact: '%Y%m%dT%H%M%S',
630
+ 'short': '%d %b %H:%M',
631
+ 'long': '%B %d, %Y %H:%M',
632
+ rfc822: function(date){
633
+ return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %Z');
634
+ },
635
+ rfc2822: function(date){
636
+ return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %z');
637
+ },
638
+ iso8601: function(date){
639
+ return (
640
+ date.getUTCFullYear() + '-' +
641
+ pad(date.getUTCMonth() + 1, 2) + '-' +
642
+ pad(date.getUTCDate(), 2) + 'T' +
643
+ pad(date.getUTCHours(), 2) + ':' +
644
+ pad(date.getUTCMinutes(), 2) + ':' +
645
+ pad(date.getUTCSeconds(), 2) + '.' +
646
+ pad(date.getUTCMilliseconds(), 3) + 'Z'
647
+ );
648
+ }
649
+ };
650
+
651
+ var parsePatterns = [],
652
+ nativeParse = Date.parse;
653
+
654
+ var parseWord = function(type, word, num){
655
+ var ret = -1,
656
+ translated = Date.getMsg(type + 's');
657
+ switch (typeOf(word)){
658
+ case 'object':
659
+ ret = translated[word.get(type)];
660
+ break;
661
+ case 'number':
662
+ ret = translated[word];
663
+ if (!ret) throw new Error('Invalid ' + type + ' index: ' + word);
664
+ break;
665
+ case 'string':
666
+ var match = translated.filter(function(name){
667
+ return this.test(name);
668
+ }, new RegExp('^' + word, 'i'));
669
+ if (!match.length) throw new Error('Invalid ' + type + ' string');
670
+ if (match.length > 1) throw new Error('Ambiguous ' + type);
671
+ ret = match[0];
672
+ }
673
+
674
+ return (num) ? translated.indexOf(ret) : ret;
675
+ };
676
+
677
+ var startCentury = 1900,
678
+ startYear = 70;
679
+
680
+ Date.extend({
681
+
682
+ getMsg: function(key, args){
683
+ return Locale.get('Date.' + key, args);
684
+ },
685
+
686
+ units: {
687
+ ms: Function.from(1),
688
+ second: Function.from(1000),
689
+ minute: Function.from(60000),
690
+ hour: Function.from(3600000),
691
+ day: Function.from(86400000),
692
+ week: Function.from(608400000),
693
+ month: function(month, year){
694
+ var d = new Date;
695
+ return Date.daysInMonth(month != null ? month : d.get('mo'), year != null ? year : d.get('year')) * 86400000;
696
+ },
697
+ year: function(year){
698
+ year = year || new Date().get('year');
699
+ return Date.isLeapYear(year) ? 31622400000 : 31536000000;
700
+ }
701
+ },
702
+
703
+ daysInMonth: function(month, year){
704
+ return [31, Date.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
705
+ },
706
+
707
+ isLeapYear: function(year){
708
+ return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
709
+ },
710
+
711
+ parse: function(from){
712
+ var t = typeOf(from);
713
+ if (t == 'number') return new Date(from);
714
+ if (t != 'string') return from;
715
+ from = from.clean();
716
+ if (!from.length) return null;
717
+
718
+ var parsed;
719
+ parsePatterns.some(function(pattern){
720
+ var bits = pattern.re.exec(from);
721
+ return (bits) ? (parsed = pattern.handler(bits)) : false;
722
+ });
723
+
724
+ if (!(parsed && parsed.isValid())){
725
+ parsed = new Date(nativeParse(from));
726
+ if (!(parsed && parsed.isValid())) parsed = new Date(from.toInt());
727
+ }
728
+ return parsed;
729
+ },
730
+
731
+ parseDay: function(day, num){
732
+ return parseWord('day', day, num);
733
+ },
734
+
735
+ parseMonth: function(month, num){
736
+ return parseWord('month', month, num);
737
+ },
738
+
739
+ parseUTC: function(value){
740
+ var localDate = new Date(value);
741
+ var utcSeconds = Date.UTC(
742
+ localDate.get('year'),
743
+ localDate.get('mo'),
744
+ localDate.get('date'),
745
+ localDate.get('hr'),
746
+ localDate.get('min'),
747
+ localDate.get('sec'),
748
+ localDate.get('ms')
749
+ );
750
+ return new Date(utcSeconds);
751
+ },
752
+
753
+ orderIndex: function(unit){
754
+ return Date.getMsg('dateOrder').indexOf(unit) + 1;
755
+ },
756
+
757
+ defineFormat: function(name, format){
758
+ formats[name] = format;
759
+ return this;
760
+ },
761
+
762
+
763
+
764
+ defineParser: function(pattern){
765
+ parsePatterns.push((pattern.re && pattern.handler) ? pattern : build(pattern));
766
+ return this;
767
+ },
768
+
769
+ defineParsers: function(){
770
+ Array.flatten(arguments).each(Date.defineParser);
771
+ return this;
772
+ },
773
+
774
+ define2DigitYearStart: function(year){
775
+ startYear = year % 100;
776
+ startCentury = year - startYear;
777
+ return this;
778
+ }
779
+
780
+ }).extend({
781
+ defineFormats: Date.defineFormat.overloadSetter()
782
+ });
783
+
784
+ var regexOf = function(type){
785
+ return new RegExp('(?:' + Date.getMsg(type).map(function(name){
786
+ return name.substr(0, 3);
787
+ }).join('|') + ')[a-z]*');
788
+ };
789
+
790
+ var replacers = function(key){
791
+ switch (key){
792
+ case 'T':
793
+ return '%H:%M:%S';
794
+ case 'x': // iso8601 covers yyyy-mm-dd, so just check if month is first
795
+ return ((Date.orderIndex('month') == 1) ? '%m[-./]%d' : '%d[-./]%m') + '([-./]%y)?';
796
+ case 'X':
797
+ return '%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%z?';
798
+ }
799
+ return null;
800
+ };
801
+
802
+ var keys = {
803
+ d: /[0-2]?[0-9]|3[01]/,
804
+ H: /[01]?[0-9]|2[0-3]/,
805
+ I: /0?[1-9]|1[0-2]/,
806
+ M: /[0-5]?\d/,
807
+ s: /\d+/,
808
+ o: /[a-z]*/,
809
+ p: /[ap]\.?m\.?/,
810
+ y: /\d{2}|\d{4}/,
811
+ Y: /\d{4}/,
812
+ z: /Z|[+-]\d{2}(?::?\d{2})?/
813
+ };
814
+
815
+ keys.m = keys.I;
816
+ keys.S = keys.M;
817
+
818
+ var currentLanguage;
819
+
820
+ var recompile = function(language){
821
+ currentLanguage = language;
822
+
823
+ keys.a = keys.A = regexOf('days');
824
+ keys.b = keys.B = regexOf('months');
825
+
826
+ parsePatterns.each(function(pattern, i){
827
+ if (pattern.format) parsePatterns[i] = build(pattern.format);
828
+ });
829
+ };
830
+
831
+ var build = function(format){
832
+ if (!currentLanguage) return {format: format};
833
+
834
+ var parsed = [];
835
+ var re = (format.source || format) // allow format to be regex
836
+ .replace(/%([a-z])/gi,
837
+ function($0, $1){
838
+ return replacers($1) || $0;
839
+ }
840
+ ).replace(/\((?!\?)/g, '(?:') // make all groups non-capturing
841
+ .replace(/ (?!\?|\*)/g, ',? ') // be forgiving with spaces and commas
842
+ .replace(/%([a-z%])/gi,
843
+ function($0, $1){
844
+ var p = keys[$1];
845
+ if (!p) return $1;
846
+ parsed.push($1);
847
+ return '(' + p.source + ')';
848
+ }
849
+ ).replace(/\[a-z\]/gi, '[a-z\\u00c0-\\uffff;\&]'); // handle unicode words
850
+
851
+ return {
852
+ format: format,
853
+ re: new RegExp('^' + re + '$', 'i'),
854
+ handler: function(bits){
855
+ bits = bits.slice(1).associate(parsed);
856
+ var date = new Date().clearTime(),
857
+ year = bits.y || bits.Y;
858
+
859
+ if (year != null) handle.call(date, 'y', year); // need to start in the right year
860
+ if ('d' in bits) handle.call(date, 'd', 1);
861
+ if ('m' in bits || bits.b || bits.B) handle.call(date, 'm', 1);
862
+
863
+ for (var key in bits) handle.call(date, key, bits[key]);
864
+ return date;
865
+ }
866
+ };
867
+ };
868
+
869
+ var handle = function(key, value){
870
+ if (!value) return this;
871
+
872
+ switch (key){
873
+ case 'a': case 'A': return this.set('day', Date.parseDay(value, true));
874
+ case 'b': case 'B': return this.set('mo', Date.parseMonth(value, true));
875
+ case 'd': return this.set('date', value);
876
+ case 'H': case 'I': return this.set('hr', value);
877
+ case 'm': return this.set('mo', value - 1);
878
+ case 'M': return this.set('min', value);
879
+ case 'p': return this.set('ampm', value.replace(/\./g, ''));
880
+ case 'S': return this.set('sec', value);
881
+ case 's': return this.set('ms', ('0.' + value) * 1000);
882
+ case 'w': return this.set('day', value);
883
+ case 'Y': return this.set('year', value);
884
+ case 'y':
885
+ value = +value;
886
+ if (value < 100) value += startCentury + (value < startYear ? 100 : 0);
887
+ return this.set('year', value);
888
+ case 'z':
889
+ if (value == 'Z') value = '+00';
890
+ var offset = value.match(/([+-])(\d{2}):?(\d{2})?/);
891
+ offset = (offset[1] + '1') * (offset[2] * 60 + (+offset[3] || 0)) + this.getTimezoneOffset();
892
+ return this.set('time', this - offset * 60000);
893
+ }
894
+
895
+ return this;
896
+ };
897
+
898
+ Date.defineParsers(
899
+ '%Y([-./]%m([-./]%d((T| )%X)?)?)?', // "1999-12-31", "1999-12-31 11:59pm", "1999-12-31 23:59:59", ISO8601
900
+ '%Y%m%d(T%H(%M%S?)?)?', // "19991231", "19991231T1159", compact
901
+ '%x( %X)?', // "12/31", "12.31.99", "12-31-1999", "12/31/2008 11:59 PM"
902
+ '%d%o( %b( %Y)?)?( %X)?', // "31st", "31st December", "31 Dec 1999", "31 Dec 1999 11:59pm"
903
+ '%b( %d%o)?( %Y)?( %X)?', // Same as above with month and day switched
904
+ '%Y %b( %d%o( %X)?)?', // Same as above with year coming first
905
+ '%o %b %d %X %z %Y', // "Thu Oct 22 08:11:23 +0000 2009"
906
+ '%T', // %H:%M:%S
907
+ '%H:%M( ?%p)?' // "11:05pm", "11:05 am" and "11:05"
908
+ );
909
+
910
+ Locale.addEvent('change', function(language){
911
+ if (Locale.get('Date')) recompile(language);
912
+ }).fireEvent('change', Locale.getCurrent());
913
+
914
+ })();
915
+
916
+
917
+ /*
918
+ ---
919
+
920
+ script: String.Extras.js
921
+
922
+ name: String.Extras
923
+
924
+ description: Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc).
925
+
926
+ license: MIT-style license
927
+
928
+ authors:
929
+ - Aaron Newton
930
+ - Guillermo Rauch
931
+ - Christopher Pitt
932
+
933
+ requires:
934
+ - Core/String
935
+ - Core/Array
936
+ - MooTools.More
937
+
938
+ provides: [String.Extras]
939
+
940
+ ...
941
+ */
942
+
943
+ (function(){
944
+
945
+ var special = {
946
+ 'a': /[àáâãäåăą]/g,
947
+ 'A': /[ÀÁÂÃÄÅĂĄ]/g,
948
+ 'c': /[ćčç]/g,
949
+ 'C': /[ĆČÇ]/g,
950
+ 'd': /[ďđ]/g,
951
+ 'D': /[ĎÐ]/g,
952
+ 'e': /[èéêëěę]/g,
953
+ 'E': /[ÈÉÊËĚĘ]/g,
954
+ 'g': /[ğ]/g,
955
+ 'G': /[Ğ]/g,
956
+ 'i': /[ìíîï]/g,
957
+ 'I': /[ÌÍÎÏ]/g,
958
+ 'l': /[ĺľł]/g,
959
+ 'L': /[ĹĽŁ]/g,
960
+ 'n': /[ñňń]/g,
961
+ 'N': /[ÑŇŃ]/g,
962
+ 'o': /[òóôõöøő]/g,
963
+ 'O': /[ÒÓÔÕÖØ]/g,
964
+ 'r': /[řŕ]/g,
965
+ 'R': /[ŘŔ]/g,
966
+ 's': /[ššş]/g,
967
+ 'S': /[ŠŞŚ]/g,
968
+ 't': /[ťţ]/g,
969
+ 'T': /[ŤŢ]/g,
970
+ 'u': /[ùúûůüµ]/g,
971
+ 'U': /[ÙÚÛŮÜ]/g,
972
+ 'y': /[ÿý]/g,
973
+ 'Y': /[ŸÝ]/g,
974
+ 'z': /[žźż]/g,
975
+ 'Z': /[ŽŹŻ]/g,
976
+ 'th': /[þ]/g,
977
+ 'TH': /[Þ]/g,
978
+ 'dh': /[ð]/g,
979
+ 'DH': /[Ð]/g,
980
+ 'ss': /[ß]/g,
981
+ 'oe': /[œ]/g,
982
+ 'OE': /[Œ]/g,
983
+ 'ae': /[æ]/g,
984
+ 'AE': /[Æ]/g
985
+ },
986
+
987
+ tidy = {
988
+ ' ': /[\xa0\u2002\u2003\u2009]/g,
989
+ '*': /[\xb7]/g,
990
+ '\'': /[\u2018\u2019]/g,
991
+ '"': /[\u201c\u201d]/g,
992
+ '...': /[\u2026]/g,
993
+ '-': /[\u2013]/g,
994
+ // '--': /[\u2014]/g,
995
+ '&raquo;': /[\uFFFD]/g
996
+ },
997
+
998
+ conversions = {
999
+ ms: 1,
1000
+ s: 1000,
1001
+ m: 6e4,
1002
+ h: 36e5
1003
+ },
1004
+
1005
+ findUnits = /(\d*.?\d+)([msh]+)/;
1006
+
1007
+ var walk = function(string, replacements){
1008
+ var result = string, key;
1009
+ for (key in replacements) result = result.replace(replacements[key], key);
1010
+ return result;
1011
+ };
1012
+
1013
+ var getRegexForTag = function(tag, contents){
1014
+ tag = tag || '';
1015
+ var regstr = contents ? "<" + tag + "(?!\\w)[^>]*>([\\s\\S]*?)<\/" + tag + "(?!\\w)>" : "<\/?" + tag + "([^>]+)?>",
1016
+ reg = new RegExp(regstr, "gi");
1017
+ return reg;
1018
+ };
1019
+
1020
+ String.implement({
1021
+
1022
+ standardize: function(){
1023
+ return walk(this, special);
1024
+ },
1025
+
1026
+ repeat: function(times){
1027
+ return new Array(times + 1).join(this);
1028
+ },
1029
+
1030
+ pad: function(length, str, direction){
1031
+ if (this.length >= length) return this;
1032
+
1033
+ var pad = (str == null ? ' ' : '' + str)
1034
+ .repeat(length - this.length)
1035
+ .substr(0, length - this.length);
1036
+
1037
+ if (!direction || direction == 'right') return this + pad;
1038
+ if (direction == 'left') return pad + this;
1039
+
1040
+ return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil());
1041
+ },
1042
+
1043
+ getTags: function(tag, contents){
1044
+ return this.match(getRegexForTag(tag, contents)) || [];
1045
+ },
1046
+
1047
+ stripTags: function(tag, contents){
1048
+ return this.replace(getRegexForTag(tag, contents), '');
1049
+ },
1050
+
1051
+ tidy: function(){
1052
+ return walk(this, tidy);
1053
+ },
1054
+
1055
+ truncate: function(max, trail, atChar){
1056
+ var string = this;
1057
+ if (trail == null && arguments.length == 1) trail = '…';
1058
+ if (string.length > max){
1059
+ string = string.substring(0, max);
1060
+ if (atChar){
1061
+ var index = string.lastIndexOf(atChar);
1062
+ if (index != -1) string = string.substr(0, index);
1063
+ }
1064
+ if (trail) string += trail;
1065
+ }
1066
+ return string;
1067
+ },
1068
+
1069
+ ms: function(){
1070
+ // "Borrowed" from https://gist.github.com/1503944
1071
+ var units = findUnits.exec(this);
1072
+ if (units == null) return Number(this);
1073
+ return Number(units[1]) * conversions[units[2]];
1074
+ }
1075
+
1076
+ });
1077
+
1078
+ })();
1079
+
1080
+
1081
+ /*
1082
+ ---
1083
+
1084
+ script: Drag.js
1085
+
1086
+ name: Drag
1087
+
1088
+ description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
1089
+
1090
+ license: MIT-style license
1091
+
1092
+ authors:
1093
+ - Valerio Proietti
1094
+ - Tom Occhinno
1095
+ - Jan Kassens
1096
+
1097
+ requires:
1098
+ - Core/Events
1099
+ - Core/Options
1100
+ - Core/Element.Event
1101
+ - Core/Element.Style
1102
+ - Core/Element.Dimensions
1103
+ - MooTools.More
1104
+
1105
+ provides: [Drag]
1106
+ ...
1107
+
1108
+ */
1109
+
1110
+ var Drag = new Class({
1111
+
1112
+ Implements: [Events, Options],
1113
+
1114
+ options: {/*
1115
+ onBeforeStart: function(thisElement){},
1116
+ onStart: function(thisElement, event){},
1117
+ onSnap: function(thisElement){},
1118
+ onDrag: function(thisElement, event){},
1119
+ onCancel: function(thisElement){},
1120
+ onComplete: function(thisElement, event){},*/
1121
+ snap: 6,
1122
+ unit: 'px',
1123
+ grid: false,
1124
+ style: true,
1125
+ limit: false,
1126
+ handle: false,
1127
+ invert: false,
1128
+ preventDefault: false,
1129
+ stopPropagation: false,
1130
+ modifiers: {x: 'left', y: 'top'}
1131
+ },
1132
+
1133
+ initialize: function(){
1134
+ var params = Array.link(arguments, {
1135
+ 'options': Type.isObject,
1136
+ 'element': function(obj){
1137
+ return obj != null;
1138
+ }
1139
+ });
1140
+
1141
+ this.element = document.id(params.element);
1142
+ this.document = this.element.getDocument();
1143
+ this.setOptions(params.options || {});
1144
+ var htype = typeOf(this.options.handle);
1145
+ this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
1146
+ this.mouse = {'now': {}, 'pos': {}};
1147
+ this.value = {'start': {}, 'now': {}};
1148
+
1149
+ this.selection = 'selectstart' in document ? 'selectstart' : 'mousedown';
1150
+
1151
+
1152
+ if ('ondragstart' in document && !('FileReader' in window) && !Drag.ondragstartFixed){
1153
+ document.ondragstart = Function.from(false);
1154
+ Drag.ondragstartFixed = true;
1155
+ }
1156
+
1157
+ this.bound = {
1158
+ start: this.start.bind(this),
1159
+ check: this.check.bind(this),
1160
+ drag: this.drag.bind(this),
1161
+ stop: this.stop.bind(this),
1162
+ cancel: this.cancel.bind(this),
1163
+ eventStop: Function.from(false)
1164
+ };
1165
+ this.attach();
1166
+ },
1167
+
1168
+ attach: function(){
1169
+ this.handles.addEvent('mousedown', this.bound.start);
1170
+ return this;
1171
+ },
1172
+
1173
+ detach: function(){
1174
+ this.handles.removeEvent('mousedown', this.bound.start);
1175
+ return this;
1176
+ },
1177
+
1178
+ start: function(event){
1179
+ var options = this.options;
1180
+
1181
+ if (event.rightClick) return;
1182
+
1183
+ if (options.preventDefault) event.preventDefault();
1184
+ if (options.stopPropagation) event.stopPropagation();
1185
+ this.mouse.start = event.page;
1186
+
1187
+ this.fireEvent('beforeStart', this.element);
1188
+
1189
+ var limit = options.limit;
1190
+ this.limit = {x: [], y: []};
1191
+
1192
+ var z, coordinates;
1193
+ for (z in options.modifiers){
1194
+ if (!options.modifiers[z]) continue;
1195
+
1196
+ var style = this.element.getStyle(options.modifiers[z]);
1197
+
1198
+ // Some browsers (IE and Opera) don't always return pixels.
1199
+ if (style && !style.match(/px$/)){
1200
+ if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent());
1201
+ style = coordinates[options.modifiers[z]];
1202
+ }
1203
+
1204
+ if (options.style) this.value.now[z] = (style || 0).toInt();
1205
+ else this.value.now[z] = this.element[options.modifiers[z]];
1206
+
1207
+ if (options.invert) this.value.now[z] *= -1;
1208
+
1209
+ this.mouse.pos[z] = event.page[z] - this.value.now[z];
1210
+
1211
+ if (limit && limit[z]){
1212
+ var i = 2;
1213
+ while (i--){
1214
+ var limitZI = limit[z][i];
1215
+ if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI;
1216
+ }
1217
+ }
1218
+ }
1219
+
1220
+ if (typeOf(this.options.grid) == 'number') this.options.grid = {
1221
+ x: this.options.grid,
1222
+ y: this.options.grid
1223
+ };
1224
+
1225
+ var events = {
1226
+ mousemove: this.bound.check,
1227
+ mouseup: this.bound.cancel
1228
+ };
1229
+ events[this.selection] = this.bound.eventStop;
1230
+ this.document.addEvents(events);
1231
+ },
1232
+
1233
+ check: function(event){
1234
+ if (this.options.preventDefault) event.preventDefault();
1235
+ 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)));
1236
+ if (distance > this.options.snap){
1237
+ this.cancel();
1238
+ this.document.addEvents({
1239
+ mousemove: this.bound.drag,
1240
+ mouseup: this.bound.stop
1241
+ });
1242
+ this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
1243
+ }
1244
+ },
1245
+
1246
+ drag: function(event){
1247
+ var options = this.options;
1248
+
1249
+ if (options.preventDefault) event.preventDefault();
1250
+ this.mouse.now = event.page;
1251
+
1252
+ for (var z in options.modifiers){
1253
+ if (!options.modifiers[z]) continue;
1254
+ this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
1255
+
1256
+ if (options.invert) this.value.now[z] *= -1;
1257
+
1258
+ if (options.limit && this.limit[z]){
1259
+ if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){
1260
+ this.value.now[z] = this.limit[z][1];
1261
+ } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){
1262
+ this.value.now[z] = this.limit[z][0];
1263
+ }
1264
+ }
1265
+
1266
+ if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]);
1267
+
1268
+ if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit);
1269
+ else this.element[options.modifiers[z]] = this.value.now[z];
1270
+ }
1271
+
1272
+ this.fireEvent('drag', [this.element, event]);
1273
+ },
1274
+
1275
+ cancel: function(event){
1276
+ this.document.removeEvents({
1277
+ mousemove: this.bound.check,
1278
+ mouseup: this.bound.cancel
1279
+ });
1280
+ if (event){
1281
+ this.document.removeEvent(this.selection, this.bound.eventStop);
1282
+ this.fireEvent('cancel', this.element);
1283
+ }
1284
+ },
1285
+
1286
+ stop: function(event){
1287
+ var events = {
1288
+ mousemove: this.bound.drag,
1289
+ mouseup: this.bound.stop
1290
+ };
1291
+ events[this.selection] = this.bound.eventStop;
1292
+ this.document.removeEvents(events);
1293
+ if (event) this.fireEvent('complete', [this.element, event]);
1294
+ }
1295
+
1296
+ });
1297
+
1298
+ Element.implement({
1299
+
1300
+ makeResizable: function(options){
1301
+ var drag = new Drag(this, Object.merge({
1302
+ modifiers: {
1303
+ x: 'width',
1304
+ y: 'height'
1305
+ }
1306
+ }, options));
1307
+
1308
+ this.store('resizer', drag);
1309
+ return drag.addEvent('drag', function(){
1310
+ this.fireEvent('resize', drag);
1311
+ }.bind(this));
1312
+ }
1313
+
1314
+ });
1315
+
1316
+
1317
+ /*
1318
+ ---
1319
+
1320
+ script: Drag.Move.js
1321
+
1322
+ name: Drag.Move
1323
+
1324
+ description: A Drag extension that provides support for the constraining of draggables to containers and droppables.
1325
+
1326
+ license: MIT-style license
1327
+
1328
+ authors:
1329
+ - Valerio Proietti
1330
+ - Tom Occhinno
1331
+ - Jan Kassens
1332
+ - Aaron Newton
1333
+ - Scott Kyle
1334
+
1335
+ requires:
1336
+ - Core/Element.Dimensions
1337
+ - Drag
1338
+
1339
+ provides: [Drag.Move]
1340
+
1341
+ ...
1342
+ */
1343
+
1344
+ Drag.Move = new Class({
1345
+
1346
+ Extends: Drag,
1347
+
1348
+ options: {/*
1349
+ onEnter: function(thisElement, overed){},
1350
+ onLeave: function(thisElement, overed){},
1351
+ onDrop: function(thisElement, overed, event){},*/
1352
+ droppables: [],
1353
+ container: false,
1354
+ precalculate: false,
1355
+ includeMargins: true,
1356
+ checkDroppables: true
1357
+ },
1358
+
1359
+ initialize: function(element, options){
1360
+ this.parent(element, options);
1361
+ element = this.element;
1362
+
1363
+ this.droppables = $$(this.options.droppables);
1364
+ this.setContainer(this.options.container);
1365
+
1366
+ if (this.options.style){
1367
+ if (this.options.modifiers.x == 'left' && this.options.modifiers.y == 'top'){
1368
+ var parent = element.getOffsetParent(),
1369
+ styles = element.getStyles('left', 'top');
1370
+ if (parent && (styles.left == 'auto' || styles.top == 'auto')){
1371
+ element.setPosition(element.getPosition(parent));
1372
+ }
1373
+ }
1374
+
1375
+ if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute');
1376
+ }
1377
+
1378
+ this.addEvent('start', this.checkDroppables, true);
1379
+ this.overed = null;
1380
+ },
1381
+
1382
+ setContainer: function(container) {
1383
+ this.container = document.id(container);
1384
+ if (this.container && typeOf(this.container) != 'element'){
1385
+ this.container = document.id(this.container.getDocument().body);
1386
+ }
1387
+ },
1388
+
1389
+ start: function(event){
1390
+ if (this.container) this.options.limit = this.calculateLimit();
1391
+
1392
+ if (this.options.precalculate){
1393
+ this.positions = this.droppables.map(function(el){
1394
+ return el.getCoordinates();
1395
+ });
1396
+ }
1397
+
1398
+ this.parent(event);
1399
+ },
1400
+
1401
+ calculateLimit: function(){
1402
+ var element = this.element,
1403
+ container = this.container,
1404
+
1405
+ offsetParent = document.id(element.getOffsetParent()) || document.body,
1406
+ containerCoordinates = container.getCoordinates(offsetParent),
1407
+ elementMargin = {},
1408
+ elementBorder = {},
1409
+ containerMargin = {},
1410
+ containerBorder = {},
1411
+ offsetParentPadding = {};
1412
+
1413
+ ['top', 'right', 'bottom', 'left'].each(function(pad){
1414
+ elementMargin[pad] = element.getStyle('margin-' + pad).toInt();
1415
+ elementBorder[pad] = element.getStyle('border-' + pad).toInt();
1416
+ containerMargin[pad] = container.getStyle('margin-' + pad).toInt();
1417
+ containerBorder[pad] = container.getStyle('border-' + pad).toInt();
1418
+ offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt();
1419
+ }, this);
1420
+
1421
+ var width = element.offsetWidth + elementMargin.left + elementMargin.right,
1422
+ height = element.offsetHeight + elementMargin.top + elementMargin.bottom,
1423
+ left = 0,
1424
+ top = 0,
1425
+ right = containerCoordinates.right - containerBorder.right - width,
1426
+ bottom = containerCoordinates.bottom - containerBorder.bottom - height;
1427
+
1428
+ if (this.options.includeMargins){
1429
+ left += elementMargin.left;
1430
+ top += elementMargin.top;
1431
+ } else {
1432
+ right += elementMargin.right;
1433
+ bottom += elementMargin.bottom;
1434
+ }
1435
+
1436
+ if (element.getStyle('position') == 'relative'){
1437
+ var coords = element.getCoordinates(offsetParent);
1438
+ coords.left -= element.getStyle('left').toInt();
1439
+ coords.top -= element.getStyle('top').toInt();
1440
+
1441
+ left -= coords.left;
1442
+ top -= coords.top;
1443
+ if (container.getStyle('position') != 'relative'){
1444
+ left += containerBorder.left;
1445
+ top += containerBorder.top;
1446
+ }
1447
+ right += elementMargin.left - coords.left;
1448
+ bottom += elementMargin.top - coords.top;
1449
+
1450
+ if (container != offsetParent){
1451
+ left += containerMargin.left + offsetParentPadding.left;
1452
+ if (!offsetParentPadding.left && left < 0) left = 0;
1453
+ top += offsetParent == document.body ? 0 : containerMargin.top + offsetParentPadding.top;
1454
+ if (!offsetParentPadding.top && top < 0) top = 0;
1455
+ }
1456
+ } else {
1457
+ left -= elementMargin.left;
1458
+ top -= elementMargin.top;
1459
+ if (container != offsetParent){
1460
+ left += containerCoordinates.left + containerBorder.left;
1461
+ top += containerCoordinates.top + containerBorder.top;
1462
+ }
1463
+ }
1464
+
1465
+ return {
1466
+ x: [left, right],
1467
+ y: [top, bottom]
1468
+ };
1469
+ },
1470
+
1471
+ getDroppableCoordinates: function(element){
1472
+ var position = element.getCoordinates();
1473
+ if (element.getStyle('position') == 'fixed'){
1474
+ var scroll = window.getScroll();
1475
+ position.left += scroll.x;
1476
+ position.right += scroll.x;
1477
+ position.top += scroll.y;
1478
+ position.bottom += scroll.y;
1479
+ }
1480
+ return position;
1481
+ },
1482
+
1483
+ checkDroppables: function(){
1484
+ var overed = this.droppables.filter(function(el, i){
1485
+ el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el);
1486
+ var now = this.mouse.now;
1487
+ return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
1488
+ }, this).getLast();
1489
+
1490
+ if (this.overed != overed){
1491
+ if (this.overed) this.fireEvent('leave', [this.element, this.overed]);
1492
+ if (overed) this.fireEvent('enter', [this.element, overed]);
1493
+ this.overed = overed;
1494
+ }
1495
+ },
1496
+
1497
+ drag: function(event){
1498
+ this.parent(event);
1499
+ if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
1500
+ },
1501
+
1502
+ stop: function(event){
1503
+ this.checkDroppables();
1504
+ this.fireEvent('drop', [this.element, this.overed, event]);
1505
+ this.overed = null;
1506
+ return this.parent(event);
1507
+ }
1508
+
1509
+ });
1510
+
1511
+ Element.implement({
1512
+
1513
+ makeDraggable: function(options){
1514
+ var drag = new Drag.Move(this, options);
1515
+ this.store('dragger', drag);
1516
+ return drag;
1517
+ }
1518
+
1519
+ });
1520
+
1521
+
1522
+ /*
1523
+ ---
1524
+
1525
+ script: Sortables.js
1526
+
1527
+ name: Sortables
1528
+
1529
+ description: Class for creating a drag and drop sorting interface for lists of items.
1530
+
1531
+ license: MIT-style license
1532
+
1533
+ authors:
1534
+ - Tom Occhino
1535
+
1536
+ requires:
1537
+ - Core/Fx.Morph
1538
+ - Drag.Move
1539
+
1540
+ provides: [Sortables]
1541
+
1542
+ ...
1543
+ */
1544
+
1545
+ var Sortables = new Class({
1546
+
1547
+ Implements: [Events, Options],
1548
+
1549
+ options: {/*
1550
+ onSort: function(element, clone){},
1551
+ onStart: function(element, clone){},
1552
+ onComplete: function(element){},*/
1553
+ opacity: 1,
1554
+ clone: false,
1555
+ revert: false,
1556
+ handle: false,
1557
+ dragOptions: {},
1558
+ unDraggableTags: ['button', 'input', 'a', 'textarea', 'select', 'option']
1559
+ },
1560
+
1561
+ initialize: function(lists, options){
1562
+ this.setOptions(options);
1563
+
1564
+ this.elements = [];
1565
+ this.lists = [];
1566
+ this.idle = true;
1567
+
1568
+ this.addLists($$(document.id(lists) || lists));
1569
+
1570
+ if (!this.options.clone) this.options.revert = false;
1571
+ if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({
1572
+ duration: 250,
1573
+ link: 'cancel'
1574
+ }, this.options.revert));
1575
+ },
1576
+
1577
+ attach: function(){
1578
+ this.addLists(this.lists);
1579
+ return this;
1580
+ },
1581
+
1582
+ detach: function(){
1583
+ this.lists = this.removeLists(this.lists);
1584
+ return this;
1585
+ },
1586
+
1587
+ addItems: function(){
1588
+ Array.flatten(arguments).each(function(element){
1589
+ this.elements.push(element);
1590
+ var start = element.retrieve('sortables:start', function(event){
1591
+ this.start.call(this, event, element);
1592
+ }.bind(this));
1593
+ (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start);
1594
+ }, this);
1595
+ return this;
1596
+ },
1597
+
1598
+ addLists: function(){
1599
+ Array.flatten(arguments).each(function(list){
1600
+ this.lists.include(list);
1601
+ this.addItems(list.getChildren());
1602
+ }, this);
1603
+ return this;
1604
+ },
1605
+
1606
+ removeItems: function(){
1607
+ return $$(Array.flatten(arguments).map(function(element){
1608
+ this.elements.erase(element);
1609
+ var start = element.retrieve('sortables:start');
1610
+ (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
1611
+
1612
+ return element;
1613
+ }, this));
1614
+ },
1615
+
1616
+ removeLists: function(){
1617
+ return $$(Array.flatten(arguments).map(function(list){
1618
+ this.lists.erase(list);
1619
+ this.removeItems(list.getChildren());
1620
+
1621
+ return list;
1622
+ }, this));
1623
+ },
1624
+
1625
+ getDroppableCoordinates: function (element){
1626
+ var offsetParent = element.getOffsetParent();
1627
+ var position = element.getPosition(offsetParent);
1628
+ var scroll = {
1629
+ w: window.getScroll(),
1630
+ offsetParent: offsetParent.getScroll()
1631
+ };
1632
+ position.x += scroll.offsetParent.x;
1633
+ position.y += scroll.offsetParent.y;
1634
+
1635
+ if (offsetParent.getStyle('position') == 'fixed'){
1636
+ position.x -= scroll.w.x;
1637
+ position.y -= scroll.w.y;
1638
+ }
1639
+
1640
+ return position;
1641
+ },
1642
+
1643
+ getClone: function(event, element){
1644
+ if (!this.options.clone) return new Element(element.tagName).inject(document.body);
1645
+ if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list);
1646
+ var clone = element.clone(true).setStyles({
1647
+ margin: 0,
1648
+ position: 'absolute',
1649
+ visibility: 'hidden',
1650
+ width: element.getStyle('width')
1651
+ }).addEvent('mousedown', function(event){
1652
+ element.fireEvent('mousedown', event);
1653
+ });
1654
+ //prevent the duplicated radio inputs from unchecking the real one
1655
+ if (clone.get('html').test('radio')){
1656
+ clone.getElements('input[type=radio]').each(function(input, i){
1657
+ input.set('name', 'clone_' + i);
1658
+ if (input.get('checked')) element.getElements('input[type=radio]')[i].set('checked', true);
1659
+ });
1660
+ }
1661
+
1662
+ return clone.inject(this.list).setPosition(this.getDroppableCoordinates(this.element));
1663
+ },
1664
+
1665
+ getDroppables: function(){
1666
+ var droppables = this.list.getChildren().erase(this.clone).erase(this.element);
1667
+ if (!this.options.constrain) droppables.append(this.lists).erase(this.list);
1668
+ return droppables;
1669
+ },
1670
+
1671
+ insert: function(dragging, element){
1672
+ var where = 'inside';
1673
+ if (this.lists.contains(element)){
1674
+ this.list = element;
1675
+ this.drag.droppables = this.getDroppables();
1676
+ } else {
1677
+ where = this.element.getAllPrevious().contains(element) ? 'before' : 'after';
1678
+ }
1679
+ this.element.inject(element, where);
1680
+ this.fireEvent('sort', [this.element, this.clone]);
1681
+ },
1682
+
1683
+ start: function(event, element){
1684
+ if (
1685
+ !this.idle ||
1686
+ event.rightClick ||
1687
+ (!this.options.handle && this.options.unDraggableTags.contains(event.target.get('tag')))
1688
+ ) return;
1689
+
1690
+ this.idle = false;
1691
+ this.element = element;
1692
+ this.opacity = element.getStyle('opacity');
1693
+ this.list = element.getParent();
1694
+ this.clone = this.getClone(event, element);
1695
+
1696
+ this.drag = new Drag.Move(this.clone, Object.merge({
1697
+
1698
+ droppables: this.getDroppables()
1699
+ }, this.options.dragOptions)).addEvents({
1700
+ onSnap: function(){
1701
+ event.stop();
1702
+ this.clone.setStyle('visibility', 'visible');
1703
+ this.element.setStyle('opacity', this.options.opacity || 0);
1704
+ this.fireEvent('start', [this.element, this.clone]);
1705
+ }.bind(this),
1706
+ onEnter: this.insert.bind(this),
1707
+ onCancel: this.end.bind(this),
1708
+ onComplete: this.end.bind(this)
1709
+ });
1710
+
1711
+ this.clone.inject(this.element, 'before');
1712
+ this.drag.start(event);
1713
+ },
1714
+
1715
+ end: function(){
1716
+ this.drag.detach();
1717
+ this.element.setStyle('opacity', this.opacity);
1718
+ var self = this;
1719
+ if (this.effect){
1720
+ var dim = this.element.getStyles('width', 'height'),
1721
+ clone = this.clone,
1722
+ pos = clone.computePosition(this.getDroppableCoordinates(clone));
1723
+
1724
+ var destroy = function(){
1725
+ this.removeEvent('cancel', destroy);
1726
+ clone.destroy();
1727
+ self.reset();
1728
+ };
1729
+
1730
+ this.effect.element = clone;
1731
+ this.effect.start({
1732
+ top: pos.top,
1733
+ left: pos.left,
1734
+ width: dim.width,
1735
+ height: dim.height,
1736
+ opacity: 0.25
1737
+ }).addEvent('cancel', destroy).chain(destroy);
1738
+ } else {
1739
+ this.clone.destroy();
1740
+ self.reset();
1741
+ }
1742
+
1743
+ },
1744
+
1745
+ reset: function(){
1746
+ this.idle = true;
1747
+ this.fireEvent('complete', this.element);
1748
+ },
1749
+
1750
+ serialize: function(){
1751
+ var params = Array.link(arguments, {
1752
+ modifier: Type.isFunction,
1753
+ index: function(obj){
1754
+ return obj != null;
1755
+ }
1756
+ });
1757
+ var serial = this.lists.map(function(list){
1758
+ return list.getChildren().map(params.modifier || function(element){
1759
+ return element.get('id');
1760
+ }, this);
1761
+ }, this);
1762
+
1763
+ var index = params.index;
1764
+ if (this.lists.length == 1) index = 0;
1765
+ return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial;
1766
+ }
1767
+
1768
+ });
1769
+
1770
+
1771
+ /*
1772
+ ---
1773
+
1774
+ script: Assets.js
1775
+
1776
+ name: Assets
1777
+
1778
+ description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
1779
+
1780
+ license: MIT-style license
1781
+
1782
+ authors:
1783
+ - Valerio Proietti
1784
+
1785
+ requires:
1786
+ - Core/Element.Event
1787
+ - MooTools.More
1788
+
1789
+ provides: [Assets]
1790
+
1791
+ ...
1792
+ */
1793
+
1794
+ var Asset = {
1795
+
1796
+ javascript: function(source, properties){
1797
+ if (!properties) properties = {};
1798
+
1799
+ var script = new Element('script', {src: source, type: 'text/javascript'}),
1800
+ doc = properties.document || document,
1801
+ load = properties.onload || properties.onLoad;
1802
+
1803
+ delete properties.onload;
1804
+ delete properties.onLoad;
1805
+ delete properties.document;
1806
+
1807
+ if (load){
1808
+ if (!script.addEventListener){
1809
+ script.addEvent('readystatechange', function(){
1810
+ if (['loaded', 'complete'].contains(this.readyState)) load.call(this);
1811
+ });
1812
+ } else {
1813
+ script.addEvent('load', load);
1814
+ }
1815
+ }
1816
+
1817
+ return script.set(properties).inject(doc.head);
1818
+ },
1819
+
1820
+ css: function(source, properties){
1821
+ if (!properties) properties = {};
1822
+
1823
+ var link = new Element('link', {
1824
+ rel: 'stylesheet',
1825
+ media: 'screen',
1826
+ type: 'text/css',
1827
+ href: source
1828
+ });
1829
+
1830
+ var load = properties.onload || properties.onLoad,
1831
+ doc = properties.document || document;
1832
+
1833
+ delete properties.onload;
1834
+ delete properties.onLoad;
1835
+ delete properties.document;
1836
+
1837
+ if (load) link.addEvent('load', load);
1838
+ return link.set(properties).inject(doc.head);
1839
+ },
1840
+
1841
+ image: function(source, properties){
1842
+ if (!properties) properties = {};
1843
+
1844
+ var image = new Image(),
1845
+ element = document.id(image) || new Element('img');
1846
+
1847
+ ['load', 'abort', 'error'].each(function(name){
1848
+ var type = 'on' + name,
1849
+ cap = 'on' + name.capitalize(),
1850
+ event = properties[type] || properties[cap] || function(){};
1851
+
1852
+ delete properties[cap];
1853
+ delete properties[type];
1854
+
1855
+ image[type] = function(){
1856
+ if (!image) return;
1857
+ if (!element.parentNode){
1858
+ element.width = image.width;
1859
+ element.height = image.height;
1860
+ }
1861
+ image = image.onload = image.onabort = image.onerror = null;
1862
+ event.delay(1, element, element);
1863
+ element.fireEvent(name, element, 1);
1864
+ };
1865
+ });
1866
+
1867
+ image.src = element.src = source;
1868
+ if (image && image.complete) image.onload.delay(1);
1869
+ return element.set(properties);
1870
+ },
1871
+
1872
+ images: function(sources, options){
1873
+ sources = Array.from(sources);
1874
+
1875
+ var fn = function(){},
1876
+ counter = 0;
1877
+
1878
+ options = Object.merge({
1879
+ onComplete: fn,
1880
+ onProgress: fn,
1881
+ onError: fn,
1882
+ properties: {}
1883
+ }, options);
1884
+
1885
+ return new Elements(sources.map(function(source, index){
1886
+ return Asset.image(source, Object.append(options.properties, {
1887
+ onload: function(){
1888
+ counter++;
1889
+ options.onProgress.call(this, counter, index, source);
1890
+ if (counter == sources.length) options.onComplete();
1891
+ },
1892
+ onerror: function(){
1893
+ counter++;
1894
+ options.onError.call(this, counter, index, source);
1895
+ if (counter == sources.length) options.onComplete();
1896
+ }
1897
+ }));
1898
+ }));
1899
+ }
1900
+
1901
+ };
1902
+
1903
+
1904
+ /*
1905
+ ---
1906
+
1907
+ script: Element.Measure.js
1908
+
1909
+ name: Element.Measure
1910
+
1911
+ description: Extends the Element native object to include methods useful in measuring dimensions.
1912
+
1913
+ credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
1914
+
1915
+ license: MIT-style license
1916
+
1917
+ authors:
1918
+ - Aaron Newton
1919
+
1920
+ requires:
1921
+ - Core/Element.Style
1922
+ - Core/Element.Dimensions
1923
+ - MooTools.More
1924
+
1925
+ provides: [Element.Measure]
1926
+
1927
+ ...
1928
+ */
1929
+
1930
+ (function(){
1931
+
1932
+ var getStylesList = function(styles, planes){
1933
+ var list = [];
1934
+ Object.each(planes, function(directions){
1935
+ Object.each(directions, function(edge){
1936
+ styles.each(function(style){
1937
+ list.push(style + '-' + edge + (style == 'border' ? '-width' : ''));
1938
+ });
1939
+ });
1940
+ });
1941
+ return list;
1942
+ };
1943
+
1944
+ var calculateEdgeSize = function(edge, styles){
1945
+ var total = 0;
1946
+ Object.each(styles, function(value, style){
1947
+ if (style.test(edge)) total = total + value.toInt();
1948
+ });
1949
+ return total;
1950
+ };
1951
+
1952
+ var isVisible = function(el){
1953
+ return !!(!el || el.offsetHeight || el.offsetWidth);
1954
+ };
1955
+
1956
+
1957
+ Element.implement({
1958
+
1959
+ measure: function(fn){
1960
+ if (isVisible(this)) return fn.call(this);
1961
+ var parent = this.getParent(),
1962
+ toMeasure = [];
1963
+ while (!isVisible(parent) && parent != document.body){
1964
+ toMeasure.push(parent.expose());
1965
+ parent = parent.getParent();
1966
+ }
1967
+ var restore = this.expose(),
1968
+ result = fn.call(this);
1969
+ restore();
1970
+ toMeasure.each(function(restore){
1971
+ restore();
1972
+ });
1973
+ return result;
1974
+ },
1975
+
1976
+ expose: function(){
1977
+ if (this.getStyle('display') != 'none') return function(){};
1978
+ var before = this.style.cssText;
1979
+ this.setStyles({
1980
+ display: 'block',
1981
+ position: 'absolute',
1982
+ visibility: 'hidden'
1983
+ });
1984
+ return function(){
1985
+ this.style.cssText = before;
1986
+ }.bind(this);
1987
+ },
1988
+
1989
+ getDimensions: function(options){
1990
+ options = Object.merge({computeSize: false}, options);
1991
+ var dim = {x: 0, y: 0};
1992
+
1993
+ var getSize = function(el, options){
1994
+ return (options.computeSize) ? el.getComputedSize(options) : el.getSize();
1995
+ };
1996
+
1997
+ var parent = this.getParent('body');
1998
+
1999
+ if (parent && this.getStyle('display') == 'none'){
2000
+ dim = this.measure(function(){
2001
+ return getSize(this, options);
2002
+ });
2003
+ } else if (parent){
2004
+ try { //safari sometimes crashes here, so catch it
2005
+ dim = getSize(this, options);
2006
+ }catch(e){}
2007
+ }
2008
+
2009
+ return Object.append(dim, (dim.x || dim.x === 0) ? {
2010
+ width: dim.x,
2011
+ height: dim.y
2012
+ } : {
2013
+ x: dim.width,
2014
+ y: dim.height
2015
+ }
2016
+ );
2017
+ },
2018
+
2019
+ getComputedSize: function(options){
2020
+
2021
+
2022
+ options = Object.merge({
2023
+ styles: ['padding','border'],
2024
+ planes: {
2025
+ height: ['top','bottom'],
2026
+ width: ['left','right']
2027
+ },
2028
+ mode: 'both'
2029
+ }, options);
2030
+
2031
+ var styles = {},
2032
+ size = {width: 0, height: 0},
2033
+ dimensions;
2034
+
2035
+ if (options.mode == 'vertical'){
2036
+ delete size.width;
2037
+ delete options.planes.width;
2038
+ } else if (options.mode == 'horizontal'){
2039
+ delete size.height;
2040
+ delete options.planes.height;
2041
+ }
2042
+
2043
+ getStylesList(options.styles, options.planes).each(function(style){
2044
+ styles[style] = this.getStyle(style).toInt();
2045
+ }, this);
2046
+
2047
+ Object.each(options.planes, function(edges, plane){
2048
+
2049
+ var capitalized = plane.capitalize(),
2050
+ style = this.getStyle(plane);
2051
+
2052
+ if (style == 'auto' && !dimensions) dimensions = this.getDimensions();
2053
+
2054
+ style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt();
2055
+ size['total' + capitalized] = style;
2056
+
2057
+ edges.each(function(edge){
2058
+ var edgesize = calculateEdgeSize(edge, styles);
2059
+ size['computed' + edge.capitalize()] = edgesize;
2060
+ size['total' + capitalized] += edgesize;
2061
+ });
2062
+
2063
+ }, this);
2064
+
2065
+ return Object.append(size, styles);
2066
+ }
2067
+
2068
+ });
2069
+
2070
+ })();
2071
+
2072
+
2073
+ /*
2074
+ ---
2075
+
2076
+ script: Element.Position.js
2077
+
2078
+ name: Element.Position
2079
+
2080
+ description: Extends the Element native object to include methods useful positioning elements relative to others.
2081
+
2082
+ license: MIT-style license
2083
+
2084
+ authors:
2085
+ - Aaron Newton
2086
+ - Jacob Thornton
2087
+
2088
+ requires:
2089
+ - Core/Options
2090
+ - Core/Element.Dimensions
2091
+ - Element.Measure
2092
+
2093
+ provides: [Element.Position]
2094
+
2095
+ ...
2096
+ */
2097
+
2098
+ (function(original){
2099
+
2100
+ var local = Element.Position = {
2101
+
2102
+ options: {/*
2103
+ edge: false,
2104
+ returnPos: false,
2105
+ minimum: {x: 0, y: 0},
2106
+ maximum: {x: 0, y: 0},
2107
+ relFixedPosition: false,
2108
+ ignoreMargins: false,
2109
+ ignoreScroll: false,
2110
+ allowNegative: false,*/
2111
+ relativeTo: document.body,
2112
+ position: {
2113
+ x: 'center', //left, center, right
2114
+ y: 'center' //top, center, bottom
2115
+ },
2116
+ offset: {x: 0, y: 0}
2117
+ },
2118
+
2119
+ getOptions: function(element, options){
2120
+ options = Object.merge({}, local.options, options);
2121
+ local.setPositionOption(options);
2122
+ local.setEdgeOption(options);
2123
+ local.setOffsetOption(element, options);
2124
+ local.setDimensionsOption(element, options);
2125
+ return options;
2126
+ },
2127
+
2128
+ setPositionOption: function(options){
2129
+ options.position = local.getCoordinateFromValue(options.position);
2130
+ },
2131
+
2132
+ setEdgeOption: function(options){
2133
+ var edgeOption = local.getCoordinateFromValue(options.edge);
2134
+ options.edge = edgeOption ? edgeOption :
2135
+ (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} :
2136
+ {x: 'left', y: 'top'};
2137
+ },
2138
+
2139
+ setOffsetOption: function(element, options){
2140
+ var parentOffset = {x: 0, y: 0};
2141
+ var parentScroll = {x: 0, y: 0};
2142
+ var offsetParent = element.measure(function(){
2143
+ return document.id(this.getOffsetParent());
2144
+ });
2145
+
2146
+ if (!offsetParent || offsetParent == element.getDocument().body) return;
2147
+
2148
+ parentScroll = offsetParent.getScroll();
2149
+ parentOffset = offsetParent.measure(function(){
2150
+ var position = this.getPosition();
2151
+ if (this.getStyle('position') == 'fixed'){
2152
+ var scroll = window.getScroll();
2153
+ position.x += scroll.x;
2154
+ position.y += scroll.y;
2155
+ }
2156
+ return position;
2157
+ });
2158
+
2159
+ options.offset = {
2160
+ parentPositioned: offsetParent != document.id(options.relativeTo),
2161
+ x: options.offset.x - parentOffset.x + parentScroll.x,
2162
+ y: options.offset.y - parentOffset.y + parentScroll.y
2163
+ };
2164
+ },
2165
+
2166
+ setDimensionsOption: function(element, options){
2167
+ options.dimensions = element.getDimensions({
2168
+ computeSize: true,
2169
+ styles: ['padding', 'border', 'margin']
2170
+ });
2171
+ },
2172
+
2173
+ getPosition: function(element, options){
2174
+ var position = {};
2175
+ options = local.getOptions(element, options);
2176
+ var relativeTo = document.id(options.relativeTo) || document.body;
2177
+
2178
+ local.setPositionCoordinates(options, position, relativeTo);
2179
+ if (options.edge) local.toEdge(position, options);
2180
+
2181
+ var offset = options.offset;
2182
+ position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt();
2183
+ position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt();
2184
+
2185
+ local.toMinMax(position, options);
2186
+
2187
+ if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position);
2188
+ if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position);
2189
+ if (options.ignoreMargins) local.toIgnoreMargins(position, options);
2190
+
2191
+ position.left = Math.ceil(position.left);
2192
+ position.top = Math.ceil(position.top);
2193
+ delete position.x;
2194
+ delete position.y;
2195
+
2196
+ return position;
2197
+ },
2198
+
2199
+ setPositionCoordinates: function(options, position, relativeTo){
2200
+ var offsetY = options.offset.y,
2201
+ offsetX = options.offset.x,
2202
+ calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(),
2203
+ top = calc.y,
2204
+ left = calc.x,
2205
+ winSize = window.getSize();
2206
+
2207
+ switch(options.position.x){
2208
+ case 'left': position.x = left + offsetX; break;
2209
+ case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break;
2210
+ default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break;
2211
+ }
2212
+
2213
+ switch(options.position.y){
2214
+ case 'top': position.y = top + offsetY; break;
2215
+ case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break;
2216
+ default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break;
2217
+ }
2218
+ },
2219
+
2220
+ toMinMax: function(position, options){
2221
+ var xy = {left: 'x', top: 'y'}, value;
2222
+ ['minimum', 'maximum'].each(function(minmax){
2223
+ ['left', 'top'].each(function(lr){
2224
+ value = options[minmax] ? options[minmax][xy[lr]] : null;
2225
+ if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value;
2226
+ });
2227
+ });
2228
+ },
2229
+
2230
+ toRelFixedPosition: function(relativeTo, position){
2231
+ var winScroll = window.getScroll();
2232
+ position.top += winScroll.y;
2233
+ position.left += winScroll.x;
2234
+ },
2235
+
2236
+ toIgnoreScroll: function(relativeTo, position){
2237
+ var relScroll = relativeTo.getScroll();
2238
+ position.top -= relScroll.y;
2239
+ position.left -= relScroll.x;
2240
+ },
2241
+
2242
+ toIgnoreMargins: function(position, options){
2243
+ position.left += options.edge.x == 'right'
2244
+ ? options.dimensions['margin-right']
2245
+ : (options.edge.x != 'center'
2246
+ ? -options.dimensions['margin-left']
2247
+ : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2));
2248
+
2249
+ position.top += options.edge.y == 'bottom'
2250
+ ? options.dimensions['margin-bottom']
2251
+ : (options.edge.y != 'center'
2252
+ ? -options.dimensions['margin-top']
2253
+ : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2));
2254
+ },
2255
+
2256
+ toEdge: function(position, options){
2257
+ var edgeOffset = {},
2258
+ dimensions = options.dimensions,
2259
+ edge = options.edge;
2260
+
2261
+ switch(edge.x){
2262
+ case 'left': edgeOffset.x = 0; break;
2263
+ case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break;
2264
+ // center
2265
+ default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break;
2266
+ }
2267
+
2268
+ switch(edge.y){
2269
+ case 'top': edgeOffset.y = 0; break;
2270
+ case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break;
2271
+ // center
2272
+ default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break;
2273
+ }
2274
+
2275
+ position.x += edgeOffset.x;
2276
+ position.y += edgeOffset.y;
2277
+ },
2278
+
2279
+ getCoordinateFromValue: function(option){
2280
+ if (typeOf(option) != 'string') return option;
2281
+ option = option.toLowerCase();
2282
+
2283
+ return {
2284
+ x: option.test('left') ? 'left'
2285
+ : (option.test('right') ? 'right' : 'center'),
2286
+ y: option.test(/upper|top/) ? 'top'
2287
+ : (option.test('bottom') ? 'bottom' : 'center')
2288
+ };
2289
+ }
2290
+
2291
+ };
2292
+
2293
+ Element.implement({
2294
+
2295
+ position: function(options){
2296
+ if (options && (options.x != null || options.y != null)){
2297
+ return (original ? original.apply(this, arguments) : this);
2298
+ }
2299
+ var position = this.setStyle('position', 'absolute').calculatePosition(options);
2300
+ return (options && options.returnPos) ? position : this.setStyles(position);
2301
+ },
2302
+
2303
+ calculatePosition: function(options){
2304
+ return local.getPosition(this, options);
2305
+ }
2306
+
2307
+ });
2308
+
2309
+ })(Element.prototype.position);
2310
+
2311
+
2312
+ /*
2313
+ ---
2314
+
2315
+ script: Class.Occlude.js
2316
+
2317
+ name: Class.Occlude
2318
+
2319
+ description: Prevents a class from being applied to a DOM element twice.
2320
+
2321
+ license: MIT-style license.
2322
+
2323
+ authors:
2324
+ - Aaron Newton
2325
+
2326
+ requires:
2327
+ - Core/Class
2328
+ - Core/Element
2329
+ - MooTools.More
2330
+
2331
+ provides: [Class.Occlude]
2332
+
2333
+ ...
2334
+ */
2335
+
2336
+ Class.Occlude = new Class({
2337
+
2338
+ occlude: function(property, element){
2339
+ element = document.id(element || this.element);
2340
+ var instance = element.retrieve(property || this.property);
2341
+ if (instance && !this.occluded)
2342
+ return (this.occluded = instance);
2343
+
2344
+ this.occluded = false;
2345
+ element.store(property || this.property, this);
2346
+ return this.occluded;
2347
+ }
2348
+
2349
+ });
2350
+
2351
+
2352
+ /*
2353
+ ---
2354
+
2355
+ script: IframeShim.js
2356
+
2357
+ name: IframeShim
2358
+
2359
+ description: Defines IframeShim, a class for obscuring select lists and flash objects in IE.
2360
+
2361
+ license: MIT-style license
2362
+
2363
+ authors:
2364
+ - Aaron Newton
2365
+
2366
+ requires:
2367
+ - Core/Element.Event
2368
+ - Core/Element.Style
2369
+ - Core/Options
2370
+ - Core/Events
2371
+ - Element.Position
2372
+ - Class.Occlude
2373
+
2374
+ provides: [IframeShim]
2375
+
2376
+ ...
2377
+ */
2378
+
2379
+ (function(){
2380
+
2381
+ var browsers = false;
2382
+
2383
+
2384
+ this.IframeShim = new Class({
2385
+
2386
+ Implements: [Options, Events, Class.Occlude],
2387
+
2388
+ options: {
2389
+ className: 'iframeShim',
2390
+ src: 'javascript:false;document.write("");',
2391
+ display: false,
2392
+ zIndex: null,
2393
+ margin: 0,
2394
+ offset: {x: 0, y: 0},
2395
+ browsers: browsers
2396
+ },
2397
+
2398
+ property: 'IframeShim',
2399
+
2400
+ initialize: function(element, options){
2401
+ this.element = document.id(element);
2402
+ if (this.occlude()) return this.occluded;
2403
+ this.setOptions(options);
2404
+ this.makeShim();
2405
+ return this;
2406
+ },
2407
+
2408
+ makeShim: function(){
2409
+ if (this.options.browsers){
2410
+ var zIndex = this.element.getStyle('zIndex').toInt();
2411
+
2412
+ if (!zIndex){
2413
+ zIndex = 1;
2414
+ var pos = this.element.getStyle('position');
2415
+ if (pos == 'static' || !pos) this.element.setStyle('position', 'relative');
2416
+ this.element.setStyle('zIndex', zIndex);
2417
+ }
2418
+ zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1;
2419
+ if (zIndex < 0) zIndex = 1;
2420
+ this.shim = new Element('iframe', {
2421
+ src: this.options.src,
2422
+ scrolling: 'no',
2423
+ frameborder: 0,
2424
+ styles: {
2425
+ zIndex: zIndex,
2426
+ position: 'absolute',
2427
+ border: 'none',
2428
+ filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
2429
+ },
2430
+ 'class': this.options.className
2431
+ }).store('IframeShim', this);
2432
+ var inject = (function(){
2433
+ this.shim.inject(this.element, 'after');
2434
+ this[this.options.display ? 'show' : 'hide']();
2435
+ this.fireEvent('inject');
2436
+ }).bind(this);
2437
+ if (!IframeShim.ready) window.addEvent('load', inject);
2438
+ else inject();
2439
+ } else {
2440
+ this.position = this.hide = this.show = this.dispose = Function.from(this);
2441
+ }
2442
+ },
2443
+
2444
+ position: function(){
2445
+ if (!IframeShim.ready || !this.shim) return this;
2446
+ var size = this.element.measure(function(){
2447
+ return this.getSize();
2448
+ });
2449
+ if (this.options.margin != undefined){
2450
+ size.x = size.x - (this.options.margin * 2);
2451
+ size.y = size.y - (this.options.margin * 2);
2452
+ this.options.offset.x += this.options.margin;
2453
+ this.options.offset.y += this.options.margin;
2454
+ }
2455
+ this.shim.set({width: size.x, height: size.y}).position({
2456
+ relativeTo: this.element,
2457
+ offset: this.options.offset
2458
+ });
2459
+ return this;
2460
+ },
2461
+
2462
+ hide: function(){
2463
+ if (this.shim) this.shim.setStyle('display', 'none');
2464
+ return this;
2465
+ },
2466
+
2467
+ show: function(){
2468
+ if (this.shim) this.shim.setStyle('display', 'block');
2469
+ return this.position();
2470
+ },
2471
+
2472
+ dispose: function(){
2473
+ if (this.shim) this.shim.dispose();
2474
+ return this;
2475
+ },
2476
+
2477
+ destroy: function(){
2478
+ if (this.shim) this.shim.destroy();
2479
+ return this;
2480
+ }
2481
+
2482
+ });
2483
+
2484
+ })();
2485
+
2486
+ window.addEvent('load', function(){
2487
+ IframeShim.ready = true;
2488
+ });
2489
+
2490
+
2491
+ /*
2492
+ ---
2493
+
2494
+ name: Locale.de-DE.Date
2495
+
2496
+ description: Date messages for German.
2497
+
2498
+ license: MIT-style license
2499
+
2500
+ authors:
2501
+ - Christoph Pojer
2502
+ - Frank Rossi
2503
+ - Ulrich Petri
2504
+ - Fabian Beiner
2505
+
2506
+ requires:
2507
+ - Locale
2508
+
2509
+ provides: [Locale.de-DE.Date]
2510
+
2511
+ ...
2512
+ */
2513
+
2514
+ Locale.define('de-DE', 'Date', {
2515
+
2516
+ months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
2517
+ months_abbr: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
2518
+ days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
2519
+ days_abbr: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
2520
+
2521
+ // Culture's date order: DD.MM.YYYY
2522
+ dateOrder: ['date', 'month', 'year'],
2523
+ shortDate: '%d.%m.%Y',
2524
+ shortTime: '%H:%M',
2525
+ AM: 'vormittags',
2526
+ PM: 'nachmittags',
2527
+ firstDayOfWeek: 1,
2528
+
2529
+ // Date.Extras
2530
+ ordinal: '.',
2531
+
2532
+ lessThanMinuteAgo: 'vor weniger als einer Minute',
2533
+ minuteAgo: 'vor einer Minute',
2534
+ minutesAgo: 'vor {delta} Minuten',
2535
+ hourAgo: 'vor einer Stunde',
2536
+ hoursAgo: 'vor {delta} Stunden',
2537
+ dayAgo: 'vor einem Tag',
2538
+ daysAgo: 'vor {delta} Tagen',
2539
+ weekAgo: 'vor einer Woche',
2540
+ weeksAgo: 'vor {delta} Wochen',
2541
+ monthAgo: 'vor einem Monat',
2542
+ monthsAgo: 'vor {delta} Monaten',
2543
+ yearAgo: 'vor einem Jahr',
2544
+ yearsAgo: 'vor {delta} Jahren',
2545
+
2546
+ lessThanMinuteUntil: 'in weniger als einer Minute',
2547
+ minuteUntil: 'in einer Minute',
2548
+ minutesUntil: 'in {delta} Minuten',
2549
+ hourUntil: 'in ca. einer Stunde',
2550
+ hoursUntil: 'in ca. {delta} Stunden',
2551
+ dayUntil: 'in einem Tag',
2552
+ daysUntil: 'in {delta} Tagen',
2553
+ weekUntil: 'in einer Woche',
2554
+ weeksUntil: 'in {delta} Wochen',
2555
+ monthUntil: 'in einem Monat',
2556
+ monthsUntil: 'in {delta} Monaten',
2557
+ yearUntil: 'in einem Jahr',
2558
+ yearsUntil: 'in {delta} Jahren'
2559
+
2560
+ });
2561
+