polymer-rails-forms 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,920 @@
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
+ moment = req.defined && req.defined(id) ? req(id) : undefined;
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
+ isLeapYear = function(year)
111
+ {
112
+ // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
113
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
114
+ },
115
+
116
+ getDaysInMonth = function(year, month)
117
+ {
118
+ return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
119
+ },
120
+
121
+ setToStartOfDay = function(date)
122
+ {
123
+ if (isDate(date)) date.setHours(0,0,0,0);
124
+ },
125
+
126
+ compareDates = function(a,b)
127
+ {
128
+ // weak date comparison (use setToStartOfDay(date) to ensure correct result)
129
+ return a.getTime() === b.getTime();
130
+ },
131
+
132
+ extend = function(to, from, overwrite)
133
+ {
134
+ var prop, hasProp;
135
+ for (prop in from) {
136
+ hasProp = to[prop] !== undefined;
137
+ if (hasProp && typeof from[prop] === 'object' && from[prop].nodeName === undefined) {
138
+ if (isDate(from[prop])) {
139
+ if (overwrite) {
140
+ to[prop] = new Date(from[prop].getTime());
141
+ }
142
+ }
143
+ else if (isArray(from[prop])) {
144
+ if (overwrite) {
145
+ to[prop] = from[prop].slice(0);
146
+ }
147
+ } else {
148
+ to[prop] = extend({}, from[prop], overwrite);
149
+ }
150
+ } else if (overwrite || !hasProp) {
151
+ to[prop] = from[prop];
152
+ }
153
+ }
154
+ return to;
155
+ },
156
+
157
+
158
+ /**
159
+ * defaults and localisation
160
+ */
161
+ defaults = {
162
+
163
+ // bind the picker to a form field
164
+ field: null,
165
+
166
+ // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
167
+ bound: undefined,
168
+
169
+ // position of the datepicker, relative to the field (default to bottom & left)
170
+ // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
171
+ position: 'bottom left',
172
+
173
+ // the default output format for `.toString()` and `field` value
174
+ format: 'YYYY-MM-DD',
175
+
176
+ // the initial date to view when first opened
177
+ defaultDate: null,
178
+
179
+ // make the `defaultDate` the initial selected value
180
+ setDefaultDate: false,
181
+
182
+ // first day of week (0: Sunday, 1: Monday etc)
183
+ firstDay: 0,
184
+
185
+ // the minimum/earliest date that can be selected
186
+ minDate: null,
187
+ // the maximum/latest date that can be selected
188
+ maxDate: null,
189
+
190
+ // number of years either side, or array of upper/lower range
191
+ yearRange: 10,
192
+
193
+ // used internally (don't config outside)
194
+ minYear: 0,
195
+ maxYear: 9999,
196
+ minMonth: undefined,
197
+ maxMonth: undefined,
198
+
199
+ isRTL: false,
200
+
201
+ // Additional text to append to the year in the calendar title
202
+ yearSuffix: '',
203
+
204
+ // Render the month after year in the calendar title
205
+ showMonthAfterYear: false,
206
+
207
+ // how many months are visible (not implemented yet)
208
+ numberOfMonths: 1,
209
+
210
+ // internationalization
211
+ i18n: {
212
+ previousMonth : 'Previous Month',
213
+ nextMonth : 'Next Month',
214
+ months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
215
+ weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
216
+ weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
217
+ },
218
+
219
+ // callback function
220
+ onSelect: null,
221
+ onOpen: null,
222
+ onClose: null,
223
+ onDraw: null
224
+ },
225
+
226
+
227
+ /**
228
+ * templating functions to abstract HTML rendering
229
+ */
230
+ renderDayName = function(opts, day, abbr)
231
+ {
232
+ day += opts.firstDay;
233
+ while (day >= 7) {
234
+ day -= 7;
235
+ }
236
+ return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
237
+ },
238
+
239
+ renderDay = function(i, isSelected, isToday, isDisabled, isEmpty)
240
+ {
241
+ if (isEmpty) {
242
+ return '<td class="is-empty"></td>';
243
+ }
244
+ var arr = [];
245
+ if (isDisabled) {
246
+ arr.push('is-disabled');
247
+ }
248
+ if (isToday) {
249
+ arr.push('is-today');
250
+ }
251
+ if (isSelected) {
252
+ arr.push('is-selected');
253
+ }
254
+ return '<td data-day="' + i + '" class="' + arr.join(' ') + '"><button class="pika-button" type="button">' + i + '</button>' + '</td>';
255
+ },
256
+
257
+ renderRow = function(days, isRTL)
258
+ {
259
+ return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>';
260
+ },
261
+
262
+ renderBody = function(rows)
263
+ {
264
+ return '<tbody>' + rows.join('') + '</tbody>';
265
+ },
266
+
267
+ renderHead = function(opts)
268
+ {
269
+ var i, arr = [];
270
+ for (i = 0; i < 7; i++) {
271
+ arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
272
+ }
273
+ return '<thead>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</thead>';
274
+ },
275
+
276
+ renderTitle = function(instance)
277
+ {
278
+ var i, j, arr,
279
+ opts = instance._o,
280
+ month = instance._m,
281
+ year = instance._y,
282
+ isMinYear = year === opts.minYear,
283
+ isMaxYear = year === opts.maxYear,
284
+ html = '<div class="pika-title">',
285
+ monthHtml,
286
+ yearHtml,
287
+ prev = true,
288
+ next = true;
289
+
290
+ for (arr = [], i = 0; i < 12; i++) {
291
+ arr.push('<option value="' + i + '"' +
292
+ (i === month ? ' selected': '') +
293
+ ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled' : '') + '>' +
294
+ opts.i18n.months[i] + '</option>');
295
+ }
296
+ monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month">' + arr.join('') + '</select></div>';
297
+
298
+ if (isArray(opts.yearRange)) {
299
+ i = opts.yearRange[0];
300
+ j = opts.yearRange[1] + 1;
301
+ } else {
302
+ i = year - opts.yearRange;
303
+ j = 1 + year + opts.yearRange;
304
+ }
305
+
306
+ for (arr = []; i < j && i <= opts.maxYear; i++) {
307
+ if (i >= opts.minYear) {
308
+ arr.push('<option value="' + i + '"' + (i === year ? ' selected': '') + '>' + (i) + '</option>');
309
+ }
310
+ }
311
+ yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year">' + arr.join('') + '</select></div>';
312
+
313
+ if (opts.showMonthAfterYear) {
314
+ html += yearHtml + monthHtml;
315
+ } else {
316
+ html += monthHtml + yearHtml;
317
+ }
318
+
319
+ if (isMinYear && (month === 0 || opts.minMonth >= month)) {
320
+ prev = false;
321
+ }
322
+
323
+ if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
324
+ next = false;
325
+ }
326
+
327
+ html += '<button class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>';
328
+ html += '<button class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>';
329
+
330
+ return html += '</div>';
331
+ },
332
+
333
+ renderTable = function(opts, data)
334
+ {
335
+ return '<table cellpadding="0" cellspacing="0" class="pika-table">' + renderHead(opts) + renderBody(data) + '</table>';
336
+ },
337
+
338
+
339
+ /**
340
+ * Pikaday constructor
341
+ */
342
+ Pikaday = function(options)
343
+ {
344
+ var self = this,
345
+ opts = self.config(options);
346
+
347
+ self._onMouseDown = function(e)
348
+ {
349
+ if (!self._v) {
350
+ return;
351
+ }
352
+ e = e || window.event;
353
+ var target = e.target || e.srcElement;
354
+ if (!target) {
355
+ return;
356
+ }
357
+
358
+ if (!hasClass(target, 'is-disabled')) {
359
+ if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) {
360
+ self.setDate(new Date(self._y, self._m, parseInt(target.innerHTML, 10)));
361
+ if (opts.bound) {
362
+ sto(function() {
363
+ self.hide();
364
+ }, 100);
365
+ }
366
+ return;
367
+ }
368
+ else if (hasClass(target, 'pika-prev')) {
369
+ self.prevMonth();
370
+ }
371
+ else if (hasClass(target, 'pika-next')) {
372
+ self.nextMonth();
373
+ }
374
+ }
375
+ if (!hasClass(target, 'pika-select')) {
376
+ if (e.preventDefault) {
377
+ e.preventDefault();
378
+ } else {
379
+ e.returnValue = false;
380
+ return false;
381
+ }
382
+ } else {
383
+ self._c = true;
384
+ }
385
+ };
386
+
387
+ self._onChange = function(e)
388
+ {
389
+ e = e || window.event;
390
+ var target = e.target || e.srcElement;
391
+ if (!target) {
392
+ return;
393
+ }
394
+ if (hasClass(target, 'pika-select-month')) {
395
+ self.gotoMonth(target.value);
396
+ }
397
+ else if (hasClass(target, 'pika-select-year')) {
398
+ self.gotoYear(target.value);
399
+ }
400
+ };
401
+
402
+ self._onInputChange = function(e)
403
+ {
404
+ var date;
405
+
406
+ if (e.firedBy === self) {
407
+ return;
408
+ }
409
+ if (hasMoment) {
410
+ date = moment(opts.field.value, opts.format);
411
+ date = (date && date.isValid()) ? date.toDate() : null;
412
+ }
413
+ else {
414
+ date = new Date(Date.parse(opts.field.value));
415
+ }
416
+ self.setDate(isDate(date) ? date : null);
417
+ if (!self._v) {
418
+ self.show();
419
+ }
420
+ };
421
+
422
+ self._onInputFocus = function()
423
+ {
424
+ self.show();
425
+ };
426
+
427
+ self._onInputClick = function()
428
+ {
429
+ self.show();
430
+ };
431
+
432
+ self._onInputBlur = function()
433
+ {
434
+ if (!self._c) {
435
+ self._b = sto(function() {
436
+ self.hide();
437
+ }, 50);
438
+ }
439
+ self._c = false;
440
+ };
441
+
442
+ self._onClick = function(e)
443
+ {
444
+ e = e || window.event;
445
+ var target = e.target || e.srcElement,
446
+ pEl = target;
447
+ if (!target) {
448
+ return;
449
+ }
450
+ if (!hasEventListeners && hasClass(target, 'pika-select')) {
451
+ if (!target.onchange) {
452
+ target.setAttribute('onchange', 'return;');
453
+ addEvent(target, 'change', self._onChange);
454
+ }
455
+ }
456
+ do {
457
+ if (hasClass(pEl, 'pika-single')) {
458
+ return;
459
+ }
460
+ }
461
+ while ((pEl = pEl.parentNode));
462
+ if (self._v && target !== opts.trigger) {
463
+ self.hide();
464
+ }
465
+ };
466
+
467
+ self.el = document.createElement('div');
468
+ self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '');
469
+
470
+ addEvent(self.el, 'mousedown', self._onMouseDown, true);
471
+ addEvent(self.el, 'change', self._onChange);
472
+
473
+ if (opts.field) {
474
+ if (opts.bound) {
475
+ document.body.appendChild(self.el);
476
+ } else {
477
+ opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
478
+ }
479
+ addEvent(opts.field, 'change', self._onInputChange);
480
+
481
+ if (!opts.defaultDate) {
482
+ if (hasMoment && opts.field.value) {
483
+ opts.defaultDate = moment(opts.field.value, opts.format).toDate();
484
+ } else {
485
+ opts.defaultDate = new Date(Date.parse(opts.field.value));
486
+ }
487
+ opts.setDefaultDate = true;
488
+ }
489
+ }
490
+
491
+ var defDate = opts.defaultDate;
492
+
493
+ if (isDate(defDate)) {
494
+ if (opts.setDefaultDate) {
495
+ self.setDate(defDate, true);
496
+ } else {
497
+ self.gotoDate(defDate);
498
+ }
499
+ } else {
500
+ self.gotoDate(new Date());
501
+ }
502
+
503
+ if (opts.bound) {
504
+ this.hide();
505
+ self.el.className += ' is-bound';
506
+ addEvent(opts.trigger, 'click', self._onInputClick);
507
+ addEvent(opts.trigger, 'focus', self._onInputFocus);
508
+ addEvent(opts.trigger, 'blur', self._onInputBlur);
509
+ } else {
510
+ this.show();
511
+ }
512
+
513
+ };
514
+
515
+
516
+ /**
517
+ * public Pikaday API
518
+ */
519
+ Pikaday.prototype = {
520
+
521
+
522
+ /**
523
+ * configure functionality
524
+ */
525
+ config: function(options)
526
+ {
527
+ if (!this._o) {
528
+ this._o = extend({}, defaults, true);
529
+ }
530
+
531
+ var opts = extend(this._o, options, true);
532
+
533
+ opts.isRTL = !!opts.isRTL;
534
+
535
+ opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
536
+
537
+ opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
538
+
539
+ opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;
540
+
541
+ var nom = parseInt(opts.numberOfMonths, 10) || 1;
542
+ opts.numberOfMonths = nom > 4 ? 4 : nom;
543
+
544
+ if (!isDate(opts.minDate)) {
545
+ opts.minDate = false;
546
+ }
547
+ if (!isDate(opts.maxDate)) {
548
+ opts.maxDate = false;
549
+ }
550
+ if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
551
+ opts.maxDate = opts.minDate = false;
552
+ }
553
+ if (opts.minDate) {
554
+ setToStartOfDay(opts.minDate);
555
+ opts.minYear = opts.minDate.getFullYear();
556
+ opts.minMonth = opts.minDate.getMonth();
557
+ }
558
+ if (opts.maxDate) {
559
+ setToStartOfDay(opts.maxDate);
560
+ opts.maxYear = opts.maxDate.getFullYear();
561
+ opts.maxMonth = opts.maxDate.getMonth();
562
+ }
563
+
564
+ if (isArray(opts.yearRange)) {
565
+ var fallback = new Date().getFullYear() - 10;
566
+ opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
567
+ opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
568
+ } else {
569
+ opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
570
+ if (opts.yearRange > 100) {
571
+ opts.yearRange = 100;
572
+ }
573
+ }
574
+
575
+ return opts;
576
+ },
577
+
578
+ /**
579
+ * return a formatted string of the current selection (using Moment.js if available)
580
+ */
581
+ toString: function(format)
582
+ {
583
+ return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString();
584
+ },
585
+
586
+ /**
587
+ * return a Moment.js object of the current selection (if available)
588
+ */
589
+ getMoment: function()
590
+ {
591
+ return hasMoment ? moment(this._d) : null;
592
+ },
593
+
594
+ /**
595
+ * set the current selection from a Moment.js object (if available)
596
+ */
597
+ setMoment: function(date, preventOnSelect)
598
+ {
599
+ if (hasMoment && moment.isMoment(date)) {
600
+ this.setDate(date.toDate(), preventOnSelect);
601
+ }
602
+ },
603
+
604
+ /**
605
+ * return a Date object of the current selection
606
+ */
607
+ getDate: function()
608
+ {
609
+ return isDate(this._d) ? new Date(this._d.getTime()) : null;
610
+ },
611
+
612
+ /**
613
+ * set the current selection
614
+ */
615
+ setDate: function(date, preventOnSelect)
616
+ {
617
+ if (!date) {
618
+ this._d = null;
619
+ return this.draw();
620
+ }
621
+ if (typeof date === 'string') {
622
+ date = new Date(Date.parse(date));
623
+ }
624
+ if (!isDate(date)) {
625
+ return;
626
+ }
627
+
628
+ var min = this._o.minDate,
629
+ max = this._o.maxDate;
630
+
631
+ if (isDate(min) && date < min) {
632
+ date = min;
633
+ } else if (isDate(max) && date > max) {
634
+ date = max;
635
+ }
636
+
637
+ this._d = new Date(date.getTime());
638
+ setToStartOfDay(this._d);
639
+ this.gotoDate(this._d);
640
+
641
+ if (this._o.field) {
642
+ this._o.field.value = this.toString();
643
+ fireEvent(this._o.field, 'change', { firedBy: this });
644
+ }
645
+ if (!preventOnSelect && typeof this._o.onSelect === 'function') {
646
+ this._o.onSelect.call(this, this.getDate());
647
+ }
648
+ },
649
+
650
+ /**
651
+ * change view to a specific date
652
+ */
653
+ gotoDate: function(date)
654
+ {
655
+ if (!isDate(date)) {
656
+ return;
657
+ }
658
+ this._y = date.getFullYear();
659
+ this._m = date.getMonth();
660
+ this.draw();
661
+ },
662
+
663
+ gotoToday: function()
664
+ {
665
+ this.gotoDate(new Date());
666
+ },
667
+
668
+ /**
669
+ * change view to a specific month (zero-index, e.g. 0: January)
670
+ */
671
+ gotoMonth: function(month)
672
+ {
673
+ if (!isNaN( (month = parseInt(month, 10)) )) {
674
+ this._m = month < 0 ? 0 : month > 11 ? 11 : month;
675
+ this.draw();
676
+ }
677
+ },
678
+
679
+ nextMonth: function()
680
+ {
681
+ if (++this._m > 11) {
682
+ this._m = 0;
683
+ this._y++;
684
+ }
685
+ this.draw();
686
+ },
687
+
688
+ prevMonth: function()
689
+ {
690
+ if (--this._m < 0) {
691
+ this._m = 11;
692
+ this._y--;
693
+ }
694
+ this.draw();
695
+ },
696
+
697
+ /**
698
+ * change view to a specific full year (e.g. "2012")
699
+ */
700
+ gotoYear: function(year)
701
+ {
702
+ if (!isNaN(year)) {
703
+ this._y = parseInt(year, 10);
704
+ this.draw();
705
+ }
706
+ },
707
+
708
+ /**
709
+ * change the minDate
710
+ */
711
+ setMinDate: function(value)
712
+ {
713
+ this._o.minDate = value;
714
+ },
715
+
716
+ /**
717
+ * change the maxDate
718
+ */
719
+ setMaxDate: function(value)
720
+ {
721
+ this._o.maxDate = value;
722
+ },
723
+
724
+ /**
725
+ * refresh the HTML
726
+ */
727
+ draw: function(force)
728
+ {
729
+ if (!this._v && !force) {
730
+ return;
731
+ }
732
+ var opts = this._o,
733
+ minYear = opts.minYear,
734
+ maxYear = opts.maxYear,
735
+ minMonth = opts.minMonth,
736
+ maxMonth = opts.maxMonth;
737
+
738
+ if (this._y <= minYear) {
739
+ this._y = minYear;
740
+ if (!isNaN(minMonth) && this._m < minMonth) {
741
+ this._m = minMonth;
742
+ }
743
+ }
744
+ if (this._y >= maxYear) {
745
+ this._y = maxYear;
746
+ if (!isNaN(maxMonth) && this._m > maxMonth) {
747
+ this._m = maxMonth;
748
+ }
749
+ }
750
+
751
+ this.el.innerHTML = renderTitle(this) + this.render(this._y, this._m);
752
+
753
+ if (opts.bound) {
754
+ this.adjustPosition();
755
+ if(opts.field.type !== 'hidden') {
756
+ sto(function() {
757
+ opts.trigger.focus();
758
+ }, 1);
759
+ }
760
+ }
761
+
762
+ if (typeof this._o.onDraw === 'function') {
763
+ var self = this;
764
+ sto(function() {
765
+ self._o.onDraw.call(self);
766
+ }, 0);
767
+ }
768
+ },
769
+
770
+ adjustPosition: function()
771
+ {
772
+ var field = this._o.trigger, pEl = field,
773
+ width = this.el.offsetWidth, height = this.el.offsetHeight,
774
+ viewportWidth = window.innerWidth || document.documentElement.clientWidth,
775
+ viewportHeight = window.innerHeight || document.documentElement.clientHeight,
776
+ scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop,
777
+ left, top, clientRect;
778
+
779
+ if (typeof field.getBoundingClientRect === 'function') {
780
+ clientRect = field.getBoundingClientRect();
781
+ left = clientRect.left + window.pageXOffset;
782
+ top = clientRect.bottom + window.pageYOffset;
783
+ } else {
784
+ left = pEl.offsetLeft;
785
+ top = pEl.offsetTop + pEl.offsetHeight;
786
+ while((pEl = pEl.offsetParent)) {
787
+ left += pEl.offsetLeft;
788
+ top += pEl.offsetTop;
789
+ }
790
+ }
791
+
792
+ // default position is bottom & left
793
+ if (left + width > viewportWidth ||
794
+ (
795
+ this._o.position.indexOf('right') > -1 &&
796
+ left - width + field.offsetWidth > 0
797
+ )
798
+ ) {
799
+ left = left - width + field.offsetWidth;
800
+ }
801
+ if (top + height > viewportHeight + scrollTop ||
802
+ (
803
+ this._o.position.indexOf('top') > -1 &&
804
+ top - height - field.offsetHeight > 0
805
+ )
806
+ ) {
807
+ top = top - height - field.offsetHeight;
808
+ }
809
+ this.el.style.cssText = [
810
+ 'position: absolute',
811
+ 'left: ' + left + 'px',
812
+ 'top: ' + top + 'px'
813
+ ].join(';');
814
+ },
815
+
816
+ /**
817
+ * render HTML for a particular month
818
+ */
819
+ render: function(year, month)
820
+ {
821
+ var opts = this._o,
822
+ now = new Date(),
823
+ days = getDaysInMonth(year, month),
824
+ before = new Date(year, month, 1).getDay(),
825
+ data = [],
826
+ row = [];
827
+ setToStartOfDay(now);
828
+ if (opts.firstDay > 0) {
829
+ before -= opts.firstDay;
830
+ if (before < 0) {
831
+ before += 7;
832
+ }
833
+ }
834
+ var cells = days + before,
835
+ after = cells;
836
+ while(after > 7) {
837
+ after -= 7;
838
+ }
839
+ cells += 7 - after;
840
+ for (var i = 0, r = 0; i < cells; i++)
841
+ {
842
+ var day = new Date(year, month, 1 + (i - before)),
843
+ isDisabled = (opts.minDate && day < opts.minDate) || (opts.maxDate && day > opts.maxDate),
844
+ isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
845
+ isToday = compareDates(day, now),
846
+ isEmpty = i < before || i >= (days + before);
847
+
848
+ row.push(renderDay(1 + (i - before), isSelected, isToday, isDisabled, isEmpty));
849
+
850
+ if (++r === 7) {
851
+ data.push(renderRow(row, opts.isRTL));
852
+ row = [];
853
+ r = 0;
854
+ }
855
+ }
856
+ return renderTable(opts, data);
857
+ },
858
+
859
+ isVisible: function()
860
+ {
861
+ return this._v;
862
+ },
863
+
864
+ show: function()
865
+ {
866
+ if (!this._v) {
867
+ if (this._o.bound) {
868
+ addEvent(document, 'click', this._onClick);
869
+ }
870
+ removeClass(this.el, 'is-hidden');
871
+ this._v = true;
872
+ this.draw();
873
+ if (typeof this._o.onOpen === 'function') {
874
+ this._o.onOpen.call(this);
875
+ }
876
+ }
877
+ },
878
+
879
+ hide: function()
880
+ {
881
+ var v = this._v;
882
+ if (v !== false) {
883
+ if (this._o.bound) {
884
+ removeEvent(document, 'click', this._onClick);
885
+ }
886
+ this.el.style.cssText = '';
887
+ addClass(this.el, 'is-hidden');
888
+ this._v = false;
889
+ if (v !== undefined && typeof this._o.onClose === 'function') {
890
+ this._o.onClose.call(this);
891
+ }
892
+ }
893
+ },
894
+
895
+ /**
896
+ * GAME OVER
897
+ */
898
+ destroy: function()
899
+ {
900
+ this.hide();
901
+ removeEvent(this.el, 'mousedown', this._onMouseDown, true);
902
+ removeEvent(this.el, 'change', this._onChange);
903
+ if (this._o.field) {
904
+ removeEvent(this._o.field, 'change', this._onInputChange);
905
+ if (this._o.bound) {
906
+ removeEvent(this._o.trigger, 'click', this._onInputClick);
907
+ removeEvent(this._o.trigger, 'focus', this._onInputFocus);
908
+ removeEvent(this._o.trigger, 'blur', this._onInputBlur);
909
+ }
910
+ }
911
+ if (this.el.parentNode) {
912
+ this.el.parentNode.removeChild(this.el);
913
+ }
914
+ }
915
+
916
+ };
917
+
918
+ return Pikaday;
919
+
920
+ }));