From a48195e52865532add00af44788c938071eb0e1d Mon Sep 17 00:00:00 2001 From: wei <> Date: Fri, 20 Jan 2006 07:02:43 +0000 Subject: Update date picker --- framework/Web/Javascripts/datepicker/calendar.png | Bin 0 -> 775 bytes framework/Web/Javascripts/datepicker/datepicker.js | 592 +++++++++++++++++++++ framework/Web/Javascripts/datepicker/default.css | 86 +++ 3 files changed, 678 insertions(+) create mode 100644 framework/Web/Javascripts/datepicker/calendar.png create mode 100644 framework/Web/Javascripts/datepicker/datepicker.js create mode 100644 framework/Web/Javascripts/datepicker/default.css (limited to 'framework/Web/Javascripts/datepicker') diff --git a/framework/Web/Javascripts/datepicker/calendar.png b/framework/Web/Javascripts/datepicker/calendar.png new file mode 100644 index 00000000..c245f1b4 Binary files /dev/null and b/framework/Web/Javascripts/datepicker/calendar.png differ diff --git a/framework/Web/Javascripts/datepicker/datepicker.js b/framework/Web/Javascripts/datepicker/datepicker.js new file mode 100644 index 00000000..5468fb6c --- /dev/null +++ b/framework/Web/Javascripts/datepicker/datepicker.js @@ -0,0 +1,592 @@ +Prado.WebUI.TDatePicker = Class.create(); +Prado.WebUI.TDatePicker.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", + + FirstDayOfWeek : 1, // 0 for sunday + + ClassName : "TDatePicker", + + FromYear : 2000, UpToYear: 2015, + + initialize : function(control, attr) + { + this.attr = attr || []; + this.control = $(control); + this.dateSlot = new Array(42); + this.weekSlot = new Array(6); + this.minimalDaysInFirstWeek = 4; + this.selectedDate = this.newDate(); + + //which element to trigger to show the calendar + if(this.attr.Trigger) + { + this.trigger = $(this.attr.Trigger) ; + var triggerEvent = this.attr.TriggerEvent || "click"; + } + else + { + this.trigger = this.control; + var triggerEvent = this.attr.TriggerEvent || "focus"; + } + + Event.observe(this.trigger, triggerEvent, this.show.bindEvent(this)); + + Object.extend(this,attr); + + this.create(); + }, + + 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"; + this._calDiv.style.position = "absolute" + + // 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"); + var previousMonth = document.createElement("button"); + previousMonth.className = "prevMonthButton"; + previousMonth.appendChild(document.createTextNode("<<")); + td.appendChild(previousMonth); + tr.appendChild(td); + + + + // + // Create the month drop down + // + td = document.createElement("td"); + tr.appendChild(td); + this._monthSelect = document.createElement("select"); + this._monthSelect.className = "months"; + 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.selectedDate.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=this.FromYear; i <= this.UpToYear; ++i) { + var opt = document.createElement("option"); + opt.innerHTML = i; + opt.value = i; + if (i == this.selectedDate.getFullYear()) { + opt.selected = false; + } + this._yearSelect.appendChild(opt); + } + td.appendChild(this._yearSelect); + + + td = document.createElement("td"); + td.className = "nextMonthButton"; + var nextMonth = document.createElement("button"); + nextMonth.appendChild(document.createTextNode(">>")); + td.appendChild(nextMonth); + tr.appendChild(td); + + // Calendar body + div = document.createElement("div"); + div.className = "calendarBody"; + this._calDiv.appendChild(div); + var calendarBody = div; + + // Create the inside of calendar body + + var text; + table = document.createElement("table"); + 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.bindEvent(this)); + Event.observe(td, "mouseout", this.hover.bindEvent(this)); + + } + } + + // Calendar Footer + div = document.createElement("div"); + div.className = "calendarFooter"; + this._calDiv.appendChild(div); + + var todayButton = document.createElement("button"); + todayButton.className = "todayButton"; + var today = this.newDate(); + var buttonText = today.SimpleFormat(this.Format); + todayButton.appendChild(document.createTextNode(buttonText)); + div.appendChild(todayButton); + + /*var clearButton = document.createElement("button"); + clearButton.className = "clearButton"; + buttonText = "Clear"; + clearButton.appendChild(document.createTextNode(buttonText)); + div.appendChild(clearButton); + */ + + if(Prado.Browser().ie) + { + this.iePopUp = document.createElement('iframe'); + this.iePopUp.src = ""; + this.iePopUp.style.position = "absolute" + this.iePopUp.scrolling="no" + this.iePopUp.frameBorder="0" + document.body.appendChild(this.iePopUp); + } + + document.body.appendChild(this._calDiv); + + this.update(); + this.updateHeader(); + + this.ieHack(true); + + // IE55+ extension + previousMonth.hideFocus = true; + nextMonth.hideFocus = true; + todayButton.hideFocus = true; + // end IE55+ extension + + // hook up events + Event.observe(previousMonth, "click", this.prevMonth.bindEvent(this)); + Event.observe(nextMonth, "click", this.nextMonth.bindEvent(this)); + Event.observe(todayButton, "click", this.selectToday.bindEvent(this)); + //Event.observe(clearButton, "click", this.clearSelection.bindEvent(this)); + Event.observe(this._monthSelect, "change", this.monthSelect.bindEvent(this)); + Event.observe(this._yearSelect, "change", this.yearSelect.bindEvent(this)); + + // ie6 extension + Event.observe(this._calDiv, "mousewheel", this.mouseWheelChange.bindEvent(this)); + + Event.observe(calendarBody, "click", this.selectDate.bindEvent(this)); + + }, + + ieHack : function(cleanup) + { + // IE hack + if(this.iePopUp) + { + this.iePopUp.style.display = "block"; + this.iePopUp.style.top = (this._calDiv.offsetTop -1 ) + "px"; + this.iePopUp.style.left = (this._calDiv.offsetLeft -1)+ "px"; + this.iePopUp.style.width = Math.abs(this._calDiv.offsetWidth -2)+ "px"; + this.iePopUp.style.height = (this._calDiv.offsetHeight + 1)+ "px"; + if(cleanup) this.iePopUp.style.display = "none"; + } + }, + + keyPressed : function(ev) + { + if(!this.showing) return; + if (!ev) ev = document.parentWindow.event; + var kc = ev.keyCode != null ? ev.keyCode : ev.charCode; + + if(kc == Event.KEY_RETURN) + { + this.setSelectedDate(this.selectedDate); + Event.stop(ev); + this.hide(); + } + if(kc == Event.KEY_ESC) + { + Event.stop(ev); this.hide(); + } + + + var getDaysPerMonth = function (nMonth, nYear) + { + nMonth = (nMonth + 12) % 12; + var days= [31,28,31,30,31,30,31,31,30,31,30,31]; + var res = days[nMonth]; + if (nMonth == 1) //feburary, leap years has 29 + res += nYear % 4 == 0 && !(nYear % 400 == 0) ? 1 : 0; + return res; + } + + if(kc < 37 || kc > 40) return true; + + var current = this.selectedDate; + var d = current.valueOf(); + if(kc == Event.KEY_LEFT) + { + if(ev.ctrlKey || ev.shiftKey) // -1 month + { + current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth() - 1,current.getFullYear())) ); // no need to catch dec -> jan for the year + d = current.setMonth( current.getMonth() - 1 ); + } + else + d -= 86400000; //-1 day + } + else if (kc == Event.KEY_RIGHT) + { + if(ev.ctrlKey || ev.shiftKey) // +1 month + { + current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth() + 1,current.getFullYear())) ); // no need to catch dec -> jan for the year + d = current.setMonth( current.getMonth() + 1 ); + } + else + d += 86400000; //+1 day + } + else if (kc == Event.KEY_UP) + { + if(ev.ctrlKey || ev.shiftKey) //-1 year + { + current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth(),current.getFullYear() - 1)) ); // no need to catch dec -> jan for the year + d = current.setFullYear( current.getFullYear() - 1 ); + } + else + d -= 604800000; // -7 days + } + else if (kc == Event.KEY_DOWN) + { + if(ev.ctrlKey || ev.shiftKey) // +1 year + { + current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth(),current.getFullYear() + 1)) ); // no need to catch dec -> jan for the year + d = current.setFullYear( current.getFullYear() + 1 ); + } + else + d += 7 * 24 * 61 * 60 * 1000; // +7 days + } + this.setSelectedDate(d); + Event.stop(ev); + }, + + 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 = this.newDate(this.selectedDate); + var n = Number(el.firstChild.data); + if (isNaN(n) || n <= 0 || n == null) + return; + + d.setDate(n); + this.setSelectedDate(d); + this.hide(); + }, + + selectToday : function() + { + if(this.selectedDate.toISODate() == this.newDate().toISODate()) + this.hide(); + + this.setSelectedDate(this.newDate()); + }, + + clearSelection : function() + { + this.setSelectedDate(this.newDate()); + 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 = this.newDate(this.selectedDate); + var m = d.getMonth() + n; + this.setMonth(m); + + return false; + }, + + onchange : function() + { + this.control.value = this.formatDate(); + }, + + formatDate : function() + { + return this.selectedDate ? this.selectedDate.SimpleFormat(this.Format) : ''; + }, + + newDate : function(date) + { + if(!date) + date = new Date(); + if(isString(date) || isNumber(date)) + date = new Date(date); + return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0,0,0); + }, + + setSelectedDate : function(date) + { + if (date == null) + return; + this.selectedDate = this.newDate(date); + + this.updateHeader(); + this.update(); + if (isFunction(this.onchange)) + this.onchange(); + }, + + getElement : function() + { + return this._calDiv; + }, + + getSelectedDate : function () + { + return isNull(this.selectedDate) ? null : this.newDate(this.selectedDate); + }, + + setYear : function(year) + { + var d = this.newDate(this.selectedDate); + d.setFullYear(year); + this.setSelectedDate(d); + }, + + setMonth : function (month) + { + var d = this.newDate(this.selectedDate); + d.setMonth(month); + this.setSelectedDate(d); + }, + + nextMonth : function () + { + this.setMonth(this.selectedDate.getMonth()+1); + }, + + prevMonth : function () + { + this.setMonth(this.selectedDate.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]-1) + "px"; + this._calDiv.style.left = pos[0] + "px"; + + this.ieHack(false); + this.documentClickEvent = this.hideOnClick.bindEvent(this); + this.documentKeyDownEvent = this.keyPressed.bindEvent(this); + Event.observe(document.body, "click", this.documentClickEvent); + var date = Date.SimpleParse(Form.Element.getValue(this.control), this.Format); + if(!isNull(date)) + { + this.selectedDate = date; + this.setSelectedDate(date); + } + Event.observe(document,"keydown", this.documentKeyDownEvent); + 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"; + if(this.iePopUp) + this.iePopUp.style.display = "none"; + this.showing = false; + Event.stopObserving(document.body, "click", this.documentClickEvent); + Event.stopObserving(document,"keydown", this.documentKeyDownEvent); + } + }, + + update : function() + { + // Calculate the number of days in the month for the selected date + var date = this.selectedDate; + var today = (this.newDate()).toISODate(); + + var selected = date.toISODate(); + 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"; + //slotNode.style.color = ""; + if (d1.toISODate() == today) { + slotNode.className += " today"; + } + if (d1.toISODate() == selected) { + // slotNode.style.color = "blue"; + 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.selectedDate.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.selectedDate.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 diff --git a/framework/Web/Javascripts/datepicker/default.css b/framework/Web/Javascripts/datepicker/default.css new file mode 100644 index 00000000..cd03bb27 --- /dev/null +++ b/framework/Web/Javascripts/datepicker/default.css @@ -0,0 +1,86 @@ +.TDatePicker +{ + border: 1px solid #919EA9; + background-color: White; + text-align: center; + font-size: 11px; + font-family: Tahoma, Arial, Helvetica, sans-serif; + cursor: default; +} + +.TDatePickerButton +{ + width: 30px; +} + +.TDatePickerImageButton +{ + padding: 2px; + border: 1px solid #919EA9; + vertical-align: top; + margin-left: 1px; +} + +.TDatePickerImageButton:hover +{ + border-color: #ddd; +} + +.TDatePicker select +{ + font-size: 11px; +} + +.TDatePicker .calendarHeader button +{ + font-size: 12px; + width: 32px; +} + +.TDatePicker .date +{ + padding: 4px 0; + border: 1px solid white; +} +.TDatePicker .hover +{ + border: 1px solid blue; +} +.TDatePicker .selected +{ + background-color: blue; + border: 1px solid blue; + color: white; +} +.TDatePicker .today +{ + font-weight: bold; +} + +.TDatePicker td.empty +{ + background-color: #ffe; + border: 1px solid white; + cursor: default; + height: 23px; +} +.TDatePicker th +{ + width: 28px; +} +.TDatePicker .grid +{ + border-spacing: 0px; + margin: 3px; +} +.TDatePicker .calendarFooter +{ + margin: 2px; + border-top: 1px solid #919EA9; + padding-top: 2px; +} +.TDatePicker .calendarFooter button +{ + font-size: 12px; + margin: 4px; +} \ No newline at end of file -- cgit v1.2.3