pikaday-gem 1.2.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MDg2MTQ5M2FkNWE5ZjUwM2ZlYzk1OTdkMDQzZWY2MWMyMTRmZGU3YQ==
5
- data.tar.gz: !binary |-
6
- YzA2ZDI0NzY4YzEzZjg5NGFkNDhjMzgyZjhmZWU1MmQ4ZjgxMDBmNw==
2
+ SHA1:
3
+ metadata.gz: d2032e2fefb0b27dafc2f14ce31322368c2712fe
4
+ data.tar.gz: 9d22e414b17135a9dff37564d8f5572fdb040e74
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZjMzOTVmZWJmNTRhMTVhOThkN2ZhNWFmMDM3MzBlMGVkY2IxNmI1YjNkNzMx
10
- NDIyNmNkNTEzNzY4MjgwNDlmYTZkNWNhYWFlNzhmMTJjYTQ4NjNmNTU2MDU2
11
- NDIwNTcwZDI4OTVkYjBkZDdiZTQ2MDBlYTIyYzI2YzE0MjIxNGE=
12
- data.tar.gz: !binary |-
13
- MmRmNzBlOGYxMDI4ZTEyYjRlNTQwMDQ5MWE3YmY1NTkxNDU2NDU3MzFlMjU5
14
- NmZmYWFjNDMwNmMzYjcyOTdmMTgyNzY1ZWFmM2JhYTM2OTk0YjY4MjVlYTIy
15
- OTY0Y2RlZTg4NTNiOTNjOTlkYjQ3ZGM2YjU5NWMwODQyYzBlMWI=
6
+ metadata.gz: 2c5ffab394cb2a992da812de8b772fe4f7917fe0caf3a411f0a6fb6cbada3d171d1a6040e3d7df1e44c7d62071aa201b7e9d771f3d0ff9bf9185dc006a4391c9
7
+ data.tar.gz: a5050af9552cbcb3aba57d054c00e9fbf1a10e595f9b555031281e086c7de25fa50c45de84f7bba8c2eb5f381b42b343b66f3dd046f3939707f14741129b022f
@@ -1,3 +1,3 @@
1
1
  module PikadayGem
2
- VERSION = "1.2.0"
2
+ VERSION = '1.4.0'
3
3
  end
