diff --git a/dist/css/datepicker.css b/dist/css/datepicker.css index b5e4730..feb6153 100644 --- a/dist/css/datepicker.css +++ b/dist/css/datepicker.css @@ -17,6 +17,7 @@ top: 0; } .datepicker { + background: #fff; border: 1px solid #ddd; border-radius: 2px; box-sizing: content-box; diff --git a/dist/js/datepicker.js b/dist/js/datepicker.js index 0b89466..f92b2b8 100644 --- a/dist/js/datepicker.js +++ b/dist/js/datepicker.js @@ -3,6 +3,7 @@ var Datepicker; (function (window, $, undefined) { var pluginName = 'datepicker', $body, $datepickersContainer, + containerBuilt = false, baseTemplate = '' + '
' + '' + @@ -66,7 +67,7 @@ var Datepicker; this.el = el; this.$el = $(el); - this.opts = $.extend({}, defaults, options); + this.opts = $.extend(true, {}, defaults, options); if ($body == undefined) { $body = $('body'); @@ -80,18 +81,13 @@ var Datepicker; this.elIsInput = true; } - if (!this.containerBuilt && !this.opts.inline && this.elIsInput) { - this._buildDatepickersContainer(); - } - this.inited = false; this.visible = false; this.silent = false; // Need to prevent unnecessary rendering this.currentDate = this.opts.startDate; this.currentView = this.opts.view; - this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); - this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000); + this._createShortCuts(); this.selectedDates = []; this.views = {}; @@ -100,12 +96,15 @@ var Datepicker; Datepicker.prototype = { - containerBuilt: false, viewIndexes: ['days', 'months', 'years'], init: function () { + if (!containerBuilt && !this.opts.inline && this.elIsInput) { + this._buildDatepickersContainer(); + } this._buildBaseHtml(); this._defineLocale(this.opts.language); + this._syncWithMinMaxDates(); if (this.elIsInput) { if (!this.opts.inline) { @@ -123,6 +122,12 @@ var Datepicker; this.inited = true; }, + _createShortCuts: function () { + + this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); + this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000); + }, + _bindEvents : function () { this.$el.on(this.opts.showEvent, this._onShowEvent.bind(this)); this.$el.on('blur', this._onBlur.bind(this)); @@ -155,7 +160,7 @@ var Datepicker; }, _buildDatepickersContainer: function () { - this.containerBuilt = true; + containerBuilt = true; $body.append('
'); $datepickersContainer = $('#datepickers-container'); }, @@ -315,6 +320,10 @@ var Datepicker; this._setInputValue(); + if (this.opts.onSelect) { + this._triggerOnChange(); + } + if (this.opts.autoClose) { this.hide(); } else { @@ -331,6 +340,9 @@ var Datepicker; selected.splice(i, 1); _this.views[_this.currentView]._render(); _this._setInputValue(); + if (_this.opts.onSelect) { + _this._triggerOnChange(); + } return true } }) @@ -349,6 +361,47 @@ var Datepicker; this._triggerOnChange() }, + /** + * Updates datepicker options + * @param {String|Object} param - parameter's name to update. If object then it will extend current options + * @param {String|Number|Object} [value] - new param value + */ + update: function (param, value) { + var len = arguments.length; + if (len == 2) { + this.opts[param] = value; + } else if (len == 1 && typeof param == 'object') { + this.opts = $.extend(true, this.opts, param) + } + + this._createShortCuts(); + this._syncWithMinMaxDates(); + this.nav._addButtonsIfNeed(); + this.nav._render(); + this.views[this.currentView]._render(); + + if (this.elIsInput && !this.opts.inline) { + this._setPositionClasses(this.opts.position); + if (this.visible) { + this.setPosition(this.opts.position) + } + } + + return this; + }, + + _syncWithMinMaxDates: function () { + var curTime = this.date.getTime(); + this.silent = true; + if (this.minTime > curTime) { + this.date = this.minDate; + } + + if (this.maxTime < curTime) { + this.date = this.maxDate; + } + this.silent = false; + }, _isSelected: function (checkDate, cellType) { return this.selectedDates.some(function (date) { @@ -404,9 +457,14 @@ var Datepicker; _setPositionClasses: function (pos) { pos = pos.split(' '); var main = pos[0], - sec = pos[1]; + sec = pos[1], + classes = 'datepicker -' + main + '-' + sec + '- -from-' + main + '-'; - this.$datepicker.addClass('-' + main + '-' + sec + '- -from-' + main + '-'); + if (this.visible) classes += ' active'; + + this.$datepicker + .removeAttr('class') + .addClass(classes); }, setPosition: function (position) { @@ -520,9 +578,14 @@ var Datepicker; }, set view (val) { + this.viewIndex = this.viewIndexes.indexOf(val); + + if (this.viewIndex < 0) { + return; + } + this.prevView = this.currentView; this.currentView = val; - this.viewIndex = this.viewIndexes.indexOf(val); if (this.inited) { if (!this.views[val]) { @@ -671,20 +734,21 @@ var Datepicker; _bindEvents: function () { this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this)); this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this)); - if (this.$buttonsContainer.length) { - this.$buttonsContainer.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this)); - } + this.d.$datepicker.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this)); }, _buildBaseHtml: function () { this._render(); + this._addButtonsIfNeed(); + }, + + _addButtonsIfNeed: function () { if (this.opts.todayButton) { this._addButton('today') } if (this.opts.clearButton) { this._addButton('clear') } - this.$navButton = $('.datepicker--nav-action', this.d.$nav); }, _render: function () { @@ -1045,20 +1109,14 @@ var Datepicker; // Select date if min view is reached var selectedDate = new Date(year, month, date), - alreadySelected = this.d._isSelected(selectedDate, this.d.cellType), - triggerOnChange = true; + alreadySelected = this.d._isSelected(selectedDate, this.d.cellType); if (!alreadySelected) { this.d.selectDate(selectedDate); } else if (alreadySelected && this.opts.toggleSelected){ this.d.removeDate(selectedDate); - } else if (alreadySelected && !this.opts.toggleSelected) { - triggerOnChange = false; } - if (triggerOnChange) { - this.d._triggerOnChange() - } }, _onClickCell: function (e) { diff --git a/index.html b/index.html index b36e46b..20d642a 100644 --- a/index.html +++ b/index.html @@ -11,20 +11,32 @@
- + + +
+
+ +
\ No newline at end of file diff --git a/js/datepicker/body.js b/js/datepicker/body.js index 7588dad..e99aa38 100644 --- a/js/datepicker/body.js +++ b/js/datepicker/body.js @@ -258,20 +258,14 @@ // Select date if min view is reached var selectedDate = new Date(year, month, date), - alreadySelected = this.d._isSelected(selectedDate, this.d.cellType), - triggerOnChange = true; + alreadySelected = this.d._isSelected(selectedDate, this.d.cellType); if (!alreadySelected) { this.d.selectDate(selectedDate); } else if (alreadySelected && this.opts.toggleSelected){ this.d.removeDate(selectedDate); - } else if (alreadySelected && !this.opts.toggleSelected) { - triggerOnChange = false; } - if (triggerOnChange) { - this.d._triggerOnChange() - } }, _onClickCell: function (e) { diff --git a/js/datepicker/datepicker.js b/js/datepicker/datepicker.js index 514dc9a..8f5e8f8 100644 --- a/js/datepicker/datepicker.js +++ b/js/datepicker/datepicker.js @@ -3,6 +3,7 @@ var Datepicker; (function (window, $, undefined) { var pluginName = 'datepicker', $body, $datepickersContainer, + containerBuilt = false, baseTemplate = '' + '
' + '' + @@ -66,7 +67,7 @@ var Datepicker; this.el = el; this.$el = $(el); - this.opts = $.extend({}, defaults, options); + this.opts = $.extend(true, {}, defaults, options); if ($body == undefined) { $body = $('body'); @@ -80,18 +81,13 @@ var Datepicker; this.elIsInput = true; } - if (!this.containerBuilt && !this.opts.inline && this.elIsInput) { - this._buildDatepickersContainer(); - } - this.inited = false; this.visible = false; this.silent = false; // Need to prevent unnecessary rendering this.currentDate = this.opts.startDate; this.currentView = this.opts.view; - this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); - this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000); + this._createShortCuts(); this.selectedDates = []; this.views = {}; @@ -100,12 +96,15 @@ var Datepicker; Datepicker.prototype = { - containerBuilt: false, viewIndexes: ['days', 'months', 'years'], init: function () { + if (!containerBuilt && !this.opts.inline && this.elIsInput) { + this._buildDatepickersContainer(); + } this._buildBaseHtml(); this._defineLocale(this.opts.language); + this._syncWithMinMaxDates(); if (this.elIsInput) { if (!this.opts.inline) { @@ -123,6 +122,12 @@ var Datepicker; this.inited = true; }, + _createShortCuts: function () { + + this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); + this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000); + }, + _bindEvents : function () { this.$el.on(this.opts.showEvent, this._onShowEvent.bind(this)); this.$el.on('blur', this._onBlur.bind(this)); @@ -155,7 +160,7 @@ var Datepicker; }, _buildDatepickersContainer: function () { - this.containerBuilt = true; + containerBuilt = true; $body.append('
'); $datepickersContainer = $('#datepickers-container'); }, @@ -315,6 +320,10 @@ var Datepicker; this._setInputValue(); + if (this.opts.onSelect) { + this._triggerOnChange(); + } + if (this.opts.autoClose) { this.hide(); } else { @@ -331,6 +340,9 @@ var Datepicker; selected.splice(i, 1); _this.views[_this.currentView]._render(); _this._setInputValue(); + if (_this.opts.onSelect) { + _this._triggerOnChange(); + } return true } }) @@ -349,6 +361,47 @@ var Datepicker; this._triggerOnChange() }, + /** + * Updates datepicker options + * @param {String|Object} param - parameter's name to update. If object then it will extend current options + * @param {String|Number|Object} [value] - new param value + */ + update: function (param, value) { + var len = arguments.length; + if (len == 2) { + this.opts[param] = value; + } else if (len == 1 && typeof param == 'object') { + this.opts = $.extend(true, this.opts, param) + } + + this._createShortCuts(); + this._syncWithMinMaxDates(); + this.nav._addButtonsIfNeed(); + this.nav._render(); + this.views[this.currentView]._render(); + + if (this.elIsInput && !this.opts.inline) { + this._setPositionClasses(this.opts.position); + if (this.visible) { + this.setPosition(this.opts.position) + } + } + + return this; + }, + + _syncWithMinMaxDates: function () { + var curTime = this.date.getTime(); + this.silent = true; + if (this.minTime > curTime) { + this.date = this.minDate; + } + + if (this.maxTime < curTime) { + this.date = this.maxDate; + } + this.silent = false; + }, _isSelected: function (checkDate, cellType) { return this.selectedDates.some(function (date) { @@ -404,9 +457,14 @@ var Datepicker; _setPositionClasses: function (pos) { pos = pos.split(' '); var main = pos[0], - sec = pos[1]; + sec = pos[1], + classes = 'datepicker -' + main + '-' + sec + '- -from-' + main + '-'; - this.$datepicker.addClass('-' + main + '-' + sec + '- -from-' + main + '-'); + if (this.visible) classes += ' active'; + + this.$datepicker + .removeAttr('class') + .addClass(classes); }, setPosition: function (position) { @@ -520,9 +578,14 @@ var Datepicker; }, set view (val) { + this.viewIndex = this.viewIndexes.indexOf(val); + + if (this.viewIndex < 0) { + return; + } + this.prevView = this.currentView; this.currentView = val; - this.viewIndex = this.viewIndexes.indexOf(val); if (this.inited) { if (!this.views[val]) { diff --git a/js/datepicker/navigation.js b/js/datepicker/navigation.js index 60feb00..07cf05e 100644 --- a/js/datepicker/navigation.js +++ b/js/datepicker/navigation.js @@ -24,20 +24,21 @@ _bindEvents: function () { this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this)); this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this)); - if (this.$buttonsContainer.length) { - this.$buttonsContainer.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this)); - } + this.d.$datepicker.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this)); }, _buildBaseHtml: function () { this._render(); + this._addButtonsIfNeed(); + }, + + _addButtonsIfNeed: function () { if (this.opts.todayButton) { this._addButton('today') } if (this.opts.clearButton) { this._addButton('clear') } - this.$navButton = $('.datepicker--nav-action', this.d.$nav); }, _render: function () { diff --git a/sass/datepicker/_datepicker.scss b/sass/datepicker/_datepicker.scss index aac4a50..af8a978 100644 --- a/sass/datepicker/_datepicker.scss +++ b/sass/datepicker/_datepicker.scss @@ -11,6 +11,7 @@ } .datepicker { + background: #fff; border: 1px solid $colorGrey; border-radius: $datepickerBorderRadius; box-sizing: content-box;