YAHOO.widget.Calendar_Core | Calendar_Core is the base class for the Calendar widget. |
Calendar_Core.js
Quick Links:
Class Summary |
Source Code
Class Summary [top]
Souce Code [top]
/** Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt **/ /** * @class * <p>Calendar_Core is the base class for the Calendar widget. In its most basic * implementation, it has the ability to render a calendar widget on the page * that can be manipulated to select a single date, move back and forth between * months and years.</p> * <p>To construct the placeholder for the calendar widget, the code is as * follows: * <xmp> * <div id="cal1Container"></div> * </xmp> * Note that the table can be replaced with any kind of element. * </p> * @constructor * @param {String} id The id of the table element that will represent the calendar widget * @param {String} containerId The id of the container element that will contain the calendar table * @param {String} monthyear The month/year string used to set the current calendar page * @param {String} selected A string of date values formatted using the date parser. The built-in default date format is MM/DD/YYYY. Ranges are defined using MM/DD/YYYY-MM/DD/YYYY. Month/day combinations are defined using MM/DD. Any combination of these can be combined by delimiting the string with commas. Example: "12/24/2005,12/25,1/18/2006-1/21/2006" */ YAHOO.widget.Calendar_Core = function(id, containerId, monthyear, selected) { if (arguments.length > 0) { this.init(id, containerId, monthyear, selected); } } /** * The path to be used for images loaded for the Calendar * @type String */ YAHOO.widget.Calendar_Core.IMG_ROOT = (window.location.href.toLowerCase().indexOf("https") == 0 ? "https://a248.e.akamai.net/sec.yimg.com/i/" : "http://us.i1.yimg.com/us.yimg.com/i/"); /** * Type constant used for renderers to represent an individual date (M/D/Y) * @final * @type String */ YAHOO.widget.Calendar_Core.DATE = "D"; /** * Type constant used for renderers to represent an individual date across any year (M/D) * @final * @type String */ YAHOO.widget.Calendar_Core.MONTH_DAY = "MD"; /** * Type constant used for renderers to represent a weekday * @final * @type String */ YAHOO.widget.Calendar_Core.WEEKDAY = "WD"; /** * Type constant used for renderers to represent a range of individual dates (M/D/Y-M/D/Y) * @final * @type String */ YAHOO.widget.Calendar_Core.RANGE = "R"; /** * Type constant used for renderers to represent a month across any year * @final * @type String */ YAHOO.widget.Calendar_Core.MONTH = "M"; /** * Constant that represents the total number of date cells that are displayed in a given month * including * @final * @type Integer */ YAHOO.widget.Calendar_Core.DISPLAY_DAYS = 42; /** * Constant used for halting the execution of the remainder of the render stack * @final * @type String */ YAHOO.widget.Calendar_Core.STOP_RENDER = "S"; YAHOO.widget.Calendar_Core.prototype = { /** * The configuration object used to set up the calendars various locale and style options. * @type Object */ Config : null, /** * The parent CalendarGroup, only to be set explicitly by the parent group * @type CalendarGroup */ parent : null, /** * The index of this item in the parent group * @type Integer */ index : -1, /** * The collection of calendar table cells * @type HTMLTableCellElement[] */ cells : null, /** * The collection of calendar week header cells * @type HTMLTableCellElement[] */ weekHeaderCells : null, /** * The collection of calendar week footer cells * @type HTMLTableCellElement[] */ weekFooterCells : null, /** * The collection of calendar cell dates that is parallel to the cells collection. The array contains dates field arrays in the format of [YYYY, M, D]. * @type Array[](Integer[]) */ cellDates : null, /** * The id that uniquely identifies this calendar. This id should match the id of the placeholder element on the page. * @type String */ id : null, /** * The DOM element reference that points to this calendar's container element. The calendar will be inserted into this element when the shell is rendered. * @type HTMLElement */ oDomContainer : null, /** * A Date object representing today's date. * @type Date */ today : null, /** * The list of render functions, along with required parameters, used to render cells. * @type Array[] */ renderStack : null, /** * A copy of the initial render functions created before rendering. * @type Array * @private */ _renderStack : null, /** * A Date object representing the month/year that the calendar is currently set to * @type Date */ pageDate : null, /** * A Date object representing the month/year that the calendar is initially set to * @type Date * @private */ _pageDate : null, /** * A Date object representing the minimum selectable date * @type Date */ minDate : null, /** * A Date object representing the maximum selectable date * @type Date */ maxDate : null, /** * The list of currently selected dates. The data format for this local collection is * an array of date field arrays, e.g: * [ * [2004,5,25], * [2004,5,26] * ] * @type Array[](Integer[]) */ selectedDates : null, /** * The private list of initially selected dates. * @type Array * @private */ _selectedDates : null, /** * A boolean indicating whether the shell of the calendar has already been rendered to the page * @type Boolean */ shellRendered : false, /** * The HTML table element that represents this calendar * @type HTMLTableElement */ table : null, /** * The HTML cell element that represents the main header cell TH used in the calendar table * @type HTMLTableCellElement */ headerCell : null }; /** * Initializes the calendar widget. This method must be called by all subclass constructors. * @param {String} id The id of the table element that will represent the calendar widget * @param {String} containerId The id of the container element that will contain the calendar table * @param {String} monthyear The month/year string used to set the current calendar page * @param {String} selected A string of date values formatted using the date parser. The built-in default date format is MM/DD/YYYY. Ranges are defined using MM/DD/YYYY-MM/DD/YYYY. Month/day combinations are defined using MM/DD. Any combination of these can be combined by delimiting the string with commas. Example: "12/24/2005,12/25,1/18/2006-1/21/2006" */ YAHOO.widget.Calendar_Core.prototype.init = function(id, containerId, monthyear, selected) { this.setupConfig(); this.id = id; this.cellDates = new Array(); this.cells = new Array(); this.renderStack = new Array(); this._renderStack = new Array(); this.oDomContainer = document.getElementById(containerId); this.today = new Date(); YAHOO.widget.DateMath.clearTime(this.today); var month; var year; if (monthyear) { var aMonthYear = monthyear.split(this.Locale.DATE_FIELD_DELIMITER); month = parseInt(aMonthYear[this.Locale.MY_MONTH_POSITION-1]); year = parseInt(aMonthYear[this.Locale.MY_YEAR_POSITION-1]); } else { month = this.today.getMonth()+1; year = this.today.getFullYear(); } this.pageDate = new Date(year, month-1, 1); this._pageDate = new Date(this.pageDate.getTime()); if (selected) { this.selectedDates = this._parseDates(selected); this._selectedDates = this.selectedDates.concat(); } else { this.selectedDates = new Array(); this._selectedDates = new Array(); } this.wireDefaultEvents(); this.wireCustomEvents(); }; /** * Wires the local DOM events for the Calendar, including cell selection, hover, and * default navigation that is used for moving back and forth between calendar pages. */ YAHOO.widget.Calendar_Core.prototype.wireDefaultEvents = function() { /** * The default event function that is attached to a date link within a calendar cell * when the calendar is rendered. * @param e The event * @param cal A reference to the calendar passed by the Event utility */ this.doSelectCell = function(e, cal) { var cell = this; var index = cell.index; var d = cal.cellDates[index]; var date = new Date(d[0],d[1]-1,d[2]); if (! cal.isDateOOM(date) && ! YAHOO.util.Dom.hasClass(cell, cal.Style.CSS_CELL_RESTRICTED) && ! YAHOO.util.Dom.hasClass(cell, cal.Style.CSS_CELL_OOB)) { if (cal.Options.MULTI_SELECT) { var link = cell.getElementsByTagName("A")[0]; link.blur(); var cellDate = cal.cellDates[index]; var cellDateIndex = cal._indexOfSelectedFieldArray(cellDate); if (cellDateIndex > -1) { cal.deselectCell(index); } else { cal.selectCell(index); } } else { var link = cell.getElementsByTagName("A")[0]; link.blur() cal.selectCell(index); } } } /** * The event that is executed when the user hovers over a cell * @param e The event * @param cal A reference to the calendar passed by the Event utility * @private */ this.doCellMouseOver = function(e, cal) { var cell = this; var index = cell.index; var d = cal.cellDates[index]; var date = new Date(d[0],d[1]-1,d[2]); if (! cal.isDateOOM(date) && ! YAHOO.util.Dom.hasClass(cell, cal.Style.CSS_CELL_RESTRICTED) && ! YAHOO.util.Dom.hasClass(cell, cal.Style.CSS_CELL_OOB)) { YAHOO.util.Dom.addClass(cell, cal.Style.CSS_CELL_HOVER); } } /** * The event that is executed when the user moves the mouse out of a cell * @param e The event * @param cal A reference to the calendar passed by the Event utility * @private */ this.doCellMouseOut = function(e, cal) { YAHOO.util.Dom.removeClass(this, cal.Style.CSS_CELL_HOVER); } /** * A wrapper event that executes the nextMonth method through a DOM event * @param e The event * @param cal A reference to the calendar passed by the Event utility * @private */ this.doNextMonth = function(e, cal) { cal.nextMonth(); } /** * A wrapper event that executes the previousMonth method through a DOM event * @param e The event * @param cal A reference to the calendar passed by the Event utility * @private */ this.doPreviousMonth = function(e, cal) { cal.previousMonth(); } } /** * This function can be extended by subclasses to attach additional DOM events to * the calendar. By default, this method is unimplemented. */ YAHOO.widget.Calendar_Core.prototype.wireCustomEvents = function() { } /** This method is called to initialize the widget configuration variables, including style, localization, and other display and behavioral options. <p>Config: Container for the CSS style configuration variables.</p> <p><strong>Config.Style</strong> - Defines the CSS classes used for different calendar elements</p> <blockquote> <div><em>CSS_CALENDAR</em> : Container table</div> <div><em>CSS_HEADER</em> : </div> <div><em>CSS_HEADER_TEXT</em> : Calendar header</div> <div><em>CSS_FOOTER</em> : Calendar footer</div> <div><em>CSS_CELL</em> : Calendar day cell</div> <div><em>CSS_CELL_OOM</em> : Calendar OOM (out of month) cell</div> <div><em>CSS_CELL_SELECTED</em> : Calendar selected cell</div> <div><em>CSS_CELL_RESTRICTED</em> : Calendar restricted cell</div> <div><em>CSS_CELL_TODAY</em> : Calendar cell for today's date</div> <div><em>CSS_ROW_HEADER</em> : The cell preceding a row (used for week number by default)</div> <div><em>CSS_ROW_FOOTER</em> : The cell following a row (not implemented by default)</div> <div><em>CSS_WEEKDAY_CELL</em> : The cells used for labeling weekdays</div> <div><em>CSS_WEEKDAY_ROW</em> : The row containing the weekday label cells</div> <div><em>CSS_CONTAINER</em> : The border style used for the default UED rendering</div> <div><em>CSS_2UPWRAPPER</em> : Special container class used to properly adjust the sizing and float</div> <div><em>CSS_NAV_LEFT</em> : Left navigation arrow</div> <div><em>CSS_NAV_RIGHT</em> : Right navigation arrow</div> <div><em>CSS_CELL_TOP</em> : Outlying cell along the top row</div> <div><em>CSS_CELL_LEFT</em> : Outlying cell along the left row</div> <div><em>CSS_CELL_RIGHT</em> : Outlying cell along the right row</div> <div><em>CSS_CELL_BOTTOM</em> : Outlying cell along the bottom row</div> <div><em>CSS_CELL_HOVER</em> : Cell hover style</div> <div><em>CSS_CELL_HIGHLIGHT1</em> : Highlight color 1 for styling cells</div> <div><em>CSS_CELL_HIGHLIGHT2</em> : Highlight color 2 for styling cells</div> <div><em>CSS_CELL_HIGHLIGHT3</em> : Highlight color 3 for styling cells</div> <div><em>CSS_CELL_HIGHLIGHT4</em> : Highlight color 4 for styling cells</div> </blockquote> <p><strong>Config.Locale</strong> - Defines the locale string arrays used for localization</p> <blockquote> <div><em>MONTHS_SHORT</em> : Array of 12 months in short format ("Jan", "Feb", etc.)</div> <div><em>MONTHS_LONG</em> : Array of 12 months in short format ("Jan", "Feb", etc.)</div> <div><em>WEEKDAYS_1CHAR</em> : Array of 7 days in 1-character format ("S", "M", etc.)</div> <div><em>WEEKDAYS_SHORT</em> : Array of 7 days in short format ("Su", "Mo", etc.)</div> <div><em>WEEKDAYS_MEDIUM</em> : Array of 7 days in medium format ("Sun", "Mon", etc.)</div> <div><em>WEEKDAYS_LONG</em> : Array of 7 days in long format ("Sunday", "Monday", etc.)</div> <div><em>DATE_DELIMITER</em> : The value used to delimit series of multiple dates (Default: ",")</div> <div><em>DATE_FIELD_DELIMITER</em> : The value used to delimit date fields (Default: "/")</div> <div><em>DATE_RANGE_DELIMITER</em> : The value used to delimit date fields (Default: "-")</div> <div><em>MY_MONTH_POSITION</em> : The value used to determine the position of the month in a month/year combo (e.g. 12/2005) (Default: 1)</div> <div><em>MY_YEAR_POSITION</em> : The value used to determine the position of the year in a month/year combo (e.g. 12/2005) (Default: 2)</div> <div><em>MD_MONTH_POSITION</em> : The value used to determine the position of the month in a month/day combo (e.g. 12/25) (Default: 1)</div> <div><em>MD_DAY_POSITION</em> : The value used to determine the position of the day in a month/day combo (e.g. 12/25) (Default: 2)</div> <div><em>MDY_MONTH_POSITION</em> : The value used to determine the position of the month in a month/day/year combo (e.g. 12/25/2005) (Default: 1)</div> <div><em>MDY_DAY_POSITION</em> : The value used to determine the position of the day in a month/day/year combo (e.g. 12/25/2005) (Default: 2)</div> <div><em>MDY_YEAR_POSITION</em> : The value used to determine the position of the year in a month/day/year combo (e.g. 12/25/2005) (Default: 3)</div> </blockquote> <p><strong>Config.Options</strong> - Defines other configurable calendar widget options</p> <blockquote> <div><em>SHOW_WEEKDAYS</em> : Boolean, determines whether to display the weekday headers (defaults to true)</div> <div><em>LOCALE_MONTHS</em> : Array, points to the desired Config.Locale array (defaults to Config.Locale.MONTHS_LONG)</div> <div><em>LOCALE_WEEKDAYS</em> : Array, points to the desired Config.Locale array (defaults to Config.Locale.WEEKDAYS_SHORT)</div> <div><em>START_WEEKDAY</em> : Integer, 0-6, representing the day that a week begins on</div> <div><em>SHOW_WEEK_HEADER</em> : Boolean, determines whether to display row headers</div> <div><em>SHOW_WEEK_FOOTER</em> : Boolean, determines whether to display row footers</div> <div><em>HIDE_BLANK_WEEKS</em> : Boolean, determines whether to hide extra weeks that are completely OOM</div> <div><em>NAV_ARROW_LEFT</em> : String, the image path used for the left navigation arrow</div> <div><em>NAV_ARROW_RIGHT</em> : String, the image path used for the right navigation arrow</div> </blockquote> */ YAHOO.widget.Calendar_Core.prototype.setupConfig = function() { /** * Container for the CSS style configuration variables. */ this.Config = new Object(); this.Config.Style = { // Style variables CSS_ROW_HEADER: "calrowhead", CSS_ROW_FOOTER: "calrowfoot", CSS_CELL : "calcell", CSS_CELL_SELECTED : "selected", CSS_CELL_RESTRICTED : "restricted", CSS_CELL_TODAY : "today", CSS_CELL_OOM : "oom", CSS_CELL_OOB : "previous", CSS_HEADER : "calheader", CSS_HEADER_TEXT : "calhead", CSS_WEEKDAY_CELL : "calweekdaycell", CSS_WEEKDAY_ROW : "calweekdayrow", CSS_FOOTER : "calfoot", CSS_CALENDAR : "yui-calendar", CSS_CONTAINER : "yui-calcontainer", CSS_2UPWRAPPER : "yui-cal2upwrapper", CSS_NAV_LEFT : "calnavleft", CSS_NAV_RIGHT : "calnavright", CSS_CELL_TOP : "calcelltop", CSS_CELL_LEFT : "calcellleft", CSS_CELL_RIGHT : "calcellright", CSS_CELL_BOTTOM : "calcellbottom", CSS_CELL_HOVER : "calcellhover", CSS_CELL_HIGHLIGHT1 : "highlight1", CSS_CELL_HIGHLIGHT2 : "highlight2", CSS_CELL_HIGHLIGHT3 : "highlight3", CSS_CELL_HIGHLIGHT4 : "highlight4" }; this.Style = this.Config.Style; this.Config.Locale = { // Locale definition MONTHS_SHORT : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], MONTHS_LONG : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], WEEKDAYS_1CHAR : ["S", "M", "T", "W", "T", "F", "S"], WEEKDAYS_SHORT : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], WEEKDAYS_MEDIUM : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], WEEKDAYS_LONG : ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], DATE_DELIMITER : ",", DATE_FIELD_DELIMITER : "/", DATE_RANGE_DELIMITER : "-", MY_MONTH_POSITION : 1, MY_YEAR_POSITION : 2, MD_MONTH_POSITION : 1, MD_DAY_POSITION : 2, MDY_MONTH_POSITION : 1, MDY_DAY_POSITION : 2, MDY_YEAR_POSITION : 3 }; this.Locale = this.Config.Locale; this.Config.Options = { // Configuration variables MULTI_SELECT : false, SHOW_WEEKDAYS : true, START_WEEKDAY : 0, SHOW_WEEK_HEADER : false, SHOW_WEEK_FOOTER : false, HIDE_BLANK_WEEKS : false, NAV_ARROW_LEFT : YAHOO.widget.Calendar_Core.IMG_ROOT + "us/tr/callt.gif", NAV_ARROW_RIGHT : YAHOO.widget.Calendar_Core.IMG_ROOT + "us/tr/calrt.gif" }; this.Options = this.Config.Options; this.customConfig(); if (! this.Options.LOCALE_MONTHS) { this.Options.LOCALE_MONTHS=this.Locale.MONTHS_LONG; } if (! this.Options.LOCALE_WEEKDAYS) { this.Options.LOCALE_WEEKDAYS=this.Locale.WEEKDAYS_SHORT; } // If true, reconfigure weekday arrays to place Mondays first if (this.Options.START_WEEKDAY > 0) { for (var w=0;w<this.Options.START_WEEKDAY;++w) { this.Locale.WEEKDAYS_SHORT.push(this.Locale.WEEKDAYS_SHORT.shift()); this.Locale.WEEKDAYS_MEDIUM.push(this.Locale.WEEKDAYS_MEDIUM.shift()); this.Locale.WEEKDAYS_LONG.push(this.Locale.WEEKDAYS_LONG.shift()); } } }; /** * This method is called when subclasses need to override configuration variables * or create new ones. Values can be explicitly set as follows: * <blockquote><code> * this.Config.Style.CSS_CELL = "newcalcell"; * this.Config.Locale.MONTHS_SHORT = ["Jan", "Fv", "Mars", "Avr", "Mai", "Juin", "Juil", "Aot", "Sept", "Oct", "Nov", "Dc"]; * </code></blockquote> */ YAHOO.widget.Calendar_Core.prototype.customConfig = function() { }; /** * Builds the date label that will be displayed in the calendar header or * footer, depending on configuration. * @return The formatted calendar month label * @type String */ YAHOO.widget.Calendar_Core.prototype.buildMonthLabel = function() { var text = this.Options.LOCALE_MONTHS[this.pageDate.getMonth()] + " " + this.pageDate.getFullYear(); return text; }; /** * Builds the date digit that will be displayed in calendar cells * @return The formatted day label * @type String */ YAHOO.widget.Calendar_Core.prototype.buildDayLabel = function(workingDate) { var day = workingDate.getDate(); return day; }; /** * Builds the calendar table shell that will be filled in with dates and formatting. * This method calls buildShellHeader, buildShellBody, and buildShellFooter (in that order) * to construct the pieces of the calendar table. The construction of the shell should * only happen one time when the calendar is initialized. */ YAHOO.widget.Calendar_Core.prototype.buildShell = function() { this.table = document.createElement("TABLE"); this.table.cellSpacing = 0; YAHOO.widget.Calendar_Core.setCssClasses(this.table, [this.Style.CSS_CALENDAR]); this.table.id = this.id; this.buildShellHeader(); this.buildShellBody(); this.buildShellFooter(); YAHOO.util.Event.addListener(window, "unload", this._unload, this); }; /** * Builds the calendar shell header by inserting a THEAD into the local calendar table. */ YAHOO.widget.Calendar_Core.prototype.buildShellHeader = function() { var head = document.createElement("THEAD"); var headRow = document.createElement("TR"); var headerCell = document.createElement("TH"); var colSpan = 7; if (this.Config.Options.SHOW_WEEK_HEADER) { this.weekHeaderCells = new Array(); colSpan += 1; } if (this.Config.Options.SHOW_WEEK_FOOTER) { this.weekFooterCells = new Array(); colSpan += 1; } headerCell.colSpan = colSpan; YAHOO.widget.Calendar_Core.setCssClasses(headerCell,[this.Style.CSS_HEADER_TEXT]); this.headerCell = headerCell; headRow.appendChild(headerCell); head.appendChild(headRow); // Append day labels, if needed if (this.Options.SHOW_WEEKDAYS) { var row = document.createElement("TR"); var fillerCell; YAHOO.widget.Calendar_Core.setCssClasses(row,[this.Style.CSS_WEEKDAY_ROW]); if (this.Config.Options.SHOW_WEEK_HEADER) { fillerCell = document.createElement("TH"); YAHOO.widget.Calendar_Core.setCssClasses(fillerCell,[this.Style.CSS_WEEKDAY_CELL]); row.appendChild(fillerCell); } for(var i=0;i<this.Options.LOCALE_WEEKDAYS.length;++i) { var cell = document.createElement("TH"); YAHOO.widget.Calendar_Core.setCssClasses(cell,[this.Style.CSS_WEEKDAY_CELL]); cell.innerHTML=this.Options.LOCALE_WEEKDAYS[i]; row.appendChild(cell); } if (this.Config.Options.SHOW_WEEK_FOOTER) { fillerCell = document.createElement("TH"); YAHOO.widget.Calendar_Core.setCssClasses(fillerCell,[this.Style.CSS_WEEKDAY_CELL]); row.appendChild(fillerCell); } head.appendChild(row); } this.table.appendChild(head); }; /** * Builds the calendar shell body (6 weeks by 7 days) */ YAHOO.widget.Calendar_Core.prototype.buildShellBody = function() { // This should only get executed once this.tbody = document.createElement("TBODY"); for (var r=0;r<6;++r) { var row = document.createElement("TR"); for (var c=0;c<this.headerCell.colSpan;++c) { var cell; if (this.Config.Options.SHOW_WEEK_HEADER && c===0) { // Row header cell = document.createElement("TH"); this.weekHeaderCells[this.weekHeaderCells.length] = cell; } else if (this.Config.Options.SHOW_WEEK_FOOTER && c==(this.headerCell.colSpan-1)){ // Row footer cell = document.createElement("TH"); this.weekFooterCells[this.weekFooterCells.length] = cell; } else { cell = document.createElement("TD"); this.cells[this.cells.length] = cell; YAHOO.widget.Calendar_Core.setCssClasses(cell, [this.Style.CSS_CELL]); YAHOO.util.Event.addListener(cell, "click", this.doSelectCell, this); YAHOO.util.Event.addListener(cell, "mouseover", this.doCellMouseOver, this); YAHOO.util.Event.addListener(cell, "mouseout", this.doCellMouseOut, this); } row.appendChild(cell); } this.tbody.appendChild(row); } this.table.appendChild(this.tbody); }; /** * Builds the calendar shell footer. In the default implementation, there is * no footer. */ YAHOO.widget.Calendar_Core.prototype.buildShellFooter = function() { }; /** * Outputs the calendar shell to the DOM, inserting it into the placeholder element. */ YAHOO.widget.Calendar_Core.prototype.renderShell = function() { this.oDomContainer.appendChild(this.table); this.shellRendered = true; }; /** * Renders the calendar after it has been configured. The render() method has a specific call chain that will execute * when the method is called: renderHeader, renderBody, renderFooter. * Refer to the documentation for those methods for information on * individual render tasks. */ YAHOO.widget.Calendar_Core.prototype.render = function() { if (! this.shellRendered) { this.buildShell(); this.renderShell(); } this.resetRenderers(); this.cellDates.length = 0; // Find starting day of the current month var workingDate = YAHOO.widget.DateMath.findMonthStart(this.pageDate); this.renderHeader(); this.renderBody(workingDate); this.renderFooter(); this.onRender(); }; /** * Appends the header contents into the widget header. */ YAHOO.widget.Calendar_Core.prototype.renderHeader = function() { this.headerCell.innerHTML = ""; var headerContainer = document.createElement("DIV"); headerContainer.className = this.Style.CSS_HEADER; headerContainer.appendChild(document.createTextNode(this.buildMonthLabel())); this.headerCell.appendChild(headerContainer); }; /** * Appends the calendar body. The default implementation calculates the number of * OOM (out of month) cells that need to be rendered at the start of the month, renders those, * and renders all the day cells using the built-in cell rendering methods. * * While iterating through all of the cells, the calendar checks for renderers in the * local render stack that match the date of the current cell, and then applies styles * as necessary. * * @param {Date} workingDate The current working Date object being used to generate the calendar */ YAHOO.widget.Calendar_Core.prototype.renderBody = function(workingDate) { this.preMonthDays = workingDate.getDay(); if (this.Options.START_WEEKDAY > 0) { this.preMonthDays -= this.Options.START_WEEKDAY; } if (this.preMonthDays < 0) { this.preMonthDays += 7; } this.monthDays = YAHOO.widget.DateMath.findMonthEnd(workingDate).getDate(); this.postMonthDays = YAHOO.widget.Calendar_Core.DISPLAY_DAYS-this.preMonthDays-this.monthDays; workingDate = YAHOO.widget.DateMath.subtract(workingDate, YAHOO.widget.DateMath.DAY, this.preMonthDays); var weekRowIndex = 0; for (var c=0;c<this.cells.length;++c) { var cellRenderers = new Array(); var cell = this.cells[c]; this.clearElement(cell); cell.index = c; cell.id = this.id + "_cell" + c; this.cellDates[this.cellDates.length]=[workingDate.getFullYear(),workingDate.getMonth()+1,workingDate.getDate()]; // Add this date to cellDates if (workingDate.getDay() == this.Options.START_WEEKDAY) { var rowHeaderCell = null; var rowFooterCell = null; if (this.Options.SHOW_WEEK_HEADER) { rowHeaderCell = this.weekHeaderCells[weekRowIndex]; this.clearElement(rowHeaderCell); } if (this.Options.SHOW_WEEK_FOOTER) { rowFooterCell = this.weekFooterCells[weekRowIndex]; this.clearElement(rowFooterCell); } if (this.Options.HIDE_BLANK_WEEKS && this.isDateOOM(workingDate) && ! YAHOO.widget.DateMath.isMonthOverlapWeek(workingDate)) { // The first day of the week is not in this month, and it's not an overlap week continue; } else { if (rowHeaderCell) { this.renderRowHeader(workingDate, rowHeaderCell); } if (rowFooterCell) { this.renderRowFooter(workingDate, rowFooterCell); } } } var renderer = null; if (workingDate.getFullYear() == this.today.getFullYear() && workingDate.getMonth() == this.today.getMonth() && workingDate.getDate() == this.today.getDate()) { cellRenderers[cellRenderers.length]=this.renderCellStyleToday; } if (this.isDateOOM(workingDate)) { cellRenderers[cellRenderers.length]=this.renderCellNotThisMonth; } else { for (var r=0;r<this.renderStack.length;++r) { var rArray = this.renderStack[r]; var type = rArray[0]; var month; var day; var year; switch (type) { case YAHOO.widget.Calendar_Core.DATE: month = rArray[1][1]; day = rArray[1][2]; year = rArray[1][0]; if (workingDate.getMonth()+1 == month && workingDate.getDate() == day && workingDate.getFullYear() == year) { renderer = rArray[2]; this.renderStack.splice(r,1); } break; case YAHOO.widget.Calendar_Core.MONTH_DAY: month = rArray[1][0]; day = rArray[1][1]; if (workingDate.getMonth()+1 == month && workingDate.getDate() == day) { renderer = rArray[2]; this.renderStack.splice(r,1); } break; case YAHOO.widget.Calendar_Core.RANGE: var date1 = rArray[1][0]; var date2 = rArray[1][1]; var d1month = date1[1]; var d1day = date1[2]; var d1year = date1[0]; var d1 = new Date(d1year, d1month-1, d1day); var d2month = date2[1]; var d2day = date2[2]; var d2year = date2[0]; var d2 = new Date(d2year, d2month-1, d2day); if (workingDate.getTime() >= d1.getTime() && workingDate.getTime() <= d2.getTime()) { renderer = rArray[2]; if (workingDate.getTime()==d2.getTime()) { this.renderStack.splice(r,1); } } break; case YAHOO.widget.Calendar_Core.WEEKDAY: var weekday = rArray[1][0]; if (workingDate.getDay()+1 == weekday) { renderer = rArray[2]; } break; case YAHOO.widget.Calendar_Core.MONTH: month = rArray[1][0]; if (workingDate.getMonth()+1 == month) { renderer = rArray[2]; } break; } if (renderer) { cellRenderers[cellRenderers.length]=renderer; } } } if (this._indexOfSelectedFieldArray([workingDate.getFullYear(),workingDate.getMonth()+1,workingDate.getDate()]) > -1) { cellRenderers[cellRenderers.length]=this.renderCellStyleSelected; } if (this.minDate) { this.minDate = YAHOO.widget.DateMath.clearTime(this.minDate); } if (this.maxDate) { this.maxDate = YAHOO.widget.DateMath.clearTime(this.maxDate); } if ( (this.minDate && (workingDate.getTime() < this.minDate.getTime())) || (this.maxDate && (workingDate.getTime() > this.maxDate.getTime())) ) { cellRenderers[cellRenderers.length]=this.renderOutOfBoundsDate; } else { cellRenderers[cellRenderers.length]=this.renderCellDefault; } for (var x=0;x<cellRenderers.length;++x) { var ren = cellRenderers[x]; if (ren.call(this,workingDate,cell) == YAHOO.widget.Calendar_Core.STOP_RENDER) { break; } } workingDate = YAHOO.widget.DateMath.add(workingDate, YAHOO.widget.DateMath.DAY, 1); // Go to the next day if (workingDate.getDay() == this.Options.START_WEEKDAY) { weekRowIndex += 1; } YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL); if (c >= 0 && c <= 6) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_TOP); } if ((c % 7) == 0) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_LEFT); } if (((c+1) % 7) == 0) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_RIGHT); } var postDays = this.postMonthDays; if (postDays >= 7 && this.Options.HIDE_BLANK_WEEKS) { var blankWeeks = Math.floor(postDays/7); for (var p=0;p<blankWeeks;++p) { postDays -= 7; } } if (c >= ((this.preMonthDays+postDays+this.monthDays)-7)) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_BOTTOM); } } }; /** * Appends the contents of the calendar widget footer into the shell. By default, * the calendar does not contain a footer, and this method must be implemented by * subclassing the widget. */ YAHOO.widget.Calendar_Core.prototype.renderFooter = function() { }; /** * @private */ YAHOO.widget.Calendar_Core.prototype._unload = function(e, cal) { for (var c in cal.cells) { c = null; } cal.cells = null; cal.tbody = null; cal.oDomContainer = null; cal.table = null; cal.headerCell = null; cal = null; }; /****************** BEGIN BUILT-IN TABLE CELL RENDERERS ************************************/ YAHOO.widget.Calendar_Core.prototype.renderOutOfBoundsDate = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_OOB); cell.innerHTML = workingDate.getDate(); return YAHOO.widget.Calendar_Core.STOP_RENDER; } /** * Renders the row header for a week. The date passed in should be * the first date of the given week. * @param {Date} workingDate The current working Date object (beginning of the week) being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar */ YAHOO.widget.Calendar_Core.prototype.renderRowHeader = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_ROW_HEADER); var useYear = this.pageDate.getFullYear(); if (! YAHOO.widget.DateMath.isYearOverlapWeek(workingDate)) { useYear = workingDate.getFullYear(); } var weekNum = YAHOO.widget.DateMath.getWeekNumber(workingDate, useYear, this.Options.START_WEEKDAY); cell.innerHTML = weekNum; if (this.isDateOOM(workingDate) && ! YAHOO.widget.DateMath.isMonthOverlapWeek(workingDate)) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_OOM); } }; /** * Renders the row footer for a week. The date passed in should be * the first date of the given week. * @param {Date} workingDate The current working Date object (beginning of the week) being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar */ YAHOO.widget.Calendar_Core.prototype.renderRowFooter = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_ROW_FOOTER); if (this.isDateOOM(workingDate) && ! YAHOO.widget.DateMath.isMonthOverlapWeek(workingDate)) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_OOM); } }; /** * Renders a single standard calendar cell in the calendar widget table. * All logic for determining how a standard default cell will be rendered is * encapsulated in this method, and must be accounted for when extending the * widget class. * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellDefault = function(workingDate, cell) { cell.innerHTML = ""; var link = document.createElement("a"); link.href="javascript:void(null);"; link.name=this.id+"__"+workingDate.getFullYear()+"_"+(workingDate.getMonth()+1)+"_"+workingDate.getDate(); link.appendChild(document.createTextNode(this.buildDayLabel(workingDate))); cell.appendChild(link); }; /** * Renders a single standard calendar cell using the CSS hightlight1 style * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellStyleHighlight1 = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT1); }; /** * Renders a single standard calendar cell using the CSS hightlight2 style * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellStyleHighlight2 = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT2); }; /** * Renders a single standard calendar cell using the CSS hightlight3 style * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellStyleHighlight3 = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT3); }; /** * Renders a single standard calendar cell using the CSS hightlight4 style * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellStyleHighlight4 = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT4); }; /** * Applies the default style used for rendering today's date to the current calendar cell * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellStyleToday = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_TODAY); }; /** * Applies the default style used for rendering selected dates to the current calendar cell * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellStyleSelected = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_SELECTED); }; /** * Applies the default style used for rendering dates that are not a part of the current * month (preceding or trailing the cells for the current month) * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderCellNotThisMonth = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_OOM); cell.innerHTML=workingDate.getDate(); return YAHOO.widget.Calendar_Core.STOP_RENDER; }; /** * Renders the current calendar cell as a non-selectable "black-out" date using the default * restricted style. * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return YAHOO.widget.Calendar_Core.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated * @type String */ YAHOO.widget.Calendar_Core.prototype.renderBodyCellRestricted = function(workingDate, cell) { YAHOO.widget.Calendar_Core.setCssClasses(cell, [this.Style.CSS_CELL,this.Style.CSS_CELL_RESTRICTED]); cell.innerHTML=workingDate.getDate(); return YAHOO.widget.Calendar_Core.STOP_RENDER; }; /******************** END BUILT-IN TABLE CELL RENDERERS ************************************/ /******************** BEGIN MONTH NAVIGATION METHODS ************************************/ /** * Adds the designated number of months to the current calendar month, and sets the current * calendar page date to the new month. * @param {Integer} count The number of months to add to the current calendar */ YAHOO.widget.Calendar_Core.prototype.addMonths = function(count) { this.pageDate = YAHOO.widget.DateMath.add(this.pageDate, YAHOO.widget.DateMath.MONTH, count); this.resetRenderers(); this.onChangePage(); }; /** * Subtracts the designated number of months from the current calendar month, and sets the current * calendar page date to the new month. * @param {Integer} count The number of months to subtract from the current calendar */ YAHOO.widget.Calendar_Core.prototype.subtractMonths = function(count) { this.pageDate = YAHOO.widget.DateMath.subtract(this.pageDate, YAHOO.widget.DateMath.MONTH, count); this.resetRenderers(); this.onChangePage(); }; /** * Adds the designated number of years to the current calendar, and sets the current * calendar page date to the new month. * @param {Integer} count The number of years to add to the current calendar */ YAHOO.widget.Calendar_Core.prototype.addYears = function(count) { this.pageDate = YAHOO.widget.DateMath.add(this.pageDate, YAHOO.widget.DateMath.YEAR, count); this.resetRenderers(); this.onChangePage(); }; /** * Subtcats the designated number of years from the current calendar, and sets the current * calendar page date to the new month. * @param {Integer} count The number of years to subtract from the current calendar */ YAHOO.widget.Calendar_Core.prototype.subtractYears = function(count) { this.pageDate = YAHOO.widget.DateMath.subtract(this.pageDate, YAHOO.widget.DateMath.YEAR, count); this.resetRenderers(); this.onChangePage(); }; /** * Navigates to the next month page in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.nextMonth = function() { this.addMonths(1); }; /** * Navigates to the previous month page in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.previousMonth = function() { this.subtractMonths(1); }; /** * Navigates to the next year in the currently selected month in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.nextYear = function() { this.addYears(1); }; /** * Navigates to the previous year in the currently selected month in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.previousYear = function() { this.subtractYears(1); }; /****************** END MONTH NAVIGATION METHODS ************************************/ /************* BEGIN SELECTION METHODS *************************************************************/ /** * Resets the calendar widget to the originally selected month and year, and * sets the calendar to the initial selection(s). */ YAHOO.widget.Calendar_Core.prototype.reset = function() { this.selectedDates.length = 0; this.selectedDates = this._selectedDates.concat(); this.pageDate = new Date(this._pageDate.getTime()); this.onReset(); }; /** * Clears the selected dates in the current calendar widget and sets the calendar * to the current month and year. */ YAHOO.widget.Calendar_Core.prototype.clear = function() { this.selectedDates.length = 0; this.pageDate = new Date(this.today.getTime()); this.onClear(); }; /** * Selects a date or a collection of dates on the current calendar. This method, by default, * does not call the render method explicitly. Once selection has completed, render must be * called for the changes to be reflected visually. * @param {String/Date/Date[]} date The date string of dates to select in the current calendar. Valid formats are * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). * This method can also take a JavaScript Date object or an array of Date objects. * @return Array of JavaScript Date objects representing all individual dates that are currently selected. * @type Date[] */ YAHOO.widget.Calendar_Core.prototype.select = function(date) { this.onBeforeSelect(); var aToBeSelected = this._toFieldArray(date); for (var a=0;a<aToBeSelected.length;++a) { var toSelect = aToBeSelected[a]; // For each date item in the list of dates we're trying to select if (this._indexOfSelectedFieldArray(toSelect) == -1) { // not already selected? this.selectedDates[this.selectedDates.length]=toSelect; } } if (this.parent) { this.parent.sync(this); } this.onSelect(); return this.getSelectedDates(); }; /** * Selects a date on the current calendar by referencing the index of the cell that should be selected. * This method is used to easily select a single cell (usually with a mouse click) without having to do * a full render. The selected style is applied to the cell directly. * @param {Integer} cellIndex The index of the cell to select in the current calendar. * @return Array of JavaScript Date objects representing all individual dates that are currently selected. * @type Date[] */ YAHOO.widget.Calendar_Core.prototype.selectCell = function(cellIndex) { this.onBeforeSelect(); this.cells = this.tbody.getElementsByTagName("TD"); var cell = this.cells[cellIndex]; var cellDate = this.cellDates[cellIndex]; var dCellDate = this._toDate(cellDate); var selectDate = cellDate.concat(); this.selectedDates.push(selectDate); if (this.parent) { this.parent.sync(this); } this.renderCellStyleSelected(dCellDate,cell); this.onSelect(); this.doCellMouseOut.call(cell, null, this); return this.getSelectedDates(); }; /** * Deselects a date or a collection of dates on the current calendar. This method, by default, * does not call the render method explicitly. Once deselection has completed, render must be * called for the changes to be reflected visually. * @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). * This method can also take a JavaScript Date object or an array of Date objects. * @return Array of JavaScript Date objects representing all individual dates that are currently selected. * @type Date[] */ YAHOO.widget.Calendar_Core.prototype.deselect = function(date) { this.onBeforeDeselect(); var aToBeSelected = this._toFieldArray(date); for (var a=0;a<aToBeSelected.length;++a) { var toSelect = aToBeSelected[a]; // For each date item in the list of dates we're trying to select var index = this._indexOfSelectedFieldArray(toSelect); if (index != -1) { this.selectedDates.splice(index,1); } } if (this.parent) { this.parent.sync(this); } this.onDeselect(); return this.getSelectedDates(); }; /** * Deselects a date on the current calendar by referencing the index of the cell that should be deselected. * This method is used to easily deselect a single cell (usually with a mouse click) without having to do * a full render. The selected style is removed from the cell directly. * @param {Integer} cellIndex The index of the cell to deselect in the current calendar. * @return Array of JavaScript Date objects representing all individual dates that are currently selected. * @type Date[] */ YAHOO.widget.Calendar_Core.prototype.deselectCell = function(i) { this.onBeforeDeselect(); this.cells = this.tbody.getElementsByTagName("TD"); var cell = this.cells[i]; var cellDate = this.cellDates[i]; var cellDateIndex = this._indexOfSelectedFieldArray(cellDate); var dCellDate = this._toDate(cellDate); var selectDate = cellDate.concat(); if (cellDateIndex > -1) { if (this.pageDate.getMonth() == dCellDate.getMonth() && this.pageDate.getFullYear() == dCellDate.getFullYear()) { YAHOO.util.Dom.removeClass(cell, this.Style.CSS_CELL_SELECTED); } this.selectedDates.splice(cellDateIndex, 1); } if (this.parent) { this.parent.sync(this); } this.onDeselect(); return this.getSelectedDates(); }; /** * Deselects all dates on the current calendar. * @return Array of JavaScript Date objects representing all individual dates that are currently selected. * Assuming that this function executes properly, the return value should be an empty array. * However, the empty array is returned for the sake of being able to check the selection status * of the calendar. * @type Date[] */ YAHOO.widget.Calendar_Core.prototype.deselectAll = function() { this.onBeforeDeselect(); var count = this.selectedDates.length; this.selectedDates.length = 0; if (this.parent) { this.parent.sync(this); } if (count > 0) { this.onDeselect(); } return this.getSelectedDates(); }; /************* END SELECTION METHODS *************************************************************/ /************* BEGIN TYPE CONVERSION METHODS ****************************************************/ /** * Converts a date (either a JavaScript Date object, or a date string) to the internal data structure * used to represent dates: [[yyyy,mm,dd],[yyyy,mm,dd]]. * @private * @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). * This method can also take a JavaScript Date object or an array of Date objects. * @return Array of date field arrays * @type Array[](Integer[]) */ YAHOO.widget.Calendar_Core.prototype._toFieldArray = function(date) { var returnDate = new Array(); if (date instanceof Date) { returnDate = [[date.getFullYear(), date.getMonth()+1, date.getDate()]]; } else if (typeof date == 'string') { returnDate = this._parseDates(date); } else if (date instanceof Array) { for (var i=0;i<date.length;++i) { var d = date[i]; returnDate[returnDate.length] = [d.getFullYear(),d.getMonth()+1,d.getDate()]; } } return returnDate; }; /** * Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. * @private * @param {Integer[]} dateFieldArray The date field array to convert to a JavaScript Date. * @return JavaScript Date object representing the date field array * @type Date */ YAHOO.widget.Calendar_Core.prototype._toDate = function(dateFieldArray) { if (dateFieldArray instanceof Date) { return dateFieldArray; } else { return new Date(dateFieldArray[0],dateFieldArray[1]-1,dateFieldArray[2]); } }; /************* END TYPE CONVERSION METHODS ******************************************************/ /************* BEGIN UTILITY METHODS ****************************************************/ /** * Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. * @private * @param {Integer[]} array1 The first date field array to compare * @param {Integer[]} array2 The first date field array to compare * @return The boolean that represents the equality of the two arrays * @type Boolean */ YAHOO.widget.Calendar_Core.prototype._fieldArraysAreEqual = function(array1, array2) { var match = false; if (array1[0]==array2[0]&&array1[1]==array2[1]&&array1[2]==array2[2]) { match=true; } return match; }; /** * Gets the index of a date field array [yyyy,mm,dd] in the current list of selected dates. * @private * @param {Integer[]} find The date field array to search for * @return The index of the date field array within the collection of selected dates. * -1 will be returned if the date is not found. * @type Integer */ YAHOO.widget.Calendar_Core.prototype._indexOfSelectedFieldArray = function(find) { var selected = -1; for (var s=0;s<this.selectedDates.length;++s) { var sArray = this.selectedDates[s]; if (find[0]==sArray[0]&&find[1]==sArray[1]&&find[2]==sArray[2]) { selected = s; break; } } return selected; }; /** * Determines whether a given date is OOM (out of month). * @param {Date} date The JavaScript Date object for which to check the OOM status * @return {Boolean} true if the date is OOM */ YAHOO.widget.Calendar_Core.prototype.isDateOOM = function(date) { var isOOM = false; if (date.getMonth() != this.pageDate.getMonth()) { isOOM = true; } return isOOM; }; /************* END UTILITY METHODS *******************************************************/ /************* BEGIN EVENT HANDLERS ******************************************************/ /** * Event executed before a date is selected in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.onBeforeSelect = function() { if (! this.Options.MULTI_SELECT) { this.clearAllBodyCellStyles(this.Style.CSS_CELL_SELECTED); this.deselectAll(); } }; /** * Event executed when a date is selected in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.onSelect = function() { }; /** * Event executed before a date is deselected in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.onBeforeDeselect = function() { }; /** * Event executed when a date is deselected in the calendar widget. */ YAHOO.widget.Calendar_Core.prototype.onDeselect = function() { }; /** * Event executed when the user navigates to a different calendar page. */ YAHOO.widget.Calendar_Core.prototype.onChangePage = function() { var me = this; this.renderHeader(); if (this.renderProcId) { clearTimeout(this.renderProcId); } this.renderProcId = setTimeout(function() { me.render(); me.renderProcId = null; }, 1); }; /** * Event executed when the calendar widget is rendered. */ YAHOO.widget.Calendar_Core.prototype.onRender = function() { }; /** * Event executed when the calendar widget is reset to its original state. */ YAHOO.widget.Calendar_Core.prototype.onReset = function() { this.render(); }; /** * Event executed when the calendar widget is completely cleared to the current month with no selections. */ YAHOO.widget.Calendar_Core.prototype.onClear = function() { this.render(); }; /** * Validates the calendar widget. This method has no default implementation * and must be extended by subclassing the widget. * @return Should return true if the widget validates, and false if * it doesn't. * @type Boolean */ YAHOO.widget.Calendar_Core.prototype.validate = function() { return true; }; /************* END EVENT HANDLERS *********************************************************/ /************* BEGIN DATE PARSE METHODS ***************************************************/ /** * Converts a date string to a date field array * @private * @param {String} sDate Date string. Valid formats are mm/dd and mm/dd/yyyy. * @return A date field array representing the string passed to the method * @type Array[](Integer[]) */ YAHOO.widget.Calendar_Core.prototype._parseDate = function(sDate) { var aDate = sDate.split(this.Locale.DATE_FIELD_DELIMITER); var rArray; if (aDate.length == 2) { rArray = [aDate[this.Locale.MD_MONTH_POSITION-1],aDate[this.Locale.MD_DAY_POSITION-1]]; rArray.type = YAHOO.widget.Calendar_Core.MONTH_DAY; } else { rArray = [aDate[this.Locale.MDY_YEAR_POSITION-1],aDate[this.Locale.MDY_MONTH_POSITION-1],aDate[this.Locale.MDY_DAY_POSITION-1]]; rArray.type = YAHOO.widget.Calendar_Core.DATE; } return rArray; }; /** * Converts a multi or single-date string to an array of date field arrays * @private * @param {String} sDates Date string with one or more comma-delimited dates. Valid formats are mm/dd, mm/dd/yyyy, mm/dd/yyyy-mm/dd/yyyy * @return An array of date field arrays * @type Array[](Integer[]) */ YAHOO.widget.Calendar_Core.prototype._parseDates = function(sDates) { var aReturn = new Array(); var aDates = sDates.split(this.Locale.DATE_DELIMITER); for (var d=0;d<aDates.length;++d) { var sDate = aDates[d]; if (sDate.indexOf(this.Locale.DATE_RANGE_DELIMITER) != -1) { // This is a range var aRange = sDate.split(this.Locale.DATE_RANGE_DELIMITER); var dateStart = this._parseDate(aRange[0]); var dateEnd = this._parseDate(aRange[1]); var fullRange = this._parseRange(dateStart, dateEnd); aReturn = aReturn.concat(fullRange); } else { // This is not a range var aDate = this._parseDate(sDate); aReturn.push(aDate); } } return aReturn; }; /** * Converts a date range to the full list of included dates * @private * @param {Integer[]} startDate Date field array representing the first date in the range * @param {Integer[]} endDate Date field array representing the last date in the range * @return An array of date field arrays * @type Array[](Integer[]) */ YAHOO.widget.Calendar_Core.prototype._parseRange = function(startDate, endDate) { var dStart = new Date(startDate[0],startDate[1]-1,startDate[2]); var dCurrent = YAHOO.widget.DateMath.add(new Date(startDate[0],startDate[1]-1,startDate[2]),YAHOO.widget.DateMath.DAY,1); var dEnd = new Date(endDate[0], endDate[1]-1, endDate[2]); var results = new Array(); results.push(startDate); while (dCurrent.getTime() <= dEnd.getTime()) { results.push([dCurrent.getFullYear(),dCurrent.getMonth()+1,dCurrent.getDate()]); dCurrent = YAHOO.widget.DateMath.add(dCurrent,YAHOO.widget.DateMath.DAY,1); } return results; }; /************* END DATE PARSE METHODS *****************************************************/ /************* BEGIN RENDERER METHODS *****************************************************/ /** * Resets the render stack of the current calendar to its original pre-render value. */ YAHOO.widget.Calendar_Core.prototype.resetRenderers = function() { this.renderStack = this._renderStack.concat(); }; /** * Clears the inner HTML, CSS class and style information from the specified cell. * @param {HTMLTableCellElement} The cell to clear */ YAHOO.widget.Calendar_Core.prototype.clearElement = function(cell) { cell.innerHTML = " "; cell.className=""; }; /** * Adds a renderer to the render stack. The function reference passed to this method will be executed * when a date cell matches the conditions specified in the date string for this renderer. * @param {String} sDates A date string to associate with the specified renderer. Valid formats * include date (12/24/2005), month/day (12/24), and range (12/1/2004-1/1/2005) * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. */ YAHOO.widget.Calendar_Core.prototype.addRenderer = function(sDates, fnRender) { var aDates = this._parseDates(sDates); for (var i=0;i<aDates.length;++i) { var aDate = aDates[i]; if (aDate.length == 2) { // this is either a range or a month/day combo if (aDate[0] instanceof Array) { // this is a range this._addRenderer(YAHOO.widget.Calendar_Core.RANGE,aDate,fnRender); } else { // this is a month/day combo this._addRenderer(YAHOO.widget.Calendar_Core.MONTH_DAY,aDate,fnRender); } } else if (aDate.length == 3) { this._addRenderer(YAHOO.widget.Calendar_Core.DATE,aDate,fnRender); } } }; /** * The private method used for adding cell renderers to the local render stack. * This method is called by other methods that set the renderer type prior to the method call. * @private * @param {String} type The type string that indicates the type of date renderer being added. * Values are YAHOO.widget.Calendar_Core.DATE, YAHOO.widget.Calendar_Core.MONTH_DAY, YAHOO.widget.Calendar_Core.WEEKDAY, * YAHOO.widget.Calendar_Core.RANGE, YAHOO.widget.Calendar_Core.MONTH * @param {Array} aDates An array of dates used to construct the renderer. The format varies based * on the renderer type * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. */ YAHOO.widget.Calendar_Core.prototype._addRenderer = function(type, aDates, fnRender) { var add = [type,aDates,fnRender]; this.renderStack.unshift(add); this._renderStack = this.renderStack.concat(); }; /** * Adds a month to the render stack. The function reference passed to this method will be executed * when a date cell matches the month passed to this method. * @param {Integer} month The month (1-12) to associate with this renderer * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. */ YAHOO.widget.Calendar_Core.prototype.addMonthRenderer = function(month, fnRender) { this._addRenderer(YAHOO.widget.Calendar_Core.MONTH,[month],fnRender); }; /** * Adds a weekday to the render stack. The function reference passed to this method will be executed * when a date cell matches the weekday passed to this method. * @param {Integer} weekay The weekday (1-7) to associate with this renderer * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. */ YAHOO.widget.Calendar_Core.prototype.addWeekdayRenderer = function(weekday, fnRender) { this._addRenderer(YAHOO.widget.Calendar_Core.WEEKDAY,[weekday],fnRender); }; //// END RENDERER METHODS //// //// BEGIN CSS METHODS //// /** * Sets the specified array of CSS classes into the referenced element * @param {HTMLElement} element The element to set the CSS classes into * @param {String[]} aStyles An array of CSS class names */ YAHOO.widget.Calendar_Core.setCssClasses = function(element, aStyles) { element.className = ""; var className = aStyles.join(" "); element.className = className; }; /** * Removes all styles from all body cells in the current calendar table. * @param {style} The CSS class name to remove from all calendar body cells */ YAHOO.widget.Calendar_Core.prototype.clearAllBodyCellStyles = function(style) { for (var c=0;c<this.cells.length;++c) { YAHOO.util.Dom.removeClass(this.cells[c],style); } }; //// END CSS METHODS //// //// BEGIN GETTER/SETTER METHODS //// /** * Sets the calendar's month explicitly. * @param {Integer} month The numeric month, from 1 (January) to 12 (December) */ YAHOO.widget.Calendar_Core.prototype.setMonth = function(month) { this.pageDate.setMonth(month); }; /** * Sets the calendar's year explicitly. * @param {Integer} year The numeric 4-digit year */ YAHOO.widget.Calendar_Core.prototype.setYear = function(year) { this.pageDate.setFullYear(year); }; /** * Gets the list of currently selected dates from the calendar. * @return An array of currently selected JavaScript Date objects. * @type Date[] */ YAHOO.widget.Calendar_Core.prototype.getSelectedDates = function() { var returnDates = new Array(); for (var d=0;d<this.selectedDates.length;++d) { var dateArray = this.selectedDates[d]; var date = new Date(dateArray[0],dateArray[1]-1,dateArray[2]); returnDates.push(date); } returnDates.sort(); return returnDates; }; /// END GETTER/SETTER METHODS /// /** * Returns a string representing the current browser. * @type String */ YAHOO.widget.Calendar_Core._getBrowser = function() { /** * UserAgent * @private * @type String */ var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf('opera')!=-1) // Opera (check first in case of spoof) return 'opera'; else if (ua.indexOf('msie')!=-1) // IE return 'ie'; else if (ua.indexOf('safari')!=-1) // Safari (check before Gecko because it includes "like Gecko") return 'safari'; else if (ua.indexOf('gecko') != -1) // Gecko return 'gecko'; else return false; } /** * Returns a string representation of the object. * @type string */ YAHOO.widget.Calendar_Core.prototype.toString = function() { return "Calendar_Core " + this.id; } YAHOO.widget.Cal_Core = YAHOO.widget.Calendar_Core;