@@ -0,0 +1,1084 @@
1
+ /*!
2
+ * Pikaday
3
+ *
4
+ * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday
5
+ */
6
+
7
+ (function (root, factory)
8
+ {
9
+ 'use strict';
10
+
11
+ var moment;
12
+ if (typeof exports === 'object') {
13
+ // CommonJS module
14
+ // Load moment.js as an optional dependency
15
+ try { moment = require('moment'); } catch (e) {}
16
+ module.exports = factory(moment);
17
+ } else if (typeof define === 'function' && define.amd) {
18
+ // AMD. Register as an anonymous module.
19
+ define(function (req)
20
+ {
21
+ // Load moment.js as an optional dependency
22
+ var id = 'moment';
23
+ try { moment = req(id); } catch (e) {}
24
+ return factory(moment);
25
+ });
26
+ } else {
27
+ root.Pikaday = factory(root.moment);
28
+ }
29
+ }(this, function (moment)
30
+ {
31
+ 'use strict';
32
+
33
+ /**
34
+ * feature detection and helper functions
35
+ */
36
+ var hasMoment = typeof moment === 'function',
37
+
38
+ hasEventListeners = !!window.addEventListener,
39
+
40
+ document = window.document,
41
+
42
+ sto = window.setTimeout,
43
+
44
+ addEvent = function(el, e, callback, capture)
45
+ {
46
+ if (hasEventListeners) {
47
+ el.addEventListener(e, callback, !!capture);
48
+ } else {
49
+ el.attachEvent('on' + e, callback);
50
+ }
51
+ },
52
+
53
+ removeEvent = function(el, e, callback, capture)
54
+ {
55
+ if (hasEventListeners) {
56
+ el.removeEventListener(e, callback, !!capture);
57
+ } else {
58
+ el.detachEvent('on' + e, callback);
59
+ }
60
+ },
61
+
62
+ fireEvent = function(el, eventName, data)
63
+ {
64
+ var ev;
65
+
66
+ if (document.createEvent) {
67
+ ev = document.createEvent('HTMLEvents');
68
+ ev.initEvent(eventName, true, false);
69
+ ev = extend(ev, data);
70
+ el.dispatchEvent(ev);
71
+ } else if (document.createEventObject) {
72
+ ev = document.createEventObject();
73
+ ev = extend(ev, data);
74
+ el.fireEvent('on' + eventName, ev);
75
+ }
76
+ },
77
+
78
+ trim = function(str)
79
+ {
80
+ return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,'');
81
+ },
82
+
83
+ hasClass = function(el, cn)
84
+ {
85
+ return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
86
+ },
87
+
88
+ addClass = function(el, cn)
89
+ {
90
+ if (!hasClass(el, cn)) {
91
+ el.className = (el.className === '') ? cn : el.className + ' ' + cn;
92
+ }
93
+ },
94
+
95
+ removeClass = function(el, cn)
96
+ {
97
+ el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
98
+ },
99
+
100
+ isArray = function(obj)
101
+ {
102
+ return (/Array/).test(Object.prototype.toString.call(obj));
103
+ },
104
+
105
+ isDate = function(obj)
106
+ {
107
+ return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
108
+ },
109
+
110
+ isWeekend = function(date)
111
+ {
112
+ var day = date.getDay();
113
+ return day === 0 || day === 6;
114
+ },
115
+
116
+ isLeapYear = function(year)
117
+ {
118
+ // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
119
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
120
+ },
121
+
122
+ getDaysInMonth = function(year, month)
123
+ {
124
+ return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
125
+ },
126
+
127
+ setToStartOfDay = function(date)
128
+ {
129
+ if (isDate(date)) date.setHours(0,0,0,0);
130
+ },
131
+
132
+ compareDates = function(a,b)
133
+ {
134
+ // weak date comparison (use setToStartOfDay(date) to ensure correct result)
135
+ return a.getTime() === b.getTime();
136
+ },
137
+
138
+ extend = function(to, from, overwrite)
139
+ {
140
+ var prop, hasProp;
141
+ for (prop in from) {
142
+ hasProp = to[prop] !== undefined;
143
+ if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) {
144
+ if (isDate(from[prop])) {
145
+ if (overwrite) {
146
+ to[prop] = new Date(from[prop].getTime());
147
+ }
148
+ }
149
+ else if (isArray(from[prop])) {
150
+ if (overwrite) {
151
+ to[prop] = from[prop].slice(0);
152
+ }
153
+ } else {
154
+ to[prop] = extend({}, from[prop], overwrite);
155
+ }
156
+ } else if (overwrite || !hasProp) {
157
+ to[prop] = from[prop];
158
+ }
159
+ }
160
+ return to;
161
+ },
162
+
163
+ adjustCalendar = function(calendar) {
164
+ if (calendar.month < 0) {
165
+ calendar.year -= Math.ceil(Math.abs(calendar.month)/12);
166
+ calendar.month += 12;
167
+ }
168
+ if (calendar.month > 11) {
169
+ calendar.year += Math.floor(Math.abs(calendar.month)/12);
170
+ calendar.month -= 12;
171
+ }
172
+ return calendar;
173
+ },
174
+
175
+ /**
176
+ * defaults and localisation
177
+ */
178
+ defaults = {
179
+
180
+ // bind the picker to a form field
181
+ field: null,
182
+
183
+ // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
184
+ bound: undefined,
185
+
186
+ // position of the datepicker, relative to the field (default to bottom & left)
187
+ // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
188
+ position: 'bottom left',
189
+
190
+ // automatically fit in the viewport even if it means repositioning from the position option
191
+ reposition: true,
192
+
193
+ // the default output format for `.toString()` and `field` value
194
+ format: 'YYYY-MM-DD',
195
+
196
+ // the initial date to view when first opened
197
+ defaultDate: null,
198
+
199
+ // make the `defaultDate` the initial selected value
200
+ setDefaultDate: false,
201
+
202
+ // first day of week (0: Sunday, 1: Monday etc)
203
+ firstDay: 0,
204
+
205
+ // the minimum/earliest date that can be selected
206
+ minDate: null,
207
+ // the maximum/latest date that can be selected
208
+ maxDate: null,
209
+
210
+ // number of years either side, or array of upper/lower range
211
+ yearRange: 10,
212
+
213
+ // show week numbers at head of row
214
+ showWeekNumber: false,
215
+
216
+ // used internally (don't config outside)
217
+ minYear: 0,
218
+ maxYear: 9999,
219
+ minMonth: undefined,
220
+ maxMonth: undefined,
221
+
222
+ startRange: null,
223
+ endRange: null,
224
+
225
+ isRTL: false,
226
+
227
+ // Additional text to append to the year in the calendar title
228
+ yearSuffix: '',
229
+
230
+ // Render the month after year in the calendar title
231
+ showMonthAfterYear: false,
232
+
233
+ // how many months are visible
234
+ numberOfMonths: 1,
235
+
236
+ // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`)
237
+ // only used for the first display or when a selected date is not visible
238
+ mainCalendar: 'left',
239
+
240
+ // Specify a DOM element to render the calendar in
241
+ container: undefined,
242
+
243
+ // internationalization
244
+ i18n: {
245
+ previousMonth : 'Previous Month',
246
+ nextMonth : 'Next Month',
247
+ months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
248
+ weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
249
+ weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
250
+ },
251
+
252
+ // Theme Classname
253
+ theme: null,
254
+
255
+ // callback function
256
+ onSelect: null,
257
+ onOpen: null,
258
+ onClose: null,
259
+ onDraw: null
260
+ },
261
+
262
+
263
+ /**
264
+ * templating functions to abstract HTML rendering
265
+ */
266
+ renderDayName = function(opts, day, abbr)
267
+ {
268
+ day += opts.firstDay;
269
+ while (day >= 7) {
270
+ day -= 7;
271
+ }
272
+ return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
273
+ },
274
+
275
+ renderDay = function(opts)
276
+ {
277
+ if (opts.isEmpty) {
278
+ return '<td class="is-empty"></td>';
279
+ }
280
+ var arr = [];
281
+ if (opts.isDisabled) {
282
+ arr.push('is-disabled');
283
+ }
284
+ if (opts.isToday) {
285
+ arr.push('is-today');
286
+ }
287
+ if (opts.isSelected) {
288
+ arr.push('is-selected');
289
+ }
290
+ if (opts.isInRange) {
291
+ arr.push('is-inrange');
292
+ }
293
+ if (opts.isStartRange) {
294
+ arr.push('is-startrange');
295
+ }
296
+ if (opts.isEndRange) {
297
+ arr.push('is-endrange');
298
+ }
299
+ return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '">' +
300
+ '<button class="pika-button pika-day" type="button" ' +
301
+ 'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
302
+ opts.day +
303
+ '</button>' +
304
+ '</td>';
305
+ },
306
+
307
+ renderWeek = function (d, m, y) {
308
+ // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified.
309
+ var onejan = new Date(y, 0, 1),
310
+ weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7);
311
+ return '<td class="pika-week">' + weekNum + '</td>';
312
+ },
313
+
314
+ renderRow = function(days, isRTL)
315
+ {
316
+ return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>';
317
+ },
318
+
319
+ renderBody = function(rows)
320
+ {
321
+ return '<tbody>' + rows.join('') + '</tbody>';
322
+ },
323
+
324
+ renderHead = function(opts)
325
+ {
326
+ var i, arr = [];
327
+ if (opts.showWeekNumber) {
328
+ arr.push('<th></th>');
329
+ }
330
+ for (i = 0; i < 7; i++) {
331
+ arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
332
+ }
333
+ return '<thead>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</thead>';
334
+ },
335
+
336
+ renderTitle = function(instance, c, year, month, refYear)
337
+ {
338
+ var i, j, arr,
339
+ opts = instance._o,
340
+ isMinYear = year === opts.minYear,
341
+ isMaxYear = year === opts.maxYear,
342
+ html = '<div class="pika-title">',
343
+ monthHtml,
344
+ yearHtml,
345
+ prev = true,
346
+ next = true;
347
+
348
+ for (arr = [], i = 0; i < 12; i++) {
349
+ arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' +
350
+ (i === month ? ' selected': '') +
351
+ ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled' : '') + '>' +
352
+ opts.i18n.months[i] + '</option>');
353
+ }
354
+ monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>';
355
+
356
+ if (isArray(opts.yearRange)) {
357
+ i = opts.yearRange[0];
358
+ j = opts.yearRange[1] + 1;
359
+ } else {
360
+ i = year - opts.yearRange;
361
+ j = 1 + year + opts.yearRange;
362
+ }
363
+
364
+ for (arr = []; i < j && i <= opts.maxYear; i++) {
365
+ if (i >= opts.minYear) {
366
+ arr.push('<option value="' + i + '"' + (i === year ? ' selected': '') + '>' + (i) + '</option>');
367
+ }
368
+ }
369
+ yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>';
370
+
371
+ if (opts.showMonthAfterYear) {
372
+ html += yearHtml + monthHtml;
373
+ } else {
374
+ html += monthHtml + yearHtml;
375
+ }
376
+
377
+ if (isMinYear && (month === 0 || opts.minMonth >= month)) {
378
+ prev = false;
379
+ }
380
+
381
+ if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
382
+ next = false;
383
+ }
384
+
385
+ if (c === 0) {
386
+ html += '<button class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>';
387
+ }
388
+ if (c === (instance._o.numberOfMonths - 1) ) {
389
+ html += '<button class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>';
390
+ }
391
+
392
+ return html += '</div>';
393
+ },
394
+
395
+ renderTable = function(opts, data)
396
+ {
397
+ return '<table cellpadding="0" cellspacing="0" class="pika-table">' + renderHead(opts) + renderBody(data) + '</table>';
398
+ },
399
+
400
+
401
+ /**
402
+ * Pikaday constructor
403
+ */
404
+ Pikaday = function(options)
405
+ {
406
+ var self = this,
407
+ opts = self.config(options);
408
+
409
+ self._onMouseDown = function(e)
410
+ {
411
+ if (!self._v) {
412
+ return;
413
+ }
414
+ e = e || window.event;
415
+ var target = e.target || e.srcElement;
416
+ if (!target) {
417
+ return;
418
+ }
419
+
420
+ if (!hasClass(target, 'is-disabled')) {
421
+ if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) {
422
+ self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day')));
423
+ if (opts.bound) {
424
+ sto(function() {
425
+ self.hide();
426
+ if (opts.field) {
427
+ opts.field.blur();
428
+ }
429
+ }, 100);
430
+ }
431
+ }
432
+ else if (hasClass(target, 'pika-prev')) {
433
+ self.prevMonth();
434
+ }
435
+ else if (hasClass(target, 'pika-next')) {
436
+ self.nextMonth();
437
+ }
438
+ }
439
+ if (!hasClass(target, 'pika-select')) {
440
+ // if this is touch event prevent mouse events emulation
441
+ if (e.preventDefault) {
442
+ e.preventDefault();
443
+ } else {
444
+ e.returnValue = false;
445
+ return false;
446
+ }
447
+ } else {
448
+ self._c = true;
449
+ }
450
+ };
451
+
452
+ self._onChange = function(e)
453
+ {
454
+ e = e || window.event;
455
+ var target = e.target || e.srcElement;
456
+ if (!target) {
457
+ return;
458
+ }
459
+ if (hasClass(target, 'pika-select-month')) {
460
+ self.gotoMonth(target.value);
461
+ }
462
+ else if (hasClass(target, 'pika-select-year')) {
463
+ self.gotoYear(target.value);
464
+ }
465
+ };
466
+
467
+ self._onInputChange = function(e)
468
+ {
469
+ var date;
470
+
471
+ if (e.firedBy === self) {
472
+ return;
473
+ }
474
+ if (hasMoment) {
475
+ date = moment(opts.field.value, opts.format);
476
+ date = (date && date.isValid()) ? date.toDate() : null;
477
+ }
478
+ else {
479
+ date = new Date(Date.parse(opts.field.value));
480
+ }
481
+ if (isDate(date)) {
482
+ self.setDate(date);
483
+ }
484
+ if (!self._v) {
485
+ self.show();
486
+ }
487
+ };
488
+
489
+ self._onInputFocus = function()
490
+ {
491
+ self.show();
492
+ };
493
+
494
+ self._onInputClick = function()
495
+ {
496
+ self.show();
497
+ };
498
+
499
+ self._onInputBlur = function()
500
+ {
501
+ // IE allows pika div to gain focus; catch blur the input field
502
+ var pEl = document.activeElement;
503
+ do {
504
+ if (hasClass(pEl, 'pika-single')) {
505
+ return;
506
+ }
507
+ }
508
+ while ((pEl = pEl.parentNode));
509
+
510
+ if (!self._c) {
511
+ self._b = sto(function() {
512
+ self.hide();
513
+ }, 50);
514
+ }
515
+ self._c = false;
516
+ };
517
+
518
+ self._onClick = function(e)
519
+ {
520
+ e = e || window.event;
521
+ var target = e.target || e.srcElement,
522
+ pEl = target;
523
+ if (!target) {
524
+ return;
525
+ }
526
+ if (!hasEventListeners && hasClass(target, 'pika-select')) {
527
+ if (!target.onchange) {
528
+ target.setAttribute('onchange', 'return;');
529
+ addEvent(target, 'change', self._onChange);
530
+ }
531
+ }
532
+ do {
533
+ if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) {
534
+ return;
535
+ }
536
+ }
537
+ while ((pEl = pEl.parentNode));
538
+ if (self._v && target !== opts.trigger && pEl !== opts.trigger) {
539
+ self.hide();
540
+ }
541
+ };
542
+
543
+ self.el = document.createElement('div');
544
+ self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : '');
545
+
546
+ addEvent(self.el, 'mousedown', self._onMouseDown, true);
547
+ addEvent(self.el, 'touchend', self._onMouseDown, true);
548
+ addEvent(self.el, 'change', self._onChange);
549
+
550
+ if (opts.field) {
551
+ if (opts.container) {
552
+ opts.container.appendChild(self.el);
553
+ } else if (opts.bound) {
554
+ document.body.appendChild(self.el);
555
+ } else {
556
+ opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
557
+ }
558
+ addEvent(opts.field, 'change', self._onInputChange);
559
+
560
+ if (!opts.defaultDate) {
561
+ if (hasMoment && opts.field.value) {
562
+ opts.defaultDate = moment(opts.field.value, opts.format).toDate();
563
+ } else {
564
+ opts.defaultDate = new Date(Date.parse(opts.field.value));
565
+ }
566
+ opts.setDefaultDate = true;
567
+ }
568
+ }
569
+
570
+ var defDate = opts.defaultDate;
571
+
572
+ if (isDate(defDate)) {
573
+ if (opts.setDefaultDate) {
574
+ self.setDate(defDate, true);
575
+ } else {
576
+ self.gotoDate(defDate);
577
+ }
578
+ } else {
579
+ self.gotoDate(new Date());
580
+ }
581
+
582
+ if (opts.bound) {
583
+ this.hide();
584
+ self.el.className += ' is-bound';
585
+ addEvent(opts.trigger, 'click', self._onInputClick);
586
+ addEvent(opts.trigger, 'focus', self._onInputFocus);
587
+ addEvent(opts.trigger, 'blur', self._onInputBlur);
588
+ } else {
589
+ this.show();
590
+ }
591
+ };
592
+
593
+
594
+ /**
595
+ * public Pikaday API
596
+ */
597
+ Pikaday.prototype = {
598
+
599
+
600
+ /**
601
+ * configure functionality
602
+ */
603
+ config: function(options)
604
+ {
605
+ if (!this._o) {
606
+ this._o = extend({}, defaults, true);
607
+ }
608
+
609
+ var opts = extend(this._o, options, true);
610
+
611
+ opts.isRTL = !!opts.isRTL;
612
+
613
+ opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
614
+
615
+ opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null;
616
+
617
+ opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
618
+
619
+ opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;
620
+
621
+ opts.disableWeekends = !!opts.disableWeekends;
622
+
623
+ opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null;
624
+
625
+ var nom = parseInt(opts.numberOfMonths, 10) || 1;
626
+ opts.numberOfMonths = nom > 4 ? 4 : nom;
627
+
628
+ if (!isDate(opts.minDate)) {
629
+ opts.minDate = false;
630
+ }
631
+ if (!isDate(opts.maxDate)) {
632
+ opts.maxDate = false;
633
+ }
634
+ if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
635
+ opts.maxDate = opts.minDate = false;
636
+ }
637
+ if (opts.minDate) {
638
+ this.setMinDate(opts.minDate);
639
+ }
640
+ if (opts.maxDate) {
641
+ this.setMaxDate(opts.maxDate);
642
+ }
643
+
644
+ if (isArray(opts.yearRange)) {
645
+ var fallback = new Date().getFullYear() - 10;
646
+ opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
647
+ opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
648
+ } else {
649
+ opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
650
+ if (opts.yearRange > 100) {
651
+ opts.yearRange = 100;
652
+ }
653
+ }
654
+
655
+ return opts;
656
+ },
657
+
658
+ /**
659
+ * return a formatted string of the current selection (using Moment.js if available)
660
+ */
661
+ toString: function(format)
662
+ {
663
+ return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString();
664
+ },
665
+
666
+ /**
667
+ * return a Moment.js object of the current selection (if available)
668
+ */
669
+ getMoment: function()
670
+ {
671
+ return hasMoment ? moment(this._d) : null;
672
+ },
673
+
674
+ /**
675
+ * set the current selection from a Moment.js object (if available)
676
+ */
677
+ setMoment: function(date, preventOnSelect)
678
+ {
679
+ if (hasMoment && moment.isMoment(date)) {
680
+ this.setDate(date.toDate(), preventOnSelect);
681
+ }
682
+ },
683
+
684
+ /**
685
+ * return a Date object of the current selection
686
+ */
687
+ getDate: function()
688
+ {
689
+ return isDate(this._d) ? new Date(this._d.getTime()) : null;
690
+ },
691
+
692
+ /**
693
+ * set the current selection
694
+ */
695
+ setDate: function(date, preventOnSelect)
696
+ {
697
+ if (!date) {
698
+ this._d = null;
699
+
700
+ if (this._o.field) {
701
+ this._o.field.value = '';
702
+ fireEvent(this._o.field, 'change', { firedBy: this });
703
+ }
704
+
705
+ return this.draw();
706
+ }
707
+ if (typeof date === 'string') {
708
+ date = new Date(Date.parse(date));
709
+ }
710
+ if (!isDate(date)) {
711
+ return;
712
+ }
713
+
714
+ var min = this._o.minDate,
715
+ max = this._o.maxDate;
716
+
717
+ if (isDate(min) && date < min) {
718
+ date = min;
719
+ } else if (isDate(max) && date > max) {
720
+ date = max;
721
+ }
722
+
723
+ this._d = new Date(date.getTime());
724
+ setToStartOfDay(this._d);
725
+ this.gotoDate(this._d);
726
+
727
+ if (this._o.field) {
728
+ this._o.field.value = this.toString();
729
+ fireEvent(this._o.field, 'change', { firedBy: this });
730
+ }
731
+ if (!preventOnSelect && typeof this._o.onSelect === 'function') {
732
+ this._o.onSelect.call(this, this.getDate());
733
+ }
734
+ },
735
+
736
+ /**
737
+ * change view to a specific date
738
+ */
739
+ gotoDate: function(date)
740
+ {
741
+ var newCalendar = true;
742
+
743
+ if (!isDate(date)) {
744
+ return;
745
+ }
746
+
747
+ if (this.calendars) {
748
+ var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
749
+ lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1),
750
+ visibleDate = date.getTime();
751
+ // get the end of the month
752
+ lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1);
753
+ lastVisibleDate.setDate(lastVisibleDate.getDate()-1);
754
+ newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate);
755
+ }
756
+
757
+ if (newCalendar) {
758
+ this.calendars = [{
759
+ month: date.getMonth(),
760
+ year: date.getFullYear()
761
+ }];
762
+ if (this._o.mainCalendar === 'right') {
763
+ this.calendars[0].month += 1 - this._o.numberOfMonths;
764
+ }
765
+ }
766
+
767
+ this.adjustCalendars();
768
+ },
769
+
770
+ adjustCalendars: function() {
771
+ this.calendars[0] = adjustCalendar(this.calendars[0]);
772
+ for (var c = 1; c < this._o.numberOfMonths; c++) {
773
+ this.calendars[c] = adjustCalendar({
774
+ month: this.calendars[0].month + c,
775
+ year: this.calendars[0].year
776
+ });
777
+ }
778
+ this.draw();
779
+ },
780
+
781
+ gotoToday: function()
782
+ {
783
+ this.gotoDate(new Date());
784
+ },
785
+
786
+ /**
787
+ * change view to a specific month (zero-index, e.g. 0: January)
788
+ */
789
+ gotoMonth: function(month)
790
+ {
791
+ if (!isNaN(month)) {
792
+ this.calendars[0].month = parseInt(month, 10);
793
+ this.adjustCalendars();
794
+ }
795
+ },
796
+
797
+ nextMonth: function()
798
+ {
799
+ this.calendars[0].month++;
800
+ this.adjustCalendars();
801
+ },
802
+
803
+ prevMonth: function()
804
+ {
805
+ this.calendars[0].month--;
806
+ this.adjustCalendars();
807
+ },
808
+
809
+ /**
810
+ * change view to a specific full year (e.g. "2012")
811
+ */
812
+ gotoYear: function(year)
813
+ {
814
+ if (!isNaN(year)) {
815
+ this.calendars[0].year = parseInt(year, 10);
816
+ this.adjustCalendars();
817
+ }
818
+ },
819
+
820
+ /**
821
+ * change the minDate
822
+ */
823
+ setMinDate: function(value)
824
+ {
825
+ setToStartOfDay(value);
826
+ this._o.minDate = value;
827
+ this._o.minYear = value.getFullYear();
828
+ this._o.minMonth = value.getMonth();
829
+ this.draw();
830
+ },
831
+
832
+ /**
833
+ * change the maxDate
834
+ */
835
+ setMaxDate: function(value)
836
+ {
837
+ setToStartOfDay(value);
838
+ this._o.maxDate = value;
839
+ this._o.maxYear = value.getFullYear();
840
+ this._o.maxMonth = value.getMonth();
841
+ this.draw();
842
+ },
843
+
844
+ setStartRange: function(value)
845
+ {
846
+ this._o.startRange = value;
847
+ },
848
+
849
+ setEndRange: function(value)
850
+ {
851
+ this._o.endRange = value;
852
+ },
853
+
854
+ /**
855
+ * refresh the HTML
856
+ */
857
+ draw: function(force)
858
+ {
859
+ if (!this._v && !force) {
860
+ return;
861
+ }
862
+ var opts = this._o,
863
+ minYear = opts.minYear,
864
+ maxYear = opts.maxYear,
865
+ minMonth = opts.minMonth,
866
+ maxMonth = opts.maxMonth,
867
+ html = '';
868
+
869
+ if (this._y <= minYear) {
870
+ this._y = minYear;
871
+ if (!isNaN(minMonth) && this._m < minMonth) {
872
+ this._m = minMonth;
873
+ }
874
+ }
875
+ if (this._y >= maxYear) {
876
+ this._y = maxYear;
877
+ if (!isNaN(maxMonth) && this._m > maxMonth) {
878
+ this._m = maxMonth;
879
+ }
880
+ }
881
+
882
+ for (var c = 0; c < opts.numberOfMonths; c++) {
883
+ html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year) + this.render(this.calendars[c].year, this.calendars[c].month) + '</div>';
884
+ }
885
+
886
+ this.el.innerHTML = html;
887
+
888
+ if (opts.bound) {
889
+ if(opts.field.type !== 'hidden') {
890
+ sto(function() {
891
+ opts.trigger.focus();
892
+ }, 1);
893
+ }
894
+ }
895
+
896
+ if (typeof this._o.onDraw === 'function') {
897
+ var self = this;
898
+ sto(function() {
899
+ self._o.onDraw.call(self);
900
+ }, 0);
901
+ }
902
+ },
903
+
904
+ adjustPosition: function()
905
+ {
906
+ var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect;
907
+
908
+ if (this._o.container) return;
909
+
910
+ this.el.style.position = 'absolute';
911
+
912
+ field = this._o.trigger;
913
+ pEl = field;
914
+ width = this.el.offsetWidth;
915
+ height = this.el.offsetHeight;
916
+ viewportWidth = window.innerWidth || document.documentElement.clientWidth;
917
+ viewportHeight = window.innerHeight || document.documentElement.clientHeight;
918
+ scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
919
+
920
+ if (typeof field.getBoundingClientRect === 'function') {
921
+ clientRect = field.getBoundingClientRect();
922
+ left = clientRect.left + window.pageXOffset;
923
+ top = clientRect.bottom + window.pageYOffset;
924
+ } else {
925
+ left = pEl.offsetLeft;
926
+ top = pEl.offsetTop + pEl.offsetHeight;
927
+ while((pEl = pEl.offsetParent)) {
928
+ left += pEl.offsetLeft;
929
+ top += pEl.offsetTop;
930
+ }
931
+ }
932
+
933
+ // default position is bottom & left
934
+ if ((this._o.reposition && left + width > viewportWidth) ||
935
+ (
936
+ this._o.position.indexOf('right') > -1 &&
937
+ left - width + field.offsetWidth > 0
938
+ )
939
+ ) {
940
+ left = left - width + field.offsetWidth;
941
+ }
942
+ if ((this._o.reposition && top + height > viewportHeight + scrollTop) ||
943
+ (
944
+ this._o.position.indexOf('top') > -1 &&
945
+ top - height - field.offsetHeight > 0
946
+ )
947
+ ) {
948
+ top = top - height - field.offsetHeight;
949
+ }
950
+
951
+ this.el.style.left = left + 'px';
952
+ this.el.style.top = top + 'px';
953
+ },
954
+
955
+ /**
956
+ * render HTML for a particular month
957
+ */
958
+ render: function(year, month)
959
+ {
960
+ var opts = this._o,
961
+ now = new Date(),
962
+ days = getDaysInMonth(year, month),
963
+ before = new Date(year, month, 1).getDay(),
964
+ data = [],
965
+ row = [];
966
+ setToStartOfDay(now);
967
+ if (opts.firstDay > 0) {
968
+ before -= opts.firstDay;
969
+ if (before < 0) {
970
+ before += 7;
971
+ }
972
+ }
973
+ var cells = days + before,
974
+ after = cells;
975
+ while(after > 7) {
976
+ after -= 7;
977
+ }
978
+ cells += 7 - after;
979
+ for (var i = 0, r = 0; i < cells; i++)
980
+ {
981
+ var day = new Date(year, month, 1 + (i - before)),
982
+ isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
983
+ isToday = compareDates(day, now),
984
+ isEmpty = i < before || i >= (days + before),
985
+ isStartRange = opts.startRange && compareDates(opts.startRange, day),
986
+ isEndRange = opts.endRange && compareDates(opts.endRange, day),
987
+ isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
988
+ isDisabled = (opts.minDate && day < opts.minDate) ||
989
+ (opts.maxDate && day > opts.maxDate) ||
990
+ (opts.disableWeekends && isWeekend(day)) ||
991
+ (opts.disableDayFn && opts.disableDayFn(day)),
992
+ dayConfig = {
993
+ day: 1 + (i - before),
994
+ month: month,
995
+ year: year,
996
+ isSelected: isSelected,
997
+ isToday: isToday,
998
+ isDisabled: isDisabled,
999
+ isEmpty: isEmpty,
1000
+ isStartRange: isStartRange,
1001
+ isEndRange: isEndRange,
1002
+ isInRange: isInRange
1003
+ };
1004
+
1005
+ row.push(renderDay(dayConfig));
1006
+
1007
+ if (++r === 7) {
1008
+ if (opts.showWeekNumber) {
1009
+ row.unshift(renderWeek(i - before, month, year));
1010
+ }
1011
+ data.push(renderRow(row, opts.isRTL));
1012
+ row = [];
1013
+ r = 0;
1014
+ }
1015
+ }
1016
+ return renderTable(opts, data);
1017
+ },
1018
+
1019
+ isVisible: function()
1020
+ {
1021
+ return this._v;
1022
+ },
1023
+
1024
+ show: function()
1025
+ {
1026
+ if (!this._v) {
1027
+ removeClass(this.el, 'is-hidden');
1028
+ this._v = true;
1029
+ this.draw();
1030
+ if (this._o.bound) {
1031
+ addEvent(document, 'click', this._onClick);
1032
+ this.adjustPosition();
1033
+ }
1034
+ if (typeof this._o.onOpen === 'function') {
1035
+ this._o.onOpen.call(this);
1036
+ }
1037
+ }
1038
+ },
1039
+
1040
+ hide: function()
1041
+ {
1042
+ var v = this._v;
1043
+ if (v !== false) {
1044
+ if (this._o.bound) {
1045
+ removeEvent(document, 'click', this._onClick);
1046
+ }
1047
+ this.el.style.position = 'static'; // reset
1048
+ this.el.style.left = 'auto';
1049
+ this.el.style.top = 'auto';
1050
+ addClass(this.el, 'is-hidden');
1051
+ this._v = false;
1052
+ if (v !== undefined && typeof this._o.onClose === 'function') {
1053
+ this._o.onClose.call(this);
1054
+ }
1055
+ }
1056
+ },
1057
+
1058
+ /**
1059
+ * GAME OVER
1060
+ */
1061
+ destroy: function()
1062
+ {
1063
+ this.hide();
1064
+ removeEvent(this.el, 'mousedown', this._onMouseDown, true);
1065
+ removeEvent(this.el, 'touchend', this._onMouseDown, true);
1066
+ removeEvent(this.el, 'change', this._onChange);
1067
+ if (this._o.field) {
1068
+ removeEvent(this._o.field, 'change', this._onInputChange);
1069
+ if (this._o.bound) {
1070
+ removeEvent(this._o.trigger, 'click', this._onInputClick);
1071
+ removeEvent(this._o.trigger, 'focus', this._onInputFocus);
1072
+ removeEvent(this._o.trigger, 'blur', this._onInputBlur);
1073
+ }
1074
+ }
1075
+ if (this.el.parentNode) {
1076
+ this.el.parentNode.removeChild(this.el);
1077
+ }
1078
+ }
1079
+
1080
+ };
1081
+
1082
+ return Pikaday;
1083
+
1084
+ }));