PageSourceSearch

https://www.mathjobs.org/styles/datepicker/datepicker.js

js mathjobs.org collected 2026-10-01 11:41:15 UTC 18,643 bytes, 77 lines download raw bytes

1'use strict';class DatePickerDialog{constructor(cdp){this.buttonLabelChoose='Choose Date';this.buttonLabelChange='Change Date';this.dayLabels=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday',];this.monthLabels=['January','February','March','April','May','June','July','August','September','October','November','December',];this.messageCursorKeys='Cursor keys can navigate dates';this.lastMessage='';this.textboxNode=cdp;this.buttonNode=document.getElementById(cdp.name+'-button');if(!this.buttonNode){var btn=document.createElement('button');btn.style.backgroundImage="url('/icons/cal.png')";btn.style.width="16px";btn.style.height="14px";btn.style.verticalAlign="middle";btn.style.margin="3px";btn.setAttribute('id',cdp.name+'-button');if(cdp.nextSibling){cdp.parentNode.insertBefore(btn,cdp.nextSibling);}else{cdp.parentNode.appendChild(btn);}
2this.buttonNode=btn;}
3this.dialogNode=document.getElementById(cdp.name+'-datepicker-dialog');if(!this.dialogNode){const div=document.createElement('div');div.setAttribute('class','datepicker-dialog');div.setAttribute('rolerole','dialog');div.setAttribute('aria-modal','true');div.setAttribute('aria-label','Choose Date');div.setAttribute('style','display: none;');div.setAttribute('id',cdp.name+'-datepicker-dialog');div.innerHTML='<div class="header">\n                <button type="button" class="prev-year" aria-label="previous year">&lt;&lt;\n                </button>\n\n                <button type="button" class="prev-month" aria-label="previous month">&lt;</button>\n\n                <h2 id="id-grid-label" class="month-year" aria-live="polite">October 2024</h2>\n\n                <button type="button" class="next-month" aria-label="next month">&gt;</button>\n\n                <button type="button" class="next-year" aria-label="next year">&gt;&gt;</button>\n              </div>\n\n              <table class="dates" role="grid" aria-labelledby="id-grid-label">\n                <thead>\n                  <tr>\n                    <th scope="col" abbr="Sunday">Su</th>\n                    <th scope="col" abbr="Monday">Mo</th>\n                    <th scope="col" abbr="Tuesday">Tu</th>\n                    <th scope="col" abbr="Wednesday">We</th>\n                    <th scope="col" abbr="Thursday">Th</th>\n                    <th scope="col" abbr="Friday">Fr</th>\n                    <th scope="col" abbr="Saturday">Sa</th>\n                  </tr>\n                </thead>\n\n                <tbody><tr><td tabindex="-1" data-date="2024-09-29" class="disabled"></td><td tabindex="-1" data-date="2024-09-30" class="disabled"></td><td tabindex="-1" data-date="2024-10-01">1</td><td tabindex="-1" data-date="2024-10-02">2</td><td tabindex="-1" data-date="2024-10-03">3</td><td tabindex="-1" data-date="2024-10-04">4</td><td tabindex="-1" data-date="2024-10-05">5</td></tr><tr><td tabindex="-1" data-date="2024-10-06">6</td><td tabindex="-1" data-date="2024-10-07">7</td><td tabindex="-1" data-date="2024-10-08">8</td><td tabindex="-1" data-date="2024-10-09">9</td><td tabindex="-1" data-date="2024-10-10">10</td><td tabindex="-1" data-date="2024-10-11">11</td><td tabindex="-1" data-date="2024-10-12">12</td></tr><tr><td tabindex="-1" data-date="2024-10-13">13</td><td tabindex="-1" data-date="2024-10-14">14</td><td tabindex="-1" data-date="2024-10-15">15</td><td tabindex="-1" data-date="2024-10-16">16</td><td tabindex="-1" data-date="2024-10-17">17</td><td tabindex="-1" data-date="2024-10-18">18</td><td tabindex="-1" data-date="2024-10-19">19</td></tr><tr><td tabindex="-1" data-date="2024-10-20">20</td><td tabindex="-1" data-date="2024-10-21">21</td><td tabindex="-1" data-date="2024-10-22">22</td><td tabindex="-1" data-date="2024-10-23">23</td><td tabindex="-1" data-date="2024-10-24">24</td><td tabindex="-1" data-date="2024-10-25">25</td><td tabindex="-1" data-date="2024-10-26">26</td></tr><tr><td tabindex="-1" data-date="2024-10-27">27</td><td tabindex="-1" data-date="2024-10-28">28</td><td tabindex="-1" data-date="2024-10-29">29</td><td tabindex="-1" data-date="2024-10-30">30</td><td tabindex="-1" data-date="2024-10-31">31</td><td tabindex="-1" data-date="2024-11-01" class="disabled"></td><td tabindex="-1" data-date="2024-11-02" class="disabled"></td></tr><tr style="display:none;"><td tabindex="-1" data-date="2024-11-03" class="disabled"></td>
3<td tabindex="-1" data-date="2024-11-04" class="disabled"></td><td tabindex="-1" data-date="2024-11-05" class="disabled"></td><td tabindex="-1" data-date="2024-11-06" class="disabled"></td><td tabindex="-1" data-date="2024-11-07" class="disabled"></td><td tabindex="-1" data-date="2024-11-08" class="disabled"></td><td tabindex="-1" data-date="2024-11-09" class="disabled"></td></tr></tbody>\n              </table>\n\n              <div class="dialog-ok-cancel-group">\n                <button class="dialog-button" value="today">Today</button>\n                <button class="dialog-button" value="cancel">Cancel</button>\n                <button class="dialog-button" value="ok">OK</button>\n              </div>\n              <div class="dialog-message" aria-live="polite"></div>';if(cdp.nextSibling){cdp.parentNode.insertBefore(div,cdp.nextSibling);}else{cdp.parentNode.appendChild(div);}
4this.dialogNode=div;}
5this.messageNode=this.dialogNode.querySelector('.dialog-message');this.monthYearNode=this.dialogNode.querySelector('.month-year');this.prevYearNode=this.dialogNode.querySelector('.prev-year');this.prevMonthNode=this.dialogNode.querySelector('.prev-month');this.nextMonthNode=this.dialogNode.querySelector('.next-month');this.nextYearNode=this.dialogNode.querySelector('.next-year');this.okButtonNode=this.dialogNode.querySelector('button[value="ok"]');this.cancelButtonNode=this.dialogNode.querySelector('button[value="cancel"]');this.todayButtonNode=this.dialogNode.querySelector('button[value="today"]');this.tbodyNode=this.dialogNode.querySelector('table.dates tbody');this.lastRowNode=null;this.days=[];this.focusDay=new Date();this.selectedDay=new Date(0,0,1);this.lastDate=-1;this.isMouseDownOnBackground=false;this.textboxNode.addEventListener('blur',this.setDateForButtonLabel.bind(this));this.buttonNode.addEventListener('keydown',this.handleButtonKeydown.bind(this));this.buttonNode.addEventListener('click',this.handleButtonClick.bind(this));this.okButtonNode.addEventListener('click',this.handleOkButton.bind(this));this.okButtonNode.addEventListener('keydown',this.handleOkButton.bind(this));this.cancelButtonNode.addEventListener('click',this.handleCancelButton.bind(this));this.cancelButtonNode.addEventListener('keydown',this.handleCancelButton.bind(this));this.todayButtonNode.addEventListener('click',this.handleTodayButton.bind(this));this.todayButtonNode.addEventListener('keydown',this.handleTodayButton.bind(this));this.prevMonthNode.addEventListener('click',this.handlePreviousMonthButton.bind(this));this.nextMonthNode.addEventListener('click',this.handleNextMonthButton.bind(this));this.prevYearNode.addEventListener('click',this.handlePreviousYearButton.bind(this));this.nextYearNode.addEventListener('click',this.handleNextYearButton.bind(this));this.prevMonthNode.addEventListener('keydown',this.handlePreviousMonthButton.bind(this));this.nextMonthNode.addEventListener('keydown',this.handleNextMonthButton.bind(this));this.prevYearNode.addEventListener('keydown',this.handlePreviousYearButton.bind(this));this.nextYearNode.addEventListener('keydown',this.handleNextYearButton.bind(this));document.body.addEventListener('pointerup',this.handleBackgroundMouseUp.bind(this),true);this.tbodyNode.innerHTML='';for(let i=0;i<6;i++){const row=this.tbodyNode.insertRow(i);this.lastRowNode=row;for(let j=0;j<7;j++){const cell=document.createElement('td');cell.tabIndex=-1;cell.addEventListener('click',this.handleDayClick.bind(this));cell.addEventListener('keydown',this.handleDayKeyDown.bind(this));cell.addEventListener('focus',this.handleDayFocus.bind(this));cell.textContent='-1';row.appendChild(cell);this.days.push(cell);}}
6this.updateGrid();this.close(false);this.setDateForButtonLabel();}
7isSameDay(day1,day2){return(day1.getFullYear()==day2.getFullYear()&&day1.getMonth()==day2.getMonth()&&day1.getDate()==day2.getDate());}
8isNotSameMonth(day1,day2){return(day1.getFullYear()!=day2.getFullYear()||day1.getMonth()!=day2.getMonth());}
9updateGrid(){const fd=this.focusDay;this.monthYearNode.textContent=this.monthLabels[fd.getMonth()]+' '+fd.getFullYear();let firstDayOfMonth=new Date(fd.getFullYear(),fd.getMonth(),1);let dayOfWeek=firstDayOfMonth.getDay();firstDayOfMonth.setDate(firstDayOfMonth.getDate()-dayOfWeek);const d=new Date(firstDayOfMonth);for(let i=0;i<this.days.length;i++){const flag=d.getMonth()!=fd.getMonth();this.updateDate(this.days[i],flag,d,this.isSameDay(d,this.selectedDay));d.setDate(d.getDate()+1);if(i===35){if(flag){this.lastRowNode.style.display='none';}else{this.lastRowNode.style.display='';}}}}
10updateDate(domNode,disable,day,selected){let d=day.getDate().toString();if(day.getDate()<=9){d='0'+d;}
11let m=day.getMonth()+1;if(day.getMonth()<9){m='0'+m;}
12domNode.tabIndex=-1;domNode.removeAttribute('aria-selected');domNode.setAttribute('data-date',day.getFullYear()+'-'+m+'-'+d);if(disable){domNode.classList.add('disabled');domNode.textContent='';}
12else{domNode.classList.remove('disabled');domNode.textContent=day.getDate();if(selected){domNode.setAttribute('aria-selected','true');domNode.tabIndex=0;}}}
13moveFocusToDay(day){const d=this.focusDay;this.focusDay=day;if(d.getMonth()!=this.focusDay.getMonth()||d.getFullYear()!=this.focusDay.getFullYear()){this.updateGrid();}
14this.setFocusDay();}
15setFocusDay(flag){if(typeof flag!=='boolean'){flag=true;}
16for(let i=0;i<this.days.length;i++){const dayNode=this.days[i];const day=this.getDayFromDataDateAttribute(dayNode);dayNode.tabIndex=-1;if(this.isSameDay(day,this.focusDay)){dayNode.tabIndex=0;if(flag){dayNode.focus();}}}}
17open(event){this.dialogNode.style.display='block';this.dialogNode.style.zIndex=2;const dL=parseInt(window.pageXOffset+event.clientX-this.dialogNode.clientWidth/2);if(dL>0)this.dialogNode.style.left=dL+'px';this.getDateFromTextbox();this.updateGrid();this.lastDate=this.focusDay.getDate();}
18isOpen(){return window.getComputedStyle(this.dialogNode).display!=='none';}
19close(flag){if(typeof flag!=='boolean'){flag=true;}
20this.setMessage('');this.dialogNode.style.display='none';if(flag){this.buttonNode.focus();}}
21changeMonth(currentDate,numMonths){const getDays=(year,month)=>new Date(year,month,0).getDate();const isPrev=numMonths<0;const numYears=Math.trunc(Math.abs(numMonths)/12);numMonths=Math.abs(numMonths)%12;const newYear=isPrev?currentDate.getFullYear()-numYears:currentDate.getFullYear()+numYears;const newMonth=isPrev?currentDate.getMonth()-numMonths:currentDate.getMonth()+numMonths;const newDate=new Date(newYear,newMonth,1);const daysInMonth=getDays(newDate.getFullYear(),newDate.getMonth()+1);this.lastDate=this.lastDate?this.lastDate:currentDate.getDate();if(this.lastDate>daysInMonth){newDate.setDate(daysInMonth);}else{newDate.setDate(this.lastDate);}
22return newDate;}
23moveToNextYear(){this.focusDay=this.changeMonth(this.focusDay,12);this.updateGrid();}
24moveToPreviousYear(){this.focusDay=this.changeMonth(this.focusDay,-12);this.updateGrid();}
25moveToNextMonth(){this.focusDay=this.changeMonth(this.focusDay,1);this.updateGrid();}
26moveToPreviousMonth(){this.focusDay=this.changeMonth(this.focusDay,-1);this.updateGrid();}
27moveFocusToNextDay(){const d=new Date(this.focusDay);d.setDate(d.getDate()+1);this.lastDate=d.getDate();this.moveFocusToDay(d);}
28moveFocusToNextWeek(){const d=new Date(this.focusDay);d.setDate(d.getDate()+7);this.lastDate=d.getDate();this.moveFocusToDay(d);}
29moveFocusToPreviousDay(){const d=new Date(this.focusDay);d.setDate(d.getDate()-1);this.lastDate=d.getDate();this.moveFocusToDay(d);}
30moveFocusToPreviousWeek(){const d=new Date(this.focusDay);d.setDate(d.getDate()-7);this.lastDate=d.getDate();this.moveFocusToDay(d);}
31moveFocusToFirstDayOfWeek(){const d=new Date(this.focusDay);d.setDate(d.getDate()-d.getDay());this.lastDate=d.getDate();this.moveFocusToDay(d);}
32moveFocusToLastDayOfWeek(){const d=new Date(this.focusDay);d.setDate(d.getDate()+(6-d.getDay()));this.lastDate=d.getDate();this.moveFocusToDay(d);}
33isDayDisabled(domNode){return domNode.classList.contains('disabled');}
34getDayFromDataDateAttribute(domNode){const parts=domNode.getAttribute('data-date').split('-');return new Date(parts[0],parseInt(parts[1])-1,parts[2]);}
35setTextboxDate(domNode){let d=this.focusDay;if(domNode){d=this.getDayFromDataDateAttribute(domNode);this.days.forEach((day)=>day===domNode?day.setAttribute('aria-selected','true'):day.removeAttribute('aria-selected'));}
36this.textboxNode.value=d.getFullYear()+'/'+(d.getMonth()+1)+'/'+d.getDate();this.setDateForButtonLabel();}
37getDateFromTextbox(){const parts=this.textboxNode.value.split('/');const month=parseInt(parts[1]);const day=parseInt(parts[2]);let year=parseInt(parts[0]);if(parts.length===3&&Number.isInteger(month)&&Number.isInteger(day)&&Number.isInteger(year)){if(year<100){year=2000+year;}
38this.focusDay=new Date(year,month-1,day);this.selectedDay=new Date(this.focusDay);}else{this.focusDay=new Date();this.selectedDay=new Date(0,0,1);}}
39setDateForButtonLabel(){const parts=this.textboxNode.value.split('/');if(parts.length===3&&Number.isInteger(parseInt(parts[0]))&&Number.isInteger(parseInt(parts[1]))&&Number.isInteger(parseInt(parts[2]))){const day=new Date(parseInt(parts[2]),parseInt(parts[0])-1,parseInt(parts[1]));let label=this.buttonLabelChange;label+=', '+this.dayLabels[day.getDay()];label+=' '+this.monthLabels[day.getMonth()];label+=' '+day.getDate();label+=', '+day.getFullYear();this.buttonNode.setAttribute('aria-label',label);}else{this.buttonNode.setAttribute('aria-label',this.buttonLabelChoose);}}
40setMessage(str){function setMessageDelayed(){this.messageNode.textContent=str;}
41if(str!==this.lastMessage){setTimeout(setMessageDelayed.bind(this),200);this.lastMessage=str;}}
42handleOkButton(event){let flag=false;switch(event.type){case'keydown':switch(event.key){case'Tab':if(!event.shiftKey){this.prevYearNode.focus();flag=true;}
43break;case'Esc':case'Escape':this.close();flag=true;break;default:break;}
44break;case'click':this.setTextboxDate();this.close();flag=true;break;default:break;}
45if(flag){event.stopPropagation();event.preventDefault();}}
46handleCancelButton(event){let flag=false;switch(event.type){case'keydown':switch(event.key){case'Esc':case'Escape':this.close();flag=true;break;default:break;}
47break;case'click':this.close();flag=true;break;default:break;}
48if(flag){event.stopPropagation();event.preventDefault();}}
49handleTodayButton(event){let flag=false;switch(event.type){case'keydown':switch(event.key){case'Esc':case'Escape':this.close();flag=true;break;case'Enter':this.focusDay=new Date();this.selectedDay=new Date(0,0,1);this.updateGrid();this.setFocusDay();flag=true;break;}
50break;case'click':this.focusDay=new Date();this.selectedDay=new Date(0,0,1);this.updateGrid();this.setFocusDay();flag=true;break;default:break;}
51if(flag){event.stopPropagation();event.preventDefault();}}
52handleNextYearButton(event){let flag=false;switch(event.type){case'keydown':switch(event.key){case'Esc':case'Escape':this.close();flag=true;break;case'Enter':this.moveToNextYear();this.setFocusDay(false);flag=true;break;}
53break;case'click':this.moveToNextYear();this.setFocusDay(false);break;default:break;}
54if(flag){event.stopPropagation();event.preventDefault();}}
55handlePreviousYearButton(event){let flag=false;switch(event.type){case'keydown':switch(event.key){case'Enter':this.moveToPreviousYear();this.setFocusDay(false);flag=true;break;case'Tab':if(event.shiftKey){this.okButtonNode.focus();flag=true;}
56break;case'Esc':case'Escape':this.close();flag=true;break;default:break;}
57break;case'click':this.moveToPreviousYear();this.setFocusDay(false);break;default:break;}
58if(flag){event.stopPropagation();event.preventDefault();}}
59handleNextMonthButton(event){let flag=false;switch(event.type){case'keydown':switch(event.key){case'Esc':case'Escape':this.close();flag=true;break;case'Enter':this.moveToNextMonth();this.setFocusDay(false);flag=true;break;}
60break;case'click':this.moveToNextMonth();this.setFocusDay(false);break;default:break;}
61if(flag){event.stopPropagation();event.preventDefault();}}
62handlePreviousMonthButton(event){let flag=false;switch(event.type){case'keydown':switch(event.key){case'Esc':case'Escape':this.close();flag=true;break;case'Enter':this.moveToPreviousMonth();this.setFocusDay(false);flag=true;break;}
63break;case'click':this.moveToPreviousMonth();this.setFocusDay(false);flag=true;break;default:break;}
64if(flag){event.stopPropagation();event.preventDefault();}}
65handleDayKeyDown(event){let flag=false;switch(event.key){case'Esc':case'Escape':this.close();break;case' ':this.setTextboxDate(event.currentTarget);flag=true;break;case'Enter':this.setTextboxDate(event.currentTarget);this.close();flag=true;break;case'Tab':this.todayButtonNode.focus();if(event.shiftKey){this.nextYearNode.focus();}
66this.setMessage('');flag=true;break;case'Right':case'ArrowRight':this.moveFocusToNextDay();flag=true;break;case'Left':case'ArrowLeft':this.moveFocusToPreviousDay();flag=true;break;case'Down':case'ArrowDown':this.moveFocusToNextWeek();flag=true;break;case'Up':case'ArrowUp':this.moveFocusToPreviousWeek();flag=true;break;case'PageUp':if(event.shiftKey){this.moveToPreviousYear();}else{this.moveToPreviousMonth();}
67this.setFocusDay();flag=true;break;case'PageDown':if(event.shiftKey){this.moveToNextYear();}else{this.moveToNextMonth();}
68this.setFocusDay();flag=true;break;case'Home':this.moveFocusToFirstDayOfWeek();flag=true;break;case'End':this.moveFocusToLastDayOfWeek();flag=true;break;}
69if(flag){event.stopPropagation();event.preventDefault();}}
70handleDayClick(event){if(!this.isDayDisabled(event.currentTarget)&&event.which!==3){this.setTextboxDate(event.currentTarget);this.close();}
71event.stopPropagation();event.preventDefault();}
72handleDayFocus(){this.setMessage(this.messageCursorKeys);}
73handleButtonKeydown(event){if(event.key==='Enter'||event.key===' '){this.open(event);this.setFocusDay();event.stopPropagation();event.preventDefault();}}
74handleButtonClick(event){if(this.isOpen()){this.close();}else{this.open(event);this.setFocusDay();}
75event.stopPropagation();event.preventDefault();}
76handleBackgroundMouseUp(event){if(!this.buttonNode.contains(event.target)&&!this.dialogNode.contains(event.target)){if(this.isOpen()){this.close(false);event.stopPropagation();event.preventDefault();}}}}
77document.querySelectorAll('.Date').forEach(function(dp){new DatePickerDialog(dp);});

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.