class SmartDateField { constructor(field, options) { this._dateYmdParser = new RegExp('^([0-9]{4})[,\._\/\-]+([0-9]{1,2})[,\._\/\-]+([0-9]{1,2})$'); this._dateDmyParser = new RegExp('^([0-9]{1,2})[,\._\/\-]+([0-9]{1,2})[,\._\/\-]+([0-9]{4})$'); this._loadOptions(options); this._formatter = new SmartDateFormat(this._format, this._minimalDate, this._maximalDate); this._lastCorrectValue = (this._defaultDate === null ? null : this._formatter.formatDate(this._defaultDate)); this._initField(field); this._subscribeEvents(); } _loadDefaultOptions() { this._format = 'd.m.y'; this._minimalDate = new Date(1900, 0, 1); this._maximalDate = new Date(2099, 11, 31); this._defaultDate = null; } _loadOptions(options) { this._loadDefaultOptions(); if (typeof(options) !== 'object' || options == null) { return; } if (typeof(options.format) === 'string' && options.format.indexOf('d') >= 0 && options.format.indexOf('m') >= 0 && options.format.indexOf('y') >= 0) { this._format = options.format; } if (typeof(options.minimal) !== 'undefined') { let date = this._parseDateValue(options.minimal); this._minimalDate = date; } if (typeof(options.maximal) !== 'undefined') { let date = this._parseDateValue(options.maximal); this._maximalDate = date; } if (typeof(options.default) !== 'undefined') { let date = this._parseDateValue(options.default); this._defaultDate = date; } this._correctDateOptions(); } _correctDateOptions() { if (this._minimalDate.valueOf() > this._maximalDate.valueOf()) { let temporaryDate = this._minimalDate; this._minimalDate = this._maximalDate; this._maximalDate = temporaryDate; } if (this._defaultDate === null) { return; } if (this._defaultDate.valueOf() < this._minimalDate.valueOf()) { this._defaultDate = this._minimalDate; } if (this._defaultDate.valueOf() > this._maximalDate.valueOf()) { this._defaultDate = this._maximalDate; } } _parseDateValue(date) { if (typeof(date) === 'object' && date !== null && date instanceof Date) { return date; } if (typeof(date) !== 'string' || date.trim() === '') { return null; } let parsed = this._dateYmdParser.exec(date); if (parsed !== null) { return new Date(Number(parsed[1]), Number(parsed[2]) - 1, Number(parsed[3])); } parsed = this._dateDmyParser.exec(date); if (parsed === null) { return null; } return new Date(Number(parsed[3]), Number(parsed[2]) - 1, Number(parsed[1])); } _initField(field) { this._field = field; this._field.placeholder = this._formatter.getPlaceHolder(); if (this._isEmptyValue(this._field.value)) { this._field.value = (this._defaultDate === null ? '' : this._formatter.formatDate(this._defaultDate)); } else { this.correctValue(true); } } _subscribeEvents() { let _this = this; let correct = function (event) { if (event === null || event.type !== 'keyup') { _this.correctValue(true); } if (_this._isServiceCode(event.keyCode)) { return; } if (event.keyCode === 27) { // Escape _this.returnLastCorrectValue(); } _this.correctValue(true); }; this._field.addEventListener('change', correct); this._field.addEventListener('keyup', correct); this._field.addEventListener('blur', function () { _this.correctValue(true); if (!_this._isEmptyValue(_this._field.value)) { _this.returnLastCorrectValue(); } }); } _isServiceCode(code) { return code === 8 /* backspace */ || code === 46 /* delete */ || code === 16 /* shift */ || code === 17 /* shift */ || code === 18 /* shift */ || code === 20 /* caps lock */ || code === 35 /* end */ || code === 36 /* home */ || code === 37 /* left */ || code === 39 /* right */ || code === 46 /* delete */; } _isEmptyValue(value) { return value.trim() === ''; } getDefaultValue() { return this._defaultDate === null ? '' : this._formatter.formatDate(this._defaultDate); } correctValue(autocomplete) { this._formatter.parse(this._field.value, autocomplete); let parsedValue = this._getLimitedParsedValue(); if (this._formatter.isComplete()) { this._lastCorrectValue = parsedValue; } if (this._field.value === parsedValue) { return; } this._setValueToField(parsedValue); } setValue(value) { let date = this._parseDateValue(value); if (date === null || date.valueOf() < this._minimalDate.valueOf() || date.valueOf() > this._maximalDate.valueOf()) { return; } this._lastCorrectValue = this._formatter.formatDate(date); this._field.value = this._lastCorrectValue; } _getLimitedParsedValue() { if (!this._formatter.isComplete()) { return this._formatter.getCorrectedValue(); } let date = this._formatter.getParsedDate(); if (date.valueOf() < this._minimalDate.valueOf()) { return this._formatter.formatDate(this._minimalDate); } else if (date.valueOf() > this._maximalDate.valueOf()) { return this._formatter.formatDate(this._maximalDate); } return this._formatter.getCorrectedValue(); } _setValueToField(newValue) { let position = this._field.selectionStart; let isAtEnd = (position === this._field.value.length); this._field.value = newValue; if (!isAtEnd && position < this._field.value.length) { this._field.selectionStart = position; this._field.selectionEnd = position; } } returnLastCorrectValue() { if (this._lastCorrectValue !== null) { this._field.value = this._lastCorrectValue; } } } SmartDateField.initBy = function (id) { return SmartDateField.initFor(document.getElementById(id)); }; SmartDateField.initFor = function (field, options) { if (typeof(field) !== 'object' || field === null || field.tagName.toLowerCase() !== 'input' || field.type.toLowerCase() !== 'text') { return; } if (typeof(field._smartDate) === 'object' && field._smartDate !== null && field._smartDate instanceof SmartDateField) { return; } field._smartDate = new SmartDateField(field, options); }; jQuery.fn.smartdate = function (options) { let collection = []; let field = null; for (let i = 0; i < this.length; i++) { field = SmartDateField.initFor(this[i], options); if (field !== null) { collection.push(field); } } return jQuery(this); }; jQuery.fn.setDateValue = function (value) { for (let i = 0; i < this.length; i++) { if (typeof(this[i]._smartDate) === 'object' && this[i]._smartDate !== null && this[i]._smartDate instanceof SmartDateField) { this[i]._smartDate.setValue(value); } } return jQuery(this); };