bhf 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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