Return-Path: X-Original-To: apmail-tapestry-commits-archive@minotaur.apache.org Delivered-To: apmail-tapestry-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id ACE5810261 for ; Sun, 27 Apr 2014 13:53:55 +0000 (UTC) Received: (qmail 28886 invoked by uid 500); 27 Apr 2014 13:53:52 -0000 Delivered-To: apmail-tapestry-commits-archive@tapestry.apache.org Received: (qmail 28672 invoked by uid 500); 27 Apr 2014 13:53:51 -0000 Mailing-List: contact commits-help@tapestry.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tapestry.apache.org Delivered-To: mailing list commits@tapestry.apache.org Received: (qmail 28650 invoked by uid 99); 27 Apr 2014 13:53:50 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 27 Apr 2014 13:53:50 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 3EF83993474; Sun, 27 Apr 2014 13:53:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jkemnade@apache.org To: commits@tapestry.apache.org Date: Sun, 27 Apr 2014 13:53:51 -0000 Message-Id: <2d7879da201a4c6cb1869e7981351585@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/3] git commit: TAP5-2229: make the DatePicker JavaScript an AMD module TAP5-2229: make the DatePicker JavaScript an AMD module Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/70d4efbc Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/70d4efbc Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/70d4efbc Branch: refs/heads/master Commit: 70d4efbce0b90dd34b20b7872e5fbe6572a248d1 Parents: f65adf6 Author: Jochen Kemnade Authored: Sun Apr 27 13:08:40 2014 +0200 Committer: Jochen Kemnade Committed: Sun Apr 27 13:08:40 2014 +0200 ---------------------------------------------------------------------- .../META-INF/modules/t5/core/datefield.coffee | 17 +- .../tapestry5/corelib/components/DateField.java | 3 +- .../tapestry5/datepicker_106/js/datepicker.js | 744 ------------------ .../META-INF/modules/t5/core/datepicker.js | 766 +++++++++++++++++++ 4 files changed, 777 insertions(+), 753 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70d4efbc/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee index bb3a6b5..aca4653 100644 --- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee +++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee @@ -15,8 +15,8 @@ # ## t5/core/datefield # # Provides support for the `core/DateField` component. -define ["./dom", "./events", "./messages", "./ajax", "underscore", "./fields"], - (dom, events, messages, ajax, _) -> +define ["./dom", "./events", "./messages", "./ajax", "underscore", "./datepicker", "./fields"], + (dom, events, messages, ajax, _, DatePicker) -> # Translate from the provided order (SUNDAY = 0, MONDAY = 1), to @@ -24,18 +24,18 @@ define ["./dom", "./events", "./messages", "./ajax", "underscore", "./fields"], serverFirstDay = parseInt messages "date-symbols.first-day" datePickerFirstDay = if serverFirstDay is 0 then 6 else serverFirstDay - 1 - # Loalize a few other things. - DatePicker.months = (messages "date-symbols.months").split "," + # Localize a few other things. days = (messages "date-symbols.days").split "," # Shuffle sunday to the end, so that monday is first. days.push days.shift() - DatePicker.days = _.map days, (name) -> name.substr(0, 1).toLowerCase() + monthsLabels = (messages "date-symbols.months").split "," + daysLabels = _.map days, (name) -> name.substr(0, 1).toLowerCase() + todayLabel = messages "core-datefield-today" + noneLabel = messages "core-datefield-none" - DatePicker.TODAY = messages "core-datefield-today" - DatePicker.NONE = messages "core-datefield-none" # Track the active popup; only one allowed at a time. May look to rework this # later so that there's just one popup and it is moved around the viewport, or @@ -114,6 +114,9 @@ define ["./dom", "./events", "./messages", "./ajax", "underscore", "./fields"], createPopup: -> @datePicker = new DatePicker() @datePicker.setFirstWeekDay datePickerFirstDay + + @datePicker.setLocalizations monthsLabels, daysLabels, todayLabel, noneLabel + @popup = dom.create("div", { class: "datefield-popup well"}).append @datePicker.create() @container.insertAfter @popup http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70d4efbc/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java index 286a845..b55cc7b 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java @@ -50,8 +50,7 @@ import java.util.Locale; * @see TextField */ // TODO: More testing; see https://issues.apache.org/jira/browse/TAPESTRY-1844 -@Import(library = "${tapestry.datepicker}/js/datepicker.js", - stylesheet = "${tapestry.datepicker}/css/datepicker.css", +@Import(stylesheet = "${tapestry.datepicker}/css/datepicker.css", module = "t5/core/datefield") @Events(EventConstants.VALIDATE) public class DateField extends AbstractField http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70d4efbc/tapestry-core/src/main/resources/META-INF/assets/tapestry5/datepicker_106/js/datepicker.js ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/datepicker_106/js/datepicker.js b/tapestry-core/src/main/resources/META-INF/assets/tapestry5/datepicker_106/js/datepicker.js deleted file mode 100644 index a0b6321..0000000 --- a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/datepicker_106/js/datepicker.js +++ /dev/null @@ -1,744 +0,0 @@ -/*----------------------------------------------------------------------------\ -| Date Picker 1.06 | -|-----------------------------------------------------------------------------| -| Created by Erik Arvidsson | -| (http://webfx.eae.net/contact.html#erik) | -| For WebFX (http://webfx.eae.net/) | -|-----------------------------------------------------------------------------| -| A DOM based Date Picker | -|-----------------------------------------------------------------------------| -| Copyright (c) 1999, 2002, 2002, 2003, 2004, 2006 Erik Arvidsson | -|-----------------------------------------------------------------------------| -| Licensed under the Apache License, Version 2.0 (the "License"); you may not | -| use this file except in compliance with the License. You may obtain a copy | -| of the License at http://www.apache.org/licenses/LICENSE-2.0 | -| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | -| Unless required by applicable law or agreed to in writing, software | -| distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | -| WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | -| License for the specific language governing permissions and limitations | -| under the License. | -|-----------------------------------------------------------------------------| -| Dependencies: datepicker.css Date picker style declarations | -|-----------------------------------------------------------------------------| -| 2002-02-10 | Changed _update method to only update the text nodes instead | -| | rewriting the entire table. Also added support for mouse wheel | -| | in IE6. | -| 2002-01-14 | Cleaned up for 1.0 public version | -| 2002-01-15 | Replace all innerHTML calls with DOM1 methods | -| 2002-01-18 | Minor IE6 bug that occured when dragging the mouse | -| 2002-01-19 | Added a popup that is shown when the user clicks on the month. | -| | This allows navigation to 6 adjacent months. | -| 2002-04-10 | Fixed a bug that occured in the popup when a date was selected | -| | that caused surroundung months to "overflow" | -| | This had the effect that one could get two October months | -| | listed. | -| 2002-09-06 | I had missed one place were window was used instead of | -| | doc.parentWindow | -| 2003-08-28 | Added support for ensurin no date overflow when changing | -| | months. | -| 2004-01-10 | Adding type on the buttons to ensure they are not submit | -| | buttons. Minor CSS change for CSS2 | -| 2006-05-28 | Changed license to Apache Software License 2.0. | -| 2011-07-27 | Separated "selected date" and "calendar date" concepts. | -| | Selected date is the date specifically selected by the user to | -| | put into the form field. Calendar date reflects the currently | -| | displayed month. These are often, but not always, the same | -| | value. Separating them simplifies a lot of logic and resolves | -| | TAP5-1409. Also somewhat smarter for whether to trigger | -| | onselect when clicking "today" (and/or "none") | -| 2012-11-11 | Minor changes to integrate into a page with Twitter Bootstrap, | -| | and to support localizing the Today/None buttons. | -| 2013-08-29 | More changes to adapt to Bootstrap 3 style | -|-----------------------------------------------------------------------------| -| Created 2001-10-?? | All changes are in the log above. | Updated 2006-05-28 | -\----------------------------------------------------------------------------*/ - -// The DatePicker constructor -// oDate : Date Optional argument representing the date to select -// Note: some minor modifications for Tapestry, to work well as a popup. -function DatePicker(oDate) -{ - // check arguments - if (arguments.length == 0) - { - this._selectedDate = null; - this._calendarDate = new Date; - this._selectedInited = false; - } - else - { - this._selectedDate = oDate; - if (!oDate) - { - this._calendarDate = new Date; - } else - { - this._calendarDate = new Date(oDate); - } - this._selectedInited = true; - - } - - this._matrix = [[],[],[],[],[],[],[]]; - this._showNone = true; - this._showToday = true; - this._firstWeekDay = 0; // start week with monday according to standards - this._redWeekDay = 6; // sunday is the default red day. -} - -// two static fields describing the name of the months abd days -DatePicker.months = [ - "January", "February", "March", "April", - "May", "June", "July", "August", - "September", "October", "November", "December"]; -DatePicker.days = ["m", "t", "w", "t", "f", "s", "s"]; - -// Allow these to be localized -DatePicker.TODAY = "Today" -DatePicker.NONE = "None" - - -// Function invoked whenever the selected date changes, whether by -// navigation or when the user selects a date. -DatePicker.prototype.onchange = function () -{ -}; - -// onselect is more specified than onchange, and is triggered only when the user makes a specific selection -// using the calendar (rather than navigating to a new month). For Tapestry, -// this will dismiss the popup. -DatePicker.prototype.onselect = function() -{ -} - - -// create the nodes inside the date picker -DatePicker.prototype.create = function (doc) -{ - if (doc == null) doc = document; - - this._document = doc; - - // create elements - this._el = doc.createElement("div"); - this._el.className = "datePicker"; - - // header - var div = doc.createElement("div"); - div.className = "header"; - this._el.appendChild(div); - - var headerTable = doc.createElement("table"); - headerTable.className = "headerTable"; - headerTable.cellSpacing = 0; - div.appendChild(headerTable); - - var tBody = doc.createElement("tbody"); - headerTable.appendChild(tBody); - - var tr = doc.createElement("tr"); - tBody.appendChild(tr); - - var td = doc.createElement("td"); - this._previousMonth = doc.createElement("button"); - this._previousMonth.className = "btn btn-default btn-xs previousButton"; - this._previousMonth.setAttribute("type", "button"); - var icon = doc.createElement("span"); - icon.className = "glyphicon glyphicon-chevron-left"; - this._previousMonth.appendChild(icon); - td.appendChild(this._previousMonth); - tr.appendChild(td); - - td = doc.createElement("td"); - td.className = "labelContainer"; - tr.appendChild(td); - - this._topLabel = doc.createElement("a"); - this._topLabel.className = "topLabel"; - this._topLabel.href = "#"; - this._topLabel.appendChild(doc.createTextNode(String.fromCharCode(160))); - td.appendChild(this._topLabel); - - this._labelPopup = doc.createElement("div"); - this._labelPopup.className = "labelPopup"; - // no insertion - - td = doc.createElement("td"); - this._nextMonth = doc.createElement("button"); - this._nextMonth.className = "btn btn-default btn-xs nextButton"; - this._nextMonth.setAttribute("type", "button"); - icon = doc.createElement("span"); - icon.className = "glyphicon glyphicon-chevron-right"; - this._nextMonth.appendChild(icon); - - td.appendChild(this._nextMonth); - tr.appendChild(td); - - // grid - div = doc.createElement("div"); - div.className = "grid"; - this._el.appendChild(div); - this._table = div; - - // footer - div = doc.createElement("div"); - div.className = "footer"; - this._el.appendChild(div); - - var footerTable = doc.createElement("table"); - footerTable.className = "footerTable"; - footerTable.cellSpacing = 0; - div.appendChild(footerTable); - - tBody = doc.createElement("tbody"); - footerTable.appendChild(tBody); - - tr = doc.createElement("tr"); - tBody.appendChild(tr); - - td = doc.createElement("td"); - this._todayButton = doc.createElement("button"); - this._todayButton.className = "btn btn-default btn-xs"; - this._todayButton.setAttribute("type", "button"); - this._todayButton.appendChild(doc.createTextNode(DatePicker.TODAY)); - td.appendChild(this._todayButton); - tr.appendChild(td); - - td = doc.createElement("td"); - td.className = "filler"; - td.appendChild(doc.createTextNode(String.fromCharCode(160))); - tr.appendChild(td); - - td = doc.createElement("td"); - this._noneButton = doc.createElement("button"); - this._noneButton.className = "btn btn-default btn-xs"; - this._noneButton.setAttribute("type", "button"); - this._noneButton.appendChild(doc.createTextNode(DatePicker.NONE)); - td.appendChild(this._noneButton); - tr.appendChild(td); - - - this._createTable(doc); - - this._updateTable(); - this._setTopLabel(); - - if (!this._showNone) - this._noneButton.style.visibility = "hidden"; - if (!this._showToday) - this._todayButton.style.visibility = "hidden"; - - // IE55+ extension - this._previousMonth.hideFocus = true; - this._nextMonth.hideFocus = true; - this._todayButton.hideFocus = true; - this._noneButton.hideFocus = true; - // end IE55+ extension - - // hook up events - var dp = this; - // buttons - this._previousMonth.onclick = function () - { - dp.goToPreviousMonth(); - }; - this._nextMonth.onclick = function () - { - dp.goToNextMonth(); - }; - this._todayButton.onclick = function () - { - dp.goToToday(); - }; - this._noneButton.onclick = function () - { - //this should always clear the date and trigger onselected... - dp.setDate(null, true); - }; - - this._el.onselectstart = function () - { - return false; - }; - - this._table.onclick = function (e) - { - // find event - if (e == null) e = doc.parentWindow.event; - - // find td - var el = e.target != null ? e.target : e.srcElement; - 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(dp._calendarDate); - var n = Number(el.firstChild.data); - if (isNaN(n) || n <= 0 || n == null) - return; - - d.setDate(n); - dp.setDate(d); - }; - - // show popup - this._topLabel.onclick = function (e) - { - dp._showLabelPopup(); - return false; - }; - - this._el.onkeydown = function (e) - { - if (e == null) e = doc.parentWindow.event; - var kc = e.keyCode != null ? e.keyCode : e.charCode; - - if (kc < 37 || kc > 40) return true; - - var d = new Date(dp._calendarDate).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.setCalendarDate(new Date(d)); - return false; - } - - // ie6 extension - this._el.onmousewheel = function (e) - { - if (e == null) e = doc.parentWindow.event; - var n = - e.wheelDelta / 120; - var d = new Date(dp._calendarDate); - var m = d.getMonth() + n; - d.setMonth(m); - - - dp.setCalendarDate(d); - - return false; - } - - doc.onclick = function (e) { - var targ; - - // find event - if (e == null) e = doc.parentWindow.event; - - if (e.target) targ = e.target; - else if (e.srcElement) targ = e.srcElement; - // find classname 'datePicker' as parent - var insideDatePicker = null; - var parent = targ.parentNode; - while (parent != null) { - if (parent.className == 'datePicker' || parent.className == 'labelPopup') { - insideDatePicker = parent; - break; - } - parent = parent.parentNode; - } - } - return this._el; -}; - -DatePicker.prototype.setCalendarDate = function(oDate) -{ - if (oDate != null) - { - //note that calendarDate should never be null! - this._calendarDate = oDate; - } - this._hideLabelPopup(); - this._setTopLabel(); - this._updateTable(); -} - -DatePicker.prototype.setDate = function (oDate, forceOnSelect) -{ - - // if null then set None - if (oDate == null) - { - //if _selectedDate isn't null, then this is an actual change... - //but if it /is/ null, we have to see if we were inited or not. If we weren't inited, then we're - //setting this to null now, and we shouldn't fire a select... - //but the problem occurs on subsequent... hm... - if (this._selectedDate != null) - { - this._selectedDate = null; - if (typeof this.onchange == "function") - this.onchange(); - this.onselect(); - } else if (forceOnSelect) - this.onselect(); - //note: setDate must inherently set the calendar date - this._selectedInited=true; - this.setCalendarDate(null); - - return; - } - - // if string or number create a Date object - if (typeof oDate == "string" || typeof oDate == "number") - { - oDate = new Date(oDate); - } - - // do not update if not really changed - if (this._selectedDate == null || !this._datesAreSame(this._selectedDate, oDate)) - { - this._selectedDate = new Date(oDate); - - if (typeof this.onchange == "function") - this.onchange(); - - //so if _selectedInited is false, then the value is different only because we set the value programmatically, post-initialization. - //that handles the creation + set event. Subsequent reveals will set it to whatever _selectedDate already was, so it's handled. - if (this._selectedInited) - this.onselect(); - else - this._selectedInited=true; - } else if (forceOnSelect) - this.onselect(); - //note: setDate must inherently set the calendar date - this.setCalendarDate(oDate); - -} - - -DatePicker.prototype.getDate = function () -{ - if (!this._selectedDate) return null; - return new Date(this._selectedDate); // create a new instance -} - -// creates the table elements and inserts them into the date picker -DatePicker.prototype._createTable = function (doc) -{ - var str, i; - var rows = 6; - var cols = 7; - var currentWeek = 0; - - var table = doc.createElement("table"); - table.className = "gridTable"; - table.cellSpacing = 0; - - var tBody = doc.createElement("tbody"); - table.appendChild(tBody); - - // days row - var tr = doc.createElement("tr"); - tr.className = "daysRow"; - - var td, tn; - var nbsp = String.fromCharCode(160); - for (i = 0; i < cols; i++) - { - td = doc.createElement("td"); - td.appendChild(doc.createTextNode(nbsp)); - tr.appendChild(td); - } - tBody.appendChild(tr); - - // upper line - tr = doc.createElement("tr"); - td = doc.createElement("td"); - td.className = "upperLine"; - td.colSpan = 7; - tr.appendChild(td); - tBody.appendChild(tr); - - // rest - for (i = 0; i < rows; i++) - { - tr = doc.createElement("tr"); - for (var j = 0; j < cols; j++) - { - td = doc.createElement("td"); - td.appendChild(doc.createTextNode(nbsp)); - tr.appendChild(td); - } - tBody.appendChild(tr); - } - str += ""; - - if (this._table != null) - this._table.appendChild(table) -}; -// this method updates all the text nodes inside the table as well -// as all the classNames on the tds -DatePicker.prototype._updateTable = function () -{ - // if no element no need to continue - if (this._table == null) return; - - var i; - var str = ""; - var rows = 6; - var cols = 7; - var currentWeek = 0; - - var cells = new Array(rows); - this._matrix = new Array(rows) - for (i = 0; i < rows; i++) - { - cells[i] = new Array(cols); - this._matrix[i] = new Array(cols); - } - - // Set the tmpDate to this month - var tmpDate = new Date(this._calendarDate.getFullYear(), - this._calendarDate.getMonth(), 1); - var today = new Date(); - // go thorugh all days this month and store the text - // and the class name in the cells matrix - for (i = 1; i < 32; i++) - { - tmpDate.setDate(i); - // convert to ISO, Monday is 0 and 6 is Sunday - var weekDay = ( tmpDate.getDay() + 6 ) % 7; - var colIndex = ( weekDay - this._firstWeekDay + 7 ) % 7; - if (tmpDate.getMonth() == this._calendarDate.getMonth()) - { - - var isToday = this._datesAreSame(tmpDate, today); - - cells[currentWeek][colIndex] = { text: "", className: "" }; - - if (this._datesAreSame(this._selectedDate, tmpDate)) - cells[currentWeek][colIndex].className += "selected "; - if (isToday) - cells[currentWeek][colIndex].className += "today "; - if (( tmpDate.getDay() + 6 ) % 7 == this._redWeekDay) // ISO - cells[currentWeek][colIndex].className += "red"; - - cells[currentWeek][colIndex].text = - this._matrix[currentWeek][colIndex] = tmpDate.getDate(); - - if (colIndex == 6) - currentWeek++; - } - } - - // fix day letter order if not standard - var weekDays = DatePicker.days; - if (this._firstWeekDay != 0) - { - weekDays = new Array(7); - for (i = 0; i < 7; i++) - weekDays[i] = DatePicker.days[ (i + this._firstWeekDay) % 7]; - } - - // update text in days row - var tds = this._table.firstChild.tBodies[0].rows[0].cells; - for (i = 0; i < cols; i++) - tds[i].firstChild.data = weekDays[i]; - - // update the text nodes and class names - var trs = this._table.firstChild.tBodies[0].rows; - var tmpCell; - var nbsp = String.fromCharCode(160); - for (var y = 0; y < rows; y++) - { - for (var x = 0; x < cols; x++) - { - tmpCell = trs[y + 2].cells[x]; - if (typeof cells[y][x] != "undefined") - { - tmpCell.className = cells[y][x].className; - tmpCell.firstChild.data = cells[y][x].text; - } - else - { - tmpCell.className = ""; - tmpCell.firstChild.data = nbsp; - } - } - } -} - -// sets the label showing the year and selected month -DatePicker.prototype._setTopLabel = function () -{ - var str = this._calendarDate.getFullYear() + " " + DatePicker.months[ this._calendarDate.getMonth() ]; - if (this._topLabel != null) - this._topLabel.lastChild.data = str; -} - -DatePicker.prototype.goToNextMonth = function () -{ - var d = new Date(this._calendarDate); - d.setDate(Math.min(d.getDate(), DatePicker.getDaysPerMonth(d.getMonth() + 1, - d.getFullYear()))); // no need to catch dec -> jan for the year - d.setMonth(d.getMonth() + 1); - this.setCalendarDate(d); -} - -DatePicker.prototype.goToPreviousMonth = function () -{ - var d = new Date(this._calendarDate); - d.setDate(Math.min(d.getDate(), DatePicker.getDaysPerMonth(d.getMonth() - 1, - d.getFullYear()))); // no need to catch jan -> dec for the year - d.setMonth(d.getMonth() - 1); - this.setCalendarDate(d); -} - -DatePicker.prototype.goToToday = function () -{ - //note: small tweak here so that clicking the "Today" button will properly update the selected date and trigger selected - //but note that we want this behavior iff "today" is already selected and visible. - //For instance: If you're looking at some date months away from today and want to jump back to today AND today is the selectedDate - //then we don't want that to close the calendar. - var today = new Date(); - var forceOnSelect=false; - if (this._selectedDate == null || (this._datesAreSame(today, this._selectedDate) && this._calendarDate.getMonth() == today.getMonth() && this._calendarDate.getFullYear() == today.getFullYear())) { - //then go ahead and force the selection... - forceOnSelect=true; - } - this.setDate(new Date(), forceOnSelect);//note that setDate calls setCalendarDate... -} - -DatePicker.prototype.setShowToday = function (bShowToday) -{ - if (typeof bShowToday == "string") - bShowToday = !/false|0|no/i.test(bShowToday); - - if (this._todayButton != null) - this._todayButton.style.visibility = bShowToday ? "visible" : "hidden"; - this._showToday = bShowToday; -} - -DatePicker.prototype.getShowToday = function () -{ - return this._showToday; -} - -DatePicker.prototype.setShowNone = function (bShowNone) -{ - if (typeof bShowNone == "string") - bShowNone = !/false|0|no/i.test(bShowNone); - - if (this._noneButton != null) - this._noneButton.style.visibility = bShowNone ? "visible" : "hidden"; - this._showNone = bShowNone; -} - -DatePicker.prototype.getShowNone = function () -{ - return this._showNone; -} - -// 0 is monday and 6 is sunday as in the ISO standard -DatePicker.prototype.setFirstWeekDay = function (nFirstWeekDay) -{ - if (this._firstWeekDay != nFirstWeekDay) - { - this._firstWeekDay = nFirstWeekDay; - this._updateTable(); - } -} - -DatePicker.prototype.getFirstWeekDay = function () -{ - return this._firstWeekDay; -} - -// 0 is monday and 6 is sunday as in the ISO standard -DatePicker.prototype.setRedWeekDay = function (nRedWeekDay) -{ - if (this._redWeekDay != nRedWeekDay) - { - this._redWeekDay = nRedWeekDay; - this._updateTable(); - } -} - -DatePicker.prototype.getRedWeekDay = function () -{ - return this._redWeekDay; -} - - -DatePicker.prototype._showLabelPopup = function () -{ - - var dateContext = function (dp, d) - { - return function (e) - { - dp._hideLabelPopup(); - dp.setCalendarDate(d); - return false; - }; - }; - - var dp = this; - - // clear all old elements in the popup - while (this._labelPopup.hasChildNodes()) - this._labelPopup.removeChild(this._labelPopup.firstChild); - - var a, tmp, tmp2; - for (var i = -3; i < 4; i++) - { - tmp = new Date(this._calendarDate); - tmp2 = new Date(this._calendarDate); // need another tmp to catch year change when checking leap - tmp2.setDate(1); - tmp2.setMonth(tmp2.getMonth() + i); - tmp.setDate(Math.min(tmp.getDate(), DatePicker.getDaysPerMonth(tmp.getMonth() + i, - tmp2.getFullYear()))); - tmp.setMonth(tmp.getMonth() + i); - - a = this._document.createElement("a"); - a.href = "javascript:void 0;"; - a.onclick = dateContext(dp, tmp); - a.appendChild(this._document.createTextNode(tmp.getFullYear() + " " + - DatePicker.months[ tmp.getMonth() ])); - if (i == 0) - a.className = "selected"; - this._labelPopup.appendChild(a); - } - - this._topLabel.parentNode.insertBefore(this._labelPopup, this._topLabel.parentNode.firstChild); -}; - -DatePicker.prototype._hideLabelPopup = function () -{ - if (this._labelPopup.parentNode) - this._labelPopup.parentNode.removeChild(this._labelPopup); -}; - -DatePicker.prototype._datesAreSame = function(d1,d2) -{ - if (d1 == null && d2 == null) - return true; - else if (d1 == null) - return false; - else if (d2 == null) - return false; - return d1.getDate() == d2.getDate() && d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear(); -} - -DatePicker._daysPerMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; -DatePicker.getDaysPerMonth = function (nMonth, nYear) -{ - nMonth = (nMonth + 12) % 12; - var res = DatePicker._daysPerMonth[nMonth]; - if (nMonth == 1) - { - res += nYear % 4 == 0 && !(nYear % 400 == 0) ? 1 : 0; - } - return res; -}; http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70d4efbc/tapestry-core/src/main/resources/META-INF/modules/t5/core/datepicker.js ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/resources/META-INF/modules/t5/core/datepicker.js b/tapestry-core/src/main/resources/META-INF/modules/t5/core/datepicker.js new file mode 100644 index 0000000..f76d1c8 --- /dev/null +++ b/tapestry-core/src/main/resources/META-INF/modules/t5/core/datepicker.js @@ -0,0 +1,766 @@ +/*----------------------------------------------------------------------------\ +| Date Picker 1.06 | +|-----------------------------------------------------------------------------| +| Created by Erik Arvidsson | +| (http://webfx.eae.net/contact.html#erik) | +| For WebFX (http://webfx.eae.net/) | +|-----------------------------------------------------------------------------| +| A DOM based Date Picker | +|-----------------------------------------------------------------------------| +| Copyright (c) 1999, 2002, 2002, 2003, 2004, 2006 Erik Arvidsson | +|-----------------------------------------------------------------------------| +| Licensed under the Apache License, Version 2.0 (the "License"); you may not | +| use this file except in compliance with the License. You may obtain a copy | +| of the License at http://www.apache.org/licenses/LICENSE-2.0 | +| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | +| WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | +| License for the specific language governing permissions and limitations | +| under the License. | +|-----------------------------------------------------------------------------| +| Dependencies: datepicker.css Date picker style declarations | +|-----------------------------------------------------------------------------| +| 2002-02-10 | Changed _update method to only update the text nodes instead | +| | rewriting the entire table. Also added support for mouse wheel | +| | in IE6. | +| 2002-01-14 | Cleaned up for 1.0 public version | +| 2002-01-15 | Replace all innerHTML calls with DOM1 methods | +| 2002-01-18 | Minor IE6 bug that occured when dragging the mouse | +| 2002-01-19 | Added a popup that is shown when the user clicks on the month. | +| | This allows navigation to 6 adjacent months. | +| 2002-04-10 | Fixed a bug that occured in the popup when a date was selected | +| | that caused surroundung months to "overflow" | +| | This had the effect that one could get two October months | +| | listed. | +| 2002-09-06 | I had missed one place were window was used instead of | +| | doc.parentWindow | +| 2003-08-28 | Added support for ensurin no date overflow when changing | +| | months. | +| 2004-01-10 | Adding type on the buttons to ensure they are not submit | +| | buttons. Minor CSS change for CSS2 | +| 2006-05-28 | Changed license to Apache Software License 2.0. | +| 2011-07-27 | Separated "selected date" and "calendar date" concepts. | +| | Selected date is the date specifically selected by the user to | +| | put into the form field. Calendar date reflects the currently | +| | displayed month. These are often, but not always, the same | +| | value. Separating them simplifies a lot of logic and resolves | +| | TAP5-1409. Also somewhat smarter for whether to trigger | +| | onselect when clicking "today" (and/or "none") | +| 2012-11-11 | Minor changes to integrate into a page with Twitter Bootstrap, | +| | and to support localizing the Today/None buttons. | +| 2013-08-29 | More changes to adapt to Bootstrap 3 style | +| 2014-04-27 | Wrap the datepicker script into an AMD module | +|-----------------------------------------------------------------------------| +| Created 2001-10-?? | All changes are in the log above. | Updated 2006-05-28 | +\----------------------------------------------------------------------------*/ + +define([], function(){ + //The DatePicker constructor + //oDate : Date Optional argument representing the date to select + //Note: some minor modifications for Tapestry, to work well as a popup. + function DatePicker(oDate) + { + // check arguments + if (arguments.length == 0) + { + this._selectedDate = null; + this._calendarDate = new Date; + this._selectedInited = false; + } + else + { + this._selectedDate = oDate; + if (!oDate) + { + this._calendarDate = new Date; + } else + { + this._calendarDate = new Date(oDate); + } + this._selectedInited = true; + + } + + this._matrix = [[],[],[],[],[],[],[]]; + this._showNone = true; + this._showToday = true; + this._firstWeekDay = 0; // start week with monday according to standards + this._redWeekDay = 6; // sunday is the default red day. + // the names of the months and days + this._months = [ + "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December"]; + this._days = ["m", "t", "w", "t", "f", "s", "s"]; + + // Allow these to be localized + this._todayLabel = "Today"; + this._noneLabel = "None"; + + } + + // Function invoked whenever the selected date changes, whether by + // navigation or when the user selects a date. + DatePicker.prototype.onchange = function () + { + }; + + // onselect is more specified than onchange, and is triggered only when the user makes a specific selection + // using the calendar (rather than navigating to a new month). For Tapestry, + // this will dismiss the popup. + DatePicker.prototype.onselect = function() + { + } + + + // create the nodes inside the date picker + DatePicker.prototype.create = function (doc) + { + if (doc == null) doc = document; + + this._document = doc; + + // create elements + this._el = doc.createElement("div"); + this._el.className = "datePicker"; + + // header + var div = doc.createElement("div"); + div.className = "header"; + this._el.appendChild(div); + + var headerTable = doc.createElement("table"); + headerTable.className = "headerTable"; + headerTable.cellSpacing = 0; + div.appendChild(headerTable); + + var tBody = doc.createElement("tbody"); + headerTable.appendChild(tBody); + + var tr = doc.createElement("tr"); + tBody.appendChild(tr); + + var td = doc.createElement("td"); + this._previousMonth = doc.createElement("button"); + this._previousMonth.className = "btn btn-default btn-xs previousButton"; + this._previousMonth.setAttribute("type", "button"); + var icon = doc.createElement("span"); + icon.className = "glyphicon glyphicon-chevron-left"; + this._previousMonth.appendChild(icon); + td.appendChild(this._previousMonth); + tr.appendChild(td); + + td = doc.createElement("td"); + td.className = "labelContainer"; + tr.appendChild(td); + + this._topLabel = doc.createElement("a"); + this._topLabel.className = "topLabel"; + this._topLabel.href = "#"; + this._topLabel.appendChild(doc.createTextNode(String.fromCharCode(160))); + td.appendChild(this._topLabel); + + this._labelPopup = doc.createElement("div"); + this._labelPopup.className = "labelPopup"; + // no insertion + + td = doc.createElement("td"); + this._nextMonth = doc.createElement("button"); + this._nextMonth.className = "btn btn-default btn-xs nextButton"; + this._nextMonth.setAttribute("type", "button"); + icon = doc.createElement("span"); + icon.className = "glyphicon glyphicon-chevron-right"; + this._nextMonth.appendChild(icon); + + td.appendChild(this._nextMonth); + tr.appendChild(td); + + // grid + div = doc.createElement("div"); + div.className = "grid"; + this._el.appendChild(div); + this._table = div; + + // footer + div = doc.createElement("div"); + div.className = "footer"; + this._el.appendChild(div); + + var footerTable = doc.createElement("table"); + footerTable.className = "footerTable"; + footerTable.cellSpacing = 0; + div.appendChild(footerTable); + + tBody = doc.createElement("tbody"); + footerTable.appendChild(tBody); + + tr = doc.createElement("tr"); + tBody.appendChild(tr); + + td = doc.createElement("td"); + this._todayButton = doc.createElement("button"); + this._todayButton.className = "btn btn-default btn-xs"; + this._todayButton.setAttribute("type", "button"); + this._todayButton.appendChild(doc.createTextNode(this._todayLabel)); + td.appendChild(this._todayButton); + tr.appendChild(td); + + td = doc.createElement("td"); + td.className = "filler"; + td.appendChild(doc.createTextNode(String.fromCharCode(160))); + tr.appendChild(td); + + td = doc.createElement("td"); + this._noneButton = doc.createElement("button"); + this._noneButton.className = "btn btn-default btn-xs"; + this._noneButton.setAttribute("type", "button"); + this._noneButton.appendChild(doc.createTextNode(this._noneLabel)); + td.appendChild(this._noneButton); + tr.appendChild(td); + + + this._createTable(doc); + + this._updateTable(); + this._setTopLabel(); + + if (!this._showNone) + this._noneButton.style.visibility = "hidden"; + if (!this._showToday) + this._todayButton.style.visibility = "hidden"; + + // IE55+ extension + this._previousMonth.hideFocus = true; + this._nextMonth.hideFocus = true; + this._todayButton.hideFocus = true; + this._noneButton.hideFocus = true; + // end IE55+ extension + + // hook up events + var dp = this; + // buttons + this._previousMonth.onclick = function () + { + dp.goToPreviousMonth(); + }; + this._nextMonth.onclick = function () + { + dp.goToNextMonth(); + }; + this._todayButton.onclick = function () + { + dp.goToToday(); + }; + this._noneButton.onclick = function () + { + //this should always clear the date and trigger onselected... + dp.setDate(null, true); + }; + + this._el.onselectstart = function () + { + return false; + }; + + this._table.onclick = function (e) + { + // find event + if (e == null) e = doc.parentWindow.event; + + // find td + var el = e.target != null ? e.target : e.srcElement; + 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(dp._calendarDate); + var n = Number(el.firstChild.data); + if (isNaN(n) || n <= 0 || n == null) + return; + + d.setDate(n); + dp.setDate(d); + }; + + // show popup + this._topLabel.onclick = function (e) + { + dp._showLabelPopup(); + return false; + }; + + this._el.onkeydown = function (e) + { + if (e == null) e = doc.parentWindow.event; + var kc = e.keyCode != null ? e.keyCode : e.charCode; + + if (kc < 37 || kc > 40) return true; + + var d = new Date(dp._calendarDate).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.setCalendarDate(new Date(d)); + return false; + } + + // ie6 extension + this._el.onmousewheel = function (e) + { + if (e == null) e = doc.parentWindow.event; + var n = - e.wheelDelta / 120; + var d = new Date(dp._calendarDate); + var m = d.getMonth() + n; + d.setMonth(m); + + + dp.setCalendarDate(d); + + return false; + } + + doc.onclick = function (e) { + var targ; + + // find event + if (e == null) e = doc.parentWindow.event; + + if (e.target) targ = e.target; + else if (e.srcElement) targ = e.srcElement; + // find classname 'datePicker' as parent + var insideDatePicker = null; + var parent = targ.parentNode; + while (parent != null) { + if (parent.className == 'datePicker' || parent.className == 'labelPopup') { + insideDatePicker = parent; + break; + } + parent = parent.parentNode; + } + } + return this._el; + }; + + DatePicker.prototype.setCalendarDate = function(oDate) + { + if (oDate != null) + { + //note that calendarDate should never be null! + this._calendarDate = oDate; + } + this._hideLabelPopup(); + this._setTopLabel(); + this._updateTable(); + } + + DatePicker.prototype.setDate = function (oDate, forceOnSelect) + { + + // if null then set None + if (oDate == null) + { + //if _selectedDate isn't null, then this is an actual change... + //but if it /is/ null, we have to see if we were inited or not. If we weren't inited, then we're + //setting this to null now, and we shouldn't fire a select... + //but the problem occurs on subsequent... hm... + if (this._selectedDate != null) + { + this._selectedDate = null; + if (typeof this.onchange == "function") + this.onchange(); + this.onselect(); + } else if (forceOnSelect) + this.onselect(); + //note: setDate must inherently set the calendar date + this._selectedInited=true; + this.setCalendarDate(null); + + return; + } + + // if string or number create a Date object + if (typeof oDate == "string" || typeof oDate == "number") + { + oDate = new Date(oDate); + } + + // do not update if not really changed + if (this._selectedDate == null || !this._datesAreSame(this._selectedDate, oDate)) + { + this._selectedDate = new Date(oDate); + + if (typeof this.onchange == "function") + this.onchange(); + + //so if _selectedInited is false, then the value is different only because we set the value programmatically, post-initialization. + //that handles the creation + set event. Subsequent reveals will set it to whatever _selectedDate already was, so it's handled. + if (this._selectedInited) + this.onselect(); + else + this._selectedInited=true; + } else if (forceOnSelect) + this.onselect(); + //note: setDate must inherently set the calendar date + this.setCalendarDate(oDate); + + } + + + DatePicker.prototype.getDate = function () + { + if (!this._selectedDate) return null; + return new Date(this._selectedDate); // create a new instance + } + + // creates the table elements and inserts them into the date picker + DatePicker.prototype._createTable = function (doc) + { + var str, i; + var rows = 6; + var cols = 7; + var currentWeek = 0; + + var table = doc.createElement("table"); + table.className = "gridTable"; + table.cellSpacing = 0; + + var tBody = doc.createElement("tbody"); + table.appendChild(tBody); + + // days row + var tr = doc.createElement("tr"); + tr.className = "daysRow"; + + var td, tn; + var nbsp = String.fromCharCode(160); + for (i = 0; i < cols; i++) + { + td = doc.createElement("td"); + td.appendChild(doc.createTextNode(nbsp)); + tr.appendChild(td); + } + tBody.appendChild(tr); + + // upper line + tr = doc.createElement("tr"); + td = doc.createElement("td"); + td.className = "upperLine"; + td.colSpan = 7; + tr.appendChild(td); + tBody.appendChild(tr); + + // rest + for (i = 0; i < rows; i++) + { + tr = doc.createElement("tr"); + for (var j = 0; j < cols; j++) + { + td = doc.createElement("td"); + td.appendChild(doc.createTextNode(nbsp)); + tr.appendChild(td); + } + tBody.appendChild(tr); + } + str += ""; + + if (this._table != null) + this._table.appendChild(table) + }; + // this method updates all the text nodes inside the table as well + // as all the classNames on the tds + DatePicker.prototype._updateTable = function () + { + // if no element no need to continue + if (this._table == null) return; + + var i; + var str = ""; + var rows = 6; + var cols = 7; + var currentWeek = 0; + + var cells = new Array(rows); + this._matrix = new Array(rows) + for (i = 0; i < rows; i++) + { + cells[i] = new Array(cols); + this._matrix[i] = new Array(cols); + } + + // Set the tmpDate to this month + var tmpDate = new Date(this._calendarDate.getFullYear(), + this._calendarDate.getMonth(), 1); + var today = new Date(); + // go thorugh all days this month and store the text + // and the class name in the cells matrix + for (i = 1; i < 32; i++) + { + tmpDate.setDate(i); + // convert to ISO, Monday is 0 and 6 is Sunday + var weekDay = ( tmpDate.getDay() + 6 ) % 7; + var colIndex = ( weekDay - this._firstWeekDay + 7 ) % 7; + if (tmpDate.getMonth() == this._calendarDate.getMonth()) + { + + var isToday = this._datesAreSame(tmpDate, today); + + cells[currentWeek][colIndex] = { text: "", className: "" }; + + if (this._datesAreSame(this._selectedDate, tmpDate)) + cells[currentWeek][colIndex].className += "selected "; + if (isToday) + cells[currentWeek][colIndex].className += "today "; + if (( tmpDate.getDay() + 6 ) % 7 == this._redWeekDay) // ISO + cells[currentWeek][colIndex].className += "red"; + + cells[currentWeek][colIndex].text = + this._matrix[currentWeek][colIndex] = tmpDate.getDate(); + + if (colIndex == 6) + currentWeek++; + } + } + + // fix day letter order if not standard + var weekDays = this._days; + if (this._firstWeekDay != 0) + { + weekDays = new Array(7); + for (i = 0; i < 7; i++) + weekDays[i] = this._days[ (i + this._firstWeekDay) % 7]; + } + + // update text in days row + var tds = this._table.firstChild.tBodies[0].rows[0].cells; + for (i = 0; i < cols; i++) + tds[i].firstChild.data = weekDays[i]; + + // update the text nodes and class names + var trs = this._table.firstChild.tBodies[0].rows; + var tmpCell; + var nbsp = String.fromCharCode(160); + for (var y = 0; y < rows; y++) + { + for (var x = 0; x < cols; x++) + { + tmpCell = trs[y + 2].cells[x]; + if (typeof cells[y][x] != "undefined") + { + tmpCell.className = cells[y][x].className; + tmpCell.firstChild.data = cells[y][x].text; + } + else + { + tmpCell.className = ""; + tmpCell.firstChild.data = nbsp; + } + } + } + } + + // sets the label showing the year and selected month + DatePicker.prototype._setTopLabel = function () + { + var str = this._calendarDate.getFullYear() + " " + this._months[ this._calendarDate.getMonth() ]; + if (this._topLabel != null) + this._topLabel.lastChild.data = str; + } + + DatePicker.prototype.goToNextMonth = function () + { + var d = new Date(this._calendarDate); + d.setDate(Math.min(d.getDate(), DatePicker.getDaysPerMonth(d.getMonth() + 1, + d.getFullYear()))); // no need to catch dec -> jan for the year + d.setMonth(d.getMonth() + 1); + this.setCalendarDate(d); + } + + DatePicker.prototype.goToPreviousMonth = function () + { + var d = new Date(this._calendarDate); + d.setDate(Math.min(d.getDate(), DatePicker.getDaysPerMonth(d.getMonth() - 1, + d.getFullYear()))); // no need to catch jan -> dec for the year + d.setMonth(d.getMonth() - 1); + this.setCalendarDate(d); + } + + DatePicker.prototype.goToToday = function () + { + //note: small tweak here so that clicking the "Today" button will properly update the selected date and trigger selected + //but note that we want this behavior iff "today" is already selected and visible. + //For instance: If you're looking at some date months away from today and want to jump back to today AND today is the selectedDate + //then we don't want that to close the calendar. + var today = new Date(); + var forceOnSelect=false; + if (this._selectedDate == null || (this._datesAreSame(today, this._selectedDate) && this._calendarDate.getMonth() == today.getMonth() && this._calendarDate.getFullYear() == today.getFullYear())) { + //then go ahead and force the selection... + forceOnSelect=true; + } + this.setDate(new Date(), forceOnSelect);//note that setDate calls setCalendarDate... + } + + DatePicker.prototype.setShowToday = function (bShowToday) + { + if (typeof bShowToday == "string") + bShowToday = !/false|0|no/i.test(bShowToday); + + if (this._todayButton != null) + this._todayButton.style.visibility = bShowToday ? "visible" : "hidden"; + this._showToday = bShowToday; + } + + DatePicker.prototype.getShowToday = function () + { + return this._showToday; + } + + DatePicker.prototype.setShowNone = function (bShowNone) + { + if (typeof bShowNone == "string") + bShowNone = !/false|0|no/i.test(bShowNone); + + if (this._noneButton != null) + this._noneButton.style.visibility = bShowNone ? "visible" : "hidden"; + this._showNone = bShowNone; + } + + DatePicker.prototype.getShowNone = function () + { + return this._showNone; + } + + // 0 is monday and 6 is sunday as in the ISO standard + DatePicker.prototype.setFirstWeekDay = function (nFirstWeekDay) + { + if (this._firstWeekDay != nFirstWeekDay) + { + this._firstWeekDay = nFirstWeekDay; + this._updateTable(); + } + } + + DatePicker.prototype.getFirstWeekDay = function () + { + return this._firstWeekDay; + } + + // 0 is monday and 6 is sunday as in the ISO standard + DatePicker.prototype.setRedWeekDay = function (nRedWeekDay) + { + if (this._redWeekDay != nRedWeekDay) + { + this._redWeekDay = nRedWeekDay; + this._updateTable(); + } + } + + DatePicker.prototype.getRedWeekDay = function () + { + return this._redWeekDay; + } + + + DatePicker.prototype.setLocalizations = function(monthNames, dayNames, todayLabel, noneLabel) + { + this._months = monthNames; + this._days = dayNames; + this._todayLabel = todayLabel; + this._noneLabel = noneLabel; + if (this._todayButton != null) + { + this._todayButton.innerHTML = todayLabel; + } + if (this._noneButton != null) + { + this._noneButton.innerHTML = noneLabel; + } + this._updateTable(); + } + + DatePicker.prototype._showLabelPopup = function () + { + + var dateContext = function (dp, d) + { + return function (e) + { + dp._hideLabelPopup(); + dp.setCalendarDate(d); + return false; + }; + }; + + var dp = this; + + // clear all old elements in the popup + while (this._labelPopup.hasChildNodes()) + this._labelPopup.removeChild(this._labelPopup.firstChild); + + var a, tmp, tmp2; + for (var i = -3; i < 4; i++) + { + tmp = new Date(this._calendarDate); + tmp2 = new Date(this._calendarDate); // need another tmp to catch year change when checking leap + tmp2.setDate(1); + tmp2.setMonth(tmp2.getMonth() + i); + tmp.setDate(Math.min(tmp.getDate(), DatePicker.getDaysPerMonth(tmp.getMonth() + i, + tmp2.getFullYear()))); + tmp.setMonth(tmp.getMonth() + i); + + a = this._document.createElement("a"); + a.href = "javascript:void 0;"; + a.onclick = dateContext(dp, tmp); + a.appendChild(this._document.createTextNode(tmp.getFullYear() + " " + + this._months[ tmp.getMonth() ])); + if (i == 0) + a.className = "selected"; + this._labelPopup.appendChild(a); + } + + this._topLabel.parentNode.insertBefore(this._labelPopup, this._topLabel.parentNode.firstChild); + }; + + DatePicker.prototype._hideLabelPopup = function () + { + if (this._labelPopup.parentNode) + this._labelPopup.parentNode.removeChild(this._labelPopup); + }; + + DatePicker.prototype._datesAreSame = function(d1,d2) + { + if (d1 == null && d2 == null) + return true; + else if (d1 == null) + return false; + else if (d2 == null) + return false; + return d1.getDate() == d2.getDate() && d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear(); + } + + DatePicker._daysPerMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; + DatePicker.getDaysPerMonth = function (nMonth, nYear) + { + nMonth = (nMonth + 12) % 12; + var res = DatePicker._daysPerMonth[nMonth]; + if (nMonth == 1) + { + res += nYear % 4 == 0 && !(nYear % 400 == 0) ? 1 : 0; + } + return res; + }; + return DatePicker; + +}); +