2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 YUI.add('calendarnavigator', function (Y, NAME) {
11 * Provides a plugin which adds navigation controls to Calendar.
13 * @module calendarnavigator
15 var CONTENT_BOX = "contentBox",
17 getCN = Y.ClassNameManager.getClassName,
18 substitute = Y.Lang.sub,
21 CALENDAR = 'calendar',
22 CALENDARNAV = 'calendarnav',
23 CAL_HD = getCN(CALENDAR, 'header'),
24 CAL_PREV_M = getCN(CALENDARNAV, 'prevmonth'),
25 CAL_NEXT_M = getCN(CALENDARNAV, 'nextmonth'),
26 CAL_DIS_M = getCN(CALENDARNAV, 'month-disabled'),
27 ydate = Y.DataType.Date;
29 * A plugin class which adds navigation controls to Calendar.
31 * @class CalendarNavigator
32 * @extends Plugin.Base
35 function CalendarNavigator() {
36 CalendarNavigator.superclass.constructor.apply(this, arguments);
40 * The namespace for the plugin. This will be the property on the widget, which will
41 * reference the plugin instance, when it's plugged in.
46 * @default "navigator"
48 CalendarNavigator.NS = "navigator";
51 * The NAME of the CalendarNavigator class. Used to prefix events generated
52 * by the plugin class.
57 * @default "pluginCalendarNavigator"
59 CalendarNavigator.NAME = "pluginCalendarNavigator";
63 * Static property used to define the default attribute
64 * configuration for the plugin.
70 CalendarNavigator.ATTRS = {
73 * The number of months to shift by when the control arrows are clicked.
75 * @attribute shiftByMonths
85 * The CSS classnames for the calendar navigator controls.
86 * @property CALENDARNAV_STRINGS
92 CalendarNavigator.CALENDARNAV_STRINGS = {
93 prev_month_class: CAL_PREV_M,
94 next_month_class: CAL_NEXT_M
98 * The template for the calendar navigator previous month control.
99 * @property PREV_MONTH_CONTROL_TEMPLATE
104 CalendarNavigator.PREV_MONTH_CONTROL_TEMPLATE = '<a class="yui3-u {prev_month_class}" role="button" aria-label="{prev_month_arialabel}" ' +
105 'tabindex="{control_tabindex}">' +
106 "<span><</span>" +
109 * The template for the calendar navigator next month control.
110 * @property NEXT_MONTH_CONTROL_TEMPLATE
116 CalendarNavigator.NEXT_MONTH_CONTROL_TEMPLATE = '<a class="yui3-u {next_month_class}" role="button" aria-label="{next_month_arialabel}" ' +
117 'tabindex="{control_tabindex}">' +
118 "<span>></span>" +
122 Y.extend(CalendarNavigator, Y.Plugin.Base, {
124 _eventAttachments : {},
128 * The initializer lifecycle implementation. Modifies the host widget's
129 * render to add navigation controls.
131 * @method initializer
133 initializer : function() {
135 // After the host has rendered its UI, place the navigation cotnrols
137 this._eventAttachments = {};
139 this.afterHostMethod("renderUI", this._initNavigationControls);
143 * The initializer destructor implementation. Responsible for destroying the initialized
144 * control mechanisms.
148 destructor : function() {
153 * Private utility method that focuses on a navigation button when it is clicked
154 * or pressed with a keyboard.
156 * @method _focusNavigation
157 * @param {Event} ev Click or keydown event from the controls
160 _focusNavigation : function (ev) {
161 ev.currentTarget.focus();
165 * Private utility method that subtracts months from the host calendar date
166 * based on the control click and the shiftByMonths property.
168 * @method _subtractMonths
169 * @param {Event} ev Click event from the controls
172 _subtractMonths : function (ev) {
173 if ( (ev.type === "click") || (ev.type === "keydown" && (ev.keyCode === 13 || ev.keyCode === 32)) ) {
174 var host = this.get(HOST),
175 oldDate = host.get("date");
176 host.set("date", ydate.addMonths(oldDate, -1*this.get("shiftByMonths")));
182 * Private utility method that adds months to the host calendar date
183 * based on the control click and the shiftByMonths property.
186 * @param {Event} ev Click event from the controls
189 _addMonths : function (ev) {
190 if ( (ev.type === "click") || (ev.type === "keydown" && (ev.keyCode === 13 || ev.keyCode === 32)) ) {
191 var host = this.get(HOST),
192 oldDate = host.get("date");
193 host.set("date", ydate.addMonths(oldDate, this.get("shiftByMonths")));
199 _updateControlState : function () {
201 var host = this.get(HOST),
202 startDate = host.get('date'),
203 endDate = ydate.addMonths(startDate, host._paneNumber - 1),
204 minDate = host._normalizeDate(host.get("minimumDate")),
205 maxDate = host._normalizeDate(host.get("maximumDate"));
207 if (ydate.areEqual(minDate, startDate)) {
208 if (this._eventAttachments.prevMonth) {
209 this._eventAttachments.prevMonth.detach();
210 this._eventAttachments.prevMonth = false;
213 if (!this._controls.prevMonth.hasClass(CAL_DIS_M)) {
214 this._controls.prevMonth.addClass(CAL_DIS_M).setAttribute("aria-disabled", "true");
218 if (!this._eventAttachments.prevMonth) {
219 this._eventAttachments.prevMonth = this._controls.prevMonth.on(["click", "keydown"], this._subtractMonths, this);
221 if (this._controls.prevMonth.hasClass(CAL_DIS_M)) {
222 this._controls.prevMonth.removeClass(CAL_DIS_M).setAttribute("aria-disabled", "false");
226 if (ydate.areEqual(maxDate, endDate)) {
227 if (this._eventAttachments.nextMonth) {
228 this._eventAttachments.nextMonth.detach();
229 this._eventAttachments.nextMonth = false;
232 if (!this._controls.nextMonth.hasClass(CAL_DIS_M)) {
233 this._controls.nextMonth.addClass(CAL_DIS_M).setAttribute("aria-disabled", "true");
237 if (!this._eventAttachments.nextMonth) {
238 this._eventAttachments.nextMonth = this._controls.nextMonth.on(["click", "keydown"], this._addMonths, this);
240 if (this._controls.nextMonth.hasClass(CAL_DIS_M)) {
241 this._controls.nextMonth.removeClass(CAL_DIS_M).setAttribute("aria-disabled", "false");
245 this._controls.prevMonth.on(["click", "keydown"], this._focusNavigation, this);
246 this._controls.nextMonth.on(["click", "keydown"], this._focusNavigation, this);
253 * Private render assist method that renders the previous month control
255 * @method _renderPrevControls
258 _renderPrevControls : function () {
259 var prevControlNode = create(substitute (CalendarNavigator.PREV_MONTH_CONTROL_TEMPLATE,
260 CalendarNavigator.CALENDARNAV_STRINGS));
261 prevControlNode.on("selectstart", this.get(HOST)._preventSelectionStart);
263 return prevControlNode;
267 * Private render assist method that renders the next month control
269 * @method _renderNextControls
272 _renderNextControls : function () {
273 var nextControlNode = create(substitute (CalendarNavigator.NEXT_MONTH_CONTROL_TEMPLATE,
274 CalendarNavigator.CALENDARNAV_STRINGS));
275 nextControlNode.on("selectstart", this.get(HOST)._preventSelectionStart);
277 return nextControlNode;
281 * Protected render assist method that initialized and renders the navigation controls.
282 * @method _initNavigationControls
285 _initNavigationControls : function() {
286 var host = this.get(HOST),
287 headerCell = host.get(CONTENT_BOX).one("." + CAL_HD);
289 CalendarNavigator.CALENDARNAV_STRINGS.control_tabindex = host.get("tabIndex");
290 CalendarNavigator.CALENDARNAV_STRINGS.prev_month_arialabel = "Go to previous month";
291 CalendarNavigator.CALENDARNAV_STRINGS.next_month_arialabel = "Go to next month";
293 this._controls.prevMonth = this._renderPrevControls();
294 this._controls.nextMonth = this._renderNextControls();
296 this._updateControlState();
298 host.after(["dateChange", "minimumDateChange", "maximumDateChange"], this._updateControlState, this);
300 headerCell.prepend(this._controls.prevMonth);
301 headerCell.append(this._controls.nextMonth);
305 Y.namespace("Plugin").CalendarNavigator = CalendarNavigator;
308 }, '3.13.0', {"requires": ["plugin", "classnamemanager", "datatype-date", "node"], "skinnable": true});