summaryrefslogtreecommitdiff
path: root/framework/Web/Javascripts/prado/datepicker.js
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Web/Javascripts/prado/datepicker.js')
-rw-r--r--framework/Web/Javascripts/prado/datepicker.js656
1 files changed, 656 insertions, 0 deletions
diff --git a/framework/Web/Javascripts/prado/datepicker.js b/framework/Web/Javascripts/prado/datepicker.js
new file mode 100644
index 00000000..68e63168
--- /dev/null
+++ b/framework/Web/Javascripts/prado/datepicker.js
@@ -0,0 +1,656 @@
+Prado.Calendar = Class.create();
+
+Prado.Calendar.Util = Class.create();
+
+Object.extend(Prado.Calendar.Util,
+{
+ IsLeapYear : function (year)
+ {
+ return ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0)));
+ },
+
+ yearLength : function(year)
+ {
+ if (this.isLeapYear(year))
+ return 366;
+ else
+ return 365;
+ },
+
+ dayOfYear : function(date)
+ {
+ var a = this.isLeapYear(date.getFullYear()) ?
+ Calendar.LEAP_NUM_DAYS : Calendar.NUM_DAYS;
+ return a[date.getMonth()] + date.getDate();
+ },
+
+ browser : function()
+ {
+ var info = { Version : "1.0" };
+ var is_major = parseInt( navigator.appVersion );
+ info.nver = is_major;
+ info.ver = navigator.appVersion;
+ info.agent = navigator.userAgent;
+ info.dom = document.getElementById ? 1 : 0;
+ info.opera = window.opera ? 1 : 0;
+ info.ie5 = ( info.ver.indexOf( "MSIE 5" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
+ info.ie6 = ( info.ver.indexOf( "MSIE 6" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
+ info.ie4 = ( document.all && !info.dom && !info.opera ) ? 1 : 0;
+ info.ie = info.ie4 || info.ie5 || info.ie6;
+ info.mac = info.agent.indexOf( "Mac" ) > -1;
+ info.ns6 = ( info.dom && parseInt( info.ver ) >= 5 ) ? 1 : 0;
+ info.ie3 = ( info.ver.indexOf( "MSIE" ) && ( is_major < 4 ) );
+ info.hotjava = ( info.agent.toLowerCase().indexOf( 'hotjava' ) != -1 ) ? 1 : 0;
+ info.ns4 = ( document.layers && !info.dom && !info.hotjava ) ? 1 : 0;
+ info.bw = ( info.ie6 || info.ie5 || info.ie4 || info.ns4 || info.ns6 || info.opera );
+ info.ver3 = ( info.hotjava || info.ie3 );
+ info.opera7 = ( ( info.agent.toLowerCase().indexOf( 'opera 7' ) > -1 ) || ( info.agent.toLowerCase().indexOf( 'opera/7' ) > -1 ) );
+ info.operaOld = info.opera && !info.opera7;
+ return info;
+ },
+
+ ImportCss : function(doc, css_file)
+ {
+ if (this.browser().ie)
+ var styleSheet = doc.createStyleSheet(css_file);
+ else
+ {
+ var elm = doc.createElement("link");
+
+ elm.rel = "stylesheet";
+ elm.href = css_file;
+
+ if (headArr = doc.getElementsByTagName("head"))
+ headArr[0].appendChild(elm);
+ }
+ }
+});
+
+Object.extend(Prado.Calendar,
+{
+ // Accumulated days per month, for normal and for leap years.
+ // Used in week number calculations.
+ NUM_DAYS : [0,31,59,90,120,151,181,212,243,273,304,334],
+ LEAP_NUM_DAYS : [0,31,60,91,121,152,182,213,244,274,305,335]
+});
+
+Prado.Calendar.prototype =
+{
+ monthNames : [ "January", "February", "March", "April",
+ "May", "June", "July", "August",
+ "September", "October", "November", "December"
+ ],
+
+ shortWeekDayNames : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
+
+ format : "yyyy-MM-dd",
+
+ css : "calendar_system.css",
+
+ initialize : function(control, attr)
+ {
+ this.attr = attr || [];
+ this.control = $(control);
+ this.dateSlot = new Array(42);
+ this.weekSlot = new Array(6);
+ this.firstDayOfWeek = 1;
+ this.minimalDaysInFirstWeek = 4;
+ this.currentDate = new Date();
+ this.selectedDate = null;
+ this.className = "Prado_Calendar";
+
+ //which element to trigger to show the calendar
+ this.trigger = this.attr.trigger ? $(this.attr.trigger) : this.control;
+ Event.observe(this.trigger, "click", this.show.bind(this));
+
+ Prado.Calendar.Util.ImportCss(document, this.css);
+
+ if(this.attr.format) this.format = this.attr.format;
+
+ //create it
+ this.create();
+ this.hookEvents();
+ },
+
+ create : function()
+ {
+ var div;
+ var table;
+ var tbody;
+ var tr;
+ var td;
+
+ // Create the top-level div element
+ this._calDiv = document.createElement("div");
+ this._calDiv.className = this.className;
+ this._calDiv.style.display = "none";
+
+ // header div
+ div = document.createElement("div");
+ div.className = "calendarHeader";
+ this._calDiv.appendChild(div);
+
+ table = document.createElement("table");
+ table.style.cellSpacing = 0;
+ div.appendChild(table);
+
+ tbody = document.createElement("tbody");
+ table.appendChild(tbody);
+
+ tr = document.createElement("tr");
+ tbody.appendChild(tr);
+
+ // Previous Month Button
+ td = document.createElement("td");
+ td.className = "prevMonthButton";
+ this._previousMonth = document.createElement("button");
+ this._previousMonth.appendChild(document.createTextNode("<<"));
+ td.appendChild(this._previousMonth);
+ tr.appendChild(td);
+
+
+
+ //
+ // Create the month drop down
+ //
+ td = document.createElement("td");
+ td.className = "labelContainer";
+ tr.appendChild(td);
+ this._monthSelect = document.createElement("select");
+ for (var i = 0 ; i < this.monthNames.length ; i++) {
+ var opt = document.createElement("option");
+ opt.innerHTML = this.monthNames[i];
+ opt.value = i;
+ if (i == this.currentDate.getMonth()) {
+ opt.selected = true;
+ }
+ this._monthSelect.appendChild(opt);
+ }
+ td.appendChild(this._monthSelect);
+
+
+ //
+ // Create the year drop down
+ //
+ td = document.createElement("td");
+ td.className = "labelContainer";
+ tr.appendChild(td);
+ this._yearSelect = document.createElement("select");
+ for(var i=1920; i < 2050; ++i) {
+ var opt = document.createElement("option");
+ opt.innerHTML = i;
+ opt.value = i;
+ if (i == this.currentDate.getFullYear()) {
+ opt.selected = false;
+ }
+ this._yearSelect.appendChild(opt);
+ }
+ td.appendChild(this._yearSelect);
+
+
+ td = document.createElement("td");
+ td.className = "nextMonthButton";
+ this._nextMonth = document.createElement("button");
+ this._nextMonth.appendChild(document.createTextNode(">>"));
+ td.appendChild(this._nextMonth);
+ tr.appendChild(td);
+
+ // Calendar body
+ div = document.createElement("div");
+ div.className = "calendarBody";
+ this._calDiv.appendChild(div);
+ this._table = div;
+
+ // Create the inside of calendar body
+
+ var text;
+ table = document.createElement("table");
+ //table.style.width="100%";
+ table.className = "grid";
+
+ div.appendChild(table);
+ var thead = document.createElement("thead");
+ table.appendChild(thead);
+ tr = document.createElement("tr");
+ thead.appendChild(tr);
+
+ for(i=0; i < 7; ++i) {
+ td = document.createElement("th");
+ text = document.createTextNode(this.shortWeekDayNames[(i+this.firstDayOfWeek)%7]);
+ td.appendChild(text);
+ td.className = "weekDayHead";
+ tr.appendChild(td);
+ }
+
+ // Date grid
+ tbody = document.createElement("tbody");
+ table.appendChild(tbody);
+
+ for(week=0; week<6; ++week) {
+ tr = document.createElement("tr");
+ tbody.appendChild(tr);
+
+ for(day=0; day<7; ++day) {
+ td = document.createElement("td");
+ td.className = "calendarDate";
+ text = document.createTextNode(String.fromCharCode(160));
+ td.appendChild(text);
+
+ tr.appendChild(td);
+ var tmp = new Object();
+ tmp.tag = "DATE";
+ tmp.value = -1;
+ tmp.data = text;
+ this.dateSlot[(week*7)+day] = tmp;
+
+ Event.observe(td, "mouseover", this.hover.bind(this));
+ Event.observe(td, "mouseout", this.hover.bind(this));
+
+ }
+ }
+
+ // Calendar Footer
+ div = document.createElement("div");
+ div.className = "calendarFooter";
+ this._calDiv.appendChild(div);
+
+ table = document.createElement("table");
+ //table.style.width="100%";
+ table.className = "footerTable";
+ //table.cellSpacing = 0;
+ div.appendChild(table);
+
+ tbody = document.createElement("tbody");
+ table.appendChild(tbody);
+
+ tr = document.createElement("tr");
+ tbody.appendChild(tr);
+
+ //
+ // The TODAY button
+ //
+ td = document.createElement("td");
+ td.className = "todayButton";
+ this._todayButton = document.createElement("button");
+ var today = new Date();
+ var buttonText = today.getDate() + " " + this.monthNames[today.getMonth()] + ", " + today.getFullYear();
+ this._todayButton.appendChild(document.createTextNode(buttonText));
+ td.appendChild(this._todayButton);
+ tr.appendChild(td);
+
+ //
+ // The CLEAR button
+ //
+ td = document.createElement("td");
+ td.className = "clearButton";
+ this._clearButton = document.createElement("button");
+ var today = new Date();
+ buttonText = "Clear";
+ this._clearButton.appendChild(document.createTextNode(buttonText));
+ td.appendChild(this._clearButton);
+ tr.appendChild(td);
+
+ document.body.appendChild(this._calDiv);
+
+ this.update();
+ this.updateHeader();
+
+ return this._calDiv;
+ },
+
+ hookEvents : function()
+ {
+ // IE55+ extension
+ this._previousMonth.hideFocus = true;
+ this._nextMonth.hideFocus = true;
+ this._todayButton.hideFocus = true;
+ // end IE55+ extension
+
+ // hook up events
+ Event.observe(this._previousMonth, "click", this.prevMonth.bind(this));
+ Event.observe(this._nextMonth, "click", this.nextMonth.bind(this));
+ Event.observe(this._todayButton, "click", this.selectToday.bind(this));
+ Event.observe(this._clearButton, "click", this.clearSelection.bind(this));
+
+ Event.observe(this._monthSelect, "change", this.monthSelect.bind(this));
+ Event.observe(this._yearSelect, "change", this.yearSelect.bind(this));
+
+ // ie6 extension
+ Event.observe(this._calDiv, "mousewheel", this.mouseWheelChange.bind(this));
+
+ Event.observe(this._table, "click", this.selectDate.bind(this));
+
+ Event.observe(this._calDiv,"keydown", this.keyPressed.bind(this));
+
+ /*
+ this._calDiv.onkeydown = function (e) {
+ if (e == null) e = document.parentWindow.event;
+ var kc = e.keyCode != null ? e.keyCode : e.charCode;
+
+ if(kc == 13) {
+ var d = new Date(dp._currentDate).valueOf();
+ dp.setSelectedDate(d);
+
+ if (!dp._alwaysVisible && dp._hideOnSelect) {
+ dp.hide();
+ }
+ return false;
+ }
+
+
+ if (kc < 37 || kc > 40) return true;
+
+ var d = new Date(dp._currentDate).valueOf();
+ if (kc == 37) // left
+ d -= 24 * 60 * 60 * 1000;
+ else if (kc == 39) // right
+ d += 24 * 60 * 60 * 1000;
+ else if (kc == 38) // up
+ d -= 7 * 24 * 60 * 60 * 1000;
+ else if (kc == 40) // down
+ d += 7 * 24 * 60 * 60 * 1000;
+
+ dp.setCurrentDate(new Date(d));
+ return false;
+ }*/
+
+
+ },
+
+ keyPressed : function(ev)
+ {
+ if (!ev) ev = document.parentWindow.event;
+ var kc = ev.keyCode != null ? ev.keyCode : ev.charCode;
+
+ if(kc = Event.KEY_RETURN)
+ {
+ //var d = new Date(this.currentDate);
+ this.setSelectedDate(this.currentDate);
+ this.hide();
+ return false;
+ }
+
+ if(kc < 37 || kc > 40) return true;
+
+ var d = new Date(this.currentDate).valueOf();
+ if(kc == Event.KEY_LEFT)
+ d -= 86400000; //-1 day
+ else if (kc == Event.KEY_RIGHT)
+ d += 86400000; //+1 day
+ else if (kc == Event.KEY_UP)
+ d -= 604800000; // -7 days
+ else if (kc == Event.KEY_DOWN)
+ d += 604800000; // +7 days
+ this.setCurrentDate(new Date(d));
+ return false;
+ },
+
+ selectDate : function(ev)
+ {
+ var el = Event.element(ev);
+ while (el.nodeType != 1)
+ el = el.parentNode;
+
+ while (el != null && el.tagName && el.tagName.toLowerCase() != "td")
+ el = el.parentNode;
+
+ // if no td found, return
+ if (el == null || el.tagName == null || el.tagName.toLowerCase() != "td")
+ return;
+
+ var d = new Date(this.currentDate);
+ var n = Number(el.firstChild.data);
+ if (isNaN(n) || n <= 0 || n == null)
+ return;
+
+ d.setDate(n);
+ this.setSelectedDate(d);
+ this.hide();
+ },
+
+ selectToday : function()
+ {
+ this.setSelectedDate(new Date());
+ this.hide();
+ },
+
+ clearSelection : function()
+ {
+ this.selectedDate = null;
+ if (isFunction(this.onchange))
+ this.onchange();
+ this.hide();
+ },
+
+ monthSelect : function(ev)
+ {
+ this.setMonth(Form.Element.getValue(Event.element(ev)));
+ },
+
+ yearSelect : function(ev)
+ {
+ this.setYear(Form.Element.getValue(Event.element(ev)));
+ },
+
+ // ie6 extension
+ mouseWheelChange : function (e)
+ {
+ if (e == null) e = document.parentWindow.event;
+ var n = - e.wheelDelta / 120;
+ var d = new Date(this.currentDate);
+ var m = this.getMonth() + n;
+ this.setMonth(m);
+ this.setCurrentDate(d);
+
+ return false;
+ },
+
+ onchange : function()
+ {
+ this.control.value = this.formatDate();
+ },
+
+ formatDate : function()
+ {
+ return Prado.Calendar.Util.FormatDate(this.selectedDate, this.format);
+ },
+
+ setCurrentDate : function(date)
+ {
+ if (date == null)
+ return;
+
+ // if string or number create a Date object
+ if (isString(date) || isNumber(date))
+ date = new Date(date);
+
+ // do not update if not really changed
+ if (this.currentDate.getDate() != date.getDate() ||
+ this.currentDate.getMonth() != date.getMonth() ||
+ this.currentDate.getFullYear() != date.getFullYear())
+ {
+
+ this.currentDate = new Date(date);
+
+ this.updateHeader();
+ this.update();
+ }
+
+ },
+
+ setSelectedDate : function(date)
+ {
+ this.selectedDate = new Date(date);
+ this.setCurrentDate(this.selectedDate);
+ if (isFunction(this.onchange))
+ this.onchange();
+ },
+
+ getElement : function()
+ {
+ return this._calDiv;
+ },
+
+ getSelectedDate : function ()
+ {
+ return isNull(this.selectedDate) ? null : new Date(this.selectedDate);
+ },
+
+ setYear : function(year)
+ {
+ var d = new Date(this.currentDate);
+ d.setFullYear(year);
+ this.setCurrentDate(d);
+ },
+
+ setMonth : function (month)
+ {
+ var d = new Date(this.currentDate);
+ d.setMonth(month);
+ this.setCurrentDate(d);
+ },
+
+ nextMonth : function ()
+ {
+ this.setMonth(this.currentDate.getMonth()+1);
+ },
+
+ prevMonth : function ()
+ {
+ this.setMonth(this.currentDate.getMonth()-1);
+ },
+
+ show : function()
+ {
+ if(!this.showing)
+ {
+ var pos = Position.cumulativeOffset(this.control);
+ pos[1] += this.control.offsetHeight;
+ this._calDiv.style.display = "block";
+ this._calDiv.style.top = pos[1] + "px";
+ this._calDiv.style.left = pos[0] + "px";
+ Event.observe(document.body, "click", this.hideOnClick.bind(this));
+ var date = Prado.Calendar.Util.ParseDate(Form.Element.getValue(this.control), this.format);
+ if(!isNull(date))
+ {
+ this.selectedDate = date;
+ this.setCurrentDate(date);
+ }
+ this.showing = true;
+ }
+ },
+
+ //hide the calendar when clicked outside any calendar
+ hideOnClick : function(ev)
+ {
+ if(!this.showing) return;
+ var el = Event.element(ev);
+ var within = false;
+ do
+ {
+ within = within || el.className == this.className;
+ within = within || el == this.trigger;
+ within = within || el == this.control;
+ if(within) break;
+ el = el.parentNode;
+ }
+ while(el);
+ if(!within) this.hide();
+ },
+
+ hide : function()
+ {
+ if(this.showing)
+ {
+ this._calDiv.style.display = "none";
+ this.showing = false;
+ Event.stopObserving(document.body, "click", this.hideOnClick.bind(this));
+ }
+ },
+
+ update : function()
+ {
+ var Util = Prado.Calendar.Util;
+
+ // Calculate the number of days in the month for the selected date
+ var date = this.currentDate;
+ var today = Util.ISODate(new Date());
+
+ var selected = isNull(this.selectedDate) ? "" : Util.ISODate(this.selectedDate);
+ var current = Util.ISODate(date);
+ var d1 = new Date(date.getFullYear(), date.getMonth(), 1);
+ var d2 = new Date(date.getFullYear(), date.getMonth()+1, 1);
+ var monthLength = Math.round((d2 - d1) / (24 * 60 * 60 * 1000));
+
+ // Find out the weekDay index for the first of this month
+ var firstIndex = (d1.getDay() - this.firstDayOfWeek) % 7 ;
+ if (firstIndex < 0)
+ firstIndex += 7;
+
+ var index = 0;
+ while (index < firstIndex) {
+ this.dateSlot[index].value = -1;
+ this.dateSlot[index].data.data = String.fromCharCode(160);
+ this.dateSlot[index].data.parentNode.className = "empty";
+ index++;
+ }
+
+ for (i = 1; i <= monthLength; i++, index++) {
+ var slot = this.dateSlot[index];
+ var slotNode = slot.data.parentNode;
+ slot.value = i;
+ slot.data.data = i;
+ slotNode.className = "date";
+ if (Util.ISODate(d1) == today) {
+ slotNode.className += " today";
+ }
+ if (Util.ISODate(d1) == current) {
+ slotNode.className += " current";
+ }
+ if (Util.ISODate(d1) == selected) {
+ slotNode.className += " selected";
+ }
+ d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()+1);
+ }
+
+ var lastDateIndex = index;
+
+ while(index < 42) {
+ this.dateSlot[index].value = -1;
+ this.dateSlot[index].data.data = String.fromCharCode(160);
+ this.dateSlot[index].data.parentNode.className = "empty";
+ ++index;
+ }
+
+ },
+
+ hover : function(ev)
+ {
+ //conditionally add the hover class to the event target element.
+ Element.condClassName(Event.element(ev), "hover", ev.type=="mouseover");
+ },
+
+ updateHeader : function () {
+
+ var options = this._monthSelect.options;
+ var m = this.currentDate.getMonth();
+ for(var i=0; i < options.length; ++i) {
+ options[i].selected = false;
+ if (options[i].value == m) {
+ options[i].selected = true;
+ }
+ }
+
+ options = this._yearSelect.options;
+ var year = this.currentDate.getFullYear();
+ for(var i=0; i < options.length; ++i) {
+ options[i].selected = false;
+ if (options[i].value == year) {
+ options[i].selected = true;
+ }
+ }
+
+ }
+
+
+}; \ No newline at end of file