add update method, improve min max dates

This commit is contained in:
t1m0n 2015-11-17 11:52:26 +03:00
parent c3925ea9a0
commit 629e1f8318
7 changed files with 184 additions and 54 deletions

View File

@ -17,6 +17,7 @@
top: 0; } top: 0; }
.datepicker { .datepicker {
background: #fff;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 2px; border-radius: 2px;
box-sizing: content-box; box-sizing: content-box;

104
dist/js/datepicker.js vendored
View File

@ -3,6 +3,7 @@ var Datepicker;
(function (window, $, undefined) { (function (window, $, undefined) {
var pluginName = 'datepicker', var pluginName = 'datepicker',
$body, $datepickersContainer, $body, $datepickersContainer,
containerBuilt = false,
baseTemplate = '' + baseTemplate = '' +
'<div class="datepicker">' + '<div class="datepicker">' +
'<nav class="datepicker--nav"></nav>' + '<nav class="datepicker--nav"></nav>' +
@ -66,7 +67,7 @@ var Datepicker;
this.el = el; this.el = el;
this.$el = $(el); this.$el = $(el);
this.opts = $.extend({}, defaults, options); this.opts = $.extend(true, {}, defaults, options);
if ($body == undefined) { if ($body == undefined) {
$body = $('body'); $body = $('body');
@ -80,18 +81,13 @@ var Datepicker;
this.elIsInput = true; this.elIsInput = true;
} }
if (!this.containerBuilt && !this.opts.inline && this.elIsInput) {
this._buildDatepickersContainer();
}
this.inited = false; this.inited = false;
this.visible = false; this.visible = false;
this.silent = false; // Need to prevent unnecessary rendering this.silent = false; // Need to prevent unnecessary rendering
this.currentDate = this.opts.startDate; this.currentDate = this.opts.startDate;
this.currentView = this.opts.view; this.currentView = this.opts.view;
this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); this._createShortCuts();
this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000);
this.selectedDates = []; this.selectedDates = [];
this.views = {}; this.views = {};
@ -100,12 +96,15 @@ var Datepicker;
Datepicker.prototype = { Datepicker.prototype = {
containerBuilt: false,
viewIndexes: ['days', 'months', 'years'], viewIndexes: ['days', 'months', 'years'],
init: function () { init: function () {
if (!containerBuilt && !this.opts.inline && this.elIsInput) {
this._buildDatepickersContainer();
}
this._buildBaseHtml(); this._buildBaseHtml();
this._defineLocale(this.opts.language); this._defineLocale(this.opts.language);
this._syncWithMinMaxDates();
if (this.elIsInput) { if (this.elIsInput) {
if (!this.opts.inline) { if (!this.opts.inline) {
@ -123,6 +122,12 @@ var Datepicker;
this.inited = true; 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 () { _bindEvents : function () {
this.$el.on(this.opts.showEvent, this._onShowEvent.bind(this)); this.$el.on(this.opts.showEvent, this._onShowEvent.bind(this));
this.$el.on('blur', this._onBlur.bind(this)); this.$el.on('blur', this._onBlur.bind(this));
@ -155,7 +160,7 @@ var Datepicker;
}, },
_buildDatepickersContainer: function () { _buildDatepickersContainer: function () {
this.containerBuilt = true; containerBuilt = true;
$body.append('<div class="datepickers-container" id="datepickers-container"></div>'); $body.append('<div class="datepickers-container" id="datepickers-container"></div>');
$datepickersContainer = $('#datepickers-container'); $datepickersContainer = $('#datepickers-container');
}, },
@ -315,6 +320,10 @@ var Datepicker;
this._setInputValue(); this._setInputValue();
if (this.opts.onSelect) {
this._triggerOnChange();
}
if (this.opts.autoClose) { if (this.opts.autoClose) {
this.hide(); this.hide();
} else { } else {
@ -331,6 +340,9 @@ var Datepicker;
selected.splice(i, 1); selected.splice(i, 1);
_this.views[_this.currentView]._render(); _this.views[_this.currentView]._render();
_this._setInputValue(); _this._setInputValue();
if (_this.opts.onSelect) {
_this._triggerOnChange();
}
return true return true
} }
}) })
@ -349,6 +361,47 @@ var Datepicker;
this._triggerOnChange() 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) { _isSelected: function (checkDate, cellType) {
return this.selectedDates.some(function (date) { return this.selectedDates.some(function (date) {
@ -404,9 +457,14 @@ var Datepicker;
_setPositionClasses: function (pos) { _setPositionClasses: function (pos) {
pos = pos.split(' '); pos = pos.split(' ');
var main = pos[0], 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) { setPosition: function (position) {
@ -520,9 +578,14 @@ var Datepicker;
}, },
set view (val) { set view (val) {
this.viewIndex = this.viewIndexes.indexOf(val);
if (this.viewIndex < 0) {
return;
}
this.prevView = this.currentView; this.prevView = this.currentView;
this.currentView = val; this.currentView = val;
this.viewIndex = this.viewIndexes.indexOf(val);
if (this.inited) { if (this.inited) {
if (!this.views[val]) { if (!this.views[val]) {
@ -671,20 +734,21 @@ var Datepicker;
_bindEvents: function () { _bindEvents: function () {
this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this)); this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this));
this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this)); this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this));
if (this.$buttonsContainer.length) { this.d.$datepicker.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this));
this.$buttonsContainer.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this));
}
}, },
_buildBaseHtml: function () { _buildBaseHtml: function () {
this._render(); this._render();
this._addButtonsIfNeed();
},
_addButtonsIfNeed: function () {
if (this.opts.todayButton) { if (this.opts.todayButton) {
this._addButton('today') this._addButton('today')
} }
if (this.opts.clearButton) { if (this.opts.clearButton) {
this._addButton('clear') this._addButton('clear')
} }
this.$navButton = $('.datepicker--nav-action', this.d.$nav);
}, },
_render: function () { _render: function () {
@ -1045,20 +1109,14 @@ var Datepicker;
// Select date if min view is reached // Select date if min view is reached
var selectedDate = new Date(year, month, date), var selectedDate = new Date(year, month, date),
alreadySelected = this.d._isSelected(selectedDate, this.d.cellType), alreadySelected = this.d._isSelected(selectedDate, this.d.cellType);
triggerOnChange = true;
if (!alreadySelected) { if (!alreadySelected) {
this.d.selectDate(selectedDate); this.d.selectDate(selectedDate);
} else if (alreadySelected && this.opts.toggleSelected){ } else if (alreadySelected && this.opts.toggleSelected){
this.d.removeDate(selectedDate); this.d.removeDate(selectedDate);
} else if (alreadySelected && !this.opts.toggleSelected) {
triggerOnChange = false;
} }
if (triggerOnChange) {
this.d._triggerOnChange()
}
}, },
_onClickCell: function (e) { _onClickCell: function (e) {

View File

@ -11,20 +11,32 @@
<div class="contents"> <div class="contents">
<article> <article>
<div class="calendar"></div> <div class="calendar"></div>
<input type="text" class="calendar"/> <input type="text" name="start" placeholder="Start"/>
<input type="text" name="end" placeholder="End"/>
<br/>
<br/>
<button>Update</button>
</article> </article>
</div> </div>
<script type="text/javascript" src="dist/js/datepicker.js"></script> <script type="text/javascript" src="dist/js/datepicker.js"></script>
<script type="text/javascript" src="dist/js/i18n/datepicker.en.js"></script> <script type="text/javascript" src="dist/js/i18n/datepicker.en.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$('.calendar').datepicker({ var $start = $('[name="start"]'),
onChangeDecade: function (val) { $end = $('[name="end"]');
console.log(val);
}, $start.datepicker({
onSelect: function (dateString, date, inst) { onSelect: function (format, date) {
console.log(dateString); $end.data('datepicker')
.update('minDate', date)
} }
}); })
$end.datepicker({
onSelect: function (format, date) {
$start.data('datepicker')
.update('maxDate', date)
}
})
</script> </script>
</body> </body>
</html> </html>

View File

@ -258,20 +258,14 @@
// Select date if min view is reached // Select date if min view is reached
var selectedDate = new Date(year, month, date), var selectedDate = new Date(year, month, date),
alreadySelected = this.d._isSelected(selectedDate, this.d.cellType), alreadySelected = this.d._isSelected(selectedDate, this.d.cellType);
triggerOnChange = true;
if (!alreadySelected) { if (!alreadySelected) {
this.d.selectDate(selectedDate); this.d.selectDate(selectedDate);
} else if (alreadySelected && this.opts.toggleSelected){ } else if (alreadySelected && this.opts.toggleSelected){
this.d.removeDate(selectedDate); this.d.removeDate(selectedDate);
} else if (alreadySelected && !this.opts.toggleSelected) {
triggerOnChange = false;
} }
if (triggerOnChange) {
this.d._triggerOnChange()
}
}, },
_onClickCell: function (e) { _onClickCell: function (e) {

View File

@ -3,6 +3,7 @@ var Datepicker;
(function (window, $, undefined) { (function (window, $, undefined) {
var pluginName = 'datepicker', var pluginName = 'datepicker',
$body, $datepickersContainer, $body, $datepickersContainer,
containerBuilt = false,
baseTemplate = '' + baseTemplate = '' +
'<div class="datepicker">' + '<div class="datepicker">' +
'<nav class="datepicker--nav"></nav>' + '<nav class="datepicker--nav"></nav>' +
@ -66,7 +67,7 @@ var Datepicker;
this.el = el; this.el = el;
this.$el = $(el); this.$el = $(el);
this.opts = $.extend({}, defaults, options); this.opts = $.extend(true, {}, defaults, options);
if ($body == undefined) { if ($body == undefined) {
$body = $('body'); $body = $('body');
@ -80,18 +81,13 @@ var Datepicker;
this.elIsInput = true; this.elIsInput = true;
} }
if (!this.containerBuilt && !this.opts.inline && this.elIsInput) {
this._buildDatepickersContainer();
}
this.inited = false; this.inited = false;
this.visible = false; this.visible = false;
this.silent = false; // Need to prevent unnecessary rendering this.silent = false; // Need to prevent unnecessary rendering
this.currentDate = this.opts.startDate; this.currentDate = this.opts.startDate;
this.currentView = this.opts.view; this.currentView = this.opts.view;
this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); this._createShortCuts();
this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000);
this.selectedDates = []; this.selectedDates = [];
this.views = {}; this.views = {};
@ -100,12 +96,15 @@ var Datepicker;
Datepicker.prototype = { Datepicker.prototype = {
containerBuilt: false,
viewIndexes: ['days', 'months', 'years'], viewIndexes: ['days', 'months', 'years'],
init: function () { init: function () {
if (!containerBuilt && !this.opts.inline && this.elIsInput) {
this._buildDatepickersContainer();
}
this._buildBaseHtml(); this._buildBaseHtml();
this._defineLocale(this.opts.language); this._defineLocale(this.opts.language);
this._syncWithMinMaxDates();
if (this.elIsInput) { if (this.elIsInput) {
if (!this.opts.inline) { if (!this.opts.inline) {
@ -123,6 +122,12 @@ var Datepicker;
this.inited = true; 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 () { _bindEvents : function () {
this.$el.on(this.opts.showEvent, this._onShowEvent.bind(this)); this.$el.on(this.opts.showEvent, this._onShowEvent.bind(this));
this.$el.on('blur', this._onBlur.bind(this)); this.$el.on('blur', this._onBlur.bind(this));
@ -155,7 +160,7 @@ var Datepicker;
}, },
_buildDatepickersContainer: function () { _buildDatepickersContainer: function () {
this.containerBuilt = true; containerBuilt = true;
$body.append('<div class="datepickers-container" id="datepickers-container"></div>'); $body.append('<div class="datepickers-container" id="datepickers-container"></div>');
$datepickersContainer = $('#datepickers-container'); $datepickersContainer = $('#datepickers-container');
}, },
@ -315,6 +320,10 @@ var Datepicker;
this._setInputValue(); this._setInputValue();
if (this.opts.onSelect) {
this._triggerOnChange();
}
if (this.opts.autoClose) { if (this.opts.autoClose) {
this.hide(); this.hide();
} else { } else {
@ -331,6 +340,9 @@ var Datepicker;
selected.splice(i, 1); selected.splice(i, 1);
_this.views[_this.currentView]._render(); _this.views[_this.currentView]._render();
_this._setInputValue(); _this._setInputValue();
if (_this.opts.onSelect) {
_this._triggerOnChange();
}
return true return true
} }
}) })
@ -349,6 +361,47 @@ var Datepicker;
this._triggerOnChange() 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) { _isSelected: function (checkDate, cellType) {
return this.selectedDates.some(function (date) { return this.selectedDates.some(function (date) {
@ -404,9 +457,14 @@ var Datepicker;
_setPositionClasses: function (pos) { _setPositionClasses: function (pos) {
pos = pos.split(' '); pos = pos.split(' ');
var main = pos[0], 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) { setPosition: function (position) {
@ -520,9 +578,14 @@ var Datepicker;
}, },
set view (val) { set view (val) {
this.viewIndex = this.viewIndexes.indexOf(val);
if (this.viewIndex < 0) {
return;
}
this.prevView = this.currentView; this.prevView = this.currentView;
this.currentView = val; this.currentView = val;
this.viewIndex = this.viewIndexes.indexOf(val);
if (this.inited) { if (this.inited) {
if (!this.views[val]) { if (!this.views[val]) {

View File

@ -24,20 +24,21 @@
_bindEvents: function () { _bindEvents: function () {
this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this)); this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this));
this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this)); this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this));
if (this.$buttonsContainer.length) { this.d.$datepicker.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this));
this.$buttonsContainer.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this));
}
}, },
_buildBaseHtml: function () { _buildBaseHtml: function () {
this._render(); this._render();
this._addButtonsIfNeed();
},
_addButtonsIfNeed: function () {
if (this.opts.todayButton) { if (this.opts.todayButton) {
this._addButton('today') this._addButton('today')
} }
if (this.opts.clearButton) { if (this.opts.clearButton) {
this._addButton('clear') this._addButton('clear')
} }
this.$navButton = $('.datepicker--nav-action', this.d.$nav);
}, },
_render: function () { _render: function () {

View File

@ -11,6 +11,7 @@
} }
.datepicker { .datepicker {
background: #fff;
border: 1px solid $colorGrey; border: 1px solid $colorGrey;
border-radius: $datepickerBorderRadius; border-radius: $datepickerBorderRadius;
box-sizing: content-box; box-sizing: content-box;