I'm not the best at javascript and I was wondering if someone might be able help me. I am using this mootools calendar http://www.monkeyphysics.com/mootools/script/2/datepickerand it works if I have a submit button. However for what I am doing I need to have it update to my database without a submit button. I was able to do this with a checkbox and comment box using this bit of code at different parts
var url = 'schoolPage.php?catID=' + chk.inputElement.getProperty('id') + '&chk=' + chk.inputElement.getProperty('checked');
var request = new Request({
url:url,
method:'POST',
onRequest: function() {
alert('making ajax call :: ' + url);
}
}).send();
However with this calendar im having trouble with where I might put this bit of code so that when the user selects a date it will be sent to the database.
Any help would be greatly appreciated i'm losing my mind trying to figure it out!
JS CODE
/**
* datepicker.js - MooTools Datepicker class
* @version 1.12
*
* 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: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],
months: ['Janvier', 'Fèvrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Dècembre'],
dayShort: 2,
monthShort: 3,
startDay: 0, // 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,
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 ($chk(this.options.minDate)) this.options.minDate = this.unformat(this.options.minDate.date, this.options.minDate.format);
if ($chk(this.options.maxDate)) this.options.maxDate = this.unformat(this.options.maxDate.date, this.options.maxDate.format);
document.addEvent('mousedown', this.close.bind(this));
},
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) {
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();
}
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();
['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) {
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
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);
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;
i.focus();
if (e.wheel > 0) {
if (i.get('value').toInt() < 23) i.set('value', this.leadZero(i.get('value').toInt() + 1));
} else {
if (i.get('value').toInt() > 0) i.set('value', this.leadZero(i.get('value').toInt() -1));
}
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;
i.focus();
if (e.wheel > 0) {
if (i.get('value').toInt() < 59) i.set('value', this.leadZero(i.get('value').toInt() + 1));
} else {
if (i.get('value').toInt() > 0) i.set('value', this.leadZero(i.get('value').toInt() -1));
}
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 (this.d.getMonth() == month) {
if (available) {
this.limit.right = true;
} else {
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.setMonth(d);
this.mode = 'month';
this.render('fade');
}.bindWithEvent(this, this.d.getMonth()));
}
this.d.setMonth(this.d.getMonth() + 1);
}
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);
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;
},
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 == '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();
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(t.valueOf() / 1000); break;
default: f += format.charAt(i);
}
}
return f;
},
unformat: function(t, format) {
var d = new Date();
var a = {};
var c, m;
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() * 1000);
}
};
return d;
}
});
Thanks