kalendae_assets 0.2.1 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Zjk4ODFiYmI5ZjVkZTc2ZjRlNDk5ZGU4OTI1ZDFiMGJmNmEzNWNlYQ==
5
+ data.tar.gz: !binary |-
6
+ ZDRhNGVkYWNlYjZmMWNjMmIxMzU3NTM4MjRiNjZlNTQyY2I5ZmMwZQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YzUxODcyOWM4MDdmYjI5OTdjNzA5YTRiODZmOWNlYTJkNWM0ZTQzN2QyNDUy
10
+ OTRmNWMxMjU0NDY2ZjVhOWE1NDA5NTFlNDUzNDM5ZjZkODdlOTczZDlkYTNi
11
+ N2MwZTk0ZTc3ZDY1MGM4M2FhYmRjZGQ0ODhjNWEzNzk1Y2ZhMzg=
12
+ data.tar.gz: !binary |-
13
+ NGU5YjBlY2U0YzQwZDNmMmYyOTIyZjI2ODFiM2M4NWM5Mjk0MjA1ZGIyZDkz
14
+ MzBlMDRkYWJjZTIzOWNiZmQwYTQxYjNhYmQ5NDg0ZGU1NjhhMzkyM2MyMDc3
15
+ NjA0MjJhOTkyODcwZmRlNDY0MGEzYjZjZTViNGZiNjQwZDhjYmM=
data/.gitignore CHANGED
@@ -4,6 +4,7 @@
4
4
  .config
5
5
  .yardoc
6
6
  Gemfile.lock
7
+ gemfiles/*.lock
7
8
  InstalledFiles
8
9
  _yardoc
9
10
  coverage
@@ -2,3 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - rbx-19mode
5
+ gemfile:
6
+ - gemfiles/rails_3.gemfile
7
+ - gemfiles/rails_4.0.gemfile
8
+ - gemfiles/rails_4.1.gemfile
@@ -0,0 +1,11 @@
1
+ appraise 'rails-3' do
2
+ gem 'rails', '~> 3.1'
3
+ end
4
+
5
+ appraise 'rails-4.0' do
6
+ gem 'rails', '~> 4.0.0'
7
+ end
8
+
9
+ appraise 'rails-4.1' do
10
+ gem 'rails', '~> 4.1.0'
11
+ end
data/README.md CHANGED
@@ -5,7 +5,11 @@
5
5
 
6
6
  **Step 1**
7
7
 
8
- Load `kalendae_assets` in your `Gemfile` as part of the `assets` group
8
+ Load `kalendae_assets` in your `Gemfile`. In Rails 4, don't put it in a group:
9
+
10
+ gem 'kalendae_assets'
11
+
12
+ In Rails 3, place it in the `assets` group:
9
13
 
10
14
  group :assets do
11
15
  gem 'kalendae_assets'
@@ -19,6 +23,12 @@ Run 'bundle install'
19
23
 
20
24
  Require `kalendae.js` in your Javascript manifest (e.g. `application.js`)
21
25
 
26
+ //= require kalendae.standalone
27
+
28
+ The standalone version bundles a copy of of moment.js. If you already have
29
+ moment.js in your app, you can use the non-standalone version to keep your
30
+ assets smaller:
31
+
22
32
  //= require kalendae
23
33
 
24
34
  **Step 4**
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 3.1"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.0.0"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.1.0"
6
+
7
+ gemspec :path => "../"
@@ -14,7 +14,8 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "kalendae_assets"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = KalendaeAssets::VERSION
17
- gem.add_dependency 'rails', '~> 3.1'
17
+ gem.add_dependency 'rails', '>= 3.1'
18
+ gem.add_development_dependency 'appraisal'
18
19
  gem.add_development_dependency 'sqlite3'
19
20
  gem.add_development_dependency 'minitest'
20
21
  gem.add_development_dependency 'capybara'
@@ -1,3 +1,3 @@
1
1
  module KalendaeAssets
2
- VERSION = "0.2.1"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -30,8 +30,10 @@ Dummy::Application.configure do
30
30
  config.action_mailer.delivery_method = :test
31
31
 
32
32
  # Raise exception on mass assignment protection for Active Record models
33
- config.active_record.mass_assignment_sanitizer = :strict
33
+ config.active_record.mass_assignment_sanitizer = :strict if Rails::VERSION::MAJOR < 4
34
34
 
35
35
  # Print deprecation notices to the stderr
36
36
  config.active_support.deprecation = :stderr
37
+
38
+ config.eager_load = true
37
39
  end
@@ -12,5 +12,9 @@ class IntegrationTest < MiniTest::Spec
12
12
  register_spec_type(/integration$/, self)
13
13
  end
14
14
 
15
- Turn.config.format = :pretty
16
- Turn.config.natural = true
15
+ unless Rails.version.to_f > 4
16
+ require 'turn'
17
+
18
+ Turn.config.format = :pretty
19
+ Turn.config.natural = true
20
+ end
@@ -1,17 +1,26 @@
1
1
  /********************************************************************
2
2
  * Kalendae, a framework agnostic javascript date picker *
3
- * Copyright(c) 2012 Jarvis Badgley (chipersoft@gmail.com) *
3
+ * Copyright(c) 2013 Jarvis Badgley (chipersoft@gmail.com) *
4
4
  * http://github.com/ChiperSoft/Kalendae *
5
- * Version 0.2 *
5
+ * Version 0.4.1 *
6
6
  ********************************************************************/
7
7
 
8
8
  (function (undefined) {
9
9
 
10
- var today;
10
+ var today, moment;
11
11
 
12
12
  var Kalendae = function (targetElement, options) {
13
+ if (typeof document.addEventListener !== 'function' && !util.isIE8()) return;
14
+
13
15
  //if the first argument isn't an element and isn't a string, assume that it is the options object
14
- if (!(targetElement instanceof Element || typeof targetElement === 'string')) options = targetElement;
16
+ var is_element = false;
17
+ try {
18
+ is_element = targetElement instanceof Element;
19
+ }
20
+ catch (err) {
21
+ is_element = !!targetElement && is_element.nodeType === 1;
22
+ }
23
+ if (!(is_element || typeof(targetElement) === 'string')) options = targetElement;
15
24
 
16
25
  var self = this,
17
26
  classes = self.classes,
@@ -35,7 +44,7 @@ var Kalendae = function (targetElement, options) {
35
44
  //generate the column headers (Su, Mo, Tu, etc)
36
45
  i = 7;
37
46
  while (i--) {
38
- columnHeaders.push( startDay.format('ddd').substr(0,opts.columnHeaderLength) );
47
+ columnHeaders.push( startDay.format(opts.columnHeaderFormat) );
39
48
  startDay.add('days',1);
40
49
  }
41
50
 
@@ -62,11 +71,11 @@ var Kalendae = function (targetElement, options) {
62
71
  self.viewStartDate = vsd.date(1);
63
72
 
64
73
  var viewDelta = ({
65
- 'past' : opts.months-1,
66
- 'today-past' : opts.months-1,
67
- 'any' : opts.months>2?Math.floor(opts.months/2):0,
68
- 'today-future' : 0,
69
- 'future' : 0
74
+ 'past' : opts.months-1,
75
+ 'today-past' : opts.months-1,
76
+ 'any' : opts.months>2?Math.floor(opts.months/2):0,
77
+ 'today-future' : 0,
78
+ 'future' : 0
70
79
  })[this.settings.direction];
71
80
 
72
81
 
@@ -78,16 +87,16 @@ var Kalendae = function (targetElement, options) {
78
87
  if (typeof opts.blackout === 'function') {
79
88
  self.blackout = opts.blackout;
80
89
  } else if (!!opts.blackout) {
81
- var bdates = parseDates(opts.blackout, opts.parseSplitDelimiter);
90
+ var bdates = parseDates(opts.blackout, opts.parseSplitDelimiter, opts.format);
82
91
  self.blackout = function (input) {
83
92
  input = moment(input).yearDay();
84
- if (input < 1 || !self._sel || self._sel.length < 1) return false;
93
+ if (input < 1 || !self._sel) return false;
85
94
  var i = bdates.length;
86
95
  while (i--) if (bdates[i].yearDay() === input) return true;
87
96
  return false;
88
- }
97
+ };
89
98
  } else {
90
- self.blackout = function () {return false;}
99
+ self.blackout = function () {return false;};
91
100
  }
92
101
 
93
102
 
@@ -108,11 +117,14 @@ var Kalendae = function (targetElement, options) {
108
117
 
109
118
  //title bar
110
119
  $title = util.make('div', {'class':classes.title}, $cal);
111
- util.make('a', {'class':classes.previousYear}, $title); //previous button
112
- util.make('a', {'class':classes.previousMonth}, $title); //previous button
113
- util.make('a', {'class':classes.nextYear}, $title); //next button
114
- util.make('a', {'class':classes.nextMonth}, $title); //next button
115
- $caption = util.make('span', {'class':classes.caption}, $title); //title caption
120
+ if(!opts.useYearNav){
121
+ util.addClassName($title, classes.disableYearNav);
122
+ }
123
+ util.make('a', {'class':classes.previousYear}, $title); //previous button
124
+ util.make('a', {'class':classes.previousMonth}, $title); //previous button
125
+ util.make('a', {'class':classes.nextYear}, $title); //next button
126
+ util.make('a', {'class':classes.nextMonth}, $title); //next button
127
+ $caption = util.make('span', {'class':classes.caption}, $title); //title caption
116
128
 
117
129
  //column headers
118
130
  $header = util.make('div', {'class':classes.header}, $cal);
@@ -120,7 +132,7 @@ var Kalendae = function (targetElement, options) {
120
132
  do {
121
133
  $span = util.make('span', {}, $header);
122
134
  $span.innerHTML = columnHeaders[i];
123
- } while (++i < 7)
135
+ } while (++i < 7);
124
136
 
125
137
  //individual day cells
126
138
  $days = util.make('div', {'class':classes.days}, $cal);
@@ -212,52 +224,56 @@ var Kalendae = function (targetElement, options) {
212
224
 
213
225
  Kalendae.prototype = {
214
226
  defaults : {
215
- attachTo: null, /* the element to attach the root container to. can be string or DOMElement */
216
- months: 1, /* total number of months to display side by side */
217
- weekStart: 0, /* day to use for the start of the week. 0 is Sunday */
218
- direction: 'any', /* past, today-past, any, today-future, future */
219
- directionScrolling: true, /* if a direction other than any is defined, prevent scrolling out of range */
220
- viewStartDate: null, /* date in the month to display. When multiple months, this is the left most */
221
- blackout: null, /* array of dates, or function to be passed a date */
222
- selected: null, /* dates already selected. can be string, date, or array of strings or dates. */
223
- mode: 'single', /* single, multiple, range */
224
- format: null, /* string used for parsing dates. */
225
- subscribe: null, /* object containing events to subscribe to */
226
-
227
- columnHeaderLength: 2, /* number of characters to show in the column headers */
228
- titleFormat: 'MMMM, YYYY', /* format mask for month titles. See momentjs.com for rules */
229
- dayNumberFormat: 'D', /* format mask for individual days */
230
- dayAttributeFormat: 'YYYY-MM-DD', /* format mask for the data-date attribute set on every span */
231
- parseSplitDelimiter: /,\s*|\s+-\s+/, /* regex to use for splitting multiple dates from a passed string */
232
- rangeDelimiter: ' - ', /* string to use between dates when outputting in range mode */
233
- multipleDelimiter: ', ', /* string to use between dates when outputting in multiple mode */
234
-
235
- dateClassMap: {}
227
+ attachTo :null, /* the element to attach the root container to. can be string or DOMElement */
228
+ months :1, /* total number of months to display side by side */
229
+ weekStart :0, /* day to use for the start of the week. 0 is Sunday */
230
+ direction :'any', /* past, today-past, any, today-future, future */
231
+ directionScrolling :true, /* if a direction other than any is defined, prevent scrolling out of range */
232
+ viewStartDate :null, /* date in the month to display. When multiple months, this is the left most */
233
+ blackout :null, /* array of dates, or function to be passed a date */
234
+ selected :null, /* dates already selected. can be string, date, or array of strings or dates. */
235
+ mode :'single', /* single, multiple, range */
236
+ dayOutOfMonthClickable:false,
237
+ format :null, /* string used for parsing dates. */
238
+ subscribe :null, /* object containing events to subscribe to */
239
+
240
+ columnHeaderFormat :'dd', /* number of characters to show in the column headers */
241
+ titleFormat :'MMMM, YYYY', /* format mask for month titles. See momentjs.com for rules */
242
+ dayNumberFormat :'D', /* format mask for individual days */
243
+ dayAttributeFormat :'YYYY-MM-DD', /* format mask for the data-date attribute set on every span */
244
+ parseSplitDelimiter : /,\s*|\s+-\s+/, /* regex to use for splitting multiple dates from a passed string */
245
+ rangeDelimiter :' - ', /* string to use between dates when outputting in range mode */
246
+ multipleDelimiter :', ', /* string to use between dates when outputting in multiple mode */
247
+ useYearNav :true,
248
+
249
+ dateClassMap :{}
236
250
  },
237
251
  classes : {
238
- container :'kalendae',
239
- calendar :'k-calendar',
240
- monthFirst :'k-first-month',
241
- monthMiddle :'k-middle-month',
242
- monthLast :'k-last-month',
243
- title :'k-title',
244
- previousMonth :'k-btn-previous-month',
245
- nextMonth :'k-btn-next-month',
246
- previousYear :'k-btn-previous-year',
247
- nextYear :'k-btn-next-year',
248
- caption :'k-caption',
249
- header :'k-header',
250
- days :'k-days',
251
- dayOutOfMonth :'k-out-of-month',
252
- dayActive :'k-active',
253
- daySelected :'k-selected',
254
- dayInRange :'k-range',
255
- dayToday :'k-today',
256
- monthSeparator :'k-separator',
257
- disablePreviousMonth :'k-disable-previous-month-btn',
258
- disableNextMonth :'k-disable-next-month-btn',
259
- disablePreviousYear :'k-disable-previous-year-btn',
260
- disableNextYear :'k-disable-next-year-btn'
252
+ container :'kalendae',
253
+ calendar :'k-calendar',
254
+ monthFirst :'k-first-month',
255
+ monthMiddle :'k-middle-month',
256
+ monthLast :'k-last-month',
257
+ title :'k-title',
258
+ previousMonth :'k-btn-previous-month',
259
+ nextMonth :'k-btn-next-month',
260
+ previousYear :'k-btn-previous-year',
261
+ nextYear :'k-btn-next-year',
262
+ caption :'k-caption',
263
+ header :'k-header',
264
+ days :'k-days',
265
+ dayOutOfMonth :'k-out-of-month',
266
+ dayInMonth :'k-in-month',
267
+ dayActive :'k-active',
268
+ daySelected :'k-selected',
269
+ dayInRange :'k-range',
270
+ dayToday :'k-today',
271
+ monthSeparator :'k-separator',
272
+ disablePreviousMonth :'k-disable-previous-month-btn',
273
+ disableNextMonth :'k-disable-next-month-btn',
274
+ disablePreviousYear :'k-disable-previous-year-btn',
275
+ disableNextYear :'k-disable-next-year-btn',
276
+ disableYearNav :'k-disable-year-nav'
261
277
  },
262
278
 
263
279
  disablePreviousMonth: false,
@@ -266,11 +282,11 @@ Kalendae.prototype = {
266
282
  disableNextYear: false,
267
283
 
268
284
  directions: {
269
- 'past' :function (date) {return moment(date).yearDay() >= today.yearDay();},
270
- 'today-past' :function (date) {return moment(date).yearDay() > today.yearDay();},
271
- 'any' :function (date) {return false;},
272
- 'today-future' :function (date) {return moment(date).yearDay() < today.yearDay();},
273
- 'future' :function (date) {return moment(date).yearDay() <= today.yearDay();}
285
+ 'past' :function (date) {return moment(date).yearDay() >= today.yearDay();},
286
+ 'today-past' :function (date) {return moment(date).yearDay() > today.yearDay();},
287
+ 'any' :function (date) {return false;},
288
+ 'today-future' :function (date) {return moment(date).yearDay() < today.yearDay();},
289
+ 'future' :function (date) {return moment(date).yearDay() <= today.yearDay();}
274
290
  },
275
291
 
276
292
  getSelectedAsDates : function () {
@@ -286,7 +302,7 @@ Kalendae.prototype = {
286
302
  var out = [];
287
303
  var i=0, c = this._sel.length;
288
304
  for (;i<c;i++) {
289
- out.push(this._sel[i].format(format || this.settings.format || 'YYYY-MM-DD'))
305
+ out.push(this._sel[i].format(format || this.settings.format || 'YYYY-MM-DD'));
290
306
  }
291
307
  return out;
292
308
  },
@@ -295,7 +311,7 @@ Kalendae.prototype = {
295
311
  var out = [];
296
312
  var i=0, c = this._sel.length;
297
313
  for (;i<c;i++) {
298
- out.push(moment(this._sel[i]))
314
+ out.push(moment(this._sel[i]));
299
315
  }
300
316
  return out;
301
317
  },
@@ -352,14 +368,24 @@ Kalendae.prototype = {
352
368
  },
353
369
 
354
370
  setSelected : function (input, draw) {
355
- this._sel = parseDates(input, this.settings.parseSplitDelimiter, this.settings.format);
356
- this._sel.sort(function (a,b) {return a.yearDay() - b.yearDay();});
371
+ var i,
372
+ new_dates = parseDates(input, this.settings.parseSplitDelimiter, this.settings.format),
373
+ old_dates = parseDates(this.getSelected(), this.settings.parseSplitDelimiter, this.settings.format);
374
+
375
+ i = old_dates.length;
376
+ while(i--) { this.removeSelected(old_dates[i], draw); }
377
+
378
+ i = new_dates.length;
379
+ while(i--) { this.addSelected(new_dates[i], draw); }
357
380
 
358
381
  if (draw !== false) this.draw();
359
382
  },
360
383
 
361
384
  addSelected : function (date, draw) {
362
- date = moment(date).hours(12);
385
+ date = moment(date, this.settings.format).hours(12);
386
+
387
+ if(this.settings.dayOutOfMonthClickable && this.settings.mode !== 'range'){ this.makeSelectedDateVisible(date); }
388
+
363
389
  switch (this.settings.mode) {
364
390
  case 'multiple':
365
391
  if (!this.isSelected(date)) this._sel.push(date);
@@ -380,18 +406,29 @@ Kalendae.prototype = {
380
406
  break;
381
407
  }
382
408
  this._sel.sort(function (a,b) {return a.yearDay() - b.yearDay();});
383
- this.publish('change', this);
409
+ this.publish('change', this, [date]);
384
410
  if (draw !== false) this.draw();
385
411
  return true;
386
412
  },
387
413
 
414
+ makeSelectedDateVisible: function (date) {
415
+ outOfViewMonth = moment(date).date('1').diff(this.viewStartDate,'months');
416
+
417
+ if(outOfViewMonth < 0){
418
+ this.viewStartDate.subtract('months',1);
419
+ }
420
+ else if(outOfViewMonth > 0 && outOfViewMonth >= this.settings.months){
421
+ this.viewStartDate.add('months',1);
422
+ }
423
+ },
424
+
388
425
  removeSelected : function (date, draw) {
389
- date = moment(date).yearDay();
426
+ date = moment(date, this.settings.format).hours(12);
390
427
  var i = this._sel.length;
391
428
  while (i--) {
392
- if (this._sel[i].yearDay() === date) {
429
+ if (this._sel[i].yearDay() === date.yearDay()) {
393
430
  this._sel.splice(i,1);
394
- this.publish('change', this);
431
+ this.publish('change', this, [date]);
395
432
  if (draw !== false) this.draw();
396
433
  return true;
397
434
  }
@@ -411,7 +448,8 @@ Kalendae.prototype = {
411
448
  j=0, k,
412
449
  s,
413
450
  dateString,
414
- opts = this.settings;
451
+ opts = this.settings,
452
+ diff;
415
453
 
416
454
  c = this.calendars.length;
417
455
 
@@ -433,7 +471,9 @@ Kalendae.prototype = {
433
471
  if (s) klass.push(({'-1':classes.dayInRange,'1':classes.daySelected, 'true':classes.daySelected})[s]);
434
472
 
435
473
  if (day.month() != month.month()) klass.push(classes.dayOutOfMonth);
436
- else if (!(this.blackout(day) || this.direction(day)) || s>0) klass.push(classes.dayActive);
474
+ else klass.push(classes.dayInMonth);
475
+
476
+ if (!(this.blackout(day) || this.direction(day) || (day.month() != month.month() && opts.dayOutOfMonthClickable === false)) || s>0) klass.push(classes.dayActive);
437
477
 
438
478
  if (day.yearDay() === today.yearDay()) klass.push(classes.dayToday);
439
479
 
@@ -451,9 +491,8 @@ Kalendae.prototype = {
451
491
  } while (++i < c);
452
492
 
453
493
  if (opts.directionScrolling) {
454
- var diff = -(moment().diff(month, 'months'));
455
494
  if (opts.direction==='today-past' || opts.direction==='past') {
456
-
495
+ diff = month.add({m:1}).diff(moment(), 'months', true);
457
496
  if (diff <= 0) {
458
497
  this.disableNextMonth = false;
459
498
  util.removeClassName(this.container, classes.disableNextMonth);
@@ -463,7 +502,7 @@ Kalendae.prototype = {
463
502
  }
464
503
 
465
504
  } else if (opts.direction==='today-future' || opts.direction==='future') {
466
-
505
+ diff = month.subtract({m:1}).diff(moment(), 'months', true);
467
506
  if (diff > opts.months) {
468
507
  this.disablePreviousMonth = false;
469
508
  util.removeClassName(this.container, classes.disablePreviousMonth);
@@ -476,7 +515,8 @@ Kalendae.prototype = {
476
515
 
477
516
 
478
517
  if (opts.direction==='today-past' || opts.direction==='past') {
479
- if (month.add({Y:1}).diff(moment(), 'years') < 0) {
518
+ diff = month.add({m:12}).diff(moment(), 'months', true);
519
+ if (diff <= -11) {
480
520
  this.disableNextYear = false;
481
521
  util.removeClassName(this.container, classes.disableNextYear);
482
522
  } else {
@@ -485,7 +525,8 @@ Kalendae.prototype = {
485
525
  }
486
526
 
487
527
  } else if (opts.direction==='today-future' || opts.direction==='future') {
488
- if (month.subtract({Y:1}).diff(moment(), 'years') > 0) {
528
+ diff = month.subtract({m:12}).diff(moment(), 'months', true);
529
+ if (diff > (11 + opts.months)) {
489
530
  this.disablePreviousYear = false;
490
531
  util.removeClassName(this.container, classes.disablePreviousYear);
491
532
  } else {
@@ -497,7 +538,7 @@ Kalendae.prototype = {
497
538
 
498
539
  }
499
540
  }
500
- }
541
+ };
501
542
 
502
543
  var parseDates = function (input, delimiter, format) {
503
544
  var output = [];
@@ -508,14 +549,15 @@ var parseDates = function (input, delimiter, format) {
508
549
  input = [input];
509
550
  }
510
551
 
511
- var c = input.length;
512
- i = 0;
552
+ var c = input.length,
553
+ i = 0;
554
+
513
555
  do {
514
556
  if (input[i]) output.push( moment(input[i], format).hours(12) );
515
557
  } while (++i < c);
516
558
 
517
559
  return output;
518
- }
560
+ };
519
561
 
520
562
 
521
563
 
@@ -524,7 +566,7 @@ window.Kalendae = Kalendae;
524
566
  var util = Kalendae.util = {
525
567
 
526
568
  isIE8: function() {
527
- return !!( (/msie 8./i).test(navigator.appVersion) && !(/opera/i).test(navigator.userAgent) && window.ActiveXObject && XDomainRequest && !window.msPerformance );
569
+ return !!( (/msie 8./i).test(navigator.appVersion) && !(/opera/i).test(navigator.userAgent) && window.ActiveXObject && XDomainRequest && !window.msPerformance );
528
570
  },
529
571
 
530
572
  // ELEMENT FUNCTIONS
@@ -620,6 +662,14 @@ var util = Kalendae.util = {
620
662
  return false;
621
663
  },
622
664
 
665
+ scrollContainer: function (elem) {
666
+ do {
667
+ var overflow = util.getStyle(elem, 'overflow');
668
+ if (overflow === 'auto' || overflow === 'scroll') return elem;
669
+ } while ((elem = elem.parentNode) && elem != window.document.body);
670
+ return null;
671
+ },
672
+
623
673
  getPosition: function (elem, isInner) {
624
674
  var x = elem.offsetLeft,
625
675
  y = elem.offsetTop,
@@ -673,7 +723,7 @@ var util = Kalendae.util = {
673
723
  else a[k] = b[k];
674
724
  }
675
725
  return a;
676
- }
726
+ };
677
727
 
678
728
  for (; i < arguments.length; i++) {
679
729
  _c(d, arguments[i]);
@@ -682,45 +732,45 @@ var util = Kalendae.util = {
682
732
  },
683
733
 
684
734
  isArray: function (array) {
685
- return !(
686
- !array ||
687
- (!array.length || array.length === 0) ||
688
- typeof array !== 'object' ||
689
- !array.constructor ||
690
- array.nodeType ||
691
- array.item
692
- );
735
+ return Object.prototype.toString.call(array) == "[object Array]"
693
736
  }
694
737
  };
695
738
 
696
739
 
697
740
  //auto-initializaiton code
698
- Kalendae.util.domReady(function () {
741
+ if (typeof document.addEventListener === 'function') Kalendae.util.domReady(function () {
699
742
  var els = util.$$('.auto-kal'),
700
743
  i = els.length,
701
- e;
744
+ e,
745
+ options,
746
+ optionsRaw;
702
747
 
703
748
  while (i--) {
704
749
  e = els[i];
750
+ optionsRaw = e.getAttribute('data-kal');
751
+ options = (optionsRaw == null || optionsRaw == "") ? {} : (new Function('return {' + optionsRaw + '};'))();
752
+
705
753
  if (e.tagName === 'INPUT') {
706
754
  //if element is an input, bind a popup calendar to the input.
707
- new Kalendae.Input(e);
755
+ new Kalendae.Input(e, options);
708
756
  } else {
709
757
  //otherwise, insert a flat calendar into the element.
710
- new Kalendae({attachTo:e});
758
+ new Kalendae(util.merge(options, {attachTo:e}));
711
759
  }
712
760
 
713
761
  }
714
762
  });
715
-
716
763
  Kalendae.Input = function (targetElement, options) {
764
+ if (typeof document.addEventListener !== 'function' && !util.isIE8()) return;
765
+
717
766
  var $input = this.input = util.$(targetElement),
718
- overwriteInput;
767
+ overwriteInput,
768
+ $closeButton;
719
769
 
720
770
  if (!$input || $input.tagName !== 'INPUT') throw "First argument for Kalendae.Input must be an <input> element or a valid element id.";
721
771
 
722
772
  var self = this,
723
- classes = self.classes
773
+ classes = self.classes,
724
774
  opts = self.settings = util.merge(self.defaults, options);
725
775
 
726
776
  //force attachment to the body
@@ -735,7 +785,7 @@ Kalendae.Input = function (targetElement, options) {
735
785
 
736
786
  //create the close button
737
787
  if (opts.closeButton) {
738
- var $closeButton = util.make('a', {'class':classes.closeButton}, self.container)
788
+ $closeButton = util.make('a', {'class':classes.closeButton}, self.container);
739
789
  util.addEvent($closeButton, 'click', function () {
740
790
  $input.blur();
741
791
  });
@@ -762,7 +812,7 @@ Kalendae.Input = function (targetElement, options) {
762
812
  });
763
813
 
764
814
  util.addEvent($input, 'blur', function () {
765
- if (noclose) {
815
+ if (noclose && util.isIE8()) {
766
816
  noclose = false;
767
817
  $input.focus();
768
818
  }
@@ -772,6 +822,16 @@ Kalendae.Input = function (targetElement, options) {
772
822
  self.setSelected(this.value);
773
823
  });
774
824
 
825
+ var $scrollContainer = util.scrollContainer($input);
826
+
827
+ if( $scrollContainer ) {
828
+
829
+ // Hide calendar when $scrollContainer is scrolled
830
+ util.addEvent($scrollContainer, 'scroll', function (event) {
831
+ $input.blur();
832
+ });
833
+ }
834
+
775
835
  self.subscribe('change', function () {
776
836
  $input.value = self.getSelected();
777
837
  });
@@ -795,36 +855,41 @@ Kalendae.Input.prototype = util.merge(Kalendae.prototype, {
795
855
  var $container = this.container,
796
856
  style = $container.style,
797
857
  $input = this.input,
798
- pos = util.getPosition($input);
858
+ pos = util.getPosition($input),
859
+ $scrollContainer = util.scrollContainer($input),
860
+ scrollTop = $scrollContainer ? $scrollContainer.scrollTop : 0,
861
+ opts = this.settings;
799
862
 
800
863
  style.display = '';
801
864
  switch (opts.side) {
802
865
  case 'left':
803
- style.left = (pos.left - util.getWidth($container) + this.settings.offsetLeft) + 'px';
804
- style.top = (pos.top + this.settings.offsetTop) + 'px';
866
+ style.left = (pos.left - util.getWidth($container) + opts.offsetLeft) + 'px';
867
+ style.top = (pos.top + opts.offsetTop - scrollTop) + 'px';
805
868
  break;
806
869
  case 'right':
807
870
  style.left = (pos.left + util.getWidth($input)) + 'px';
808
- style.top = (pos.top + this.settings.offsetTop) + 'px';
871
+ style.top = (pos.top + opts.offsetTop - scrollTop) + 'px';
809
872
  break;
810
873
  case 'top':
811
- style.left = (pos.left + this.settings.offsetLeft) + 'px';
812
- style.top = (pos.top - util.getHeight($container) + this.settings.offsetTop) + 'px';
874
+ style.left = (pos.left + opts.offsetLeft) + 'px';
875
+ style.top = (pos.top - util.getHeight($container) + opts.offsetTop - scrollTop) + 'px';
813
876
  break;
814
877
  case 'bottom':
815
878
  /* falls through */
816
879
  default:
817
- style.left = (pos.left + this.settings.offsetLeft) + 'px';
818
- style.top = (pos.top + util.getHeight($input) + this.settings.offsetTop) + 'px';
880
+ style.left = (pos.left + opts.offsetLeft) + 'px';
881
+ style.top = (pos.top + util.getHeight($input) + opts.offsetTop - scrollTop) + 'px';
819
882
  break;
820
883
  }
821
884
 
822
885
  style.position = util.isFixed($input) ? 'fixed' : 'absolute';
823
886
 
887
+ this.publish('show', this);
824
888
  },
825
889
 
826
890
  hide : function () {
827
891
  this.container.style.display = 'none';
892
+ this.publish('hide', this);
828
893
  }
829
894
 
830
895
  });
@@ -916,736 +981,22 @@ var MinPubSub = function(d){
916
981
  }
917
982
  };
918
983
 
919
- };// moment.js
920
- // Altered slightly for use in Kalendae.js
921
- // version : 1.5.0
922
- // author : Tim Wood
923
- // license : MIT
924
- // momentjs.com
925
-
926
- var moment = Kalendae.moment = (function (Date, undefined) {
927
-
928
- var moment,
929
- round = Math.round,
930
- languages = {},
931
- hasModule = (typeof module !== 'undefined'),
932
- paramsToParse = 'months|monthsShort|monthsParse|weekdays|weekdaysShort|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
933
- i,
934
- jsonRegex = /^\/?Date\((\-?\d+)/i,
935
- charactersToReplace = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?|ZZ?|LT|LL?L?L?)/g,
936
- nonuppercaseLetters = /[^A-Z]/g,
937
- timezoneRegex = /\([A-Za-z ]+\)|:[0-9]{2} [A-Z]{3} /g,
938
- tokenCharacters = /(\\)?(MM?M?M?|dd?d?d|DD?D?D?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|ZZ?|T)/g,
939
- inputCharacters = /(\\)?([0-9]+|([a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+|([\+\-]\d\d:?\d\d))/gi,
940
- isoRegex = /\d{4}.\d\d.\d\d(T(\d\d(.\d\d(.\d\d)?)?)?([\+\-]\d\d:?\d\d)?)?/,
941
- isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
942
- isoTimes = [
943
- ['HH:mm:ss', /T\d\d:\d\d:\d\d/],
944
- ['HH:mm', /T\d\d:\d\d/],
945
- ['HH', /T\d\d/]
946
- ],
947
- timezoneParseRegex = /([\+\-]|\d\d)/gi,
948
- VERSION = "1.5.0",
949
- shortcuts = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|');
950
-
951
- // Moment prototype object
952
- function Moment(date, isUTC) {
953
- this._d = date;
954
- this._isUTC = !!isUTC;
955
- }
956
-
957
- // left zero fill a number
958
- // see http://jsperf.com/left-zero-filling for performance comparison
959
- function leftZeroFill(number, targetLength) {
960
- var output = number + '';
961
- while (output.length < targetLength) {
962
- output = '0' + output;
963
- }
964
- return output;
965
- }
966
-
967
- // helper function for _.addTime and _.subtractTime
968
- function dateAddRemove(date, _input, adding, val) {
969
- var isString = (typeof _input === 'string'),
970
- input = isString ? {} : _input,
971
- ms, d, M, currentDate;
972
- if (isString && val) {
973
- input[_input] = +val;
974
- }
975
- ms = (input.ms || input.milliseconds || 0) +
976
- (input.s || input.seconds || 0) * 1e3 + // 1000
977
- (input.m || input.minutes || 0) * 6e4 + // 1000 * 60
978
- (input.h || input.hours || 0) * 36e5; // 1000 * 60 * 60
979
- d = (input.d || input.days || 0) +
980
- (input.w || input.weeks || 0) * 7;
981
- M = (input.M || input.months || 0) +
982
- (input.y || input.years || 0) * 12;
983
- if (ms) {
984
- date.setTime(+date + ms * adding);
985
- }
986
- if (d) {
987
- date.setDate(date.getDate() + d * adding);
988
- }
989
- if (M) {
990
- currentDate = date.getDate();
991
- date.setDate(1);
992
- date.setMonth(date.getMonth() + M * adding);
993
- date.setDate(Math.min(new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(), currentDate));
994
- }
995
- return date;
996
- }
997
-
998
- // check if is an array
999
- function isArray(input) {
1000
- return Object.prototype.toString.call(input) === '[object Array]';
1001
- }
1002
-
1003
- // convert an array to a date.
1004
- // the array should mirror the parameters below
1005
- // note: all values past the year are optional and will default to the lowest possible value.
1006
- // [year, month, day , hour, minute, second, millisecond]
1007
- function dateFromArray(input) {
1008
- return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0);
1009
- }
1010
-
1011
- // format date using native date object
1012
- function formatMoment(m, inputString) {
1013
- var currentMonth = m.month(),
1014
- currentDate = m.date(),
1015
- currentYear = m.year(),
1016
- currentDay = m.day(),
1017
- currentHours = m.hours(),
1018
- currentMinutes = m.minutes(),
1019
- currentSeconds = m.seconds(),
1020
- currentZone = -m.zone(),
1021
- ordinal = moment.ordinal,
1022
- meridiem = moment.meridiem;
1023
- // check if the character is a format
1024
- // return formatted string or non string.
1025
- //
1026
- // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380)
1027
- // for minification and performance
1028
- // see http://jsperf.com/object-of-functions-vs-switch for performance comparison
1029
- function replaceFunction(input) {
1030
- // create a couple variables to be used later inside one of the cases.
1031
- var a, b;
1032
- switch (input) {
1033
- // MONTH
1034
- case 'M' :
1035
- return currentMonth + 1;
1036
- case 'Mo' :
1037
- return (currentMonth + 1) + ordinal(currentMonth + 1);
1038
- case 'MM' :
1039
- return leftZeroFill(currentMonth + 1, 2);
1040
- case 'MMM' :
1041
- return moment.monthsShort[currentMonth];
1042
- case 'MMMM' :
1043
- return moment.months[currentMonth];
1044
- // DAY OF MONTH
1045
- case 'D' :
1046
- return currentDate;
1047
- case 'Do' :
1048
- return currentDate + ordinal(currentDate);
1049
- case 'DD' :
1050
- return leftZeroFill(currentDate, 2);
1051
- // DAY OF YEAR
1052
- case 'DDD' :
1053
- a = new Date(currentYear, currentMonth, currentDate);
1054
- b = new Date(currentYear, 0, 1);
1055
- return ~~ (((a - b) / 864e5) + 1.5);
1056
- case 'DDDo' :
1057
- a = replaceFunction('DDD');
1058
- return a + ordinal(a);
1059
- case 'DDDD' :
1060
- return leftZeroFill(replaceFunction('DDD'), 3);
1061
- // WEEKDAY
1062
- case 'd' :
1063
- return currentDay;
1064
- case 'do' :
1065
- return currentDay + ordinal(currentDay);
1066
- case 'ddd' :
1067
- return moment.weekdaysShort[currentDay];
1068
- case 'dddd' :
1069
- return moment.weekdays[currentDay];
1070
- // WEEK OF YEAR
1071
- case 'w' :
1072
- a = new Date(currentYear, currentMonth, currentDate - currentDay + 5);
1073
- b = new Date(a.getFullYear(), 0, 4);
1074
- return ~~ ((a - b) / 864e5 / 7 + 1.5);
1075
- case 'wo' :
1076
- a = replaceFunction('w');
1077
- return a + ordinal(a);
1078
- case 'ww' :
1079
- return leftZeroFill(replaceFunction('w'), 2);
1080
- // YEAR
1081
- case 'YY' :
1082
- return leftZeroFill(currentYear % 100, 2);
1083
- case 'YYYY' :
1084
- return currentYear;
1085
- // AM / PM
1086
- case 'a' :
1087
- return currentHours > 11 ? meridiem.pm : meridiem.am;
1088
- case 'A' :
1089
- return currentHours > 11 ? meridiem.PM : meridiem.AM;
1090
- // 24 HOUR
1091
- case 'H' :
1092
- return currentHours;
1093
- case 'HH' :
1094
- return leftZeroFill(currentHours, 2);
1095
- // 12 HOUR
1096
- case 'h' :
1097
- return currentHours % 12 || 12;
1098
- case 'hh' :
1099
- return leftZeroFill(currentHours % 12 || 12, 2);
1100
- // MINUTE
1101
- case 'm' :
1102
- return currentMinutes;
1103
- case 'mm' :
1104
- return leftZeroFill(currentMinutes, 2);
1105
- // SECOND
1106
- case 's' :
1107
- return currentSeconds;
1108
- case 'ss' :
1109
- return leftZeroFill(currentSeconds, 2);
1110
- // TIMEZONE
1111
- case 'zz' :
1112
- // depreciating 'zz' fall through to 'z'
1113
- case 'z' :
1114
- return (m._d.toString().match(timezoneRegex) || [''])[0].replace(nonuppercaseLetters, '');
1115
- case 'Z' :
1116
- return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(Math.abs(currentZone) / 60), 2) + ':' + leftZeroFill(~~(Math.abs(currentZone) % 60), 2);
1117
- case 'ZZ' :
1118
- return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(10 * Math.abs(currentZone) / 6), 4);
1119
- // LONG DATES
1120
- case 'L' :
1121
- case 'LL' :
1122
- case 'LLL' :
1123
- case 'LLLL' :
1124
- case 'LT' :
1125
- return formatMoment(m, moment.longDateFormat[input]);
1126
- // DEFAULT
1127
- default :
1128
- return input.replace(/(^\[)|(\\)|\]$/g, "");
1129
- }
1130
- }
1131
- return inputString.replace(charactersToReplace, replaceFunction);
1132
- }
1133
-
1134
- // date from string and format string
1135
- function makeDateFromStringAndFormat(string, format) {
1136
- var inArray = [0, 0, 1, 0, 0, 0, 0],
1137
- timezoneHours = 0,
1138
- timezoneMinutes = 0,
1139
- isUsingUTC = false,
1140
- inputParts = string.match(inputCharacters),
1141
- formatParts = format.match(tokenCharacters),
1142
- len = Math.min(inputParts.length, formatParts.length),
1143
- i,
1144
- isPm;
1145
-
1146
- // function to convert string input to date
1147
- function addTime(format, input) {
1148
- var a;
1149
- switch (format) {
1150
- // MONTH
1151
- case 'M' :
1152
- // fall through to MM
1153
- case 'MM' :
1154
- inArray[1] = ~~input - 1;
1155
- break;
1156
- case 'MMM' :
1157
- // fall through to MMMM
1158
- case 'MMMM' :
1159
- for (a = 0; a < 12; a++) {
1160
- if (moment.monthsParse[a].test(input)) {
1161
- inArray[1] = a;
1162
- break;
1163
- }
1164
- }
1165
- break;
1166
- // DAY OF MONTH
1167
- case 'D' :
1168
- // fall through to DDDD
1169
- case 'DD' :
1170
- // fall through to DDDD
1171
- case 'DDD' :
1172
- // fall through to DDDD
1173
- case 'DDDD' :
1174
- inArray[2] = ~~input;
1175
- break;
1176
- // YEAR
1177
- case 'YY' :
1178
- input = ~~input;
1179
- inArray[0] = input + (input > 70 ? 1900 : 2000);
1180
- break;
1181
- case 'YYYY' :
1182
- inArray[0] = ~~Math.abs(input);
1183
- break;
1184
- // AM / PM
1185
- case 'a' :
1186
- // fall through to A
1187
- case 'A' :
1188
- isPm = (input.toLowerCase() === 'pm');
1189
- break;
1190
- // 24 HOUR
1191
- case 'H' :
1192
- // fall through to hh
1193
- case 'HH' :
1194
- // fall through to hh
1195
- case 'h' :
1196
- // fall through to hh
1197
- case 'hh' :
1198
- inArray[3] = ~~input;
1199
- break;
1200
- // MINUTE
1201
- case 'm' :
1202
- // fall through to mm
1203
- case 'mm' :
1204
- inArray[4] = ~~input;
1205
- break;
1206
- // SECOND
1207
- case 's' :
1208
- // fall through to ss
1209
- case 'ss' :
1210
- inArray[5] = ~~input;
1211
- break;
1212
- // TIMEZONE
1213
- case 'Z' :
1214
- // fall through to ZZ
1215
- case 'ZZ' :
1216
- isUsingUTC = true;
1217
- a = (input || '').match(timezoneParseRegex);
1218
- if (a && a[1]) {
1219
- timezoneHours = ~~a[1];
1220
- }
1221
- if (a && a[2]) {
1222
- timezoneMinutes = ~~a[2];
1223
- }
1224
- // reverse offsets
1225
- if (a && a[0] === '+') {
1226
- timezoneHours = -timezoneHours;
1227
- timezoneMinutes = -timezoneMinutes;
1228
- }
1229
- break;
1230
- }
1231
- }
1232
- for (i = 0; i < len; i++) {
1233
- addTime(formatParts[i], inputParts[i]);
1234
- }
1235
- // handle am pm
1236
- if (isPm && inArray[3] < 12) {
1237
- inArray[3] += 12;
1238
- }
1239
- // if is 12 am, change hours to 0
1240
- if (isPm === false && inArray[3] === 12) {
1241
- inArray[3] = 0;
1242
- }
1243
- // handle timezone
1244
- inArray[3] += timezoneHours;
1245
- inArray[4] += timezoneMinutes;
1246
- // return
1247
- return isUsingUTC ? new Date(Date.UTC.apply({}, inArray)) : dateFromArray(inArray);
1248
- }
1249
-
1250
- // compare two arrays, return the number of differences
1251
- function compareArrays(array1, array2) {
1252
- var len = Math.min(array1.length, array2.length),
1253
- lengthDiff = Math.abs(array1.length - array2.length),
1254
- diffs = 0,
1255
- i;
1256
- for (i = 0; i < len; i++) {
1257
- if (~~array1[i] !== ~~array2[i]) {
1258
- diffs++;
1259
- }
1260
- }
1261
- return diffs + lengthDiff;
1262
- }
1263
-
1264
- // date from string and array of format strings
1265
- function makeDateFromStringAndArray(string, formats) {
1266
- var output,
1267
- inputParts = string.match(inputCharacters),
1268
- scores = [],
1269
- scoreToBeat = 99,
1270
- i,
1271
- curDate,
1272
- curScore;
1273
- for (i = 0; i < formats.length; i++) {
1274
- curDate = makeDateFromStringAndFormat(string, formats[i]);
1275
- curScore = compareArrays(inputParts, formatMoment(new Moment(curDate), formats[i]).match(inputCharacters));
1276
- if (curScore < scoreToBeat) {
1277
- scoreToBeat = curScore;
1278
- output = curDate;
1279
- }
1280
- }
1281
- return output;
1282
- }
1283
-
1284
- // date from iso format
1285
- function makeDateFromString(string) {
1286
- var format = 'YYYY-MM-DDT',
1287
- i;
1288
- if (isoRegex.exec(string)) {
1289
- for (i = 0; i < 3; i++) {
1290
- if (isoTimes[i][1].exec(string)) {
1291
- format += isoTimes[i][0];
1292
- break;
1293
- }
1294
- }
1295
- return makeDateFromStringAndFormat(string, format + 'Z');
1296
- }
1297
- return new Date(string);
1298
- }
1299
-
1300
- // helper function for _date.from() and _date.fromNow()
1301
- function substituteTimeAgo(string, number, withoutSuffix) {
1302
- var rt = moment.relativeTime[string];
1303
- return (typeof rt === 'function') ?
1304
- rt(number || 1, !!withoutSuffix, string) :
1305
- rt.replace(/%d/i, number || 1);
1306
- }
1307
-
1308
- function relativeTime(milliseconds, withoutSuffix) {
1309
- var seconds = round(Math.abs(milliseconds) / 1000),
1310
- minutes = round(seconds / 60),
1311
- hours = round(minutes / 60),
1312
- days = round(hours / 24),
1313
- years = round(days / 365),
1314
- args = seconds < 45 && ['s', seconds] ||
1315
- minutes === 1 && ['m'] ||
1316
- minutes < 45 && ['mm', minutes] ||
1317
- hours === 1 && ['h'] ||
1318
- hours < 22 && ['hh', hours] ||
1319
- days === 1 && ['d'] ||
1320
- days <= 25 && ['dd', days] ||
1321
- days <= 45 && ['M'] ||
1322
- days < 345 && ['MM', round(days / 30)] ||
1323
- years === 1 && ['y'] || ['yy', years];
1324
- args[2] = withoutSuffix;
1325
- return substituteTimeAgo.apply({}, args);
1326
- }
1327
-
1328
- moment = function (input, format) {
1329
- if (input === null || input === '') {
1330
- return null;
1331
- }
1332
- var date,
1333
- matched;
1334
- // parse Moment object
1335
- if (input && input._d instanceof Date) {
1336
- date = new Date(+input._d);
1337
- // parse string and format
1338
- } else if (format) {
1339
- if (isArray(format)) {
1340
- date = makeDateFromStringAndArray(input, format);
1341
- } else {
1342
- date = makeDateFromStringAndFormat(input, format);
1343
- }
1344
- // evaluate it as a JSON-encoded date
1345
- } else {
1346
- matched = jsonRegex.exec(input);
1347
- date = input === undefined ? new Date() :
1348
- matched ? new Date(+matched[1]) :
1349
- input instanceof Date ? input :
1350
- isArray(input) ? dateFromArray(input) :
1351
- typeof input === 'string' ? makeDateFromString(input) :
1352
- new Date(input);
1353
- }
1354
- return new Moment(date);
1355
- };
1356
-
1357
- // creating with utc
1358
- moment.utc = function (input, format) {
1359
- if (isArray(input)) {
1360
- return new Moment(new Date(Date.UTC.apply({}, input)), true);
1361
- }
1362
- return (format && input) ? moment(input + ' 0', format + ' Z').utc() : moment(input).utc();
1363
- };
1364
-
1365
- // humanizeDuration
1366
- moment.humanizeDuration = function (num, type, withSuffix) {
1367
- var difference = +num,
1368
- rel = moment.relativeTime,
1369
- output;
1370
- switch (type) {
1371
- case "seconds" :
1372
- difference *= 1000; // 1000
1373
- break;
1374
- case "minutes" :
1375
- difference *= 60000; // 60 * 1000
1376
- break;
1377
- case "hours" :
1378
- difference *= 3600000; // 60 * 60 * 1000
1379
- break;
1380
- case "days" :
1381
- difference *= 86400000; // 24 * 60 * 60 * 1000
1382
- break;
1383
- case "weeks" :
1384
- difference *= 604800000; // 7 * 24 * 60 * 60 * 1000
1385
- break;
1386
- case "months" :
1387
- difference *= 2592000000; // 30 * 24 * 60 * 60 * 1000
1388
- break;
1389
- case "years" :
1390
- difference *= 31536000000; // 365 * 24 * 60 * 60 * 1000
1391
- break;
1392
- default :
1393
- withSuffix = !!type;
1394
- break;
1395
- }
1396
- output = relativeTime(difference, !withSuffix);
1397
- return withSuffix ? (difference <= 0 ? rel.past : rel.future).replace(/%s/i, output) : output;
1398
- };
1399
-
1400
- // version number
1401
- moment.version = VERSION;
1402
-
1403
- // default format
1404
- moment.defaultFormat = isoFormat;
1405
-
1406
- // language switching and caching
1407
- moment.lang = function (key, values) {
1408
- var i,
1409
- param,
1410
- req,
1411
- parse = [];
1412
- if (values) {
1413
- for (i = 0; i < 12; i++) {
1414
- parse[i] = new RegExp('^' + values.months[i] + '|^' + values.monthsShort[i].replace('.', ''), 'i');
1415
- }
1416
- values.monthsParse = values.monthsParse || parse;
1417
- languages[key] = values;
1418
- }
1419
- if (languages[key]) {
1420
- for (i = 0; i < paramsToParse.length; i++) {
1421
- param = paramsToParse[i];
1422
- moment[param] = languages[key][param] || moment[param];
1423
- }
1424
- } else {
1425
- if (hasModule) {
1426
- req = require('./lang/' + key);
1427
- moment.lang(key, req);
1428
- }
1429
- }
1430
- };
1431
-
1432
- // set default language
1433
- moment.lang('en', {
1434
- months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
1435
- monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
1436
- weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
1437
- weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
1438
- longDateFormat : {
1439
- LT : "h:mm A",
1440
- L : "MM/DD/YYYY",
1441
- LL : "MMMM D YYYY",
1442
- LLL : "MMMM D YYYY LT",
1443
- LLLL : "dddd, MMMM D YYYY LT"
1444
- },
1445
- meridiem : {
1446
- AM : 'AM',
1447
- am : 'am',
1448
- PM : 'PM',
1449
- pm : 'pm'
1450
- },
1451
- calendar : {
1452
- sameDay : '[Today at] LT',
1453
- nextDay : '[Tomorrow at] LT',
1454
- nextWeek : 'dddd [at] LT',
1455
- lastDay : '[Yesterday at] LT',
1456
- lastWeek : '[last] dddd [at] LT',
1457
- sameElse : 'L'
1458
- },
1459
- relativeTime : {
1460
- future : "in %s",
1461
- past : "%s ago",
1462
- s : "a few seconds",
1463
- m : "a minute",
1464
- mm : "%d minutes",
1465
- h : "an hour",
1466
- hh : "%d hours",
1467
- d : "a day",
1468
- dd : "%d days",
1469
- M : "a month",
1470
- MM : "%d months",
1471
- y : "a year",
1472
- yy : "%d years"
1473
- },
1474
- ordinal : function (number) {
1475
- var b = number % 10;
1476
- return (~~ (number % 100 / 10) === 1) ? 'th' :
1477
- (b === 1) ? 'st' :
1478
- (b === 2) ? 'nd' :
1479
- (b === 3) ? 'rd' : 'th';
1480
- }
1481
- });
1482
-
1483
- // compare moment object
1484
- moment.isMoment = function (obj) {
1485
- return obj instanceof Moment;
1486
- };
1487
-
1488
- // shortcut for prototype
1489
- moment.fn = Moment.prototype = {
1490
-
1491
- clone : function () {
1492
- return moment(this);
1493
- },
1494
-
1495
- valueOf : function () {
1496
- return +this._d;
1497
- },
1498
-
1499
- 'native' : function () {
1500
- return this._d;
1501
- },
1502
-
1503
- toString : function () {
1504
- return this._d.toString();
1505
- },
1506
-
1507
- toDate : function () {
1508
- return this._d;
1509
- },
1510
-
1511
- utc : function () {
1512
- this._isUTC = true;
1513
- return this;
1514
- },
1515
-
1516
- local : function () {
1517
- this._isUTC = false;
1518
- return this;
1519
- },
1520
-
1521
- format : function (inputString) {
1522
- return formatMoment(this, inputString ? inputString : moment.defaultFormat);
1523
- },
1524
-
1525
- add : function (input, val) {
1526
- this._d = dateAddRemove(this._d, input, 1, val);
1527
- return this;
1528
- },
1529
-
1530
- subtract : function (input, val) {
1531
- this._d = dateAddRemove(this._d, input, -1, val);
1532
- return this;
1533
- },
1534
-
1535
- diff : function (input, val, asFloat) {
1536
- var inputMoment = moment(input),
1537
- zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
1538
- diff = this._d - inputMoment._d - zoneDiff,
1539
- year = this.year() - inputMoment.year(),
1540
- month = this.month() - inputMoment.month(),
1541
- date = this.date() - inputMoment.date(),
1542
- output;
1543
- if (val === 'months') {
1544
- output = year * 12 + month + date / 30;
1545
- } else if (val === 'years') {
1546
- output = year + month / 12;
1547
- } else {
1548
- output = val === 'seconds' ? diff / 1e3 : // 1000
1549
- val === 'minutes' ? diff / 6e4 : // 1000 * 60
1550
- val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
1551
- val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
1552
- val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
1553
- diff;
1554
- }
1555
- return asFloat ? output : round(output);
1556
- },
1557
-
1558
- from : function (time, withoutSuffix) {
1559
- return moment.humanizeDuration(this.diff(time), !withoutSuffix);
1560
- },
1561
-
1562
- fromNow : function (withoutSuffix) {
1563
- return this.from(moment(), withoutSuffix);
1564
- },
1565
-
1566
- calendar : function () {
1567
- var diff = this.diff(moment().sod(), 'days', true),
1568
- calendar = moment.calendar,
1569
- allElse = calendar.sameElse,
1570
- format = diff < -6 ? allElse :
1571
- diff < -1 ? calendar.lastWeek :
1572
- diff < 0 ? calendar.lastDay :
1573
- diff < 1 ? calendar.sameDay :
1574
- diff < 2 ? calendar.nextDay :
1575
- diff < 7 ? calendar.nextWeek : allElse;
1576
- return this.format(typeof format === 'function' ? format.apply(this) : format);
1577
- },
1578
-
1579
- isLeapYear : function () {
1580
- var year = this.year();
1581
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
1582
- },
1583
-
1584
- isDST : function () {
1585
- return (this.zone() < moment([this.year()]).zone() ||
1586
- this.zone() < moment([this.year(), 5]).zone());
1587
- },
1588
-
1589
- day : function (input) {
1590
- var day = this._d.getDay();
1591
- return (typeof input === 'undefined') ? day :
1592
- this.add({ d : input - day });
1593
- },
1594
-
1595
- sod: function () {
1596
- return this.clone()
1597
- .hours(0)
1598
- .minutes(0)
1599
- .seconds(0)
1600
- .milliseconds(0);
1601
- },
1602
-
1603
- eod: function () {
1604
- // end of day = start of day plus 1 day, minus 1 millisecond
1605
- return this.sod().add({
1606
- d : 1,
1607
- ms : -1
1608
- });
1609
- },
1610
-
1611
- zone : function () {
1612
- return this._isUTC ? 0 : this._d.getTimezoneOffset();
1613
- },
1614
-
1615
- daysInMonth : function () {
1616
- return this.clone().month(this.month() + 1).date(0).date();
1617
- }
1618
- };
1619
-
1620
- // helper for adding shortcuts
1621
- function makeShortcut(name, key) {
1622
- moment.fn[name] = function (input) {
1623
- var utc = this._isUTC ? 'UTC' : '';
1624
- if (typeof input !== 'undefined') {
1625
- this._d['set' + utc + key](input);
1626
- return this;
1627
- } else {
1628
- return this._d['get' + utc + key]();
1629
- }
1630
- };
1631
- }
1632
-
1633
- // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
1634
- for (i = 0; i < shortcuts.length; i ++) {
1635
- makeShortcut(shortcuts[i].toLowerCase(), shortcuts[i]);
1636
- }
1637
-
1638
- // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
1639
- makeShortcut('year', 'FullYear');
1640
-
1641
- return moment;
1642
- })(Date);
984
+ };
985
+ if (!Kalendae.moment) {
986
+ if (window.moment) {
987
+ Kalendae.moment = window.moment;
988
+ } else {
989
+ throw "Kalendae requires moment.js. You must use kalendae.standalone.js if moment is not available on the page.";
990
+ }
991
+ }
992
+
993
+ moment = Kalendae.moment;
1643
994
 
1644
995
  //function to reset the date object to 00:00 GMT
1645
996
  moment.fn.stripTime = function () {
1646
997
  this._d = new Date(Math.floor(this._d.valueOf() / 86400000) * 86400000);
1647
998
  return this;
1648
- }
999
+ };
1649
1000
 
1650
1001
 
1651
1002
  //function to get the total number of days since the epoch.
@@ -1653,11 +1004,11 @@ moment.fn.yearDay = function (input) {
1653
1004
  var yearday = Math.floor(this._d / 86400000);
1654
1005
  return (typeof input === 'undefined') ? yearday :
1655
1006
  this.add({ d : input - yearday });
1656
- }
1007
+ };
1657
1008
 
1658
- today = moment().stripTime();
1009
+ today = Kalendae.moment().stripTime();
1659
1010
 
1660
- if (typeof jQuery !== 'undefined') {
1011
+ if (typeof jQuery !== 'undefined' && (typeof document.addEventListener === 'function' || util.isIE8())) {
1661
1012
  jQuery.fn.kalendae = function (options) {
1662
1013
  this.each(function (i, e) {
1663
1014
  if (e.tagName === 'INPUT') {
@@ -1669,7 +1020,7 @@ if (typeof jQuery !== 'undefined') {
1669
1020
  }
1670
1021
  });
1671
1022
  return this;
1672
- }
1023
+ };
1673
1024
  }
1674
1025
 
1675
1026