bhf 0.4.4 → 0.4.5

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.
@@ -1,6 +1,6 @@
1
1
  // MooTools: the javascript framework.
2
- // Load this file's selection again by visiting: http://mootools.net/more/9a67e76ac21beb650c34657e727bc592
3
- // Or build this file again with packager using: packager build More/String.Extras More/Sortables More/Locale More/Locale.en-US.Date More/Locale.de-DE.Date
2
+ // Load this file's selection again by visiting: http://mootools.net/more/c278dccc6c5a065496983e2e621825a4
3
+ // Or build this file again with packager using: packager build More/Date More/String.Extras More/Sortables More/IframeShim More/Locale More/Locale.en-US.Date More/Locale.de-DE.Date
4
4
  /*
5
5
  ---
6
6
 
@@ -36,6 +36,874 @@ MooTools.More = {
36
36
  };
37
37
 
38
38
 
39
+ /*
40
+ ---
41
+
42
+ script: Object.Extras.js
43
+
44
+ name: Object.Extras
45
+
46
+ description: Extra Object generics, like getFromPath which allows a path notation to child elements.
47
+
48
+ license: MIT-style license
49
+
50
+ authors:
51
+ - Aaron Newton
52
+
53
+ requires:
54
+ - Core/Object
55
+ - /MooTools.More
56
+
57
+ provides: [Object.Extras]
58
+
59
+ ...
60
+ */
61
+
62
+ (function(){
63
+
64
+ var defined = function(value){
65
+ return value != null;
66
+ };
67
+
68
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
69
+
70
+ Object.extend({
71
+
72
+ getFromPath: function(source, parts){
73
+ if (typeof parts == 'string') parts = parts.split('.');
74
+ for (var i = 0, l = parts.length; i < l; i++){
75
+ if (hasOwnProperty.call(source, parts[i])) source = source[parts[i]];
76
+ else return null;
77
+ }
78
+ return source;
79
+ },
80
+
81
+ cleanValues: function(object, method){
82
+ method = method || defined;
83
+ for (var key in object) if (!method(object[key])){
84
+ delete object[key];
85
+ }
86
+ return object;
87
+ },
88
+
89
+ erase: function(object, key){
90
+ if (hasOwnProperty.call(object, key)) delete object[key];
91
+ return object;
92
+ },
93
+
94
+ run: function(object){
95
+ var args = Array.slice(arguments, 1);
96
+ for (var key in object) if (object[key].apply){
97
+ object[key].apply(object, args);
98
+ }
99
+ return object;
100
+ }
101
+
102
+ });
103
+
104
+ })();
105
+
106
+
107
+ /*
108
+ ---
109
+
110
+ script: Locale.js
111
+
112
+ name: Locale
113
+
114
+ description: Provides methods for localization.
115
+
116
+ license: MIT-style license
117
+
118
+ authors:
119
+ - Aaron Newton
120
+ - Arian Stolwijk
121
+
122
+ requires:
123
+ - Core/Events
124
+ - /Object.Extras
125
+ - /MooTools.More
126
+
127
+ provides: [Locale, Lang]
128
+
129
+ ...
130
+ */
131
+
132
+ (function(){
133
+
134
+ var current = null,
135
+ locales = {},
136
+ inherits = {};
137
+
138
+ var getSet = function(set){
139
+ if (instanceOf(set, Locale.Set)) return set;
140
+ else return locales[set];
141
+ };
142
+
143
+ var Locale = this.Locale = {
144
+
145
+ define: function(locale, set, key, value){
146
+ var name;
147
+ if (instanceOf(locale, Locale.Set)){
148
+ name = locale.name;
149
+ if (name) locales[name] = locale;
150
+ } else {
151
+ name = locale;
152
+ if (!locales[name]) locales[name] = new Locale.Set(name);
153
+ locale = locales[name];
154
+ }
155
+
156
+ if (set) locale.define(set, key, value);
157
+
158
+
159
+
160
+ if (!current) current = locale;
161
+
162
+ return locale;
163
+ },
164
+
165
+ use: function(locale){
166
+ locale = getSet(locale);
167
+
168
+ if (locale){
169
+ current = locale;
170
+
171
+ this.fireEvent('change', locale);
172
+
173
+
174
+ }
175
+
176
+ return this;
177
+ },
178
+
179
+ getCurrent: function(){
180
+ return current;
181
+ },
182
+
183
+ get: function(key, args){
184
+ return (current) ? current.get(key, args) : '';
185
+ },
186
+
187
+ inherit: function(locale, inherits, set){
188
+ locale = getSet(locale);
189
+
190
+ if (locale) locale.inherit(inherits, set);
191
+ return this;
192
+ },
193
+
194
+ list: function(){
195
+ return Object.keys(locales);
196
+ }
197
+
198
+ };
199
+
200
+ Object.append(Locale, new Events);
201
+
202
+ Locale.Set = new Class({
203
+
204
+ sets: {},
205
+
206
+ inherits: {
207
+ locales: [],
208
+ sets: {}
209
+ },
210
+
211
+ initialize: function(name){
212
+ this.name = name || '';
213
+ },
214
+
215
+ define: function(set, key, value){
216
+ var defineData = this.sets[set];
217
+ if (!defineData) defineData = {};
218
+
219
+ if (key){
220
+ if (typeOf(key) == 'object') defineData = Object.merge(defineData, key);
221
+ else defineData[key] = value;
222
+ }
223
+ this.sets[set] = defineData;
224
+
225
+ return this;
226
+ },
227
+
228
+ get: function(key, args, _base){
229
+ var value = Object.getFromPath(this.sets, key);
230
+ if (value != null){
231
+ var type = typeOf(value);
232
+ if (type == 'function') value = value.apply(null, Array.from(args));
233
+ else if (type == 'object') value = Object.clone(value);
234
+ return value;
235
+ }
236
+
237
+ // get value of inherited locales
238
+ var index = key.indexOf('.'),
239
+ set = index < 0 ? key : key.substr(0, index),
240
+ names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include('en-US');
241
+ if (!_base) _base = [];
242
+
243
+ for (var i = 0, l = names.length; i < l; i++){
244
+ if (_base.contains(names[i])) continue;
245
+ _base.include(names[i]);
246
+
247
+ var locale = locales[names[i]];
248
+ if (!locale) continue;
249
+
250
+ value = locale.get(key, args, _base);
251
+ if (value != null) return value;
252
+ }
253
+
254
+ return '';
255
+ },
256
+
257
+ inherit: function(names, set){
258
+ names = Array.from(names);
259
+
260
+ if (set && !this.inherits.sets[set]) this.inherits.sets[set] = [];
261
+
262
+ var l = names.length;
263
+ while (l--) (set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]);
264
+
265
+ return this;
266
+ }
267
+
268
+ });
269
+
270
+
271
+
272
+ })();
273
+
274
+
275
+ /*
276
+ ---
277
+
278
+ name: Locale.en-US.Date
279
+
280
+ description: Date messages for US English.
281
+
282
+ license: MIT-style license
283
+
284
+ authors:
285
+ - Aaron Newton
286
+
287
+ requires:
288
+ - /Locale
289
+
290
+ provides: [Locale.en-US.Date]
291
+
292
+ ...
293
+ */
294
+
295
+ Locale.define('en-US', 'Date', {
296
+
297
+ months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
298
+ months_abbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
299
+ days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
300
+ days_abbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
301
+
302
+ // Culture's date order: MM/DD/YYYY
303
+ dateOrder: ['month', 'date', 'year'],
304
+ shortDate: '%m/%d/%Y',
305
+ shortTime: '%I:%M%p',
306
+ AM: 'AM',
307
+ PM: 'PM',
308
+ firstDayOfWeek: 0,
309
+
310
+ // Date.Extras
311
+ ordinal: function(dayOfMonth){
312
+ // 1st, 2nd, 3rd, etc.
313
+ return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
314
+ },
315
+
316
+ lessThanMinuteAgo: 'less than a minute ago',
317
+ minuteAgo: 'about a minute ago',
318
+ minutesAgo: '{delta} minutes ago',
319
+ hourAgo: 'about an hour ago',
320
+ hoursAgo: 'about {delta} hours ago',
321
+ dayAgo: '1 day ago',
322
+ daysAgo: '{delta} days ago',
323
+ weekAgo: '1 week ago',
324
+ weeksAgo: '{delta} weeks ago',
325
+ monthAgo: '1 month ago',
326
+ monthsAgo: '{delta} months ago',
327
+ yearAgo: '1 year ago',
328
+ yearsAgo: '{delta} years ago',
329
+
330
+ lessThanMinuteUntil: 'less than a minute from now',
331
+ minuteUntil: 'about a minute from now',
332
+ minutesUntil: '{delta} minutes from now',
333
+ hourUntil: 'about an hour from now',
334
+ hoursUntil: 'about {delta} hours from now',
335
+ dayUntil: '1 day from now',
336
+ daysUntil: '{delta} days from now',
337
+ weekUntil: '1 week from now',
338
+ weeksUntil: '{delta} weeks from now',
339
+ monthUntil: '1 month from now',
340
+ monthsUntil: '{delta} months from now',
341
+ yearUntil: '1 year from now',
342
+ yearsUntil: '{delta} years from now'
343
+
344
+ });
345
+
346
+
347
+ /*
348
+ ---
349
+
350
+ script: Date.js
351
+
352
+ name: Date
353
+
354
+ description: Extends the Date native object to include methods useful in managing dates.
355
+
356
+ license: MIT-style license
357
+
358
+ authors:
359
+ - Aaron Newton
360
+ - Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/
361
+ - Harald Kirshner - mail [at] digitarald.de; http://digitarald.de
362
+ - Scott Kyle - scott [at] appden.com; http://appden.com
363
+
364
+ requires:
365
+ - Core/Array
366
+ - Core/String
367
+ - Core/Number
368
+ - MooTools.More
369
+ - Locale
370
+ - Locale.en-US.Date
371
+
372
+ provides: [Date]
373
+
374
+ ...
375
+ */
376
+
377
+ (function(){
378
+
379
+ var Date = this.Date;
380
+
381
+ var DateMethods = Date.Methods = {
382
+ ms: 'Milliseconds',
383
+ year: 'FullYear',
384
+ min: 'Minutes',
385
+ mo: 'Month',
386
+ sec: 'Seconds',
387
+ hr: 'Hours'
388
+ };
389
+
390
+ ['Date', 'Day', 'FullYear', 'Hours', 'Milliseconds', 'Minutes', 'Month', 'Seconds', 'Time', 'TimezoneOffset',
391
+ 'Week', 'Timezone', 'GMTOffset', 'DayOfYear', 'LastMonth', 'LastDayOfMonth', 'UTCDate', 'UTCDay', 'UTCFullYear',
392
+ 'AMPM', 'Ordinal', 'UTCHours', 'UTCMilliseconds', 'UTCMinutes', 'UTCMonth', 'UTCSeconds', 'UTCMilliseconds'].each(function(method){
393
+ Date.Methods[method.toLowerCase()] = method;
394
+ });
395
+
396
+ var pad = function(n, digits, string){
397
+ if (digits == 1) return n;
398
+ return n < Math.pow(10, digits - 1) ? (string || '0') + pad(n, digits - 1, string) : n;
399
+ };
400
+
401
+ Date.implement({
402
+
403
+ set: function(prop, value){
404
+ prop = prop.toLowerCase();
405
+ var method = DateMethods[prop] && 'set' + DateMethods[prop];
406
+ if (method && this[method]) this[method](value);
407
+ return this;
408
+ }.overloadSetter(),
409
+
410
+ get: function(prop){
411
+ prop = prop.toLowerCase();
412
+ var method = DateMethods[prop] && 'get' + DateMethods[prop];
413
+ if (method && this[method]) return this[method]();
414
+ return null;
415
+ }.overloadGetter(),
416
+
417
+ clone: function(){
418
+ return new Date(this.get('time'));
419
+ },
420
+
421
+ increment: function(interval, times){
422
+ interval = interval || 'day';
423
+ times = times != null ? times : 1;
424
+
425
+ switch (interval){
426
+ case 'year':
427
+ return this.increment('month', times * 12);
428
+ case 'month':
429
+ var d = this.get('date');
430
+ this.set('date', 1).set('mo', this.get('mo') + times);
431
+ return this.set('date', d.min(this.get('lastdayofmonth')));
432
+ case 'week':
433
+ return this.increment('day', times * 7);
434
+ case 'day':
435
+ return this.set('date', this.get('date') + times);
436
+ }
437
+
438
+ if (!Date.units[interval]) throw new Error(interval + ' is not a supported interval');
439
+
440
+ return this.set('time', this.get('time') + times * Date.units[interval]());
441
+ },
442
+
443
+ decrement: function(interval, times){
444
+ return this.increment(interval, -1 * (times != null ? times : 1));
445
+ },
446
+
447
+ isLeapYear: function(){
448
+ return Date.isLeapYear(this.get('year'));
449
+ },
450
+
451
+ clearTime: function(){
452
+ return this.set({hr: 0, min: 0, sec: 0, ms: 0});
453
+ },
454
+
455
+ diff: function(date, resolution){
456
+ if (typeOf(date) == 'string') date = Date.parse(date);
457
+
458
+ return ((date - this) / Date.units[resolution || 'day'](3, 3)).round(); // non-leap year, 30-day month
459
+ },
460
+
461
+ getLastDayOfMonth: function(){
462
+ return Date.daysInMonth(this.get('mo'), this.get('year'));
463
+ },
464
+
465
+ getDayOfYear: function(){
466
+ return (Date.UTC(this.get('year'), this.get('mo'), this.get('date') + 1)
467
+ - Date.UTC(this.get('year'), 0, 1)) / Date.units.day();
468
+ },
469
+
470
+ setDay: function(day, firstDayOfWeek){
471
+ if (firstDayOfWeek == null){
472
+ firstDayOfWeek = Date.getMsg('firstDayOfWeek');
473
+ if (firstDayOfWeek === '') firstDayOfWeek = 1;
474
+ }
475
+
476
+ day = (7 + Date.parseDay(day, true) - firstDayOfWeek) % 7;
477
+ var currentDay = (7 + this.get('day') - firstDayOfWeek) % 7;
478
+
479
+ return this.increment('day', day - currentDay);
480
+ },
481
+
482
+ getWeek: function(firstDayOfWeek){
483
+ if (firstDayOfWeek == null){
484
+ firstDayOfWeek = Date.getMsg('firstDayOfWeek');
485
+ if (firstDayOfWeek === '') firstDayOfWeek = 1;
486
+ }
487
+
488
+ var date = this,
489
+ dayOfWeek = (7 + date.get('day') - firstDayOfWeek) % 7,
490
+ dividend = 0,
491
+ firstDayOfYear;
492
+
493
+ if (firstDayOfWeek == 1){
494
+ // ISO-8601, week belongs to year that has the most days of the week (i.e. has the thursday of the week)
495
+ var month = date.get('month'),
496
+ startOfWeek = date.get('date') - dayOfWeek;
497
+
498
+ if (month == 11 && startOfWeek > 28) return 1; // Week 1 of next year
499
+
500
+ if (month == 0 && startOfWeek < -2){
501
+ // Use a date from last year to determine the week
502
+ date = new Date(date).decrement('day', dayOfWeek);
503
+ dayOfWeek = 0;
504
+ }
505
+
506
+ firstDayOfYear = new Date(date.get('year'), 0, 1).get('day') || 7;
507
+ if (firstDayOfYear > 4) dividend = -7; // First week of the year is not week 1
508
+ } else {
509
+ // In other cultures the first week of the year is always week 1 and the last week always 53 or 54.
510
+ // Days in the same week can have a different weeknumber if the week spreads across two years.
511
+ firstDayOfYear = new Date(date.get('year'), 0, 1).get('day');
512
+ }
513
+
514
+ dividend += date.get('dayofyear');
515
+ dividend += 6 - dayOfWeek; // Add days so we calculate the current date's week as a full week
516
+ dividend += (7 + firstDayOfYear - firstDayOfWeek) % 7; // Make up for first week of the year not being a full week
517
+
518
+ return (dividend / 7);
519
+ },
520
+
521
+ getOrdinal: function(day){
522
+ return Date.getMsg('ordinal', day || this.get('date'));
523
+ },
524
+
525
+ getTimezone: function(){
526
+ return this.toString()
527
+ .replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/, '$1')
528
+ .replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, '$1$2$3');
529
+ },
530
+
531
+ getGMTOffset: function(){
532
+ var off = this.get('timezoneOffset');
533
+ return ((off > 0) ? '-' : '+') + pad((off.abs() / 60).floor(), 2) + pad(off % 60, 2);
534
+ },
535
+
536
+ setAMPM: function(ampm){
537
+ ampm = ampm.toUpperCase();
538
+ var hr = this.get('hr');
539
+ if (hr > 11 && ampm == 'AM') return this.decrement('hour', 12);
540
+ else if (hr < 12 && ampm == 'PM') return this.increment('hour', 12);
541
+ return this;
542
+ },
543
+
544
+ getAMPM: function(){
545
+ return (this.get('hr') < 12) ? 'AM' : 'PM';
546
+ },
547
+
548
+ parse: function(str){
549
+ this.set('time', Date.parse(str));
550
+ return this;
551
+ },
552
+
553
+ isValid: function(date){
554
+ if (!date) date = this;
555
+ return typeOf(date) == 'date' && !isNaN(date.valueOf());
556
+ },
557
+
558
+ format: function(format){
559
+ if (!this.isValid()) return 'invalid date';
560
+
561
+ if (!format) format = '%x %X';
562
+ if (typeof format == 'string') format = formats[format.toLowerCase()] || format;
563
+ if (typeof format == 'function') return format(this);
564
+
565
+ var d = this;
566
+ return format.replace(/%([a-z%])/gi,
567
+ function($0, $1){
568
+ switch ($1){
569
+ case 'a': return Date.getMsg('days_abbr')[d.get('day')];
570
+ case 'A': return Date.getMsg('days')[d.get('day')];
571
+ case 'b': return Date.getMsg('months_abbr')[d.get('month')];
572
+ case 'B': return Date.getMsg('months')[d.get('month')];
573
+ case 'c': return d.format('%a %b %d %H:%M:%S %Y');
574
+ case 'd': return pad(d.get('date'), 2);
575
+ case 'e': return pad(d.get('date'), 2, ' ');
576
+ case 'H': return pad(d.get('hr'), 2);
577
+ case 'I': return pad((d.get('hr') % 12) || 12, 2);
578
+ case 'j': return pad(d.get('dayofyear'), 3);
579
+ case 'k': return pad(d.get('hr'), 2, ' ');
580
+ case 'l': return pad((d.get('hr') % 12) || 12, 2, ' ');
581
+ case 'L': return pad(d.get('ms'), 3);
582
+ case 'm': return pad((d.get('mo') + 1), 2);
583
+ case 'M': return pad(d.get('min'), 2);
584
+ case 'o': return d.get('ordinal');
585
+ case 'p': return Date.getMsg(d.get('ampm'));
586
+ case 's': return Math.round(d / 1000);
587
+ case 'S': return pad(d.get('seconds'), 2);
588
+ case 'T': return d.format('%H:%M:%S');
589
+ case 'U': return pad(d.get('week'), 2);
590
+ case 'w': return d.get('day');
591
+ case 'x': return d.format(Date.getMsg('shortDate'));
592
+ case 'X': return d.format(Date.getMsg('shortTime'));
593
+ case 'y': return d.get('year').toString().substr(2);
594
+ case 'Y': return d.get('year');
595
+ case 'z': return d.get('GMTOffset');
596
+ case 'Z': return d.get('Timezone');
597
+ }
598
+ return $1;
599
+ }
600
+ );
601
+ },
602
+
603
+ toISOString: function(){
604
+ return this.format('iso8601');
605
+ }
606
+
607
+ }).alias({
608
+ toJSON: 'toISOString',
609
+ compare: 'diff',
610
+ strftime: 'format'
611
+ });
612
+
613
+ // The day and month abbreviations are standardized, so we cannot use simply %a and %b because they will get localized
614
+ var rfcDayAbbr = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
615
+ rfcMonthAbbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
616
+
617
+ var formats = {
618
+ db: '%Y-%m-%d %H:%M:%S',
619
+ compact: '%Y%m%dT%H%M%S',
620
+ 'short': '%d %b %H:%M',
621
+ 'long': '%B %d, %Y %H:%M',
622
+ rfc822: function(date){
623
+ return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %Z');
624
+ },
625
+ rfc2822: function(date){
626
+ return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %z');
627
+ },
628
+ iso8601: function(date){
629
+ return (
630
+ date.getUTCFullYear() + '-' +
631
+ pad(date.getUTCMonth() + 1, 2) + '-' +
632
+ pad(date.getUTCDate(), 2) + 'T' +
633
+ pad(date.getUTCHours(), 2) + ':' +
634
+ pad(date.getUTCMinutes(), 2) + ':' +
635
+ pad(date.getUTCSeconds(), 2) + '.' +
636
+ pad(date.getUTCMilliseconds(), 3) + 'Z'
637
+ );
638
+ }
639
+ };
640
+
641
+ var parsePatterns = [],
642
+ nativeParse = Date.parse;
643
+
644
+ var parseWord = function(type, word, num){
645
+ var ret = -1,
646
+ translated = Date.getMsg(type + 's');
647
+ switch (typeOf(word)){
648
+ case 'object':
649
+ ret = translated[word.get(type)];
650
+ break;
651
+ case 'number':
652
+ ret = translated[word];
653
+ if (!ret) throw new Error('Invalid ' + type + ' index: ' + word);
654
+ break;
655
+ case 'string':
656
+ var match = translated.filter(function(name){
657
+ return this.test(name);
658
+ }, new RegExp('^' + word, 'i'));
659
+ if (!match.length) throw new Error('Invalid ' + type + ' string');
660
+ if (match.length > 1) throw new Error('Ambiguous ' + type);
661
+ ret = match[0];
662
+ }
663
+
664
+ return (num) ? translated.indexOf(ret) : ret;
665
+ };
666
+
667
+ var startCentury = 1900,
668
+ startYear = 70;
669
+
670
+ Date.extend({
671
+
672
+ getMsg: function(key, args){
673
+ return Locale.get('Date.' + key, args);
674
+ },
675
+
676
+ units: {
677
+ ms: Function.from(1),
678
+ second: Function.from(1000),
679
+ minute: Function.from(60000),
680
+ hour: Function.from(3600000),
681
+ day: Function.from(86400000),
682
+ week: Function.from(608400000),
683
+ month: function(month, year){
684
+ var d = new Date;
685
+ return Date.daysInMonth(month != null ? month : d.get('mo'), year != null ? year : d.get('year')) * 86400000;
686
+ },
687
+ year: function(year){
688
+ year = year || new Date().get('year');
689
+ return Date.isLeapYear(year) ? 31622400000 : 31536000000;
690
+ }
691
+ },
692
+
693
+ daysInMonth: function(month, year){
694
+ return [31, Date.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
695
+ },
696
+
697
+ isLeapYear: function(year){
698
+ return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
699
+ },
700
+
701
+ parse: function(from){
702
+ var t = typeOf(from);
703
+ if (t == 'number') return new Date(from);
704
+ if (t != 'string') return from;
705
+ from = from.clean();
706
+ if (!from.length) return null;
707
+
708
+ var parsed;
709
+ parsePatterns.some(function(pattern){
710
+ var bits = pattern.re.exec(from);
711
+ return (bits) ? (parsed = pattern.handler(bits)) : false;
712
+ });
713
+
714
+ if (!(parsed && parsed.isValid())){
715
+ parsed = new Date(nativeParse(from));
716
+ if (!(parsed && parsed.isValid())) parsed = new Date(from.toInt());
717
+ }
718
+ return parsed;
719
+ },
720
+
721
+ parseDay: function(day, num){
722
+ return parseWord('day', day, num);
723
+ },
724
+
725
+ parseMonth: function(month, num){
726
+ return parseWord('month', month, num);
727
+ },
728
+
729
+ parseUTC: function(value){
730
+ var localDate = new Date(value);
731
+ var utcSeconds = Date.UTC(
732
+ localDate.get('year'),
733
+ localDate.get('mo'),
734
+ localDate.get('date'),
735
+ localDate.get('hr'),
736
+ localDate.get('min'),
737
+ localDate.get('sec'),
738
+ localDate.get('ms')
739
+ );
740
+ return new Date(utcSeconds);
741
+ },
742
+
743
+ orderIndex: function(unit){
744
+ return Date.getMsg('dateOrder').indexOf(unit) + 1;
745
+ },
746
+
747
+ defineFormat: function(name, format){
748
+ formats[name] = format;
749
+ return this;
750
+ },
751
+
752
+
753
+
754
+ defineParser: function(pattern){
755
+ parsePatterns.push((pattern.re && pattern.handler) ? pattern : build(pattern));
756
+ return this;
757
+ },
758
+
759
+ defineParsers: function(){
760
+ Array.flatten(arguments).each(Date.defineParser);
761
+ return this;
762
+ },
763
+
764
+ define2DigitYearStart: function(year){
765
+ startYear = year % 100;
766
+ startCentury = year - startYear;
767
+ return this;
768
+ }
769
+
770
+ }).extend({
771
+ defineFormats: Date.defineFormat.overloadSetter()
772
+ });
773
+
774
+ var regexOf = function(type){
775
+ return new RegExp('(?:' + Date.getMsg(type).map(function(name){
776
+ return name.substr(0, 3);
777
+ }).join('|') + ')[a-z]*');
778
+ };
779
+
780
+ var replacers = function(key){
781
+ switch (key){
782
+ case 'T':
783
+ return '%H:%M:%S';
784
+ case 'x': // iso8601 covers yyyy-mm-dd, so just check if month is first
785
+ return ((Date.orderIndex('month') == 1) ? '%m[-./]%d' : '%d[-./]%m') + '([-./]%y)?';
786
+ case 'X':
787
+ return '%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%z?';
788
+ }
789
+ return null;
790
+ };
791
+
792
+ var keys = {
793
+ d: /[0-2]?[0-9]|3[01]/,
794
+ H: /[01]?[0-9]|2[0-3]/,
795
+ I: /0?[1-9]|1[0-2]/,
796
+ M: /[0-5]?\d/,
797
+ s: /\d+/,
798
+ o: /[a-z]*/,
799
+ p: /[ap]\.?m\.?/,
800
+ y: /\d{2}|\d{4}/,
801
+ Y: /\d{4}/,
802
+ z: /Z|[+-]\d{2}(?::?\d{2})?/
803
+ };
804
+
805
+ keys.m = keys.I;
806
+ keys.S = keys.M;
807
+
808
+ var currentLanguage;
809
+
810
+ var recompile = function(language){
811
+ currentLanguage = language;
812
+
813
+ keys.a = keys.A = regexOf('days');
814
+ keys.b = keys.B = regexOf('months');
815
+
816
+ parsePatterns.each(function(pattern, i){
817
+ if (pattern.format) parsePatterns[i] = build(pattern.format);
818
+ });
819
+ };
820
+
821
+ var build = function(format){
822
+ if (!currentLanguage) return {format: format};
823
+
824
+ var parsed = [];
825
+ var re = (format.source || format) // allow format to be regex
826
+ .replace(/%([a-z])/gi,
827
+ function($0, $1){
828
+ return replacers($1) || $0;
829
+ }
830
+ ).replace(/\((?!\?)/g, '(?:') // make all groups non-capturing
831
+ .replace(/ (?!\?|\*)/g, ',? ') // be forgiving with spaces and commas
832
+ .replace(/%([a-z%])/gi,
833
+ function($0, $1){
834
+ var p = keys[$1];
835
+ if (!p) return $1;
836
+ parsed.push($1);
837
+ return '(' + p.source + ')';
838
+ }
839
+ ).replace(/\[a-z\]/gi, '[a-z\\u00c0-\\uffff;\&]'); // handle unicode words
840
+
841
+ return {
842
+ format: format,
843
+ re: new RegExp('^' + re + '$', 'i'),
844
+ handler: function(bits){
845
+ bits = bits.slice(1).associate(parsed);
846
+ var date = new Date().clearTime(),
847
+ year = bits.y || bits.Y;
848
+
849
+ if (year != null) handle.call(date, 'y', year); // need to start in the right year
850
+ if ('d' in bits) handle.call(date, 'd', 1);
851
+ if ('m' in bits || bits.b || bits.B) handle.call(date, 'm', 1);
852
+
853
+ for (var key in bits) handle.call(date, key, bits[key]);
854
+ return date;
855
+ }
856
+ };
857
+ };
858
+
859
+ var handle = function(key, value){
860
+ if (!value) return this;
861
+
862
+ switch (key){
863
+ case 'a': case 'A': return this.set('day', Date.parseDay(value, true));
864
+ case 'b': case 'B': return this.set('mo', Date.parseMonth(value, true));
865
+ case 'd': return this.set('date', value);
866
+ case 'H': case 'I': return this.set('hr', value);
867
+ case 'm': return this.set('mo', value - 1);
868
+ case 'M': return this.set('min', value);
869
+ case 'p': return this.set('ampm', value.replace(/\./g, ''));
870
+ case 'S': return this.set('sec', value);
871
+ case 's': return this.set('ms', ('0.' + value) * 1000);
872
+ case 'w': return this.set('day', value);
873
+ case 'Y': return this.set('year', value);
874
+ case 'y':
875
+ value = +value;
876
+ if (value < 100) value += startCentury + (value < startYear ? 100 : 0);
877
+ return this.set('year', value);
878
+ case 'z':
879
+ if (value == 'Z') value = '+00';
880
+ var offset = value.match(/([+-])(\d{2}):?(\d{2})?/);
881
+ offset = (offset[1] + '1') * (offset[2] * 60 + (+offset[3] || 0)) + this.getTimezoneOffset();
882
+ return this.set('time', this - offset * 60000);
883
+ }
884
+
885
+ return this;
886
+ };
887
+
888
+ Date.defineParsers(
889
+ '%Y([-./]%m([-./]%d((T| )%X)?)?)?', // "1999-12-31", "1999-12-31 11:59pm", "1999-12-31 23:59:59", ISO8601
890
+ '%Y%m%d(T%H(%M%S?)?)?', // "19991231", "19991231T1159", compact
891
+ '%x( %X)?', // "12/31", "12.31.99", "12-31-1999", "12/31/2008 11:59 PM"
892
+ '%d%o( %b( %Y)?)?( %X)?', // "31st", "31st December", "31 Dec 1999", "31 Dec 1999 11:59pm"
893
+ '%b( %d%o)?( %Y)?( %X)?', // Same as above with month and day switched
894
+ '%Y %b( %d%o( %X)?)?', // Same as above with year coming first
895
+ '%o %b %d %X %z %Y', // "Thu Oct 22 08:11:23 +0000 2009"
896
+ '%T', // %H:%M:%S
897
+ '%H:%M( ?%p)?' // "11:05pm", "11:05 am" and "11:05"
898
+ );
899
+
900
+ Locale.addEvent('change', function(language){
901
+ if (Locale.get('Date')) recompile(language);
902
+ }).fireEvent('change', Locale.getCurrent());
903
+
904
+ })();
905
+
906
+
39
907
  /*
40
908
  ---
41
909
 
@@ -851,11 +1719,13 @@ var Sortables = new Class({
851
1719
  /*
852
1720
  ---
853
1721
 
854
- script: Object.Extras.js
1722
+ script: Element.Measure.js
855
1723
 
856
- name: Object.Extras
1724
+ name: Element.Measure
857
1725
 
858
- description: Extra Object generics, like getFromPath which allows a path notation to child elements.
1726
+ description: Extends the Element native object to include methods useful in measuring dimensions.
1727
+
1728
+ credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
859
1729
 
860
1730
  license: MIT-style license
861
1731
 
@@ -863,52 +1733,151 @@ authors:
863
1733
  - Aaron Newton
864
1734
 
865
1735
  requires:
866
- - Core/Object
1736
+ - Core/Element.Style
1737
+ - Core/Element.Dimensions
867
1738
  - /MooTools.More
868
1739
 
869
- provides: [Object.Extras]
1740
+ provides: [Element.Measure]
870
1741
 
871
1742
  ...
872
1743
  */
