Created
October 20, 2010 17:54
-
-
Save iloveitaly/636941 to your computer and use it in GitHub Desktop.
Modification of the mootools datepicker to normalize input / output unix dates as UTC
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
/** | |
* datepicker.js - MooTools Datepicker class | |
* @version 1.16 | |
* | |
* by MonkeyPhysics.com | |
* | |
* Source/Documentation available at: | |
* http://www.monkeyphysics.com/mootools/script/2/datepicker | |
* | |
* -- | |
* | |
* Smoothly animating, very configurable and easy to install. | |
* No Ajax, pure Javascript. 4 skins available out of the box. | |
* | |
* -- | |
* | |
* Some Rights Reserved | |
* http://creativecommons.org/licenses/by-sa/3.0/ | |
* | |
*/ | |
var DatePicker = new Class({ | |
Implements: Options, | |
// working date, which we will keep modifying to render the calendars | |
d: '', | |
// just so that we need not request it over and over | |
today: '', | |
// current user-choice in date object format | |
choice: {}, | |
// size of body, used to animate the sliding | |
bodysize: {}, | |
// to check availability of next/previous buttons | |
limit: {}, | |
// element references: | |
attachTo: null, // selector for target inputs | |
picker: null, // main datepicker container | |
slider: null, // slider that contains both oldContents and newContents, used to animate between 2 different views | |
oldContents: null, // used in animating from-view to new-view | |
newContents: null, // used in animating from-view to new-view | |
input: null, // original input element (used for input/output) | |
visual: null, // visible input (used for rendering) | |
options: { | |
pickerClass: 'datepicker', | |
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], | |
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], | |
dayShort: 2, | |
monthShort: 3, | |
startDay: 1, // Sunday (0) through Saturday (6) - be aware that this may affect your layout, since the days on the right might have a different margin | |
timePicker: false, | |
timePickerOnly: false, | |
yearPicker: true, | |
yearsPerPage: 20, | |
format: 'd-m-Y', | |
allowEmpty: false, | |
inputOutputFormat: 'U', // default to unix timestamp | |
animationDuration: 400, | |
useFadeInOut: !Browser.Engine.trident, // dont animate fade-in/fade-out for IE | |
startView: 'month', // allowed values: {time, month, year, decades} | |
positionOffset: { x: 0, y: 0 }, | |
minDate: null, // { date: '[date-string]', format: '[date-string-interpretation-format]' } | |
maxDate: null, // same as minDate | |
debug: false, | |
toggleElements: null, | |
// and some event hooks: | |
onShow: $empty, // triggered when the datepicker pops up | |
onClose: $empty, // triggered after the datepicker is closed (destroyed) | |
onSelect: $empty // triggered when a date is selected | |
}, | |
initialize: function(attachTo, options) { | |
this.attachTo = attachTo; | |
this.setOptions(options).attach(); | |
if (this.options.timePickerOnly) { | |
this.options.timePicker = true; | |
this.options.startView = 'time'; | |
} | |
this.formatMinMaxDates(); | |
document.addEvent('mousedown', this.close.bind(this)); | |
}, | |
formatMinMaxDates: function() { | |
if (this.options.minDate && this.options.minDate.format) { | |
this.options.minDate = this.unformat(this.options.minDate.date, this.options.minDate.format); | |
} | |
if (this.options.maxDate && this.options.maxDate.format) { | |
this.options.maxDate = this.unformat(this.options.maxDate.date, this.options.maxDate.format); | |
this.options.maxDate.setHours(23); | |
this.options.maxDate.setMinutes(59); | |
this.options.maxDate.setSeconds(59); | |
} | |
}, | |
attach: function() { | |
// toggle the datepicker through a separate element? | |
if ($chk(this.options.toggleElements)) { | |
var togglers = $$(this.options.toggleElements); | |
document.addEvents({ | |
'keydown': function(e) { | |
if (e.key == "tab") { | |
this.close(null, true); | |
} | |
}.bind(this) | |
}); | |
}; | |
// attach functionality to the inputs | |
$$(this.attachTo).each(function(item, index) { | |
// never double attach | |
if (item.retrieve('datepicker')) return; | |
// determine starting value(s) | |
if ($chk(item.get('value'))) { | |
var init_clone_val = this.format(new Date(this.unformat(item.get('value'), this.options.inputOutputFormat)), this.options.format); | |
} else if (!this.options.allowEmpty) { | |
var init_clone_val = this.format(new Date(), this.options.format); | |
} else { | |
var init_clone_val = ''; | |
} | |
// create clone | |
var display = item.getStyle('display'); | |
var clone = item | |
.setStyle('display', this.options.debug ? display : 'none') | |
.store('datepicker', true) // to prevent double attachment... | |
.clone() | |
.store('datepicker', true) // ...even for the clone (!) | |
.removeProperty('name') // secure clean (form)submission | |
.setStyle('display', display) | |
.set('value', init_clone_val) | |
.inject(item, 'after'); | |
// events | |
if ($chk(this.options.toggleElements)) { | |
togglers[index] | |
.setStyle('cursor', 'pointer') | |
.addEvents({ | |
'click': function(e) { | |
this.onFocus(item, clone); | |
}.bind(this) | |
}); | |
clone.addEvents({ | |
'blur': function() { | |
item.set('value', clone.get('value')); | |
} | |
}); | |
} else { | |
clone.addEvents({ | |
'keydown': function(e) { | |
if (this.options.allowEmpty && (e.key == "delete" || e.key == "backspace")) { | |
item.set('value', ''); | |
e.target.set('value', ''); | |
this.close(null, true); | |
} else if (e.key == "tab") { | |
this.close(null, true); | |
} else { | |
e.stop(); | |
} | |
}.bind(this), | |
'focus': function(e) { | |
this.onFocus(item, clone); | |
}.bind(this) | |
}); | |
} | |
}.bind(this)); | |
}, | |
onFocus: function(original_input, visual_input) { | |
this.isFocused = true; | |
var init_visual_date, d = visual_input.getCoordinates(); | |
if ($chk(original_input.get('value'))) { | |
init_visual_date = this.unformat(original_input.get('value'), this.options.inputOutputFormat).valueOf(); | |
} else { | |
init_visual_date = new Date(); | |
if ($chk(this.options.maxDate) && init_visual_date.valueOf() > this.options.maxDate.valueOf()) { | |
init_visual_date = new Date(this.options.maxDate.valueOf()); | |
} | |
if ($chk(this.options.minDate) && init_visual_date.valueOf() < this.options.minDate.valueOf()) { | |
init_visual_date = new Date(this.options.minDate.valueOf()); | |
} | |
} | |
this.show({ left: d.left + this.options.positionOffset.x, top: d.top + d.height + this.options.positionOffset.y }, init_visual_date); | |
this.input = original_input; | |
this.visual = visual_input; | |
this.options.onShow(); | |
}, | |
dateToObject: function(d) { | |
return { | |
year: d.getFullYear(), | |
month: d.getMonth(), | |
day: d.getDate(), | |
hours: d.getHours(), | |
minutes: d.getMinutes(), | |
seconds: d.getSeconds() | |
}; | |
}, | |
dateFromObject: function(values) { | |
var d = new Date(); | |
d.setDate(1); | |
['year', 'month', 'day', 'hours', 'minutes', 'seconds'].each(function(type) { | |
var v = values[type]; | |
if (!$chk(v)) return; | |
switch (type) { | |
case 'day': d.setDate(v); break; | |
case 'month': d.setMonth(v); break; | |
case 'year': d.setFullYear(v); break; | |
case 'hours': d.setHours(v); break; | |
case 'minutes': d.setMinutes(v); break; | |
case 'seconds': d.setSeconds(v); break; | |
} | |
}); | |
return d; | |
}, | |
show: function(position, timestamp) { | |
this.formatMinMaxDates(); | |
if ($chk(timestamp)) { | |
this.d = new Date(timestamp); | |
} else { | |
this.d = new Date(); | |
} | |
this.today = new Date(); | |
this.choice = this.dateToObject(this.d); | |
this.mode = (this.options.startView == 'time' && !this.options.timePicker) ? 'month' : this.options.startView; | |
this.render(); | |
this.picker.setStyles(position); | |
}, | |
render: function(fx) { | |
if (!$chk(this.picker)) { | |
this.constructPicker(); | |
} else { | |
// swap contents so we can fill the newContents again and animate | |
var o = this.oldContents; | |
this.oldContents = this.newContents; | |
this.newContents = o; | |
this.newContents.empty(); | |
} | |
// remember current working date | |
var startDate = new Date(this.d.getTime()); | |
// intially assume both left and right are allowed | |
this.limit = { right: false, left: false }; | |
// render! booty! | |
if (this.mode == 'decades') { | |
this.renderDecades(); | |
} else if (this.mode == 'year') { | |
this.renderYear(); | |
} else if (this.mode == 'time') { | |
this.renderTime(); | |
this.limit = { right: true, left: true }; // no left/right in timeview | |
} else { | |
this.renderMonth(); | |
} | |
this.picker.getElement('.previous').setStyle('visibility', this.limit.left ? 'hidden' : 'visible'); | |
this.picker.getElement('.next').setStyle('visibility', this.limit.right ? 'hidden' : 'visible'); | |
this.picker.getElement('.titleText').setStyle('cursor', this.allowZoomOut() ? 'pointer' : 'default'); | |
// restore working date | |
this.d = startDate; | |
// if ever the opacity is set to '0' it was only to have us fade it in here | |
// refer to the constructPicker() function, which instantiates the picker at opacity 0 when fading is desired | |
this.picker.get('tween').cancel(); | |
if (this.picker.getStyle('opacity') == 0) { | |
this.picker.tween('opacity', 0, 1); | |
} | |
// animate | |
if ($chk(fx)) this.fx(fx); | |
}, | |
fx: function(fx) { | |
if (fx == 'right') { | |
this.oldContents.setStyles({ left: 0, opacity: 1 }); | |
this.newContents.setStyles({ left: this.bodysize.x, opacity: 1 }); | |
this.slider.setStyle('left', 0).tween('left', 0, -this.bodysize.x); | |
} else if (fx == 'left') { | |
this.oldContents.setStyles({ left: this.bodysize.x, opacity: 1 }); | |
this.newContents.setStyles({ left: 0, opacity: 1 }); | |
this.slider.setStyle('left', -this.bodysize.x).tween('left', -this.bodysize.x, 0); | |
} else if (fx == 'fade') { | |
this.slider.setStyle('left', 0); | |
this.oldContents.setStyle('left', 0).set('tween', { duration: this.options.animationDuration / 2 }).tween('opacity', 1, 0); | |
this.newContents.setStyles({ opacity: 0, left: 0}).set('tween', { duration: this.options.animationDuration }).tween('opacity', 0, 1); | |
} | |
}, | |
constructPicker: function() { | |
this.picker = new Element('div', { 'class': this.options.pickerClass }).inject(document.body); | |
if (this.options.useFadeInOut) { | |
this.picker.setStyle('opacity', 0).set('tween', { duration: this.options.animationDuration }); | |
} | |
var h = new Element('div', { 'class': 'header' }).inject(this.picker); | |
var titlecontainer = new Element('div', { 'class': 'title' }).inject(h); | |
new Element('div', { 'class': 'previous' }).addEvent('click', this.previous.bind(this)).set('text', '«').inject(h); | |
new Element('div', { 'class': 'next' }).addEvent('click', this.next.bind(this)).set('text', '»').inject(h); | |
new Element('div', { 'class': 'closeButton' }).addEvent('click', this.close.bindWithEvent(this, true)).set('text', 'x').inject(h); | |
new Element('span', { 'class': 'titleText' }).addEvent('click', this.zoomOut.bind(this)).inject(titlecontainer); | |
var b = new Element('div', { 'class': 'body' }).inject(this.picker); | |
this.bodysize = b.getSize(); | |
this.slider = new Element('div', { styles: { position: 'absolute', top: 0, left: 0, width: 2 * this.bodysize.x, height: this.bodysize.y }}) | |
.set('tween', { duration: this.options.animationDuration, transition: Fx.Transitions.Quad.easeInOut }).inject(b); | |
this.oldContents = new Element('div', { styles: { position: 'absolute', top: 0, left: this.bodysize.x, width: this.bodysize.x, height: this.bodysize.y }}).inject(this.slider); | |
this.newContents = new Element('div', { styles: { position: 'absolute', top: 0, left: 0, width: this.bodysize.x, height: this.bodysize.y }}).inject(this.slider); | |
}, | |
renderTime: function() { | |
var container = new Element('div', { 'class': 'time' }).inject(this.newContents); | |
if (this.options.timePickerOnly) { | |
this.picker.getElement('.titleText').set('text', 'Select a time'); | |
} else { | |
this.picker.getElement('.titleText').set('text', this.format(this.d, 'j M, Y')); | |
} | |
new Element('input', { type: 'text', 'class': 'hour' }) | |
.set('value', this.leadZero(this.d.getHours())) | |
.addEvents({ | |
mousewheel: function(e) { | |
var i = e.target, v = i.get('value').toInt(); | |
i.focus(); | |
if (e.wheel > 0) { | |
v = (v < 23) ? v + 1 : 0; | |
} else { | |
v = (v > 0) ? v - 1 : 23; | |
} | |
i.set('value', this.leadZero(v)); | |
e.stop(); | |
}.bind(this) | |
}) | |
.set('maxlength', 2) | |
.inject(container); | |
new Element('input', { type: 'text', 'class': 'minutes' }) | |
.set('value', this.leadZero(this.d.getMinutes())) | |
.addEvents({ | |
mousewheel: function(e) { | |
var i = e.target, v = i.get('value').toInt(); | |
i.focus(); | |
if (e.wheel > 0) { | |
v = (v < 59) ? v + 1 : 0; | |
} else { | |
v = (v > 0) ? v - 1 : 59; | |
} | |
i.set('value', this.leadZero(v)); | |
e.stop(); | |
}.bind(this) | |
}) | |
.set('maxlength', 2) | |
.inject(container); | |
new Element('div', { 'class': 'separator' }).set('text', ':').inject(container); | |
new Element('input', { type: 'submit', value: 'OK', 'class': 'ok' }) | |
.addEvents({ | |
click: function(e) { | |
e.stop(); | |
this.select($merge(this.dateToObject(this.d), { hours: this.picker.getElement('.hour').get('value').toInt(), minutes: this.picker.getElement('.minutes').get('value').toInt() })); | |
}.bind(this) | |
}) | |
.set('maxlength', 2) | |
.inject(container); | |
}, | |
renderMonth: function() { | |
var month = this.d.getMonth(); | |
this.picker.getElement('.titleText').set('text', this.options.months[month] + ' ' + this.d.getFullYear()); | |
this.d.setDate(1); | |
while (this.d.getDay() != this.options.startDay) { | |
this.d.setDate(this.d.getDate() - 1); | |
} | |
var container = new Element('div', { 'class': 'days' }).inject(this.newContents); | |
var titles = new Element('div', { 'class': 'titles' }).inject(container); | |
var d, i, classes, e, weekcontainer; | |
for (d = this.options.startDay; d < (this.options.startDay + 7); d++) { | |
new Element('div', { 'class': 'title day day' + (d % 7) }).set('text', this.options.days[(d % 7)].substring(0,this.options.dayShort)).inject(titles); | |
} | |
var available = false; | |
var t = this.today.toDateString(); | |
var currentChoice = this.dateFromObject(this.choice).toDateString(); | |
for (i = 0; i < 42; i++) { | |
classes = []; | |
classes.push('day'); | |
classes.push('day'+this.d.getDay()); | |
if (this.d.toDateString() == t) classes.push('today'); | |
if (this.d.toDateString() == currentChoice) classes.push('selected'); | |
if (this.d.getMonth() != month) classes.push('otherMonth'); | |
if (i % 7 == 0) { | |
weekcontainer = new Element('div', { 'class': 'week week'+(Math.floor(i/7)) }).inject(container); | |
} | |
e = new Element('div', { 'class': classes.join(' ') }).set('text', this.d.getDate()).inject(weekcontainer); | |
if (this.limited('date')) { | |
e.addClass('unavailable'); | |
if (available) { | |
this.limit.right = true; | |
} else if (this.d.getMonth() == month) { | |
this.limit.left = true; | |
} | |
} else { | |
available = true; | |
e.addEvent('click', function(e, d) { | |
if (this.options.timePicker) { | |
this.d.setDate(d.day); | |
this.d.setMonth(d.month); | |
this.mode = 'time'; | |
this.render('fade'); | |
} else { | |
this.select(d); | |
} | |
}.bindWithEvent(this, { day: this.d.getDate(), month: this.d.getMonth(), year: this.d.getFullYear() })); | |
} | |
this.d.setDate(this.d.getDate() + 1); | |
} | |
if (!available) this.limit.right = true; | |
}, | |
renderYear: function() { | |
var month = this.today.getMonth(); | |
var thisyear = this.d.getFullYear() == this.today.getFullYear(); | |
var selectedyear = this.d.getFullYear() == this.choice.year; | |
this.picker.getElement('.titleText').set('text', this.d.getFullYear()); | |
this.d.setMonth(0); | |
var i, e; | |
var available = false; | |
var container = new Element('div', { 'class': 'months' }).inject(this.newContents); | |
for (i = 0; i <= 11; i++) { | |
e = new Element('div', { 'class': 'month month'+(i+1)+(i == month && thisyear ? ' today' : '')+(i == this.choice.month && selectedyear ? ' selected' : '') }) | |
.set('text', this.options.monthShort ? this.options.months[i].substring(0, this.options.monthShort) : this.options.months[i]).inject(container); | |
if (this.limited('month')) { | |
e.addClass('unavailable'); | |
if (available) { | |
this.limit.right = true; | |
} else { | |
this.limit.left = true; | |
} | |
} else { | |
available = true; | |
e.addEvent('click', function(e, d) { | |
this.d.setDate(1); | |
this.d.setMonth(d); | |
this.mode = 'month'; | |
this.render('fade'); | |
}.bindWithEvent(this, i)); | |
} | |
this.d.setMonth(i); | |
} | |
if (!available) this.limit.right = true; | |
}, | |
renderDecades: function() { | |
// start neatly at interval (eg. 1980 instead of 1987) | |
while (this.d.getFullYear() % this.options.yearsPerPage > 0) { | |
this.d.setFullYear(this.d.getFullYear() - 1); | |
} | |
this.picker.getElement('.titleText').set('text', this.d.getFullYear() + '-' + (this.d.getFullYear() + this.options.yearsPerPage - 1)); | |
var i, y, e; | |
var available = false; | |
var container = new Element('div', { 'class': 'years' }).inject(this.newContents); | |
if ($chk(this.options.minDate) && this.d.getFullYear() <= this.options.minDate.getFullYear()) { | |
this.limit.left = true; | |
} | |
for (i = 0; i < this.options.yearsPerPage; i++) { | |
y = this.d.getFullYear(); | |
e = new Element('div', { 'class': 'year year' + i + (y == this.today.getFullYear() ? ' today' : '') + (y == this.choice.year ? ' selected' : '') }).set('text', y).inject(container); | |
if (this.limited('year')) { | |
e.addClass('unavailable'); | |
if (available) { | |
this.limit.right = true; | |
} else { | |
this.limit.left = true; | |
} | |
} else { | |
available = true; | |
e.addEvent('click', function(e, d) { | |
this.d.setFullYear(d); | |
this.mode = 'year'; | |
this.render('fade'); | |
}.bindWithEvent(this, y)); | |
} | |
this.d.setFullYear(this.d.getFullYear() + 1); | |
} | |
if (!available) { | |
this.limit.right = true; | |
} | |
if ($chk(this.options.maxDate) && this.d.getFullYear() >= this.options.maxDate.getFullYear()) { | |
this.limit.right = true; | |
} | |
}, | |
limited: function(type) { | |
var cs = $chk(this.options.minDate); | |
var ce = $chk(this.options.maxDate); | |
if (!cs && !ce) return false; | |
switch (type) { | |
case 'year': | |
return (cs && this.d.getFullYear() < this.options.minDate.getFullYear()) || (ce && this.d.getFullYear() > this.options.maxDate.getFullYear()); | |
case 'month': | |
// todo: there has got to be an easier way...? | |
var ms = ('' + this.d.getFullYear() + this.leadZero(this.d.getMonth())).toInt(); | |
return cs && ms < ('' + this.options.minDate.getFullYear() + this.leadZero(this.options.minDate.getMonth())).toInt() | |
|| ce && ms > ('' + this.options.maxDate.getFullYear() + this.leadZero(this.options.maxDate.getMonth())).toInt() | |
case 'date': | |
return (cs && this.d < this.options.minDate) || (ce && this.d > this.options.maxDate); | |
} | |
}, | |
allowZoomOut: function() { | |
if (this.mode == 'time' && this.options.timePickerOnly) return false; | |
if (this.mode == 'decades') return false; | |
if (this.mode == 'year' && !this.options.yearPicker) return false; | |
return true; | |
}, | |
zoomOut: function() { | |
if (!this.allowZoomOut()) return; | |
if (this.mode == 'year') { | |
this.mode = 'decades'; | |
} else if (this.mode == 'time') { | |
this.mode = 'month'; | |
} else { | |
this.mode = 'year'; | |
} | |
this.render('fade'); | |
}, | |
previous: function() { | |
if (this.mode == 'decades') { | |
this.d.setFullYear(this.d.getFullYear() - this.options.yearsPerPage); | |
} else if (this.mode == 'year') { | |
this.d.setFullYear(this.d.getFullYear() - 1); | |
} else if (this.mode == 'month') { | |
this.d.setMonth(this.d.getMonth() - 1); | |
} | |
this.render('left'); | |
}, | |
next: function() { | |
if (this.mode == 'decades') { | |
this.d.setFullYear(this.d.getFullYear() + this.options.yearsPerPage); | |
} else if (this.mode == 'year') { | |
this.d.setFullYear(this.d.getFullYear() + 1); | |
} else if (this.mode == 'month') { | |
this.d.setMonth(this.d.getMonth() + 1); | |
} | |
this.render('right'); | |
}, | |
close: function(e, force) { | |
if (!$(this.picker)) return; | |
var clickOutside = ($chk(e) && e.target != this.picker && !this.picker.hasChild(e.target) && e.target != this.visual); | |
if (force || clickOutside) { | |
if (this.options.useFadeInOut) { | |
this.picker.set('tween', { duration: this.options.animationDuration / 2, onComplete: this.destroy.bind(this) }).tween('opacity', 1, 0); | |
} else { | |
this.destroy(); | |
} | |
} | |
}, | |
destroy: function() { | |
this.picker.destroy(); | |
this.picker = null; | |
this.options.onClose(); | |
}, | |
select: function(values) { | |
this.choice = $merge(this.choice, values); | |
var d = this.dateFromObject(this.choice); | |
this.input.set('value', this.format(d, this.options.inputOutputFormat)); | |
this.visual.set('value', this.format(d, this.options.format)); | |
this.options.onSelect(d); | |
this.close(null, true); | |
}, | |
leadZero: function(v) { | |
return v < 10 ? '0'+v : v; | |
}, | |
format: function(t, format) { | |
var f = ''; | |
var h = t.getHours(); | |
var m = t.getMonth(); | |
for (var i = 0; i < format.length; i++) { | |
switch(format.charAt(i)) { | |
case '\\': i++; f+= format.charAt(i); break; | |
case 'y': f += (100 + t.getYear() + '').substring(1); break | |
case 'Y': f += t.getFullYear(); break; | |
case 'm': f += this.leadZero(m + 1); break; | |
case 'n': f += (m + 1); break; | |
case 'M': f += this.options.months[m].substring(0,this.options.monthShort); break; | |
case 'F': f += this.options.months[m]; break; | |
case 'd': f += this.leadZero(t.getDate()); break; | |
case 'j': f += t.getDate(); break; | |
case 'D': f += this.options.days[t.getDay()].substring(0,this.options.dayShort); break; | |
case 'l': f += this.options.days[t.getDay()]; break; | |
case 'G': f += h; break; | |
case 'H': f += this.leadZero(h); break; | |
case 'g': f += (h % 12 ? h % 12 : 12); break; | |
case 'h': f += this.leadZero(h % 12 ? h % 12 : 12); break; | |
case 'a': f += (h > 11 ? 'pm' : 'am'); break; | |
case 'A': f += (h > 11 ? 'PM' : 'AM'); break; | |
case 'i': f += this.leadZero(t.getMinutes()); break; | |
case 's': f += this.leadZero(t.getSeconds()); break; | |
case 'U': f += Math.floor(Date.UTC(t.getFullYear(), t.getMonth(), t.getDate(), h, t.getMinutes(), t.getSeconds(), t.getMilliseconds()) / 1000); break; | |
default: f += format.charAt(i); | |
} | |
} | |
return f; | |
}, | |
unformat: function(t, format) { | |
var d = new Date(); | |
var a = {}; | |
var c, m; | |
t = t.toString(); | |
for (var i = 0; i < format.length; i++) { | |
c = format.charAt(i); | |
switch(c) { | |
case '\\': r = null; i++; break; | |
case 'y': r = '[0-9]{2}'; break; | |
case 'Y': r = '[0-9]{4}'; break; | |
case 'm': r = '0[1-9]|1[012]'; break; | |
case 'n': r = '[1-9]|1[012]'; break; | |
case 'M': r = '[A-Za-z]{'+this.options.monthShort+'}'; break; | |
case 'F': r = '[A-Za-z]+'; break; | |
case 'd': r = '0[1-9]|[12][0-9]|3[01]'; break; | |
case 'j': r = '[1-9]|[12][0-9]|3[01]'; break; | |
case 'D': r = '[A-Za-z]{'+this.options.dayShort+'}'; break; | |
case 'l': r = '[A-Za-z]+'; break; | |
case 'G': | |
case 'H': | |
case 'g': | |
case 'h': r = '[0-9]{1,2}'; break; | |
case 'a': r = '(am|pm)'; break; | |
case 'A': r = '(AM|PM)'; break; | |
case 'i': | |
case 's': r = '[012345][0-9]'; break; | |
case 'U': r = '-?[0-9]+$'; break; | |
default: r = null; | |
} | |
if ($chk(r)) { | |
m = t.match('^'+r); | |
if ($chk(m)) { | |
a[c] = m[0]; | |
t = t.substring(a[c].length); | |
} else { | |
if (this.options.debug) alert("Fatal Error in DatePicker\n\nUnexpected format at: '"+t+"' expected format character '"+c+"' (pattern '"+r+"')"); | |
return d; | |
} | |
} else { | |
t = t.substring(1); | |
} | |
} | |
for (c in a) { | |
var v = a[c]; | |
switch(c) { | |
case 'y': d.setFullYear(v < 30 ? 2000 + v.toInt() : 1900 + v.toInt()); break; // assume between 1930 - 2029 | |
case 'Y': d.setFullYear(v); break; | |
case 'm': | |
case 'n': d.setMonth(v - 1); break; | |
// FALL THROUGH NOTICE! "M" has no break, because "v" now is the full month (eg. 'February'), which will work with the next format "F": | |
case 'M': v = this.options.months.filter(function(item, index) { return item.substring(0,this.options.monthShort) == v }.bind(this))[0]; | |
case 'F': d.setMonth(this.options.months.indexOf(v)); break; | |
case 'd': | |
case 'j': d.setDate(v); break; | |
case 'G': | |
case 'H': d.setHours(v); break; | |
case 'g': | |
case 'h': if (a['a'] == 'pm' || a['A'] == 'PM') { d.setHours(v == 12 ? 0 : v.toInt() + 12); } else { d.setHours(v); } break; | |
case 'i': d.setMinutes(v); break; | |
case 's': d.setSeconds(v); break; | |
case 'U': d = new Date((v.toInt() + ((new Date()).getTimezoneOffset() * 60)) * 1000); | |
} | |
}; | |
return d; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment