vendor/assets/javascripts/pikaday.js in pikaday-gem-1.1.0.0 vs vendor/assets/javascripts/pikaday.js in pikaday-gem-1.2.0

- old
+ new

@@ -1,29 +1,34 @@ /*! * Pikaday * - * Copyright © 2013 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday + * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday */ -(function (root, define, factory) +(function (root, factory) { 'use strict'; - if (typeof define === 'function' && define.amd) { + var moment; + if (typeof exports === 'object') { + // CommonJS module + // Load moment.js as an optional dependency + try { moment = require('moment'); } catch (e) {} + module.exports = factory(moment); + } else if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(function (req) { // Load moment.js as an optional dependency var id = 'moment'; - var moment = req.defined && req.defined(id) ? req(id) : undefined; - return factory(moment || root.moment); + moment = req.defined && req.defined(id) ? req(id) : undefined; + return factory(moment); }); } else { - // Browser global root.Pikaday = factory(root.moment); } -}(window, window.define, function (moment) +}(this, function (moment) { 'use strict'; /** * feature detection and helper functions @@ -159,10 +164,14 @@ field: null, // automatically show/hide the picker on `field` focus (default `true` if `field` is set) bound: undefined, + // position of the datepicker, relative to the field (default to bottom & left) + // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position) + position: 'bottom left', + // the default output format for `.toString()` and `field` value format: 'YYYY-MM-DD', // the initial date to view when first opened defaultDate: null, @@ -187,10 +196,16 @@ minMonth: undefined, maxMonth: undefined, isRTL: false, + // Additional text to append to the year in the calendar title + yearSuffix: '', + + // Render the month after year in the calendar title + showMonthAfterYear: false, + // how many months are visible (not implemented yet) numberOfMonths: 1, // internationalization i18n: { @@ -265,20 +280,22 @@ month = instance._m, year = instance._y, isMinYear = year === opts.minYear, isMaxYear = year === opts.maxYear, html = '<div class="pika-title">', + monthHtml, + yearHtml, prev = true, next = true; for (arr = [], i = 0; i < 12; i++) { arr.push('<option value="' + i + '"' + (i === month ? ' selected': '') + ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled' : '') + '>' + opts.i18n.months[i] + '</option>'); } - html += '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month">' + arr.join('') + '</select></div>'; + monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month">' + arr.join('') + '</select></div>'; if (isArray(opts.yearRange)) { i = opts.yearRange[0]; j = opts.yearRange[1] + 1; } else { @@ -289,12 +306,18 @@ for (arr = []; i < j && i <= opts.maxYear; i++) { if (i >= opts.minYear) { arr.push('<option value="' + i + '"' + (i === year ? ' selected': '') + '>' + (i) + '</option>'); } } - html += '<div class="pika-label">' + year + '<select class="pika-select pika-select-year">' + arr.join('') + '</select></div>'; + yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year">' + arr.join('') + '</select></div>'; + if (opts.showMonthAfterYear) { + html += yearHtml + monthHtml; + } else { + html += monthHtml + yearHtml; + } + if (isMinYear && (month === 0 || opts.minMonth >= month)) { prev = false; } if (isMaxYear && (month === 11 || opts.maxMonth <= month)) { @@ -434,11 +457,11 @@ if (hasClass(pEl, 'pika-single')) { return; } } while ((pEl = pEl.parentNode)); - if (self._v && target !== opts.field) { + if (self._v && target !== opts.trigger) { self.hide(); } }; self.el = document.createElement('div'); @@ -478,13 +501,13 @@ } if (opts.bound) { this.hide(); self.el.className += ' is-bound'; - addEvent(opts.field, 'click', self._onInputClick); - addEvent(opts.field, 'focus', self._onInputFocus); - addEvent(opts.field, 'blur', self._onInputBlur); + addEvent(opts.trigger, 'click', self._onInputClick); + addEvent(opts.trigger, 'focus', self._onInputFocus); + addEvent(opts.trigger, 'blur', self._onInputBlur); } else { this.show(); } }; @@ -511,10 +534,12 @@ opts.field = (opts.field && opts.field.nodeName) ? opts.field : null; opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field); + opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field; + var nom = parseInt(opts.numberOfMonths, 10) || 1; opts.numberOfMonths = nom > 4 ? 4 : nom; if (!isDate(opts.minDate)) { opts.minDate = false; @@ -567,14 +592,14 @@ }, /** * set the current selection from a Moment.js object (if available) */ - setMoment: function(date) + setMoment: function(date, preventOnSelect) { if (hasMoment && moment.isMoment(date)) { - this.setDate(date.toDate()); + this.setDate(date.toDate(), preventOnSelect); } }, /** * return a Date object of the current selection @@ -679,10 +704,26 @@ this.draw(); } }, /** + * change the minDate + */ + setMinDate: function(value) + { + this._o.minDate = value; + }, + + /** + * change the maxDate + */ + setMaxDate: function(value) + { + this._o.maxDate = value; + }, + + /** * refresh the HTML */ draw: function(force) { if (!this._v && !force) { @@ -708,31 +749,72 @@ } this.el.innerHTML = renderTitle(this) + this.render(this._y, this._m); if (opts.bound) { - var pEl = opts.field, - left = pEl.offsetLeft, - top = pEl.offsetTop + pEl.offsetHeight; - while((pEl = pEl.offsetParent)) { - left += pEl.offsetLeft; - top += pEl.offsetTop; + this.adjustPosition(); + if(opts.field.type !== 'hidden') { + sto(function() { + opts.trigger.focus(); + }, 1); } - this.el.style.cssText = 'position:absolute;left:' + left + 'px;top:' + top + 'px;'; - sto(function() { - opts.field.focus(); - }, 1); } if (typeof this._o.onDraw === 'function') { var self = this; sto(function() { self._o.onDraw.call(self); }, 0); } }, + adjustPosition: function() + { + var field = this._o.trigger, pEl = field, + width = this.el.offsetWidth, height = this.el.offsetHeight, + viewportWidth = window.innerWidth || document.documentElement.clientWidth, + viewportHeight = window.innerHeight || document.documentElement.clientHeight, + scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop, + left, top, clientRect; + + if (typeof field.getBoundingClientRect === 'function') { + clientRect = field.getBoundingClientRect(); + left = clientRect.left + window.pageXOffset; + top = clientRect.bottom + window.pageYOffset; + } else { + left = pEl.offsetLeft; + top = pEl.offsetTop + pEl.offsetHeight; + while((pEl = pEl.offsetParent)) { + left += pEl.offsetLeft; + top += pEl.offsetTop; + } + } + + // default position is bottom & left + if (left + width > viewportWidth || + ( + this._o.position.indexOf('right') > -1 && + left - width + field.offsetWidth > 0 + ) + ) { + left = left - width + field.offsetWidth; + } + if (top + height > viewportHeight + scrollTop || + ( + this._o.position.indexOf('top') > -1 && + top - height - field.offsetHeight > 0 + ) + ) { + top = top - height - field.offsetHeight; + } + this.el.style.cssText = [ + 'position: absolute', + 'left: ' + left + 'px', + 'top: ' + top + 'px' + ].join(';'); + }, + /** * render HTML for a particular month */ render: function(year, month) { @@ -819,13 +901,13 @@ removeEvent(this.el, 'mousedown', this._onMouseDown, true); removeEvent(this.el, 'change', this._onChange); if (this._o.field) { removeEvent(this._o.field, 'change', this._onInputChange); if (this._o.bound) { - removeEvent(this._o.field, 'click', this._onInputClick); - removeEvent(this._o.field, 'focus', this._onInputFocus); - removeEvent(this._o.field, 'blur', this._onInputBlur); + removeEvent(this._o.trigger, 'click', this._onInputClick); + removeEvent(this._o.trigger, 'focus', this._onInputFocus); + removeEvent(this._o.trigger, 'blur', this._onInputBlur); } } if (this.el.parentNode) { this.el.parentNode.removeChild(this.el); } @@ -833,6 +915,6 @@ }; return Pikaday; -})); +})); \ No newline at end of file