873
1744
 
874
1745
  (function(){
875
1746
 
876
- var defined = function(value){
877
- return value != null;
1747
+ var getStylesList = function(styles, planes){
1748
+ var list = [];
1749
+ Object.each(planes, function(directions){
1750
+ Object.each(directions, function(edge){
1751
+ styles.each(function(style){
1752
+ list.push(style + '-' + edge + (style == 'border' ? '-width' : ''));
1753
+ });
1754
+ });
1755
+ });
1756
+ return list;
878
1757
  };
879
1758
 
880
- var hasOwnProperty = Object.prototype.hasOwnProperty;
1759
+ var calculateEdgeSize = function(edge, styles){
1760
+ var total = 0;
1761
+ Object.each(styles, function(value, style){
1762
+ if (style.test(edge)) total = total + value.toInt();
1763
+ });
1764
+ return total;
1765
+ };
881
1766
 
882
- Object.extend({
1767
+ var isVisible = function(el){
1768
+ return !!(!el || el.offsetHeight || el.offsetWidth);
1769
+ };
883
1770
 
884
- getFromPath: function(source, parts){
885
- if (typeof parts == 'string') parts = parts.split('.');
886
- for (var i = 0, l = parts.length; i < l; i++){
887
- if (hasOwnProperty.call(source, parts[i])) source = source[parts[i]];
888
- else return null;
1771
+
1772
+ Element.implement({
1773
+
1774
+ measure: function(fn){
1775
+ if (isVisible(this)) return fn.call(this);
1776
+ var parent = this.getParent(),
1777
+ toMeasure = [];
1778
+ while (!isVisible(parent) && parent != document.body){
1779
+ toMeasure.push(parent.expose());
1780
+ parent = parent.getParent();
889
1781
  }
890
- return source;
1782
+ var restore = this.expose(),
1783
+ result = fn.call(this);
1784
+ restore();
1785
+ toMeasure.each(function(restore){
1786
+ restore();
1787
+ });
1788
+ return result;
891
1789
  },
892
1790
 
893
- cleanValues: function(object, method){
894
- method = method || defined;
895
- for (var key in object) if (!method(object[key])){
896
- delete object[key];
1791
+ expose: function(){
1792
+ if (this.getStyle('display') != 'none') return function(){};
1793
+ var before = this.style.cssText;
1794
+ this.setStyles({
1795
+ display: 'block',
1796
+ position: 'absolute',
1797
+ visibility: 'hidden'
1798
+ });
1799
+ return function(){
1800
+ this.style.cssText = before;
1801
+ }.bind(this);
1802
+ },
1803
+
1804
+ getDimensions: function(options){
1805
+ options = Object.merge({computeSize: false}, options);
1806
+ var dim = {x: 0, y: 0};
1807
+
1808
+ var getSize = function(el, options){
1809
+ return (options.computeSize) ? el.getComputedSize(options) : el.getSize();
1810
+ };
1811
+
1812
+ var parent = this.getParent('body');
1813
+
1814
+ if (parent && this.getStyle('display') == 'none'){
1815
+ dim = this.measure(function(){
1816
+ return getSize(this, options);
1817
+ });
1818
+ } else if (parent){
1819
+ try { //safari sometimes crashes here, so catch it
1820
+ dim = getSize(this, options);
1821
+ }catch(e){}
897
1822
  }
898
- return object;
899
- },
900
1823
 
901
- erase: function(object, key){
902
- if (hasOwnProperty.call(object, key)) delete object[key];
903
- return object;
1824
+ return Object.append(dim, (dim.x || dim.x === 0) ? {
1825
+ width: dim.x,
1826
+ height: dim.y
1827
+ } : {
1828
+ x: dim.width,
1829
+ y: dim.height
1830
+ }
1831
+ );
904
1832
  },
905
1833
 
906
- run: function(object){
907
- var args = Array.slice(arguments, 1);
908
- for (var key in object) if (object[key].apply){
909
- object[key].apply(object, args);
1834
+ getComputedSize: function(options){
1835
+
1836
+
1837
+ options = Object.merge({
1838
+ styles: ['padding','border'],
1839
+ planes: {
1840
+ height: ['top','bottom'],
1841
+ width: ['left','right']
1842
+ },
1843
+ mode: 'both'
1844
+ }, options);
1845
+
1846
+ var styles = {},
1847
+ size = {width: 0, height: 0},
1848
+ dimensions;
1849
+
1850
+ if (options.mode == 'vertical'){
1851
+ delete size.width;
1852
+ delete options.planes.width;
1853
+ } else if (options.mode == 'horizontal'){
1854
+ delete size.height;
1855
+ delete options.planes.height;
910
1856
  }
911
- return object;
1857
+
1858
+ getStylesList(options.styles, options.planes).each(function(style){
1859
+ styles[style] = this.getStyle(style).toInt();
1860
+ }, this);
1861
+
1862
+ Object.each(options.planes, function(edges, plane){
1863
+
1864
+ var capitalized = plane.capitalize(),
1865
+ style = this.getStyle(plane);
1866
+
1867
+ if (style == 'auto' && !dimensions) dimensions = this.getDimensions();
1868
+
1869
+ style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt();
1870
+ size['total' + capitalized] = style;
1871
+
1872
+ edges.each(function(edge){
1873
+ var edgesize = calculateEdgeSize(edge, styles);
1874
+ size['computed' + edge.capitalize()] = edgesize;
1875
+ size['total' + capitalized] += edgesize;
1876
+ });
1877
+
1878
+ }, this);
1879
+
1880
+ return Object.append(size, styles);
912
1881
  }
913
1882
 
914
1883
  });
@@ -919,177 +1888,288 @@ Object.extend({
919
1888
  /*
920
1889
  ---
921
1890
 
922
- script: Locale.js
1891
+ script: Element.Position.js
923
1892
 
924
- name: Locale
1893
+ name: Element.Position
925
1894
 
926
- description: Provides methods for localization.
1895
+ description: Extends the Element native object to include methods useful positioning elements relative to others.
927
1896
 
928
1897
  license: MIT-style license
929
1898
 
930
1899
  authors:
931
1900
  - Aaron Newton
932
- - Arian Stolwijk
1901
+ - Jacob Thornton
933
1902
 
934
1903
  requires:
935
- - Core/Events
936
- - /Object.Extras
937
- - /MooTools.More
1904
+ - Core/Options
1905
+ - Core/Element.Dimensions
1906
+ - Element.Measure
938
1907
 
939
- provides: [Locale, Lang]
1908
+ provides: [Element.Position]
940
1909
 
941
1910
  ...
942
1911
  */
943
1912
 
944
- (function(){
1913
+ (function(original){
945
1914
 
946
- var current = null,
947
- locales = {},
948
- inherits = {};
1915
+ var local = Element.Position = {
949
1916
 
950
- var getSet = function(set){
951
- if (instanceOf(set, Locale.Set)) return set;
952
- else return locales[set];
953
- };
1917
+ options: {/*
1918
+ edge: false,
1919
+ returnPos: false,
1920
+ minimum: {x: 0, y: 0},
1921
+ maximum: {x: 0, y: 0},
1922
+ relFixedPosition: false,
1923
+ ignoreMargins: false,
1924
+ ignoreScroll: false,
1925
+ allowNegative: false,*/
1926
+ relativeTo: document.body,
1927
+ position: {
1928
+ x: 'center', //left, center, right
1929
+ y: 'center' //top, center, bottom
1930
+ },
1931
+ offset: {x: 0, y: 0}
1932
+ },
954
1933
 
955
- var Locale = this.Locale = {
1934
+ getOptions: function(element, options){
1935
+ options = Object.merge({}, local.options, options);
1936
+ local.setPositionOption(options);
1937
+ local.setEdgeOption(options);
1938
+ local.setOffsetOption(element, options);
1939
+ local.setDimensionsOption(element, options);
1940
+ return options;
1941
+ },
956
1942
 
957
- define: function(locale, set, key, value){
958
- var name;
959
- if (instanceOf(locale, Locale.Set)){
960
- name = locale.name;
961
- if (name) locales[name] = locale;
962
- } else {
963
- name = locale;
964
- if (!locales[name]) locales[name] = new Locale.Set(name);
965
- locale = locales[name];
966
- }
1943
+ setPositionOption: function(options){
1944
+ options.position = local.getCoordinateFromValue(options.position);
1945
+ },
967
1946
 
968
- if (set) locale.define(set, key, value);
1947
+ setEdgeOption: function(options){
1948
+ var edgeOption = local.getCoordinateFromValue(options.edge);
1949
+ options.edge = edgeOption ? edgeOption :
1950
+ (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} :
1951
+ {x: 'left', y: 'top'};
1952
+ },
969
1953
 
970
-
1954
+ setOffsetOption: function(element, options){
1955
+ var parentOffset = {x: 0, y: 0},
1956
+ offsetParent = element.measure(function(){
1957
+ return document.id(this.getOffsetParent());
1958
+ }),
1959
+ parentScroll = offsetParent.getScroll();
1960
+
1961
+ if (!offsetParent || offsetParent == element.getDocument().body) return;
1962
+ parentOffset = offsetParent.measure(function(){
1963
+ var position = this.getPosition();
1964
+ if (this.getStyle('position') == 'fixed'){
1965
+ var scroll = window.getScroll();
1966
+ position.x += scroll.x;
1967
+ position.y += scroll.y;
1968
+ }
1969
+ return position;
1970
+ });
971
1971
 
972
- if (!current) current = locale;
1972
+ options.offset = {
1973
+ parentPositioned: offsetParent != document.id(options.relativeTo),
1974
+ x: options.offset.x - parentOffset.x + parentScroll.x,
1975
+ y: options.offset.y - parentOffset.y + parentScroll.y
1976
+ };
1977
+ },
973
1978
 
974
- return locale;
1979
+ setDimensionsOption: function(element, options){
1980
+ options.dimensions = element.getDimensions({
1981
+ computeSize: true,
1982
+ styles: ['padding', 'border', 'margin']
1983
+ });
975
1984
  },
976
1985
 
977
- use: function(locale){
978
- locale = getSet(locale);
1986
+ getPosition: function(element, options){
1987
+ var position = {};
1988
+ options = local.getOptions(element, options);
1989
+ var relativeTo = document.id(options.relativeTo) || document.body;
979
1990
 
980
- if (locale){
981
- current = locale;
1991
+ local.setPositionCoordinates(options, position, relativeTo);
1992
+ if (options.edge) local.toEdge(position, options);
982
1993
 
983
- this.fireEvent('change', locale);
1994
+ var offset = options.offset;
1995
+ position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt();
1996
+ position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt();
984
1997
 
985
-
1998
+ local.toMinMax(position, options);
1999
+
2000
+ if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position);
2001
+ if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position);
2002
+ if (options.ignoreMargins) local.toIgnoreMargins(position, options);
2003
+
2004
+ position.left = Math.ceil(position.left);
2005
+ position.top = Math.ceil(position.top);
2006
+ delete position.x;
2007
+ delete position.y;
2008
+
2009
+ return position;
2010
+ },
2011
+
2012
+ setPositionCoordinates: function(options, position, relativeTo){
2013
+ var offsetY = options.offset.y,
2014
+ offsetX = options.offset.x,
2015
+ calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(),
2016
+ top = calc.y,
2017
+ left = calc.x,
2018
+ winSize = window.getSize();
2019
+
2020
+ switch(options.position.x){
2021
+ case 'left': position.x = left + offsetX; break;
2022
+ case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break;
2023
+ default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break;
986
2024
  }
987
2025
 
988
- return this;
2026
+ switch(options.position.y){
2027
+ case 'top': position.y = top + offsetY; break;
2028
+ case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break;
2029
+ default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break;
2030
+ }
989
2031
  },
990
2032
 
991
- getCurrent: function(){
992
- return current;
2033
+ toMinMax: function(position, options){
2034
+ var xy = {left: 'x', top: 'y'}, value;
2035
+ ['minimum', 'maximum'].each(function(minmax){
2036
+ ['left', 'top'].each(function(lr){
2037
+ value = options[minmax] ? options[minmax][xy[lr]] : null;
2038
+ if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value;
2039
+ });
2040
+ });
993
2041
  },
994
2042
 
995
- get: function(key, args){
996
- return (current) ? current.get(key, args) : '';
2043
+ toRelFixedPosition: function(relativeTo, position){
2044
+ var winScroll = window.getScroll();
2045
+ position.top += winScroll.y;
2046
+ position.left += winScroll.x;
997
2047
  },
998
2048
 
999
- inherit: function(locale, inherits, set){
1000
- locale = getSet(locale);
2049
+ toIgnoreScroll: function(relativeTo, position){
2050
+ var relScroll = relativeTo.getScroll();
2051
+ position.top -= relScroll.y;
2052
+ position.left -= relScroll.x;
2053
+ },
1001
2054
 
1002
- if (locale) locale.inherit(inherits, set);
1003
- return this;
2055
+ toIgnoreMargins: function(position, options){
2056
+ position.left += options.edge.x == 'right'
2057
+ ? options.dimensions['margin-right']
2058
+ : (options.edge.x != 'center'
2059
+ ? -options.dimensions['margin-left']
2060
+ : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2));
2061
+
2062
+ position.top += options.edge.y == 'bottom'
2063
+ ? options.dimensions['margin-bottom']
2064
+ : (options.edge.y != 'center'
2065
+ ? -options.dimensions['margin-top']
2066
+ : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2));
1004
2067
  },
1005
2068
 
1006
- list: function(){
1007
- return Object.keys(locales);
1008
- }
2069
+ toEdge: function(position, options){
2070
+ var edgeOffset = {},
2071
+ dimensions = options.dimensions,
2072
+ edge = options.edge;
1009
2073
 
1010
- };
2074
+ switch(edge.x){
2075
+ case 'left': edgeOffset.x = 0; break;
2076
+ case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break;
2077
+ // center
2078
+ default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break;
2079
+ }
1011
2080
 
1012
- Object.append(Locale, new Events);
2081
+ switch(edge.y){
2082
+ case 'top': edgeOffset.y = 0; break;
2083
+ case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break;
2084
+ // center
2085
+ default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break;
2086
+ }
1013
2087
 
1014
- Locale.Set = new Class({
2088
+ position.x += edgeOffset.x;
2089
+ position.y += edgeOffset.y;
2090
+ },
1015
2091
 
1016
- sets: {},
2092
+ getCoordinateFromValue: function(option){
2093
+ if (typeOf(option) != 'string') return option;
2094
+ option = option.toLowerCase();
1017
2095
 
1018
- inherits: {
1019
- locales: [],
1020
- sets: {}
1021
- },
2096
+ return {
2097
+ x: option.test('left') ? 'left'
2098
+ : (option.test('right') ? 'right' : 'center'),
2099
+ y: option.test(/upper|top/) ? 'top'
2100
+ : (option.test('bottom') ? 'bottom' : 'center')
2101
+ };
2102
+ }
1022
2103
 
1023
- initialize: function(name){
1024
- this.name = name || '';
1025
- },
2104
+ };
1026
2105
 
1027
- define: function(set, key, value){
1028
- var defineData = this.sets[set];
1029
- if (!defineData) defineData = {};
2106
+ Element.implement({
1030
2107
 
1031
- if (key){
1032
- if (typeOf(key) == 'object') defineData = Object.merge(defineData, key);
1033
- else defineData[key] = value;
2108
+ position: function(options){
2109
+ if (options && (options.x != null || options.y != null)){
2110
+ return (original ? original.apply(this, arguments) : this);
1034
2111
  }
1035
- this.sets[set] = defineData;
1036
-
1037
- return this;
2112
+ var position = this.setStyle('position', 'absolute').calculatePosition(options);
2113
+ return (options && options.returnPos) ? position : this.setStyles(position);
1038
2114
  },
1039
2115
 
1040
- get: function(key, args, _base){
1041
- var value = Object.getFromPath(this.sets, key);
1042
- if (value != null){
1043
- var type = typeOf(value);
1044
- if (type == 'function') value = value.apply(null, Array.from(args));
1045
- else if (type == 'object') value = Object.clone(value);
1046
- return value;
1047
- }
2116
+ calculatePosition: function(options){
2117
+ return local.getPosition(this, options);
2118
+ }
1048
2119
 
1049
- // get value of inherited locales
1050
- var index = key.indexOf('.'),
1051
- set = index < 0 ? key : key.substr(0, index),
1052
- names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include('en-US');
1053
- if (!_base) _base = [];
2120
+ });
1054
2121
 
1055
- for (var i = 0, l = names.length; i < l; i++){
1056
- if (_base.contains(names[i])) continue;
1057
- _base.include(names[i]);
2122
+ })(Element.prototype.position);
1058
2123
 
1059
- var locale = locales[names[i]];
1060
- if (!locale) continue;
1061
2124
 
1062
- value = locale.get(key, args, _base);
1063
- if (value != null) return value;
1064
- }
2125
+ /*
2126
+ ---
1065
2127
 
1066
- return '';
1067
- },
2128
+ script: Class.Occlude.js
1068
2129
 
1069
- inherit: function(names, set){
1070
- names = Array.from(names);
2130
+ name: Class.Occlude
1071
2131
 
1072
- if (set && !this.inherits.sets[set]) this.inherits.sets[set] = [];
2132
+ description: Prevents a class from being applied to a DOM element twice.
1073
2133
 
1074
- var l = names.length;
1075
- while (l--) (set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]);
2134
+ license: MIT-style license.
1076
2135
 
1077
- return this;
1078
- }
2136
+ authors:
2137
+ - Aaron Newton
1079
2138
 
1080
- });
2139
+ requires:
2140
+ - Core/Class
2141
+ - Core/Element
2142
+ - /MooTools.More
1081
2143
 
2144
+ provides: [Class.Occlude]
1082
2145
 
2146
+ ...
2147
+ */
1083
2148
 
1084
- })();
2149
+ Class.Occlude = new Class({
2150
+
2151
+ occlude: function(property, element){
2152
+ element = document.id(element || this.element);
2153
+ var instance = element.retrieve(property || this.property);
2154
+ if (instance && !this.occluded)
2155
+ return (this.occluded = instance);
2156
+
2157
+ this.occluded = false;
2158
+ element.store(property || this.property, this);
2159
+ return this.occluded;
2160
+ }
2161
+
2162
+ });
1085
2163
 
1086
2164
 
1087
2165
  /*
1088
2166
  ---
1089
2167
 
1090
- name: Locale.en-US.Date
2168
+ script: IframeShim.js
1091
2169
 
1092
- description: Date messages for US English.
2170
+ name: IframeShim
2171
+
2172
+ description: Defines IframeShim, a class for obscuring select lists and flash objects in IE.
1093
2173
 
1094
2174
  license: MIT-style license
1095
2175
 
@@ -1097,62 +2177,120 @@ authors:
1097
2177
  - Aaron Newton
1098
2178
 
1099
2179
  requires:
1100
- - /Locale
2180
+ - Core/Element.Event
2181
+ - Core/Element.Style
2182
+ - Core/Options
2183
+ - Core/Events
2184
+ - /Element.Position
2185
+ - /Class.Occlude
1101
2186
 
1102
- provides: [Locale.en-US.Date]
2187
+ provides: [IframeShim]
1103
2188
 
1104
2189
  ...
1105
2190
  */
1106
2191
 
1107
- Locale.define('en-US', 'Date', {
2192
+ var IframeShim = new Class({
1108
2193
 
1109
- months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1110
- months_abbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1111
- days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
1112
- days_abbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
2194
+ Implements: [Options, Events, Class.Occlude],
1113
2195
 
1114
- // Culture's date order: MM/DD/YYYY
1115
- dateOrder: ['month', 'date', 'year'],
1116
- shortDate: '%m/%d/%Y',
1117
- shortTime: '%I:%M%p',
1118
- AM: 'AM',
1119
- PM: 'PM',
1120
- firstDayOfWeek: 0,
2196
+ options: {
2197
+ className: 'iframeShim',
2198
+ src: 'javascript:false;document.write("");',
2199
+ display: false,
2200
+ zIndex: null,
2201
+ margin: 0,
2202
+ offset: {x: 0, y: 0},
2203
+ browsers: (Browser.ie6 || (Browser.firefox && Browser.version < 3 && Browser.Platform.mac))
2204
+ },
1121
2205
 
1122
- // Date.Extras
1123
- ordinal: function(dayOfMonth){
1124
- // 1st, 2nd, 3rd, etc.
1125
- return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
2206
+ property: 'IframeShim',
2207
+
2208
+ initialize: function(element, options){
2209
+ this.element = document.id(element);
2210
+ if (this.occlude()) return this.occluded;
2211
+ this.setOptions(options);
2212
+ this.makeShim();
2213
+ return this;
1126
2214
  },
1127
2215
 
1128
- lessThanMinuteAgo: 'less than a minute ago',
1129
- minuteAgo: 'about a minute ago',
1130
- minutesAgo: '{delta} minutes ago',
1131
- hourAgo: 'about an hour ago',
1132
- hoursAgo: 'about {delta} hours ago',
1133
- dayAgo: '1 day ago',
1134
- daysAgo: '{delta} days ago',
1135
- weekAgo: '1 week ago',
1136
- weeksAgo: '{delta} weeks ago',
1137
- monthAgo: '1 month ago',
1138
- monthsAgo: '{delta} months ago',
1139
- yearAgo: '1 year ago',
1140
- yearsAgo: '{delta} years ago',
2216
+ makeShim: function(){
2217
+ if (this.options.browsers){
2218
+ var zIndex = this.element.getStyle('zIndex').toInt();
1141
2219
 
1142
- lessThanMinuteUntil: 'less than a minute from now',
1143
- minuteUntil: 'about a minute from now',
1144
- minutesUntil: '{delta} minutes from now',
1145
- hourUntil: 'about an hour from now',
1146
- hoursUntil: 'about {delta} hours from now',
1147
- dayUntil: '1 day from now',
1148
- daysUntil: '{delta} days from now',
1149
- weekUntil: '1 week from now',
1150
- weeksUntil: '{delta} weeks from now',
1151
- monthUntil: '1 month from now',
1152
- monthsUntil: '{delta} months from now',
1153
- yearUntil: '1 year from now',
1154
- yearsUntil: '{delta} years from now'
2220
+ if (!zIndex){
2221
+ zIndex = 1;
2222
+ var pos = this.element.getStyle('position');
2223
+ if (pos == 'static' || !pos) this.element.setStyle('position', 'relative');
2224
+ this.element.setStyle('zIndex', zIndex);
2225
+ }
2226
+ zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1;
2227
+ if (zIndex < 0) zIndex = 1;
2228
+ this.shim = new Element('iframe', {
2229
+ src: this.options.src,
2230
+ scrolling: 'no',
2231
+ frameborder: 0,
2232
+ styles: {
2233
+ zIndex: zIndex,
2234
+ position: 'absolute',
2235
+ border: 'none',
2236
+ filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
2237
+ },
2238
+ 'class': this.options.className
2239
+ }).store('IframeShim', this);
2240
+ var inject = (function(){
2241
+ this.shim.inject(this.element, 'after');
2242
+ this[this.options.display ? 'show' : 'hide']();
2243
+ this.fireEvent('inject');
2244
+ }).bind(this);
2245
+ if (!IframeShim.ready) window.addEvent('load', inject);
2246
+ else inject();
2247
+ } else {
2248
+ this.position = this.hide = this.show = this.dispose = Function.from(this);
2249
+ }
2250
+ },
2251
+
2252
+ position: function(){
2253
+ if (!IframeShim.ready || !this.shim) return this;
2254
+ var size = this.element.measure(function(){
2255
+ return this.getSize();
2256
+ });
2257
+ if (this.options.margin != undefined){
2258
+ size.x = size.x - (this.options.margin * 2);
2259
+ size.y = size.y - (this.options.margin * 2);
2260
+ this.options.offset.x += this.options.margin;
2261
+ this.options.offset.y += this.options.margin;
2262
+ }
2263
+ this.shim.set({width: size.x, height: size.y}).position({
2264
+ relativeTo: this.element,
2265
+ offset: this.options.offset
2266
+ });
2267
+ return this;
2268
+ },
2269
+
2270
+ hide: function(){
2271
+ if (this.shim) this.shim.setStyle('display', 'none');
2272
+ return this;
2273
+ },
2274
+
2275
+ show: function(){
2276
+ if (this.shim) this.shim.setStyle('display', 'block');
2277
+ return this.position();
2278
+ },
2279
+
2280
+ dispose: function(){
2281
+ if (this.shim) this.shim.dispose();
2282
+ return this;
2283
+ },
2284
+
2285
+ destroy: function(){
2286
+ if (this.shim) this.shim.destroy();
2287
+ return this;
2288
+ }
2289
+
2290
+ });
1155
2291
 
2292
+ window.addEvent('load', function(){
2293
+ IframeShim.ready = true;
1156
2294
  });
1157
2295
 
1158
2296