PageSourceSearch

https://lewistonutah.gov/wp-content/plugins/tw-meeting-repository/…/accdc/calendar_generator.js?ver=2.0.1

js lewistonutah.gov collected 2026-10-04 10:23:55 UTC 67,073 bytes, 2,041 lines download raw bytes

1/*!
2ARIA Calendar Module R2.0
3Copyright 2010-2018 Bryan Garaventa (WhatSock.com)
4Refactoring Contributions Copyright 2018 Danny Allen (dannya.com) / Wonderscore Ltd (wonderscore.co.uk)
5Part of AccDC, a Cross-Browser JavaScript accessibility API, distributed under the terms of the Open Source Initiative OSI - MIT License
6*/
7
8(function(){
9
10	$A.setCalendar = function(pId, trigger, targ, commentsEnabled, callback, config){
11
12		var config = config || {},
13			helpText =
14				config.helpText
15					? config.helpText
16					: 'Press the arrow keys to navigate by day, PageUp and PageDown to navigate by month, Alt+PageUp and Alt+PageDown to navigate by year, or Escape to cancel.',
17
18			// Control the behavior of date selection clicks
19			handleClick = (callback && typeof callback === 'function') ? callback : function(ev, dc){
20				// format selected calendar value and set into input field
21				targ.value = dc.formatDate(
22					dc,
23					{
24						'YYYY': dc.range.current.year,
25						'MMMM': dc.range[dc.range.current.month].name,
26						'dddd': dc.range.wDays[dc.range.current.wDay].lng,
27						'MM': ('00' + (dc.range.current.month + 1)).slice(-2),
28						'DD': ('00' + dc.range.current.mDay).slice(-2),
29						'Do': dc.getDateOrdinalSuffix(dc.range.current.mDay),
30						'M': (dc.range.current.month + 1),
31						'D': dc.range.current.mDay
32					}
33				);
34
35				dc.close();
36			},
37
38			pressed = {},
39			changePressed = function(ev){
40				pressed.alt = ev.altKey;
41				pressed.ctrl = ev.ctrlKey;
42				pressed.shift = ev.shiftKey;
43			};
44
45		// Calendar object declaration start
46		$A(
47						[
48						{
49						id: pId,
50						role: config.role || 'Calendar',
51						trigger: trigger,
52						bind: 'opendatepicker',
53						allowReopen: true,
54						showHiddenClose: false,
55						controlType: 'DatePicker',
56						tooltipTxt: config.tooltipTxt || 'Press Escape to cancel',
57						markedTxt: config.markedTxt || 'Selected',
58						disabledTxt: config.disabledTxt || 'Disabled',
59						commentedTxt: config.commentedTxt || 'Has Comment',
60						prevTxt: config.prevTxt || 'Previous',
61						nextTxt: config.nextTxt || 'Next',
62						monthTxt: config.monthTxt || 'Month',
63						yearTxt: config.yearTxt || 'Year',
64						leftButtonYearText: config.leftButtonYearText || '⇐',
65						rightButtonYearText: config.rightButtonYearText || '⇒',
66						leftButtonMonthText: config.leftButtonMonthText || '←',
67						rightButtonMonthText: config.rightButtonMonthText || '→',
68						drawFullCalendar: (config.drawFullCalendar === true),
69						highlightToday: (config.highlightToday === true),
70						pageUpDownNatural: (config.pageUpDownNatural === true),
71						autoPosition: isNaN(config.autoPosition) ? 9 : config.autoPosition,
72						offsetTop: isNaN(config.offsetTop) ? 0 : config.offsetTop,
73						offsetLeft: isNaN(config.offsetLeft) ? 0 : config.offsetLeft,
74						posAnchor: config.posAnchor,
75						targetObj: config.targetObj,
76						inputDateFormat: config.inputDateFormat || 'dddd MMMM D, YYYY',
77						audibleDateFormat: config.audibleDateFormat || 'D, MMMM YYYY (dddd)',
78						initialDate: ((config.initialDate instanceof Date) ? config.initialDate : new Date()),
79						minDate: ((config.minDate !== undefined) ? (config.minDate instanceof Date ? config.minDate : new Date((new Date()).setDate((new Date()).getDate() + config.minDate))) : undefined),
80						maxDate: ((config.maxDate !== undefined) ? (config.maxDate instanceof Date ? config.maxDate : new Date((new Date()).setDate((new Date()).getDate() + config.maxDate))) : undefined),
81						disableWeekdays: (config.disableWeekdays !== undefined) ? config.disableWeekdays : false,
82						disableWeekends: (config.disableWeekends !== undefined) ? config.disableWeekends : false,
83						cssObj: config.cssObj ||
84										{
85										position: 'absolute',
86										zIndex: 1
87										},
88						className: config.className || 'calendar',
89						range:
90										{
91										disabledWDays: [],
92										0:
93														{
94														name: config.months && config.months[0] ? config.months[0] : 'January',
95														max: 31,
96														marked: {},
97														disabled: {},
98														disabledWDays: [],
99														comments: {},
100														message: {}
101														},
102										1:
103														{
104														name: config.months && config.months[1] ? config.months[1] : 'February',
105														max: 28,
106														marked: {},
107														disabled: {},
108														disabledWDays: [],
109														comments: {},
110														message: {}
111														},
112										2:
113														{
114														name: config.months && config.months[2] ? config.months[2] : 'March',
115														max: 31,
116														marked: {},
117														disabled: {},
118														disabledWDays: [],
119														comments: {},
120														message: {}
121														},
122										3:
123														{
124														name: config.months && config.months[3] ? config.months[3] : 'April',
125														max: 30,
126														marked: {},
127														disabled: {},
128														disabledWDays: [],
129														comments: {},
130														message: {}
131														},
132										4:
133														{
134														name: config.months && config.months[4] ? config.months[4] : 'May',
135														max: 31,
136														marked: {},
137														disabled: {},
138														disabledWDays: [],
139														comments: {},
140														message: {}
141														},
142										5:
143														{
144														name: config.months && config.months[5] ? config.months[5] : 'June',
145														max: 30,
146														marked: {},
147														disabled: {},
148														disabledWDays: [],
149														comments: {},
150														message: {}
151														},
152										6:
153														{
154														name: config.months && config.months[6] ? config.months[6] : 'July',
155														max: 31,
156														marked: {},
157														disabled: {},
158														disabledWDays: [],
159														comments: {},
160														message: {}
161														},
162										7:
163														{
164														name: config.months && config.months[7] ? config.months[7] : 'August',
165														max: 31,
166														marked: {},
167														disabled: {},
168														disabledWDays: [],
169														comments: {},
170														message: {}
171														},
172										8:
173														{
174														name: config.months && config.months[8] ? config.months[8] : 'September',
175														max: 30,
176														marked: {},
177														disabled: {},
178														disabledWDays: [],
179														comments: {},
180														message: {}
181														},
182										9:
183														{
184														name: config.months && config.months[9] ? config.months[9] : 'October',
185														max: 31,
186														marked: {},
187														disabled: {},
188														disabledWDays: [],
189														comments: {},
190														message: {}
191														},
192										10:
193														{
194														name: config.months && config.months[10] ? config.months[10] : 'November',
195														max: 30,
196														marked: {},
197														disabled: {},
198														disabledWDays: [],
199														comments: {},
200														message: {}
201														},
202										11:
203														{
204														name: config.months && config.months[11] ? config.months[11] : 'December',
205														max: 31,
206														marked: {},
207														disabled: {},
208														disabledWDays: [],
209														comments: {},
210														message: {}
211														},
212										wDays:
213														[
214														{
215														shrt: config.days && config.days[0] ? config.days[0].s : 'S',
216														lng: config.days && config.days[0] ? config.days[0].l : 'Sunday'
217														},
218														{
219														shrt: config.days && config.days[1] ? config.days[1].s : 'M',
220														lng: config.days && config.days[1] ? config.days[1].l : 'Monday'
221														},
222														{
223														shrt: config.days && config.days[2] ? config.days[2].s : 'T',
224														lng: config.days && config.days[2] ? config.days[2].l : 'Tuesday'
225														},
226														{
227														shrt: config.days && config.days[3] ? config.days[3].s : 'W',
228														lng: config.days && config.days[3] ? config.days[3].l : 'Wednesday'
229														},
230														{
231														shrt: config.days && config.days[4] ? config.days[4].s : 'T',
232														lng: config.days && config.days[4] ? config.days[4].l : 'Thursday'
233														},
234														{
235														shrt: config.days && config.days[5] ? config.days[5].s : 'F',
236														lng: config.days && config.days[5] ? config.days[5].l : 'Friday'
237														},
238														{
239														shrt: config.days && config.days[6] ? config.days[6].s : 'S',
240														lng: config.days && config.days[6] ? config.days[6].l : 'Saturday'
241														}
242														],
243										// Change the week day offset for the calendar display
244										wdOffset: isNaN(config.wdOffset) ? 0 : config.wdOffset
245										},
246						getWDay: function(dc, d, r){
247							var d = typeof d === 'number' ? d : dc.range.current.wDay, o = dc.range.wdOffset;
248
249							if (o < 0)
250								d = (d + o) < 0 ? 7 + o : d + o;
251
252							else if (o > 0)
253								d = (d + o) > 6 ? -1 + ((d + o) - 6) : d + o;
254
255							if (r)
256								d = 6 - d;
257							return d;
258						},
259						getDateOrdinalSuffix: function (i) {
260							var j = i % 10,
261								k = i % 100;
262
263							if (j == 1 && k != 11) {
264								return i + 'st';
265							}
266							if (j == 2 && k != 12) {
267								return i + 'nd';
268							}
269							if (j == 3 && k != 13) {
270								return i + 'rd';
271							}
272
273							return i + 'th';
274						},
275						formatDate: function (dc, dateFormatTokens, dateFormat) {
276							// if dateFormat is not specified, use component default
277							if (typeof dateFormat !== 'string') {
278								dateFormat = dc.inputDateFormat;
279							}
280
281							var re = new RegExp(Object.keys(dateFormatTokens).join('|'), 'gi');
282
283							return dateFormat.replace(re, function (matched){
284								return dateFormatTokens[matched];
285							});
286						},
287						modifyDateValues: function (values, modifications) {
288							// Note: Months are zero based
289							for (var key in modifications) {
290								var modification = modifications[key];
291
292								if (key === 'month') {
293									values.month += modification;
294
295									if (modification < 0) {
296										// Subtraction
297										if (values.month < 0) {
298											values.month = 11;
299
300											if (values.year) {
301												values.year -= 1;
302											}
303										}
304
305									} else {
306										// Addition
307										if (values.month > 11) {
308											values.month = 0;
309
310											if (values.year) {
311												values.year += 1;
312											}
313										}
314									}
315								}
316							}
317
318							return values;
319						},
320						setFocus: function(o, p, s){
321							var dc = this;
322
323							if (!o)
324								return false;
325
326							this.current = o;
327							$A.query('td.dayInMonth.selected', this.containerDiv, function(i, p){
328								$A.setAttr(p,
329												{
330												tabindex: '-1'
331												});
332
333								$A.remClass(p, 'selected');
334							});
335							$A.addClass(o, 'selected');
336							$A.setAttr(o,
337											{
338											tabindex: '0'
339											});
340
341							if (!s){
342								if (dc.navBtn == 'PM'){
343									dc.buttons.pM.focus();
344									$A.announce(dc.range[dc.range.current.month].name);
345									dc.navBtnS = true;
346								}
347
348								else if (dc.navBtn == 'NM'){
349									dc.buttons.nM.focus();
350									$A.announce(dc.range[dc.range.current.month].name);
351									dc.navBtnS = true;
352								}
353
354								else if (dc.navBtn == 'PY'){
355									dc.buttons.pY.focus();
356									$A.announce(dc.range.current.year.toString());
357									dc.navBtnS = true;
358								}
359
360								else if (dc.navBtn == 'NY'){
361									dc.buttons.nY.focus();
362									$A.announce(dc.range.current.year.toString());
363									dc.navBtnS = true;
364								}
365
366								else
367									o.focus();
368							}
369
370							if (dc.fn.navBtn)
371								dc.fn.navBtn = '';
372
373							else
374								dc.navBtn = '';
375
376							return true;
377						},
378						setCurrent: function(dc){
379							dc.range.current =
380											{
381											mDay: dc.date.getDate(),
382											month: dc.date.getMonth(),
383											year: dc.date.getFullYear(),
384											wDay: dc.date.getDay()
385											};
386						},
387						setDayMarked: function (dc, dateObj, isMarked) {
388							var year = dateObj.getFullYear(),
389								month = dateObj.getMonth(),
390								day = dateObj.getDate();
391
392							if (isMarked) {
393								// initialise marked array for month if it doesn't exist
394								if (typeof dc.range[month].marked[year] !== 'object') {
395									dc.range[month].marked[year] = [];
396								}
397
398								// set day as marked
399								dc.range[month].marked[year].push(day);
400
401							} else {
402								// unset day as marked
403								if (typeof dc.range[month].marked[year] === 'object') {
404									var arrIndex = dc.range[month].marked[year].indexOf(day);
405
406									if (arrIndex !== -1) {
407										delete dc.range[month].marked[year][arrIndex];
408									}
409								}
410							}
411						},
412						clearAllMarked: function (dc) {
413							for (var month in dc.range) {
414								dc.range[month].marked = {};
415							}
416						},
417						setDayDisabled: function (dc, dateObj, isDisabled) {
418							var year = dateObj.getFullYear(),
419									month = dateObj.getMonth(),
420									day = dateObj.getDate();
421
422							if (isDisabled) {
423								// initialise disabled array for month if it doesn't exist
424								if (typeof dc.range[month].disabled[year] !== 'object') {
425									dc.range[month].disabled[year] = [];
426								}
427
428								// set day as disabled
429								dc.range[month].disabled[year].push(day);
430
431							} else {
432								// unset day as disabled
433								if (typeof dc.range[month].disabled[year] === 'object') {
434									var arrIndex = dc.range[month].disabled[year].indexOf(day);
435
436									if (arrIndex !== -1) {
437										delete dc.range[month].disabled[year][arrIndex];
438									}
439								}
440							}
441						},
442						setMonthDisabled: function (dc, dateObj, isDisabled) {
443							var year = dateObj.getFullYear(),
444									month = dateObj.getMonth();
445
446							if (isDisabled) {
447								// reset month disabled array
448								dc.range[month].disabled[year] = [];
449
450								// set each day in month as disabled
451								for (var day = 1; day <= dc.range[month].max; day++){
452									dc.range[month].disabled[year].push(day);
453								}
454
455							} else {
456								// unset month as disabled
457								dc.range[month].disabled[year] = [];
458							}
459						},
460						setDayOfWeekDisabled: function (dc, dateObj, daysOfWeek, isDisabled) {
461							var year = dateObj.getFullYear(),
462									month = dateObj.getMonth();
463
464							// initialise disabled array for month if it doesn't exist
465							if (typeof dc.range[month].disabled[year] !== 'object') {
466								dc.range[month].disabled[year] = [];
467							}
468
469							// initialise local modifiable date that we will use to call the native getDay() method on
470							var date = new Date(year, month, 1);
471
472							for (var day = 1; day <= dc.range[month].max; day++){
473								date.setDate(day);
474
475								if (daysOfWeek.indexOf(date.getDay()) !== -1) {
476									if (isDisabled) {
477										dc.range[month].disabled[year].push(day);
478
479									} else {
480										// unset day as disabled
481										var arrIndex = dc.range[month].marked[year].indexOf(day);
482
483										if (arrIndex !== -1) {
484											delete dc.range[month].marked[year][arrIndex];
485										}
486									}
487								}
488							}
489						},
490						setWeekdaysDisabled: function (dc, dateObj, isDisabled) {
491							// 0 = Sunday, 6 = Saturday
492							dc.setDayOfWeekDisabled(dc, dateObj, [1, 2, 3, 4, 5], isDisabled);
493						},
494						setWeekendsDisabled: function (dc, dateObj, isDisabled) {
495							// 0 = Sunday, 6 = Saturday, which are the days we are not setting
496							dc.setDayOfWeekDisabled(dc, dateObj, [0, 6], isDisabled);
497						},
498						clearAllDisabled: function (dc) {
499							for (var month in dc.range) {
500								dc.range[month].disabled = {};
501							}
502						},
503						setMonthMessage: function (dc, dateObj, message) {
504							var year = dateObj.getFullYear(),
505									month = dateObj.getMonth();
506
507							if ((typeof message === 'string') && (message.length > 0)) {
508								// set month message
509								dc.range[month].message[year] = message;
510
511							} else {
512								// unset month message
513								delete dc.range[month].message[year];
514							}
515						},
516						clearAllMessage: function (dc) {
517							for (var month in dc.range) {
518								dc.range[month].message = {};
519							}
520						},
521						isDisabledDate: function(dc, counter, dateObj, cmpObj){
522							if (!cmpObj) {
523								cmpObj = dc.range.current;
524							}
525
526							var disabled = dc.range[cmpObj.month].disabled[cmpObj.year],
527								disabledAll = dc.range[cmpObj.month].disabled['*'],
528								disabledWDays = dc.range[cmpObj.month].disabledWDays,
529								disabledAllWDays = dc.range.disabledWDays;
530
531							var wkd = dateObj.getDay();
532
533							return !!((disabled && $A.inArray(counter, disabled) !== -1) || (disabledAll && $A.inArray(counter, disabledAll) !== -1)
534								|| (disabledWDays.length && $A.inArray(wkd, disabledWDays) !== -1)
535								|| (disabledAllWDays.length && $A.inArray(wkd, disabledAllWDays) !== -1)
536								|| dc.isOutsideDateRange(dateObj));
537
538						},
539						isOutsideDateRange: function(dateObj){
540							var dateCmp = this.createDateComparisonValue(dateObj);
541
542							return (
543								(this.minDateComparisonValue && (dateCmp < this.minDateComparisonValue)) ||
544								(this.maxDateComparisonValue && (dateCmp > this.maxDateComparisonValue))
545							);
546						},
547						createDayCell: function(i, cellDateObj, cssClasses, isDisabled, isSelected){
548							var dc = this;
549
550							var cell = '<td ';
551
552							// set correct ARIA attributes
553							if (isSelected){
554								cell += 'aria-current="date" ';
555							}
556
557							if (isDisabled){
558								cell += 'aria-disabled="true" ';
559							}
560
561							cell += 'aria-label="';
562
563							// draw comment?
564							var comments = dc.range[dc.range.current.month].comments[dc.range.current.year],
565								commentsAll = dc.range[dc.range.current.month].comments['*'];
566
567							var comm = '';
568							if (comments && comments[i])
569								comm = comments[i];
570							else if (commentsAll && commentsAll[i])
571								comm = commentsAll[i];
572
573							if (comm){
574								cell += dc.commentedTxt.replace(/<|>|\"/g, '') + ' ';
575							}
576
577							var month = cellDateObj.getMonth();
578							var dateFormatTokens = {
579								'YYYY': cellDateObj.getFullYear(),
580								'MMMM': dc.range[month].name,
581								'dddd': dc.range.wDays[cellDateObj.getDay()].lng,
582								'MM': ('00' + (month + 1)).slice(-2),
583								'DD': ('00' + i).slice(-2),
584								'Do': dc.getDateOrdinalSuffix(i),
585								'M': (month + 1),
586								'D': i
587							};
588
589							// set audible date value
590							var re = new RegExp(Object.keys(dateFormatTokens).join('|'), 'gi');
591
592							cell += dc.audibleDateFormat.replace(re, function (matched){
593								return dateFormatTokens[matched];
594							});
595
596							if (comm){
597								cell += comm.replace(/<|>|\n/g, ' ').replace(/\"/g, '\"');
598							}
599							cell += '" role="link" tabindex="-1" ';
600
601							// CSS classes
602							cell += 'class="day ' + (cssClasses ? cssClasses : '');
603
604							if (dc.highlightToday === true){
605								if (dc.createDateComparisonValue(cellDateObj) === dc.currentDateComparisonValue) {
606									cell += ' dayToday';
607								}
608							}
609
610							// set date as visually marked?
611							var isMarked = (
612								dc.range[dc.range.current.month].marked[dc.range.current.year] &&
613								(dc.range[dc.range.current.month].marked[dc.range.current.year].indexOf(i) !== -1)
614							);
615
616							if ((isSelected && !isDisabled) || isMarked){
617								cell += ' dayMarked';
618							}
619
620							if (isDisabled){
621								cell += ' disabled';
622							}
623
624							if (comm){
625								cell += ' comment';
626							}
627							cell += '" ';
628
629							// Title attribute
630							cell += 'title="';
631
632							if (isMarked){
633								cell += dc.markedTxt.replace(/<|>|\"/g, '');
634
635							} else if (isDisabled){
636								cell += dc.disabledTxt.replace(/<|>|\"/g, '');
637							}
638
639							if (comm){
640								cell += ' ' + dc.commentedTxt.replace(/<|>|\"/g, '');
641							}
642							cell += '" id="' + dc.baseId + i + '"><span aria-hidden="true">' + i + '</span></td>';
643
644							return cell;
645						},
646						createDateComparisonValue: function (dateObj){
647							return parseInt(
648								(
649									dateObj.getFullYear() +
650									('00' + dateObj.getMonth()).slice(-2) +
651									('00' + dateObj.getDate()).slice(-2)
652								),
653								10
654							);
655						},
656						setDate: function(dc, dateObj){
657							// if dateObj is not specified, set to an initial value...
658							if (dateObj === undefined){
659								// ensure initialDate value is within any set date range
660								if ((dc.minDate || dc.maxDate) && dc.isOutsideDateRange(dc.initialDate)) {
661									// initialDate config value is outside of the valid date range, determine an optimal initial date value
662									if (dc.initialDate < dc.minDate) {
663										dateObj = dc.minDate;
664									} else if (dc.initialDate > dc.maxDate) {
665										dateObj = dc.maxDate;
666									}
667
668								} else {
669									// set to initialDate config value
670									dateObj = dc.initialDate;
671								}
672							}
673
674							dc.date = dateObj;
675							dc.setCurrent(dc);
676							dc.fn.current = {};
677							$A.internal.extend(true, dc.fn.current, dc.range.current);
678						},
679						runOnceBefore: function(dc){
680							// If we have minDate / maxDate set, ensure they don't have time precision, and create comparison value
681							if (dc.minDate) {
682								dc.minDate.setHours(0, 0, 0, 0);
683								dc.minDateComparisonValue = dc.createDateComparisonValue(dc.minDate);
684							}
685							if (dc.maxDate) {
686								dc.maxDate.setHours(0, 0, 0, 0);
687								dc.maxDateComparisonValue = dc.createDateComparisonValue(dc.maxDate);
688							}
689
690							// set date to initialDate
691							this.setDate(dc);
692
693							// Cache current date for comparison
694							dc.currentDate = new Date();
695							dc.currentDateComparisonValue = dc.createDateComparisonValue(dc.currentDate);
696						},
697						runBefore: function(dc){
698							// Run custom specified function?
699							if (typeof config.runBefore === 'function'){
700								config.runBefore(dc);
701							}
702
703							// based on config option, disable weekdays?
704							if (dc.disableWeekdays) {
705								dc.setWeekdaysDisabled(dc, dc.date, true);
706							}
707
708							// based on config option, disable weekends?
709							if (dc.disableWeekends) {
710								dc.setWeekendsDisabled(dc, dc.date, true);
711							}
712
713							if (config.ajax && typeof config.ajax === 'function' && !dc.stopAjax && !dc.ajaxLoading){
714								dc.ajaxLoading = dc.cancel = true;
715								dc.fn.navBtn = dc.navBtn;
716								config.ajax.apply(dc, [dc, false]);
717							}
718
719							if (dc.range.current.month === 1)
720								dc.range[1].max = (new Date(dc.range.current.year, 1, 29).getMonth() == 1) ? 29 : 28;
721							dc.baseId = 'b' + $A.genId();
722							dc.prevBtnId = dc.baseId + 'p';
723							dc.nextBtnId = dc.baseId + 'n';
724
725							// Calculate prev/next month date values, and whether they are within the allowed date range
726							var prevDateValues = dc.modifyDateValues(
727												{
728									month: dc.range.current.month,
729									year: dc.range.current.year
730												},
731												{
732														month: -1
733												}
734											);
735
736							var prevMonth = new Date();
737							prevMonth.setMonth(prevDateValues.month);
738							prevMonth.setFullYear(prevDateValues.year);
739
740							var nextDateValues = dc.modifyDateValues(
741								{
742									month: dc.range.current.month,
743									year: dc.range.current.year
744								},
745								{
746									month: 1
747								}
748							);
749
750							var nextMonth = new Date();
751							nextMonth.setMonth(nextDateValues.month);
752							nextMonth.setFullYear(nextDateValues.year);
753
754							// Draw the year display and prev/next year buttons?
755							var yearSelector = '';
756
757							if (!config.condenseYear){
758								var hasPrevYear = !dc.isOutsideDateRange(new Date((dc.range.current.year - 1), 0, 1)),
759									hasNextYear = !dc.isOutsideDateRange(new Date((dc.range.current.year + 1), 0, 1));
760
761								yearSelector = '<tr class="yearSelector" role="presentation">' +
762									'<td class="nav prev btn year' + (!hasPrevYear ? ' disabled' : '') + '" accesskey="1" title="'
763									+ dc.prevTxt.replace(/<|>|\"/g, '') + ' '
764									+ dc.yearTxt.replace(/<|>|\"/g, '') + '" aria-label="' + dc.prevTxt.replace(/<|>|\"/g, '') + ' '
765									+ dc.yearTxt.replace(/<|>|\"/g, '') + '"'
766									+ (!hasPrevYear ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"')
767									+ ' role="button" id="' + dc.prevBtnId + 'Y"><span aria-hidden="true">' + dc.leftButtonYearText + '</span></td>' +
768									'<td title="'
769									+ dc.tooltipTxt.replace(/<|>|\"/g, '') + '" colspan="5" class="year" role="presentation"><span>'
770									+ dc.range.current.year + '</span></td>' +
771									'<td class="nav next nav prev btn' + (!hasNextYear ? ' disabled' : '') + '" accesskey="2" title="'
772									+ dc.nextTxt.replace(/<|>|\"/g, '') + ' '
773									+ dc.yearTxt.replace(/<|>|\"/g, '') + '" aria-label="' + dc.nextTxt.replace(/<|>|\"/g, '') + ' '
774									+ dc.yearTxt.replace(/<|>|\"/g, '') + '"'
775									+ (!hasNextYear ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"')
776									+ ' role="button" id="' + dc.nextBtnId + 'Y"><span aria-hidden="true">' + dc.rightButtonYearText + '</span></td></tr>';
777							}
778
779							// Draw the month display and prev/next month buttons
780							var hasPrevMonth = !dc.isOutsideDateRange(new Date(prevDateValues.year, prevDateValues.month, dc.range[prevDateValues.month].max)),
781							hasNextMonth = !dc.isOutsideDateRange(new Date(nextDateValues.year, nextDateValues.month, 1));
782
783							var monthSelector = '<tr class="monthSelector" role="presentation">' +
784								'<td class="nav prev btn month' + (!hasPrevMonth ? ' disabled' : '') + '" accesskey="3" title="'
785								+ dc.prevTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '" aria-label="'
786								+ dc.prevTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '"'
787								+ (!hasPrevMonth ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"')
788								+ ' role="button" id="' + dc.prevBtnId + '"><span aria-hidden="true">' + dc.leftButtonMonthText + '</span></td>' +
789								'<td colspan="5" class="month" role="presentation"><span>'
790								+ dc.range[dc.range.current.month].name + (!config.condenseYear ? '' : ' ' + dc.range.current.year) + '</span></td>' +
791								'<td class="nav next btn month' + (!hasNextMonth ? ' disabled' : '') + '" accesskey="4" title="'
792								+ dc.nextTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '" aria-label="'
793								+ dc.nextTxt.replace(/<|>|\"/g, '') + ' ' + dc.monthTxt.replace(/<|>|\"/g, '') + '"'
794								+ (!hasNextMonth ? ' aria-disabled="true" tabindex="-1"' : ' tabindex="0"')
795								+ ' role="button" id="' + dc.nextBtnId + '"><span aria-hidden="true">' + dc.rightButtonMonthText + '</span></td></tr>';
796
797							// Start constructing the Datepicker table element
798							dc.source = '<table role="application" class="calendar" aria-label="' + dc.role
799								+ '">' + yearSelector + monthSelector + '<tr role="presentation">';
800							dc.iter = 0;
801
802							// Draw day headers
803							for (var i = 0; i < 7; i++){
804								var di = dc.getWDay(dc, i), d = dc.range.wDays[di];
805
806								if (!i){
807									dc.iter = dc.iterE = (di + 6) > 6 ? -1 + di : di + 6;
808									dc.iterS = di;
809								}
810								dc.source += '<th scope="col" class="week" title="' + d.lng + '" role="presentation"><span>' + d.shrt
811									+ '</span></th>';
812							}
813							dc.source += '</tr><tr role="presentation">';
814
815							// Start drawing day cells
816							var m = new Date();
817							m.setDate(1);
818							m.setMonth(dc.range.current.month);
819							m.setFullYear(dc.range.current.year);
820
821							var f = m.getDay();
822							m.setDate(dc.range[dc.range.current.month].max);
823							var e = m.getDay(),
824								w = dc.iterS;
825
826							// Draw the full calendar? (a full grid containing previous / next month cells)
827							if (dc.drawFullCalendar === true){
828								var daysInMonth = (new Date(prevDateValues.year, (prevDateValues.month + 1), 0)).getDate(),
829									counter = (daysInMonth - (new Date(dc.range.current.year, dc.range.current.month, 0)).getDay() + dc.range.wdOffset);
830							}
831
832							while (w != f){
833								w = (w + 1) > 6 ? 0 : w + 1;
834
835								if (dc.drawFullCalendar === true){
836									prevMonth.setDate(counter);
837									dc.source += dc.createDayCell(counter, prevMonth, 'dayInPrevMonth', dc.isDisabledDate(dc, counter, prevMonth));
838									++counter;
839
840								} else{
841									dc.source += '<td class="empty" role="presentation"><span>&nbsp;</span></td>';
842								}
843							}
844
845							dc.range.track = {};
846
847							for (var i = 1; i <= 31; i++){
848								dc.range.track[dc.baseId + i] = i;
849							}
850
851							for (var i = 1; i <= dc.range[dc.range.current.month].max; i++){
852								m.setDate(i);
853
854								var isSelected = ((i == dc.fn.current.mDay) && (dc.range.current.month == dc.fn.current.month) &&
855									(dc.range.current.year == dc.fn.current.year));
856
857								// Draw calendar day cell
858								dc.source += dc.createDayCell(i, m, 'dayInMonth', dc.isDisabledDate(dc, i, m), isSelected);
859
860								var w = m.getDay();
861
862								if (w == dc.iter && i < dc.range[dc.range.current.month].max)
863									dc.source += '</tr><tr role="presentation">';
864							}
865
866							if (dc.drawFullCalendar === true){
867								var counter = 1;
868							}
869
870							while (e != dc.iter){
871								e = (e + 1) > 6 ? 0 : e + 1;
872
873								if (dc.drawFullCalendar === true){
874									nextMonth.setDate(counter);
875									dc.source += dc.createDayCell(counter, nextMonth, 'dayInNextMonth', dc.isDisabledDate(dc, counter, nextMonth));
876									++counter;
877
878								} else{
879									dc.source += '<td class="empty" role="presentation"><span>&nbsp;</span></td>';
880								}
881							}
882							dc.source += '</tr></table>';
883
884							// if a message is set for the month, draw it
885							if (dc.range[dc.range.current.month].message[dc.range.current.year]){
886								dc.source +=
887									'<div class="monthMessage">' +
888									'	<p>' + dc.range[dc.range.current.month].message[dc.range.current.year] + '</p>' +
889									'</div>';
890							}
891
892							// Close other calendar pickers that are currently open
893							$A.find('*', function(dc){
894								if (dc.controlType && dc.controlType == 'DatePicker' && dc.loaded)
895									dc.close();
896							});
897						},
898						click: function(ev, dc){
899							ev.stopPropagation();
900						},
901						runDuring: function(dc){
902							dc.datepickerLoaded = false;
903							$A.bind('body', 'click.datepicker', function(ev){
904								if (dc.datepickerLoaded)
905									dc.close();
906							});
907
908							$A.setAttr(dc.accDCObj,
909											{
910											role: 'dialog',
911											'data-helptext': dc.helpText,
912											'aria-label': dc.role
913											});
914
915							dc.fn.sraStart.innerHTML = dc.fn.sraEnd.innerHTML = '';
916							$A.setAttr(dc.fn.sraStart,
917											{
918											'aria-hidden': 'true'
919											});
920
921							$A.setAttr(dc.fn.sraEnd,
922											{
923											'aria-hidden': 'true'
924											});
925						},
926						runAfter: function(dc){
927							dc.buttons =
928											{
929											pY: config.condenseYear ? null : $A.getEl(dc.prevBtnId + 'Y'),
930											nY: config.condenseYear ? null : $A.getEl(dc.nextBtnId + 'Y'),
931											pM: $A.getEl(dc.prevBtnId),
932											nM: $A.getEl(dc.nextBtnId)
933											};
934
935							if (!config.condenseYear && dc.disableNavPrevYearBtn)
936								$A.setAttr(dc.buttons.pY, 'aria-disabled', 'true');
937
938							if (!config.condenseYear && dc.disableNavNextYearBtn)
939								$A.setAttr(dc.buttons.nY, 'aria-disabled', 'true');
940
941							if (dc.disableNavPrevMonthBtn)
942								$A.setAttr(dc.buttons.pM, 'aria-disabled', 'true');
943
944							if (dc.disableNavNextMonthBtn)
945								$A.setAttr(dc.buttons.nM, 'aria-disabled', 'true');
946
947							if (!dc.prevCurrent)
948								dc.prevCurrent = {};
949							$A.internal.extend(true, dc.prevCurrent, dc.range.current);
950
951							var nMonth = function(){
952								if (dc.disableNavNextMonthBtn && ($A.getAttr(dc.buttons.nM, 'aria-disabled') == 'true'))
953									return;
954
955								$A.internal.extend(true, dc.prevCurrent, dc.range.current);
956
957								var dateValues = dc.modifyDateValues(
958									{
959										month: dc.range.current.month,
960										year: dc.range.current.year
961									},
962									{
963										month: 1
964									}
965								);
966
967								// Only change to next month if its first day is inside the valid date range
968								if(!dc.isOutsideDateRange(new Date(dateValues.year, dateValues.month, 1))){
969									var day = dc.range.current.mDay > dc.range[dateValues.month].max ? dc.range[dateValues.month].max : dc.range.current.mDay,
970										intendedDate = new Date(dateValues.year, dateValues.month, day);
971
972									// If intended selected date one month ahead is outside of date range, set
973									// selected date to the next available date
974									if (dc.isOutsideDateRange(intendedDate))
975										dc.date = dc.maxDate;
976									else
977										dc.date = intendedDate;
978								}
979
980								else {
981									dc.date = dc.maxDate;
982								}
983
984								dc.setCurrent(dc);
985								dc.reopen = true;
986								dc.open();
987
988							}, pMonth = function(){
989								if (dc.disableNavPrevMonthBtn && ($A.getAttr(dc.buttons.pM, 'aria-disabled') == 'true'))
990									return;
991
992								$A.internal.extend(true, dc.prevCurrent, dc.range.current);
993
994								var dateValues = dc.modifyDateValues(
995									{
996										month: dc.range.current.month,
997										year: dc.range.current.year
998									},
999									{
1000										month: -1
1001									}
1002								);
1003
1004								// Only change to previous month if its last day is inside the valid date range
1005								if(!dc.isOutsideDateRange(new Date(dateValues.year, dateValues.month, dc.range[dateValues.month].max))){
1006									var day = dc.range.current.mDay > dc.range[dateValues.month].max ? dc.range[dateValues.month].max : dc.range.current.mDay,
1007										intendedDate = new Date(dateValues.year, dateValues.month, day);
1008
1009									// If intended selected date one month previously is outside of date range, set
1010									// selected date to the next available date
1011									if(dc.isOutsideDateRange(intendedDate))
1012										dc.date = dc.minDate;
1013									else
1014										dc.date = intendedDate;
1015								}
1016
1017								else{
1018									dc.date = dc.minDate;
1019								}
1020
1021								dc.setCurrent(dc);
1022								dc.reopen = true;
1023								dc.open();
1024
1025							}, gYear = function(forward){
1026								if ((!forward && ((!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') == 'true')
1027									|| (config.condenseYear && dc.disableNavPrevYearBtn)))) {
1028
1029									return;
1030
1031								} else if ((forward && ((!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') == 'true')
1032										|| (config.condenseYear && dc.disableNavNextYearBtn)))) {
1033
1034									return;
1035								}
1036
1037								$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1038
1039								var month = dc.range.current.month,
1040									year = forward ? dc.range.current.year + 1 : dc.range.current.year - 1;
1041
1042								if (month === 1)
1043									dc.range[1].max = 28;
1044								var day = dc.range.current.mDay > dc.range[month].max ? dc.range[month].max : dc.range.current.mDay;
1045
1046								// Only change year if the intended date is inside of any set date range
1047								var intendedDate = new Date(year, month, day);
1048
1049								if (dc.isOutsideDateRange(intendedDate)){
1050									return;
1051								}
1052
1053								dc.date = intendedDate;
1054								dc.setCurrent(dc);
1055								dc.reopen = true;
1056								dc.open();
1057							};
1058							var isKP = false;
1059							$A.bind('#' + dc.containerDivId + ' td.day',
1060											{
1061											focus: function(ev){
1062												if ($A.hasClass(this, 'comment')){
1063													var tooltipDC = dc.children[0], year = dc.range[dc.range.current.month].comments[dc.range.current.year],
1064														all = dc.range[dc.range.current.month].comments['*'], comm = '';
1065
1066													if (year && year[dc.range.current.mDay])
1067														comm = year[dc.range.current.mDay];
1068
1069													else if (all && all[dc.range.current.mDay])
1070														comm = all[dc.range.current.mDay];
1071													comm = trim(comm.replace(/<|>/g, ''));
1072
1073													if (comm){
1074														tooltipDC.source = comm;
1075														tooltipDC.open();
1076													}
1077												}
1078
1079												else if (dc.children[0].loaded)
1080													dc.children[0].close();
1081
1082												if (dc.children[1].openEditor){
1083													dc.children[1].openEditor = false;
1084													dc.children[1].reset();
1085												}
1086											},
1087											click: function(ev){
1088												// If items from a previous / next month are selected, modify the date accordingly
1089												if ($A.hasClass(this, 'dayInPrevMonth')){
1090													var prevDateValues = dc.modifyDateValues(
1091														{
1092															month: dc.range.current.month,
1093															year: dc.range.current.year
1094														},
1095														{
1096															month: -1
1097														}
1098													);
1099
1100													dc.date = new Date(prevDateValues.year, prevDateValues.month, dc.range.track[this.id]);
1101
1102												} else if ($A.hasClass(this, 'dayInNextMonth')){
1103													var nextDateValues = dc.modifyDateValues(
1104														{
1105															month: dc.range.current.month,
1106															year: dc.range.current.year
1107														},
1108														{
1109															month: 1
1110														}
1111													);
1112
1113													dc.date = new Date(nextDateValues.year, nextDateValues.month, dc.range.track[this.id]);
1114
1115												} else {
1116													// Selection in current month, just adjust the date
1117													dc.date.setDate(dc.range.track[this.id]);
1118												}
1119
1120												dc.setCurrent(dc);
1121
1122												if ($A.hasClass(this, 'selected') || (!commentsEnabled && !$A.hasClass(this, 'comment'))){
1123													if ($A.getAttr(this, 'aria-disabled') != 'true'){
1124														$A.internal.extend(true, dc.fn.current, dc.range.current);
1125														handleClick.apply(this, [ev, dc, targ]);
1126													}
1127
1128													else{
1129														ev.stopPropagation();
1130														ev.preventDefault();
1131													}
1132												}
1133
1134												else
1135													dc.setFocus(this);
1136												ev.preventDefault();
1137											},
1138											keydown: function(ev){
1139												changePressed(ev);
1140												var k = ev.which || ev.keyCode;
1141
1142												if (k == 13){
1143													isKP = true;
1144
1145													if ($A.getAttr(this, 'aria-disabled') != 'true'){
1146														$A.internal.extend(true, dc.fn.current, dc.range.current);
1147														handleClick.apply(this, [ev, dc, targ]);
1148													}
1149
1150													ev.preventDefault();
1151												}
1152
1153												else if (k == 32 && commentsEnabled && config.editor && config.editor.show && !dc.children[1].openEditor){
1154													dc.children[1].openEditor = true;
1155													dc.children[1].reset();
1156													ev.preventDefault();
1157												}
1158
1159												else if ((k >= 37 && k <= 40) || k == 27 || (k >= 33 && k <= 36)){
1160													var wd = dc.range.current.wDay;
1161
1162													if (k == 37){
1163														// Left arrow key
1164														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1165
1166														if (dc.range.current.mDay > 1){
1167															dc.range.current.mDay--;
1168															dc.range.current.wDay = !wd ? 6 : wd - 1;
1169
1170															dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this);
1171														}
1172
1173														else if (dc.range.current.mDay == 1
1174															&& $A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true'){
1175
1176															var dateValues = dc.modifyDateValues(
1177																{
1178																	month: dc.range.current.month,
1179																	year: dc.range.current.year
1180																},
1181																{
1182																	month: -1
1183																}
1184															);
1185															var day = dc.range[dateValues.month].max;
1186
1187															if (dateValues.month === 1)
1188																day = (new Date(dateValues.year, 1, 29).getMonth() == 1) ? 29 : 28;
1189
1190															dc.date = new Date(dateValues.year, dateValues.month, day);
1191															dc.setCurrent(dc);
1192															dc.reopen = true;
1193															dc.open();
1194														}
1195													}
1196
1197													else if (k == 39){
1198														// Right arrow key
1199														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1200
1201														if (dc.range.current.mDay < dc.range[dc.range.current.month].max){
1202															dc.range.current.mDay++;
1203															dc.range.current.wDay = wd == 6 ? 0 : wd + 1;
1204
1205															dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this);
1206														}
1207
1208														else if (dc.range.current.mDay == dc.range[dc.range.current.month].max
1209															&& $A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true'){
1210
1211															var dateValues = dc.modifyDateValues(
1212																{
1213																	month: dc.range.current.month,
1214																	year: dc.range.current.year
1215																},
1216																{
1217																	month: 1
1218																}
1219															);
1220
1221															dc.date = new Date(dateValues.year, dateValues.month, 1);
1222															dc.setCurrent(dc);
1223															dc.reopen = true;
1224															dc.open();
1225														}
1226													}
1227
1228													else if (k == 38){
1229														// Up arrow key
1230														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1231
1232														if ((dc.range.current.mDay - 7) > 0){
1233															dc.range.current.mDay -= 7;
1234
1235															dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this);
1236														}
1237
1238														else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true'){
1239															// Go to previous month
1240															var dateValues = dc.modifyDateValues(
1241																{
1242																	month: dc.range.current.month,
1243																	year: dc.range.current.year
1244																},
1245																{
1246																	month: -1
1247																}
1248															);
1249
1250															if (dateValues.month === 1 && (new Date(dateValues.year, 1, 29).getMonth() == 1))
1251																dc.range[dateValues.month].max = 29;
1252
1253															else if (dateValues.month === 1)
1254																dc.range[dateValues.month].max = 28;
1255
1256															var day = dc.range[dateValues.month].max + (dc.range.current.mDay - 7),
1257																intendedDate = new Date(dateValues.year, dateValues.month, day);
1258
1259															// If intended selected date one month previous is outside of date range, do not attempt
1260															// to select the date cell
1261															if (!dc.isOutsideDateRange(intendedDate)){
1262																dc.date = intendedDate;
1263																dc.setCurrent(dc);
1264																dc.reopen = true;
1265																dc.open();
1266															}
1267														}
1268													}
1269
1270													else if (k == 40){
1271														// Down arrow key
1272														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1273
1274														if ((dc.range.current.mDay + 7) <= dc.range[dc.range.current.month].max){
1275															dc.range.current.mDay += 7;
1276
1277															dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this);
1278														}
1279
1280														else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true'){
1281															// Go to next month
1282															var dateValues = dc.modifyDateValues(
1283																{
1284																	month: dc.range.current.month,
1285																	year: dc.range.current.year
1286																},
1287																{
1288																	month: 1
1289																}
1290															);
1291
1292															var day = dc.range.current.mDay + 7 - dc.range[dc.range.current.month].max,
1293																intendedDate = new Date(dateValues.year, dateValues.month, day);
1294
1295															// If intended selected date one month ahead is outside of date range, do not attempt
1296															// to select the date cell
1297															if (!dc.isOutsideDateRange(intendedDate)){
1298																dc.date = intendedDate;
1299																dc.setCurrent(dc);
1300																dc.reopen = true;
1301																dc.open();
1302															}
1303														}
1304													}
1305
1306													else if (k == 27){
1307														// Esc key
1308														dc.close();
1309													}
1310
1311													else if (k == 33){
1312														// PageUp key
1313														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1314
1315														if (dc.pageUpDownNatural === true){
1316															if (pressed.alt){
1317																gYear(false);
1318															} else{
1319																pMonth();
1320															}
1321
1322														} else{
1323															if (pressed.alt){
1324																gYear(true);
1325															} else{
1326																nMonth();
1327															}
1328														}
1329													}
1330
1331													else if (k == 34){
1332														// PageDown key
1333														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1334
1335														if (dc.pageUpDownNatural === true){
1336															if (pressed.alt){
1337																gYear(true);
1338															} else{
1339																nMonth();
1340															}
1341
1342														} else{
1343															if (pressed.alt){
1344																gYear(false);
1345															} else{
1346																pMonth();
1347															}
1348														}
1349													}
1350
1351													else if (k == 36){
1352														// Home key (goes to the first day of the row)
1353														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1354
1355														if (wd != dc.iterS && dc.range.current.mDay > 1){
1356															while (dc.range.current.wDay != dc.iterS && $A.getEl(dc.baseId + (dc.range.current.mDay - 1))){
1357																dc.range.current.wDay = (dc.range.current.wDay - 1) < 0 ? 6 : dc.range.current.wDay - 1;
1358																dc.range.current.mDay--;
1359															}
1360															dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this);
1361														}
1362													}
1363
1364													else if (k == 35){
1365														// End key (goes to the last day of the row)
1366														$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1367
1368														if (wd != dc.iterE && dc.range.current.mDay < dc.range[dc.range.current.month].max){
1369															while (dc.range.current.wDay != dc.iterE && $A.getEl(dc.baseId + (dc.range.current.mDay + 1))){
1370																dc.range.current.wDay = (dc.range.current.wDay + 1) > 6 ? 0 : dc.range.current.wDay + 1;
1371																dc.range.current.mDay++;
1372															}
1373															dc.setFocus(dc.range.index[dc.range.current.mDay - 1], this);
1374														}
1375													}
1376													ev.preventDefault();
1377												}
1378
1379												else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){
1380													// Tab key (without any simultaneous modifiers Alt / Ctrl / Shift)
1381													$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1382
1383													if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true')
1384														dc.buttons.pY.focus();
1385
1386													else if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true')
1387														dc.buttons.nY.focus();
1388
1389													else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true')
1390														dc.buttons.pM.focus();
1391
1392													else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true')
1393														dc.buttons.nM.focus();
1394
1395													ev.preventDefault();
1396												}
1397
1398												else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){
1399													// Tab key (with simultaneous Shift modifier)
1400													$A.internal.extend(true, dc.prevCurrent, dc.range.current);
1401
1402													if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true')
1403														dc.buttons.nM.focus();
1404
1405													else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true')
1406														dc.buttons.pM.focus();
1407
1408													else if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true')
1409														dc.buttons.nY.focus();
1410
1411													else if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true')
1412														dc.buttons.pY.focus();
1413
1414													ev.preventDefault();
1415												}
1416											},
1417											keyup: function(ev){
1418												changePressed(ev);
1419												var k = ev.which || ev.keyCode;
1420
1421												if (k == 13 && !isKP && !dc.isAdd){
1422													if ($A.getAttr(this, 'aria-disabled') != 'true'){
1423														$A.internal.extend(true, dc.fn.current, dc.range.current);
1424
1425														if (!dc.setFocus.firstOpen)
1426															handleClick.apply(this, [ev, dc, targ]);
1427													}
1428
1429													ev.preventDefault();
1430												}
1431
1432												isKP = dc.setFocus.firstOpen = dc.isAdd = false;
1433											}
1434											});
1435
1436							$A.bind(dc.buttons.pM,
1437											{
1438											click: function(ev){
1439												dc.navBtn = 'PM';
1440												pMonth();
1441												ev.preventDefault();
1442											},
1443											keydown: function(ev){
1444												changePressed(ev);
1445												var k = ev.which || ev.keyCode;
1446
1447												if (k == 13 || k == 32){
1448													dc.navBtn = 'PM';
1449													pMonth();
1450													ev.preventDefault();
1451												}
1452
1453												else if (k == 27){
1454													dc.close();
1455													ev.preventDefault();
1456												}
1457
1458												else if (!config.condenseYear && k == 38){
1459													dc.buttons.pY.focus();
1460													ev.preventDefault();
1461												}
1462
1463												else if (k == 39){
1464													dc.buttons.nM.focus();
1465													ev.preventDefault();
1466												}
1467
1468												else if (k == 37 || k == 40){
1469													ev.preventDefault();
1470												}
1471
1472												else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){
1473													if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true')
1474														dc.buttons.nM.focus();
1475
1476													else
1477														$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1478
1479													ev.preventDefault();
1480												}
1481
1482												else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){
1483													if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true')
1484														dc.buttons.nY.focus();
1485
1486													else if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true')
1487														dc.buttons.pY.focus();
1488
1489													else
1490														$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1491
1492													ev.preventDefault();
1493												}
1494											},
1495											keyup: function(ev){
1496												changePressed(ev);
1497											}
1498											});
1499							$A.bind(dc.buttons.nM,
1500											{
1501											click: function(ev){
1502												dc.navBtn = 'NM';
1503												nMonth();
1504												ev.preventDefault();
1505											},
1506											keydown: function(ev){
1507												changePressed(ev);
1508												var k = ev.which || ev.keyCode;
1509
1510												if (k == 13 || k == 32){
1511													dc.navBtn = 'NM';
1512													nMonth();
1513													ev.preventDefault();
1514												}
1515
1516												else if (k == 27){
1517													dc.close();
1518													ev.preventDefault();
1519												}
1520
1521												else if (!config.condenseYear && k == 38){
1522													dc.buttons.nY.focus();
1523													ev.preventDefault();
1524												}
1525
1526												else if (k == 37){
1527													dc.buttons.pM.focus();
1528													ev.preventDefault();
1529												}
1530
1531												else if (k == 39 || k == 40){
1532													ev.preventDefault();
1533												}
1534
1535												else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){
1536													$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1537													ev.preventDefault();
1538												}
1539
1540												else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){
1541													if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true')
1542														dc.buttons.pM.focus();
1543
1544													else if (!config.condenseYear && $A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true')
1545														dc.buttons.nY.focus();
1546
1547													else if (!config.condenseYear && $A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true')
1548														dc.buttons.pY.focus();
1549
1550													else
1551														$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1552
1553													ev.preventDefault();
1554												}
1555											},
1556											keyup: function(ev){
1557												changePressed(ev);
1558											}
1559											});
1560
1561							if (!config.condenseYear)
1562								$A.bind(dc.buttons.pY,
1563												{
1564												click: function(ev){
1565													dc.navBtn = 'PY';
1566													gYear();
1567													ev.preventDefault();
1568												},
1569												keydown: function(ev){
1570													changePressed(ev);
1571													var k = ev.which || ev.keyCode;
1572
1573													if (k == 13 || k == 32){
1574														dc.navBtn = 'PY';
1575														gYear();
1576														ev.preventDefault();
1577													}
1578
1579													else if (k == 27){
1580														dc.close();
1581														ev.preventDefault();
1582													}
1583
1584													else if (k == 39){
1585														dc.buttons.nY.focus();
1586														ev.preventDefault();
1587													}
1588
1589													else if (k == 40){
1590														dc.buttons.pM.focus();
1591														ev.preventDefault();
1592													}
1593
1594													else if (k == 37 || k == 38){
1595														ev.preventDefault();
1596													}
1597
1598													else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){
1599														if ($A.getAttr(dc.buttons.nY, 'aria-disabled') != 'true')
1600															dc.buttons.nY.focus();
1601
1602														else if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true')
1603															dc.buttons.pM.focus();
1604
1605														else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true')
1606															dc.buttons.nM.focus();
1607
1608														else
1609															$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1610
1611														ev.preventDefault();
1612													}
1613
1614													else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){
1615														$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1616														ev.preventDefault();
1617													}
1618												},
1619												keyup: function(ev){
1620													changePressed(ev);
1621												}
1622												});
1623
1624							if (!config.condenseYear)
1625								$A.bind(dc.buttons.nY,
1626												{
1627												click: function(ev){
1628													dc.navBtn = 'NY';
1629													gYear(true);
1630													ev.preventDefault();
1631												},
1632												keydown: function(ev){
1633													changePressed(ev);
1634													var k = ev.which || ev.keyCode;
1635
1636													if (k == 13 || k == 32){
1637														dc.navBtn = 'NY';
1638														gYear(true);
1639														ev.preventDefault();
1640													}
1641
1642													else if (k == 27){
1643														dc.close();
1644														ev.preventDefault();
1645													}
1646
1647													else if (k == 37){
1648														dc.buttons.pY.focus();
1649														ev.preventDefault();
1650													}
1651
1652													else if (k == 40){
1653														dc.buttons.nM.focus();
1654														ev.preventDefault();
1655													}
1656
1657													else if (k == 38 || k == 39){
1658														ev.preventDefault();
1659													}
1660
1661													else if (k == 9 && !pressed.alt && !pressed.ctrl && !pressed.shift){
1662														if ($A.getAttr(dc.buttons.pM, 'aria-disabled') != 'true')
1663															dc.buttons.pM.focus();
1664
1665														else if ($A.getAttr(dc.buttons.nM, 'aria-disabled') != 'true')
1666															dc.buttons.nM.focus();
1667
1668														else
1669															$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1670
1671														ev.preventDefault();
1672													}
1673
1674													else if (k == 9 && !pressed.alt && !pressed.ctrl && pressed.shift){
1675														if ($A.getAttr(dc.buttons.pY, 'aria-disabled') != 'true')
1676															dc.buttons.pY.focus();
1677
1678														else
1679															$A.query('td.day[tabindex="0"]', dc.containerDiv)[0].focus();
1680
1681														ev.preventDefault();
1682													}
1683												},
1684												keyup: function(ev){
1685													changePressed(ev);
1686												}
1687												});
1688
1689							dc.range.index = $A.query('td.dayInMonth', dc.containerDiv);
1690							dc.setFocus.firstOpen = true;
1691
1692							dc.setFocus(dc.range.index[dc.range.current.mDay - 1]);
1693
1694							if (commentsEnabled && config.editor && config.editor.show)
1695								dc.children[1].open();
1696
1697							$A.bind(window, 'resize.datepicker', function(ev){
1698								dc.setPosition();
1699							});
1700
1701							$A.setAttr(dc.triggerObj, 'aria-expanded', 'true');
1702							setTimeout(function(){
1703								dc.datepickerLoaded = true;
1704							}, 750);
1705
1706							if (!dc.navBtnS){
1707								if (!('ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0))
1708									$A.announce(dc.helpText);
1709							}
1710							dc.navBtnS = false;
1711						},
1712						helpText: helpText,
1713						runAfterClose: function(dc){
1714							if (!dc.reopen){
1715								if (config.resetCurrent){
1716									dc.date = new Date();
1717									dc.setCurrent(dc);
1718									$A.internal.extend(true, dc.fn.current, dc.range.current);
1719								}
1720
1721								if (commentsEnabled)
1722									dc.children[0].close();
1723
1724								if (commentsEnabled && config.editor && config.editor.show){
1725									dc.children[1].lock = false;
1726									dc.children[1].close();
1727								}
1728							}
1729
1730							else
1731								dc.reopen = false;
1732
1733							if (config.ajax && typeof config.ajax === 'function')
1734								dc.lock = dc.ajaxLoading = false;
1735
1736							$A.unbind(window, '.datepicker');
1737							$A.unbind('body', '.datepicker');
1738
1739							$A.setAttr(dc.triggerObj, 'aria-expanded', 'false');
1740
1741							// Run custom specified function?
1742							if (typeof config.runAfterClose === 'function'){
1743								config.runAfterClose(dc);
1744							}
1745						}
1746						}
1747						]);
1748		// Calendar object declaration end
1749
1750		$A.setAttr(trigger, 'aria-expanded', 'false');
1751
1752		var odc = $A.reg[pId], odcDel = false, odcDelFn = function(){
1753			odcDel = false;
1754		};
1755		$A.bind(trigger, 'click', function(ev){
1756			if (!odcDel && !odc.loaded){
1757				odcDel = true;
1758				$A.trigger(this, 'opendatepicker');
1759				setTimeout(odcDelFn, 1000);
1760			}
1761
1762			else if (!odcDel && odc.loaded){
1763				odcDel = true;
1764				odc.close();
1765				setTimeout(odcDelFn, 1000);
1766			}
1767			ev.preventDefault();
1768		});
1769
1770		// Comment object declaration start
1771		$A($A.reg[pId],
1772						[
1773						{
1774						id: pId + 'commentTooltip',
1775						role: config.comments && config.comments.role || 'Comment',
1776						returnFocus: false,
1777						showHiddenClose: false,
1778						allowReopen: true,
1779						autoPosition: isNaN(config.comments && config.comments.autoPosition) ? 1 : config.comments.autoPosition,
1780						offsetTop: isNaN(config.comments && config.comments.offsetTop) ? 0 : config.comments.offsetTop,
1781						offsetLeft: isNaN(config.comments && config.comments.offsetLeft) ? 0 : config.comments.offsetLeft,
1782						cssObj:
1783										{
1784										position: 'absolute',
1785										zIndex: $A.reg[pId].cssObj.zIndex
1786										},
1787						className: config.comments && config.comments.className || 'commentTooltip',
1788						runBefore: function(dc){
1789							dc.triggerObj = dc.parent.accDCObj;
1790						}
1791						}
1792						]);
1793		// Comment object declaration end
1794
1795		// Form object declaration start
1796		$A($A.reg[pId],
1797						[
1798						{
1799						id: pId + 'commentAdd',
1800						role: config.editor && config.editor.role || 'Edit',
1801						returnFocus: false,
1802						allowReopen: true,
1803						autoPosition: isNaN(config.editor && config.editor.autoPosition) ? 6 : config.editor.autoPosition,
1804						offsetTop: isNaN(config.editor && config.editor.offsetTop) ? 0 : config.editor.offsetTop,
1805						offsetLeft: isNaN(config.editor && config.editor.offsetLeft) ? 0 : config.editor.offsetLeft,
1806						cssObj:
1807										{
1808										position: 'absolute',
1809										zIndex: $A.reg[pId].cssObj.zIndex
1810										},
1811						className: config.editor && config.editor.className || 'commentAdd',
1812						openEditor: false,
1813						source: '<textarea style="visibility: hidden; display: none;" class="commentTa" title="'
1814							+ $A.reg[pId + 'commentTooltip'].role + '"></textarea><button title="'
1815							+ (config.editor && config.editor.role || 'Edit') + ' ' + $A.reg[pId + 'commentTooltip'].role
1816								+ '" class="commentBtn">' + (config.editor && config.editor.role || 'Edit') + '</button>',
1817						runBefore: function(dc){
1818							dc.triggerObj = dc.parent.accDCObj;
1819						},
1820						click: function(ev, dc){
1821							ev.stopPropagation();
1822						},
1823						runDuring: function(dc){
1824							$A.setAttr(dc.accDCObj,
1825											{
1826											role: 'dialog',
1827											'aria-label': dc.role
1828											});
1829
1830							$A.setAttr(dc.containerDiv, 'role', 'application');
1831
1832							dc.fn.sraStart.innerHTML = dc.fn.sraEnd.innerHTML = '';
1833							$A.setAttr(dc.fn.sraStart,
1834											{
1835											'aria-hidden': 'true'
1836											});
1837
1838							$A.setAttr(dc.fn.sraEnd,
1839											{
1840											'aria-hidden': 'true'
1841											});
1842						},
1843						add: function(dc){
1844							var comm = trim(dc.textarea.value.replace(/<|>|\n/g, ' '));
1845
1846							if (!dc.comments[dc.parent.range.current.year])
1847								dc.comments[dc.parent.range.current.year] = {};
1848							dc.comments[dc.parent.range.current.year][dc.parent.range.current.mDay] = comm;
1849							var lbl = dc.parent.range.current.mDay + ', ' + dc.parent.range.wDays[dc.parent.range.current.wDay].lng + ' '
1850								+ dc.parent.range[dc.parent.range.current.month].name + ' ' + dc.parent.range.current.year, pre = '';
1851
1852							if ((dc.parent.range[dc.parent.range.current.month].disabled[dc.parent.range.current.year]
1853								&& $A.inArray(dc.parent.range.current.mDay,
1854									dc.parent.range[dc.parent.range.current.month].disabled[dc.parent.range.current.year]) !== -1)
1855								|| (dc.parent.range[dc.parent.range.current.month].disabled['*'] && $A.inArray(dc.parent.range.current.mDay,
1856									dc.parent.range[dc.parent.range.current.month].disabled['*']) !== -1))
1857								pre += dc.parent.disabledTxt.replace(/<|>|\"/g, '') + ' ';
1858
1859							if (!comm)
1860								$A.remClass(dc.parent.current, 'comment');
1861
1862							else{
1863								$A.addClass(dc.parent.current, 'comment');
1864								pre += dc.parent.commentedTxt.replace(/<|>|\"/g, '') + ' ';
1865							}
1866							lbl = pre + lbl;
1867							$A.setAttr(dc.parent.current,
1868											{
1869											title: trim(pre),
1870											'aria-label': lbl + ' ' + comm.replace(/\"/g, '\"')
1871											});
1872						},
1873						reset: function(){
1874							var dc = this;
1875
1876							if (dc.openEditor){
1877								dc.comments = dc.parent.range[dc.parent.range.current.month].comments;
1878
1879								if (!dc.textarea)
1880									dc.textarea = $A.query('textarea', dc.containerDiv, function(){
1881										$A.css(this,
1882														{
1883														visibility: '',
1884														display: ''
1885														});
1886
1887										dc.css('left', dc.parent.accDCObj.offsetLeft);
1888										$A.bind(this,
1889														{
1890														focus: function(ev){
1891															if (dc.parent.children[0].loaded)
1892																dc.parent.children[0].close();
1893														},
1894														keydown: function(ev){
1895															var k = ev.which || ev.keyCode;
1896
1897															if (this.value.length > 800)
1898																this.value = this.value.substring(0, 799);
1899
1900															if (k == 13){
1901																dc.parent.isAdd = true;
1902																dc.add.apply(this, [dc]);
1903																dc.parent.current.focus();
1904																dc.openEditor = false;
1905																dc.reset();
1906																ev.preventDefault();
1907															}
1908
1909															else if (k == 27){
1910																dc.parent.current.focus();
1911																dc.openEditor = false;
1912																dc.reset();
1913																ev.preventDefault();
1914															}
1915														}
1916														});
1917									})[0];
1918
1919								else{
1920									$A.css(dc.textarea,
1921													{
1922													visibility: '',
1923													display: ''
1924													});
1925
1926									dc.css('left', dc.parent.accDCObj.offsetLeft);
1927								}
1928								$A.setAttr(dc.textarea,
1929												{
1930												title: dc.parent.range.current.mDay + ', '
1931													+ dc.parent.range.wDays[dc.parent.range.current.wDay].lng + ' '
1932													+ dc.parent.range[dc.parent.range.current.month].name + ' ' + dc.parent.range.current.year
1933												}).focus();
1934
1935								if (dc.comments[dc.parent.range.current.year]
1936									&& dc.comments[dc.parent.range.current.year][dc.parent.range.current.mDay])
1937									dc.textarea.value = dc.comments[dc.parent.range.current.year][dc.parent.range.current.mDay];
1938								$A.setAttr(dc.commentBtn,
1939												{
1940												title: (config.editor && config.editor.action1 || 'Save') + ' ' + $A.reg[pId + 'commentTooltip'].role
1941												}).innerHTML = config.editor && config.editor.action1 || 'Save';
1942							}
1943
1944							else{
1945								if (dc.textarea){
1946									dc.textarea.value = '';
1947									$A.css(dc.textarea,
1948													{
1949													visibility: 'hidden',
1950													display: 'none'
1951													});
1952								}
1953
1954								dc.css('left', dc.parent.accDCObj.offsetLeft + dc.parent.accDCObj.offsetWidth - dc.accDCObj.offsetWidth);
1955								$A.setAttr(dc.commentBtn,
1956												{
1957												title: (config.editor && config.editor.role || 'Edit') + ' ' + $A.reg[pId + 'commentTooltip'].role
1958												}).innerHTML = config.editor && config.editor.role || 'Edit';
1959							}
1960						},
1961						runAfter: function(dc){
1962							$A.query('button', dc.containerDiv, function(){
1963								dc.commentBtn = this;
1964								$A.bind(this,
1965												{
1966												focus: function(ev){
1967													if (dc.parent.children[0].loaded)
1968														dc.parent.children[0].close();
1969												},
1970												click: function(ev){
1971													if (dc.openEditor){
1972														dc.parent.isAdd = true;
1973														dc.add.apply(this, [dc]);
1974														dc.parent.current.focus();
1975														dc.openEditor = false;
1976														dc.reset();
1977													}
1978
1979													else{
1980														dc.openEditor = true;
1981														dc.reset();
1982													}
1983													ev.preventDefault();
1984												},
1985												keydown: function(ev){
1986													var k = ev.which || ev.keyCode;
1987
1988													if (k == 27){
1989														if (dc.openEditor){
1990															dc.parent.current.focus();
1991															dc.openEditor = false;
1992															dc.reset();
1993														}
1994
1995														ev.preventDefault();
1996													}
1997												}
1998												});
1999							});
2000							dc.reset();
2001							dc.lock = true;
2002
2003							$A.bind(window, 'resize.dateeditor', function(ev){
2004								dc.setPosition();
2005								dc.reset();
2006							});
2007
2008							$A.bind($A.query('textarea', dc.containerDiv)[0], 'keydown', function(ev){
2009								var k = ev.which || ev.keyCode;
2010
2011								if (k == 9 && !ev.altKey && !ev.ctrlKey && ev.shiftKey){
2012									$A.query('button', dc.containerDiv)[0].focus();
2013									ev.preventDefault();
2014								}
2015							});
2016						},
2017						tabOut: function(ev, dc){
2018							$A.query('textarea', dc.containerDiv)[0].focus();
2019						},
2020						runBeforeClose: function(dc){
2021							dc.openEditor = false;
2022							dc.textarea = null;
2023
2024							$A.unbind(window, 'resize.dateeditor');
2025
2026							if (config.ajax && typeof config.ajax === 'function')
2027								config.ajax.apply(dc.parent, [dc.parent, true]);
2028
2029							dc.parent.setFocus.firstOpen = true;
2030						},
2031						lock: commentsEnabled && config.editor && config.editor.show ? false : true
2032						}
2033						]);
2034	// Form object declaration end
2035
2036	};
2037
2038	var trim = function(str){
2039		return str.replace(/^\s+|\s+$/g, '');
2040	};
2041})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.