Created
January 30, 2018 14:24
-
-
Save e-vural/679db14714dae1c2e2dc7f6029ce20ae to your computer and use it in GitHub Desktop.
Combodate minDate - maxDate minMonth- maxMonth perfect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Combodate - 1.0.4 | |
* Dropdown date and time picker. | |
* Converts text input into dropdowns to pick day, month, year, hour, minute and second. | |
* Uses momentjs as datetime library http://momentjs.com. | |
* For i18n include corresponding file from https://github.com/timrwood/moment/tree/master/lang | |
* | |
* Confusion at noon and midnight - see http://en.wikipedia.org/wiki/12-hour_clock#Confusion_at_noon_and_midnight | |
* In combodate: | |
* 12:00 pm --> 12:00 (24-h format, midday) | |
* 12:00 am --> 00:00 (24-h format, midnight, start of day) | |
* | |
* Differs from momentjs parse rules: | |
* 00:00 pm, 12:00 pm --> 12:00 (24-h format, day not change) | |
* 00:00 am, 12:00 am --> 00:00 (24-h format, day not change) | |
* | |
* | |
* Author: Vitaliy Potapov | |
* Project page: http://github.com/vitalets/combodate | |
* Copyright (c) 2012 Vitaliy Potapov. Released under MIT License. | |
**/ | |
(function ($) { | |
var Combodate = function (element, options) { | |
this.$element = $(element); | |
if(!this.$element.is('input')) { | |
$.error('Combodate should be applied to INPUT element'); | |
return; | |
} | |
this.options = $.extend({}, $.fn.combodate.defaults, options, this.$element.data()); | |
this.init(); | |
}; | |
Combodate.prototype = { | |
constructor: Combodate, | |
init: function () { | |
this.map = { | |
//key regexp moment.method | |
day: ['D', 'date'], | |
month: ['M', 'month'], | |
year: ['Y', 'year'], | |
hour: ['[Hh]', 'hours'], | |
minute: ['m', 'minutes'], | |
second: ['s', 'seconds'], | |
ampm: ['[Aa]', ''] | |
}; | |
this.$widget = $('<span class="combodate"></span>').html(this.getTemplate()); | |
this.initCombos(); | |
//update original input on change | |
this.$widget.on('change', 'select', $.proxy(function(){ | |
this.$element.val(this.getValue()); | |
}, this)); | |
this.$widget.find('select').css('width', 'auto'); | |
//hide original input and insert widget | |
this.$element.hide().after(this.$widget); | |
//set initial value | |
this.setValue(this.$element.val() || this.options.value); | |
}, | |
/* | |
Replace tokens in template with <select> elements | |
*/ | |
getTemplate: function() { | |
var tpl = this.options.template; | |
//first pass | |
$.each(this.map, function(k, v) { | |
v = v[0]; | |
var r = new RegExp(v+'+'), | |
token = v.length > 1 ? v.substring(1, 2) : v; | |
tpl = tpl.replace(r, '{'+token+'}'); | |
}); | |
//replace spaces with | |
tpl = tpl.replace(/ /g, ' '); | |
//second pass | |
$.each(this.map, function(k, v) { | |
v = v[0]; | |
var token = v.length > 1 ? v.substring(1, 2) : v; | |
tpl = tpl.replace('{'+token+'}', '<select class="'+k+'"></select>'); | |
}); | |
return tpl; | |
}, | |
/* | |
Initialize combos that presents in template | |
*/ | |
initCombos: function() { | |
var that = this; | |
$.each(this.map, function(k, v) { | |
var $c = that.$widget.find('.'+k), f, items; | |
if($c.length) { | |
that['$'+k] = $c; //set properties like this.$day, this.$month etc. | |
f = 'fill' + k.charAt(0).toUpperCase() + k.slice(1); //define method name to fill items, e.g `fillDays` | |
items = that[f](); | |
that['$'+k].html(that.renderItems(items)); | |
} | |
}); | |
}, | |
/* | |
Initialize items of combos. Handles `firstItem` option | |
*/ | |
initItems: function(key) { | |
var values = [], | |
relTime; | |
if(this.options.firstItem === 'name') { | |
//need both to support moment ver < 2 and >= 2 | |
relTime = moment.relativeTime || moment.langData()._relativeTime; | |
var header = typeof relTime[key] === 'function' ? relTime[key](1, true, key, false) : relTime[key]; | |
//take last entry (see momentjs lang files structure) | |
header = header.split(' ').reverse()[0]; | |
values.push(['', header]); | |
} else if(this.options.firstItem === 'empty') { | |
values.push(['', '']); | |
} | |
return values; | |
}, | |
/* | |
render items to string of <option> tags | |
*/ | |
renderItems: function(items) { | |
var str = []; | |
for(var i=0; i<items.length; i++) { | |
str.push('<option value="'+items[i][0]+'">'+items[i][1]+'</option>'); | |
} | |
return str.join("\n"); | |
}, | |
/* | |
fill day | |
*/ | |
fillDay: function() { | |
var items = this.initItems('d'), name, i, | |
twoDigit = this.options.template.indexOf('DD') !== -1; | |
var minMonth = this.options.minMonth; | |
var maxMonth = this.options.maxMonth; | |
var minYear= this.options.minYear; | |
var maxYear = this.options.maxYear; | |
var minDate = this.options.minDate; | |
var maxDate = this.options.maxDate; | |
var beforeMonthDays = moment(minYear+"-"+this.leadZero(+minMonth + +1), "YYYY-MM").daysInMonth() // 29 | |
var currentMonthDays = moment(maxYear+"-"+this.leadZero(+maxMonth + +1), "YYYY-MM").daysInMonth() // 29 | |
if(minDate > maxDate){ | |
console.log("daya uzunlugu"); | |
console.log(minYear); | |
console.log(minMonth); | |
console.log(beforeMonthDays); | |
for(i= minDate; i<=beforeMonthDays; i++){ | |
name = twoDigit ? this.leadZero(i) : i; | |
items.push([i, name]); | |
} | |
for(i= 1; i<=maxDate; i++){ | |
name = twoDigit ? this.leadZero(i) : i; | |
items.push([i, name]); | |
} | |
}else{ | |
for(i=this.options.minDate; i<=this.options.maxDate; i++) { | |
name = twoDigit ? this.leadZero(i) : i; | |
items.push([i, name]); | |
} | |
} | |
return items; | |
}, | |
/* | |
fill month | |
*/ | |
fillMonth: function() { | |
var items = this.initItems('M'), name, i, | |
longNames = this.options.template.indexOf('MMMM') !== -1, | |
shortNames = this.options.template.indexOf('MMM') !== -1, | |
twoDigit = this.options.template.indexOf('MM') !== -1; | |
var minMonth = this.options.minMonth; | |
var maxMonth = this.options.maxMonth; | |
if(minMonth > maxMonth){ | |
var monthFark = 11 - minMonth; | |
var l = monthFark + 1; | |
for(var a = 1;a<=l;a++){ | |
i = minMonth; | |
if(longNames) { | |
//see https://github.com/timrwood/momentjs.com/pull/36 | |
name = moment().date(1).month(i).format('MMMM'); | |
} else if(shortNames) { | |
name = moment().date(1).month(i).format('MMM'); | |
} else if(twoDigit) { | |
name = this.leadZero(+i + +1); | |
} else { | |
name = i+1; | |
} | |
items.push([i, name]); | |
minMonth++; | |
} | |
var l = maxMonth + 1; | |
for(var a = 1;a<=l;a++){ | |
i = maxMonth; | |
if(longNames) { | |
//see https://github.com/timrwood/momentjs.com/pull/36 | |
name = moment().date(1).month(i).format('MMMM'); | |
} else if(shortNames) { | |
name = moment().date(1).month(i).format('MMM'); | |
} else if(twoDigit) { | |
name = this.leadZero(+i + +1); | |
} else { | |
name = i+1; | |
} | |
items.push([i, name]); | |
maxMonth++; | |
} | |
}else{ | |
for(i=this.options.minMonth; i<=this.options.maxMonth; i++) { | |
// for(i=0; i<=11; i++) { | |
if(longNames) { | |
//see https://github.com/timrwood/momentjs.com/pull/36 | |
name = moment().date(1).month(i).format('MMMM'); | |
} else if(shortNames) { | |
name = moment().date(1).month(i).format('MMM'); | |
} else if(twoDigit) { | |
name = this.leadZero(+i + +1); | |
} else { | |
name = i+1; | |
} | |
items.push([i, name]); | |
} | |
} | |
return items; | |
}, | |
/* | |
fill year | |
*/ | |
fillYear: function() { | |
var items = [], name, i, | |
longNames = this.options.template.indexOf('YYYY') !== -1; | |
for(i=this.options.maxYear; i>=this.options.minYear; i--) { | |
name = longNames ? i : (i+'').substring(2); | |
items[this.options.yearDescending ? 'push' : 'unshift']([i, name]); | |
} | |
items = this.initItems('y').concat(items); | |
return items; | |
}, | |
/* | |
fill hour | |
*/ | |
fillHour: function() { | |
var items = this.initItems('h'), name, i, | |
h12 = this.options.template.indexOf('h') !== -1, | |
h24 = this.options.template.indexOf('H') !== -1, | |
twoDigit = this.options.template.toLowerCase().indexOf('hh') !== -1, | |
min = h12 ? 1 : 0, | |
max = h12 ? 12 : 23; | |
for(i=min; i<=max; i++) { | |
name = twoDigit ? this.leadZero(i) : i; | |
items.push([i, name]); | |
} | |
return items; | |
}, | |
/* | |
fill minute | |
*/ | |
fillMinute: function() { | |
var items = this.initItems('m'), name, i, | |
twoDigit = this.options.template.indexOf('mm') !== -1; | |
for(i=0; i<=59; i+= this.options.minuteStep) { | |
name = twoDigit ? this.leadZero(i) : i; | |
items.push([i, name]); | |
} | |
return items; | |
}, | |
/* | |
fill second | |
*/ | |
fillSecond: function() { | |
var items = this.initItems('s'), name, i, | |
twoDigit = this.options.template.indexOf('ss') !== -1; | |
for(i=0; i<=59; i+= this.options.secondStep) { | |
name = twoDigit ? this.leadZero(i) : i; | |
items.push([i, name]); | |
} | |
return items; | |
}, | |
/* | |
fill ampm | |
*/ | |
fillAmpm: function() { | |
var ampmL = this.options.template.indexOf('a') !== -1, | |
ampmU = this.options.template.indexOf('A') !== -1, | |
items = [ | |
['am', ampmL ? 'am' : 'AM'], | |
['pm', ampmL ? 'pm' : 'PM'] | |
]; | |
return items; | |
}, | |
/* | |
Returns current date value from combos. | |
If format not specified - `options.format` used. | |
If format = `null` - Moment object returned. | |
*/ | |
getValue: function(format) { | |
var dt, values = {}, | |
that = this, | |
notSelected = false; | |
//getting selected values | |
$.each(this.map, function(k, v) { | |
if(k === 'ampm') { | |
return; | |
} | |
var def = k === 'day' ? 1 : 0; | |
values[k] = that['$'+k] ? parseInt(that['$'+k].val(), 10) : def; | |
if(isNaN(values[k])) { | |
notSelected = true; | |
return false; | |
} | |
}); | |
//if at least one visible combo not selected - return empty string | |
if(notSelected) { | |
return ''; | |
} | |
//convert hours 12h --> 24h | |
if(this.$ampm) { | |
//12:00 pm --> 12:00 (24-h format, midday), 12:00 am --> 00:00 (24-h format, midnight, start of day) | |
if(values.hour === 12) { | |
values.hour = this.$ampm.val() === 'am' ? 0 : 12; | |
} else { | |
values.hour = this.$ampm.val() === 'am' ? values.hour : values.hour+12; | |
} | |
} | |
dt = moment([values.year, values.month, values.day, values.hour, values.minute, values.second]); | |
//highlight invalid date | |
this.highlight(dt); | |
format = format === undefined ? this.options.format : format; | |
if(format === null) { | |
return dt.isValid() ? dt : null; | |
} else { | |
return dt.isValid() ? dt.format(format) : ''; | |
} | |
}, | |
setValue: function(value) { | |
if(!value) { | |
return; | |
} | |
var dt = typeof value === 'string' ? moment(value, this.options.format) : moment(value), | |
that = this, | |
values = {}; | |
//function to find nearest value in select options | |
function getNearest($select, value) { | |
var delta = {}; | |
$select.children('option').each(function(i, opt){ | |
var optValue = $(opt).attr('value'), | |
distance; | |
if(optValue === '') return; | |
distance = Math.abs(optValue - value); | |
if(typeof delta.distance === 'undefined' || distance < delta.distance) { | |
delta = {value: optValue, distance: distance}; | |
} | |
}); | |
return delta.value; | |
} | |
if(dt.isValid()) { | |
//read values from date object | |
$.each(this.map, function(k, v) { | |
if(k === 'ampm') { | |
return; | |
} | |
values[k] = dt[v[1]](); | |
}); | |
if(this.$ampm) { | |
//12:00 pm --> 12:00 (24-h format, midday), 12:00 am --> 00:00 (24-h format, midnight, start of day) | |
if(values.hour >= 12) { | |
values.ampm = 'pm'; | |
if(values.hour > 12) { | |
values.hour -= 12; | |
} | |
} else { | |
values.ampm = 'am'; | |
if(values.hour === 0) { | |
values.hour = 12; | |
} | |
} | |
} | |
$.each(values, function(k, v) { | |
//call val() for each existing combo, e.g. this.$hour.val() | |
if(that['$'+k]) { | |
if(k === 'minute' && that.options.minuteStep > 1 && that.options.roundTime) { | |
v = getNearest(that['$'+k], v); | |
} | |
if(k === 'second' && that.options.secondStep > 1 && that.options.roundTime) { | |
v = getNearest(that['$'+k], v); | |
} | |
that['$'+k].val(v); | |
} | |
}); | |
this.$element.val(dt.format(this.options.format)); | |
} | |
}, | |
/* | |
highlight combos if date is invalid | |
*/ | |
highlight: function(dt) { | |
if(!dt.isValid()) { | |
if(this.options.errorClass) { | |
this.$widget.addClass(this.options.errorClass); | |
} else { | |
//store original border color | |
if(!this.borderColor) { | |
this.borderColor = this.$widget.find('select').css('border-color'); | |
} | |
this.$widget.find('select').css('border-color', 'red'); | |
} | |
} else { | |
if(this.options.errorClass) { | |
this.$widget.removeClass(this.options.errorClass); | |
} else { | |
this.$widget.find('select').css('border-color', this.borderColor); | |
} | |
} | |
}, | |
leadZero: function(v) { | |
return v <= 9 ? '0' + v : v; | |
}, | |
destroy: function() { | |
this.$widget.remove(); | |
this.$element.removeData('combodate').show(); | |
} | |
//todo: clear method | |
}; | |
$.fn.combodate = function ( option ) { | |
var d, args = Array.apply(null, arguments); | |
args.shift(); | |
//getValue returns date as string / object (not jQuery object) | |
if(option === 'getValue' && this.length && (d = this.eq(0).data('combodate'))) { | |
return d.getValue.apply(d, args); | |
} | |
return this.each(function () { | |
var $this = $(this), | |
data = $this.data('combodate'), | |
options = typeof option == 'object' && option; | |
if (!data) { | |
$this.data('combodate', (data = new Combodate(this, options))); | |
} | |
if (typeof option == 'string' && typeof data[option] == 'function') { | |
data[option].apply(data, args); | |
} | |
}); | |
}; | |
$.fn.combodate.defaults = { | |
//in this format value stored in original input | |
format: 'DD-MM-YYYY HH:mm', | |
//in this format items in dropdowns are displayed | |
template: 'D / MMM / YYYY H : mm', | |
//initial value, can be `new Date()` | |
value: null, | |
minYear: 1970, | |
maxYear: 2015, | |
minDate: 1, | |
maxDate: 31, | |
minMonth: 0, | |
maxMonth: 11, | |
yearDescending: true, | |
minuteStep: 5, | |
secondStep: 1, | |
firstItem: 'empty', //'name', 'empty', 'none' | |
errorClass: null, | |
roundTime: true ,//whether to round minutes and seconds if step >// 1 | |
// smartDays: true | |
}; | |
}(window.jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment