Element.addMethods({ purgeChildren: function(element) { $A(element.childNodes).each(function(e){$(e).remove();});}, build: function(element, type, options, style) { newElement = Element.build(type, options, style); element.appendChild(newElement); return newElement;}
}); Element.build = function(type, options, style)
{ e = $(document.createElement(type)); $H(options).each(function(pair) { eval("e." + pair.key + " = pair.value" );}); if (style)
$H(style).each(function(pair) { eval("e.style." + pair.key + " = pair.value" );}); return e;}; nil=null; Date.one_day = 24*60*60*1000; Date.weekdays = $w("S M T W T F S"); Date.months = $w("January February March April May June July August September October November December" ); Date.padded2 = function(hour) { padded2 = hour.toString(); if (parseInt(hour) < 10) padded2="0" + padded2; return padded2;}
Date.prototype.getPaddedMinutes = function() { return Date.padded2(this.getMinutes());}
Date.prototype.getAMPMHour = function() { hour=this.getHours(); return (hour == 0) ? 12 : (hour > 12 ? hour - 12 : hour ) }
Date.prototype.getAMPM = function() { return (this.getHours() < 12) ? "AM" : "PM";}
Date.prototype.stripTime = function() { return new Date(this.getFullYear(), this.getMonth(), this.getDate());}; Date.prototype.daysDistance = function(compare_date) { return (compare_date - this) / Date.one_day;}; Date.prototype.toFormattedString = function(include_time){ str = Date.months[this.getMonth()] + " " + this.getDate() + ", " + this.getFullYear(); if (include_time) { hour=this.getHours(); str += " " + this.getAMPMHour() + ":" + this.getPaddedMinutes() + " " + this.getAMPM() }
return str;}
window.f_height = function() { return([window.innerHeight ? window.innerHeight : null, document.documentElement ? document.documentElement.clientHeight : null, document.body ? document.body.clientHeight : null].compact().first());}
window.f_scrollTop = function() { return ([window.pageYOffset ? window.pageYOffset : null, document.documentElement ? document.documentElement.scrollTop : null, document.body ? document.body.scrollTop : null].compact().first() );}
CalendarDateSelect = Class.create(); CalendarDateSelect.prototype = { initialize: function(target_element, options) { this.options = $H({ embedded: false, time: false, year_range: 10, calendar_div: nil, close_on_click: nil, minute_interval: 5
}).merge(options || {}); this.target_element = $(target_element); this.selection_made = $F(this.target_element)!=""; if (this.target_element.calendar_date_select)
{ this.target_element.calendar_date_select.close(); return false;}
this.target_element.calendar_date_select = this; this.calendar_div = $(this.options['calendar_div']); if (!this.target_element) { alert("Target element " + target_element + " not found!"); return false;}
this.parseDate(); if (this.calendar_div == nil) { this.calendar_div = $( this.options.embedded ? this.target_element.parentNode : document.body ).build('div');}
if (!this.options.embedded) { this.calendar_div.style.position = "absolute"; this.positionCalendarDiv();}
this.calendar_div.addClassName("calendar_date_select"); if (this.options["embedded"]) this.options["close_on_click"]=false; if (this.options['close_on_click']===nil )
{ if (this.options['time'])
this.options["close_on_click"] = false; else
this.options['close_on_click'] = true;}
if(!this.options["embedded"]) Event.observe(document.body, "mousedown", this.bodyClick_handler=this.bodyClick.bindAsEventListener(this)); this.initFrame(); if(!this.options["embedded"]) setTimeout(function(){ if (( parseInt(this.calendar_div.style.top) + this.calendar_div.getDimensions().height ) > (window.f_scrollTop() + window.f_height()))
this.positionCalendarDiv(true);}.bindAsEventListener(this), 1);}, positionCalendarDiv: function(above) { pos = Position.cumulativeOffset(this.target_element); this.calendar_div.style.left = pos[0].toString() + "px"; if (above)
this.calendar_div.style.top = (pos[1] - this.calendar_div.getDimensions().height ).toString() + "px"; else
this.calendar_div.style.top = (pos[1] + this.target_element.getDimensions().height ).toString() + "px";}, initFrame: function() { that=this; $w("header body time footer buttons").each(function(name) { eval(name + "_div = that." + name + "_div = that.calendar_div.build('div', { className: 'cds_"+name+"' }, { clear: 'left'} ); ");}); this.initTimeDiv(); this.initButtonsDiv(); this.updateFooter("&nbsp;"); this.next_month_button = header_div.build("input", { type: "button", value : ">", className: "next" }); this.prev_month_button = header_div.build("input", { type: "button", value : "<", className: "prev" }); this.month_select = header_div.build("select", { className: "month"}); this.year_select = header_div.build("select", { className: "year"}); for(x=0; x<12; x++)
this.month_select.options[x]=new Option(Date.months[x],x); Event.observe(this.prev_month_button, 'mousedown', function () { this.navMonth(this.date.getMonth() - 1 ) }.bindAsEventListener(this)); Event.observe(this.next_month_button, 'mousedown', function () { this.navMonth(this.date.getMonth() + 1 ) }.bindAsEventListener(this)); Event.observe(this.month_select, 'change', (function () { this.navMonth($F(this.month_select)) }).bindAsEventListener(this)); Event.observe(this.year_select, 'change', (function () { this.navYear($F(this.year_select)) }).bindAsEventListener(this)); this.calendar_day_grid = []; days_table = body_div.build("table", { cellPadding: "0px", cellSpacing: "0px", width: "100%" }).build("tbody"); weekdays_row = days_table.build("tr", {className: "weekdays"}); Date.weekdays.each( function(weekday) { weekdays_row.build("td", {innerHTML: weekday});}); for(cell_index=0; cell_index<42; cell_index++)
{ weekday=cell_index%7; if ( cell_index %7==0 ) days_row = days_table.build("tr", {className: "days"}); (this.calendar_day_grid[cell_index] = days_row.build("td", { calendar_date_select: this, onmouseover: function () { this.calendar_date_select.dayHover(this);}, onmouseout: function () { this.calendar_date_select.dayHoverOut(this) }, onclick: function() { this.calendar_date_select.updateSelectedDate(this);}, className: (weekday==0) || (weekday==6) ? " weekend" : ""
}, { cursor: "pointer" } )).build("div"); this.calendar_day_grid[cell_index];}
this.refresh();}, initButtonsDiv: function()
{ buttons_div = this.buttons_div; buttons_div.build("input", { value: (this.options["time"] ? "Now" : "Today" ), onclick: this.today.bindAsEventListener(this), type: "button"
}); if (this.allowCloseButtons())
{ buttons_div.build("input", { value: "OK", onclick: this.close.bindAsEventListener(this), type: "button"
});}
}, initTimeDiv: function()
{ time_div = this.time_div; if (this.options["time"])
{ time_div.build("span", {innerHTML:" @ "})
this.hour_select = time_div.build("select", { calendar_date_select: this, onchange: function() { this.calendar_date_select.updateSelectedDate( { hour: this.value });}
}); time_div.build("span", {innerHTML:"&nbsp; : "}); this.minute_select = time_div.build("select", { calendar_date_select: this, onchange: function() { this.calendar_date_select.updateSelectedDate( {minute: this.value }) }
}); t=new Date(); for(x=0;x<=23;x++) { t.setHours(x); this.hour_select.options[x] = new Option( "" + t.getAMPMHour() + " " + t.getAMPM(), x ) }
x=0; for(m=0;m<=60;m+=this.options["minute_interval"]) { this.minute_select.options[x++] = new Option( Date.padded2(m), m ) }
} else (time_div.remove());}, allowCloseButtons: function() { return ( !this.options["embedded"] && this.options["time"]);}, dateString: function() { return (this.selection_made) ? this.selected_date.toFormattedString(this.options['time']) : "&nbsp;";}, navMonth: function(month) { prev_day = this.date.getDate(); this.date.setMonth(month); this.refresh();}, navYear: function(year) { this.date.setYear(year); this.refresh();}, refresh: function ()
{ this.month_select.selectedIndex = this.date.getMonth(); range=this.options["year_range"]; this.year_select.purgeChildren(); for( x=0; x<=range*2; x++)
{ year = x+(this.date.getFullYear() - range); this.year_select.options[x]=new Option(year,year);}
this.year_select.selectedIndex = range; this.beginning_date = new Date(this.date).stripTime(); this.beginning_date.setDate(1); pre_days = this.beginning_date.getDay()
if (pre_days < 3) pre_days+=7; this.beginning_date.setDate(1 - pre_days); iterator = new Date(this.beginning_date); today = new Date().stripTime(); this_month = this.date.getMonth(); for (cell_index=0;cell_index<42; cell_index++)
{ day = iterator.getDate(); month = iterator.getMonth(); cell = this.calendar_day_grid[cell_index]; Element.remove(cell.childNodes[0]); div = cell.build("div", {innerHTML:day}); if (month!=this_month) div.className = "other"; cell.day=day; cell.month = month; cell.year = iterator.getFullYear(); iterator.setDate( day + 1);}
if (this.today_cell) this.today_cell.removeClassName("today"); if ( $R(0,42).include(days_until = this.beginning_date.daysDistance(today)) ) { this.today_cell = this.calendar_day_grid[days_until]; this.today_cell.addClassName("today");}
if (this.options["time"]) { this.hour_select.selectedIndex = this.selected_date.getHours(); this.minute_select.selectedIndex = this.selected_date.getMinutes() / this.options["minute_interval"]; this.hour_select.onchange(); this.minute_select.onchange();}
this.setSelectedClass(); this.updateFooter();}, dayHover: function(element) { element.addClassName("hover"); hover_date = new Date(this.selected_date); hover_date.setYear(element.year); hover_date.setMonth(element.month); hover_date.setDate(element.day); this.updateFooter(hover_date.toFormattedString(this.options['time']));}, dayHoverOut: function(element) { element.removeClassName("hover"); this.updateFooter();}, setSelectedClass: function() { if (!this.selection_made) return; if (this.selected_cell) this.selected_cell.removeClassName("selected"); if ($R(0,42).include( days_until = this.beginning_date.daysDistance(this.selected_date.stripTime()) )) { this.selected_cell = this.calendar_day_grid[days_until]; this.selected_cell.addClassName("selected");}
}, reparse: function() { this.parseDate(); this.refresh();}, parseDate: function()
{ this.date = new Date(this.options['date'] || $F(this.target_element)); if (isNaN(this.date.getDate())) this.date = new Date(); this.selected_date = new Date(this.date); this.date.setDate(1);}, updateFooter:function(text) { if (!text) text=this.dateString(); this.footer_div.purgeChildren(); this.footer_div.build("text", {innerHTML: text });}, updateSelectedDate:function(parts) { if (parts.day) { this.selection_made = true; this.selected_date.setDate(parts.day); this.selected_date.setMonth(parts.month); this.selected_date.setYear(parts.year);}
if (parts.hour) this.selected_date.setHours(parts.hour); if (parts.minute) this.selected_date.setMinutes(parts.minute); if (this.selection_made) this.target_element.value = this.dateString(); if (this.options.close_on_click) { this.close();}
this.updateFooter(); this.setSelectedClass();}, today: function() { this.date = new Date(); d=new Date(); this.updateSelectedDate( { day: d.getDate(), month: d.getMonth(), year: d.getFullYear(), hour: d.getHours(), minute: d.getMinutes() } ); this.refresh();}, close: function() { this.target_element.calendar_date_select = nil; Event.stopObserving(document.body, "mousedown", this.bodyClick_handler); this.calendar_div.remove(); this.target_element.focus();}, bodyClick: function(e) { if (! $(Event.element(e)).descendantOf(this.calendar_div) ) this.close();}
}
