JAVASCRIPT   27

datepickr

Guest on 20th August 2022 12:47:13 AM

  1. /*
  2.     datepickr - pick your date not your nose
  3.     Copyright (c) 2012
  4. */
  5.  
  6. var datepickr = (function() {
  7.         var datepickrs = [],
  8.         currentDate = new Date(),
  9.         date = {
  10.                 current: {
  11.                         year: function() {
  12.                                 return currentDate.getFullYear();
  13.                         },
  14.                         month: {
  15.                                 integer: function() {
  16.                                         return currentDate.getMonth();
  17.                                 },
  18.                                 string: function(full) {
  19.                                         var date = currentDate.getMonth();
  20.                                         return monthToStr(date, full);
  21.                                 }
  22.                         },
  23.                         day: function() {
  24.                                 return currentDate.getDate();                  
  25.                         }
  26.                 },
  27.                 month: {
  28.                         string: function(full, currentMonthView) {
  29.                                 var date = currentMonthView;
  30.                                 return monthToStr(date, full);
  31.                         },
  32.                         numDays: function(currentMonthView, currentYearView) {
  33.                                 // checks to see if february is a leap year otherwise return the respective # of days
  34.                                 return (currentMonthView == 1 && !(currentYearView & 3) && (currentYearView % 1e2 || !(currentYearView % 4e2))) ? 29 : daysInMonth[currentMonthView];
  35.                         }
  36.                 }
  37.         },
  38.         weekdays = ['Sun', 'Mon', 'Tues', 'Wednes', 'Thurs', 'Fri', 'Satur'],
  39.         months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  40.         daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
  41.         suffix = { 1: 'st', 2: 'nd', 3: 'rd', 21: 'st', 22: 'nd', 23: 'rd', 31: 'st' },
  42.         buildCache = [],
  43.         handlers = {
  44.                 calendarClick: function(e) {
  45.                         if(e.target.className) {
  46.                                 switch(e.target.className) {
  47.                                         case 'prev-month':
  48.                                         case 'prevMonth':
  49.                                                 this.currentMonthView--;
  50.                                                 if(this.currentMonthView < 0) {
  51.                                                         this.currentYearView--;
  52.                                                         this.currentMonthView = 11;
  53.                                                 }
  54.                                                 rebuildCalendar.call(this);
  55.                                         break;
  56.                                         case 'next-month':
  57.                                         case 'nextMonth':
  58.                                                 this.currentMonthView++;
  59.                                                 if(this.currentMonthView > 11) {
  60.                                                         this.currentYearView++;
  61.                                                         this.currentMonthView = 0;
  62.                                                 }
  63.                                                 rebuildCalendar.call(this);
  64.                                         break;
  65.                                         case 'day':
  66.                                                 this.element.value = formatDate(new Date(this.currentYearView, this.currentMonthView, e.target.innerHTML).getTime(), this.config.dateFormat);
  67.                                                 this.close();
  68.                                         break;
  69.                                 }
  70.                         }
  71.                 },
  72.                 documentClick: function(e) {
  73.                         if(e.target != this.element && e.target != this.calendar) {
  74.                                 var parentNode = e.target.parentNode;
  75.                                 if(parentNode != this.calender) {
  76.                                         while(parentNode != this.calendar) {
  77.                                                 parentNode = parentNode.parentNode;
  78.                                                 if(parentNode == null) {
  79.                                                         this.close();
  80.                                                         break;
  81.                                                 }
  82.                                         }
  83.                                 }
  84.                         }
  85.                 }
  86.         };
  87.        
  88.         function formatDate(milliseconds, dateFormat) {
  89.                 var formattedDate = '',
  90.                 dateObj = new Date(milliseconds),
  91.                 format = {
  92.                         d: function() {
  93.                                 var day = format.j();
  94.                                 return (day < 10) ? '0' + day : day;
  95.                         },
  96.                         D: function() {
  97.                                 return weekdays[format.w()].substring(0, 3);
  98.                         },
  99.                         j: function() {
  100.                                 return dateObj.getDate();
  101.                         },
  102.                         l: function() {
  103.                                 return weekdays[format.w()] + 'day';
  104.                         },
  105.                         S: function() {
  106.                                 return suffix[format.j()] || 'th';
  107.                         },
  108.                         w: function() {
  109.                                 return dateObj.getDay();
  110.                         },
  111.                         F: function() {
  112.                                 return monthToStr(format.n(), true);
  113.                         },
  114.                         m: function() {
  115.                                 var month = format.n() + 1;
  116.                                 return (month < 10) ? '0' + month : month;
  117.                         },
  118.                         M: function() {
  119.                                 return monthToStr(format.n(), false);
  120.                         },
  121.                         n: function() {
  122.                                 return dateObj.getMonth();
  123.                         },
  124.                         Y: function() {
  125.                                 return dateObj.getFullYear();
  126.                         },
  127.                         y: function() {
  128.                                 return format.Y().toString().substring(2, 4);
  129.                         }
  130.                 },
  131.                 formatPieces = dateFormat.split('');
  132.                
  133.                 foreach(formatPieces, function(formatPiece) {
  134.                         formattedDate += format[formatPiece] ? format[formatPiece]() : formatPiece;
  135.                 });
  136.                
  137.                 return formattedDate;
  138.         }
  139.        
  140.         function foreach(items, callback) {
  141.                 var i = 0, x = items.length;
  142.                 for(i; i < x; i++) {
  143.                         if(callback(items[i], i) === false) {
  144.                                 break;
  145.                         }
  146.                 }
  147.         }
  148.        
  149.         function addEvent(element, eventType, callback) {
  150.                 if(element.addEventListener) {
  151.                         element.addEventListener(eventType, callback, false);
  152.                 } else if(element.attachEvent) {
  153.                         var fixedCallback = function(e) {
  154.                                 e = e || window.event;
  155.                                 e.preventDefault = (function(e) {
  156.                                         return function() { e.returnValue = false; }
  157.                                 })(e);
  158.                                 e.stopPropagation = (function(e) {
  159.                                         return function() { e.cancelBubble = true; }
  160.                                 })(e);
  161.                                 e.target = e.srcElement;
  162.                                 callback.call(element, e);
  163.                         };
  164.                         element.attachEvent('on' + eventType, fixedCallback);
  165.                 }
  166.         }
  167.        
  168.         function removeEvent(element, eventType, callback) {
  169.                 if(element.removeEventListener) {
  170.                         element.removeEventListener(eventType, callback, false);
  171.                 } else if(element.detachEvent) {
  172.                         element.detachEvent('on' + eventType, callback);
  173.                 }
  174.         }
  175.        
  176.         function buildNode(nodeName, attributes, content) {
  177.                 var element;
  178.                
  179.                 if(!(nodeName in buildCache)) {
  180.                         buildCache[nodeName] = document.createElement(nodeName);
  181.                 }
  182.                
  183.                 element = buildCache[nodeName].cloneNode(false);
  184.                
  185.                 if(attributes != null) {
  186.                         for(var attribute in attributes) {
  187.                                 element[attribute] = attributes[attribute];
  188.                         }
  189.                 }
  190.                
  191.                 if(content != null) {
  192.                         if(typeof(content) == 'object') {
  193.                                 element.appendChild(content);
  194.                         } else {
  195.                                 element.innerHTML = content;
  196.                         }
  197.                 }
  198.                
  199.                 return element;
  200.         }
  201.        
  202.         function monthToStr(date, full) {
  203.                 return ((full == true) ? months[date] : ((months[date].length > 3) ? months[date].substring(0, 3) : months[date]));
  204.         }
  205.        
  206.         function isToday(day, currentMonthView, currentYearView) {
  207.                 return day == date.current.day() && currentMonthView == date.current.month.integer() && currentYearView == date.current.year();
  208.         }
  209.        
  210.         function buildWeekdays() {
  211.                 var weekdayHtml = document.createDocumentFragment();
  212.                 foreach(weekdays, function(weekday) {
  213.                         weekdayHtml.appendChild(buildNode('th', {}, weekday.substring(0, 2)));
  214.                 });
  215.                 return weekdayHtml;
  216.         }
  217.        
  218.         function rebuildCalendar() {
  219.                 while(this.calendarBody.hasChildNodes()){
  220.                         this.calendarBody.removeChild(this.calendarBody.lastChild);
  221.                 }
  222.                
  223.                 var firstOfMonth = new Date(this.currentYearView, this.currentMonthView, 1).getDay(),
  224.                 numDays = date.month.numDays(this.currentMonthView, this.currentYearView);
  225.                
  226.                 this.currentMonth.innerHTML = date.month.string(this.config.fullCurrentMonth, this.currentMonthView) + ' ' + this.currentYearView;
  227.                 this.calendarBody.appendChild(buildDays(firstOfMonth, numDays, this.currentMonthView, this.currentYearView));
  228.         }
  229.        
  230.         function buildCurrentMonth(config, currentMonthView, currentYearView) {
  231.                 return buildNode('span', { className: 'current-month' }, date.month.string(config.fullCurrentMonth, currentMonthView) + ' ' + currentYearView);
  232.         }
  233.        
  234.         function buildMonths(config, currentMonthView, currentYearView) {
  235.                 var months = buildNode('div', { className: 'months' }),
  236.                 prevMonth = buildNode('span', { className: 'prev-month' }, buildNode('span', { className: 'prevMonth' }, '&lt;')),
  237.                 nextMonth = buildNode('span', { className: 'next-month' }, buildNode('span', { className: 'nextMonth' }, '&gt;'));
  238.                
  239.                 months.appendChild(prevMonth);
  240.                 months.appendChild(nextMonth);
  241.                
  242.                 return months;
  243.         }
  244.        
  245.         function buildDays(firstOfMonth, numDays, currentMonthView, currentYearView) {
  246.                 var calendarBody = document.createDocumentFragment(),
  247.                 row = buildNode('tr'),
  248.                 dayCount = 0, i;
  249.                
  250.                 // print out previous month's "days"
  251.                 for(i = 1; i <= firstOfMonth; i++) {
  252.                         row.appendChild(buildNode('td', null, '&nbsp;'));
  253.                         dayCount++;
  254.                 }
  255.                
  256.                 for(i = 1; i <= numDays; i++) {
  257.                         // if we have reached the end of a week, wrap to the next line
  258.                         if(dayCount == 7) {
  259.                                 calendarBody.appendChild(row);
  260.                                 row = buildNode('tr');
  261.                                 dayCount = 0;
  262.                         }
  263.                        
  264.                         var todayClassName = isToday(i, currentMonthView, currentYearView) ? { className: 'today' } : null;
  265.                         row.appendChild(buildNode('td', todayClassName, buildNode('span', { className: 'day' }, i)));
  266.                        
  267.                         dayCount++;
  268.                 }
  269.                
  270.                 // if we haven't finished at the end of the week, start writing out the "days" for the next month
  271.                 for(i = 1; i <= (7 - dayCount); i++) {
  272.                         row.appendChild(buildNode('td', null, '&nbsp;'));
  273.                 }
  274.                
  275.                 calendarBody.appendChild(row);
  276.                
  277.                 return calendarBody;
  278.         }
  279.        
  280.         function buildCalendar() {
  281.                 var firstOfMonth = new Date(this.currentYearView, this.currentMonthView, 1).getDay(),
  282.                 numDays = date.month.numDays(this.currentMonthView, this.currentYearView),
  283.                 self = this;
  284.                
  285.                 var inputLeft = inputTop = 0,
  286.                 obj = this.element;
  287.                
  288.                 if(obj.offsetParent) {
  289.                         do {
  290.                                 inputLeft += obj.offsetLeft;
  291.                                 inputTop += obj.offsetTop;
  292.                         } while (obj = obj.offsetParent);
  293.                 }
  294.                
  295.                 var calendarContainer = buildNode('div', { className: 'calendar' });
  296.                 calendarContainer.style.cssText = 'display: none; position: absolute; top: ' + (inputTop + this.element.offsetHeight) + 'px; left: ' + inputLeft + 'px; z-index: 100;';
  297.                
  298.                 this.currentMonth = buildCurrentMonth(this.config, this.currentMonthView, this.currentYearView)
  299.                 var months = buildMonths(this.config, this.currentMonthView, this.currentYearView);
  300.                 months.appendChild(this.currentMonth);
  301.                
  302.                 var calendar = buildNode('table', null, buildNode('thead', null, buildNode('tr', { className: 'weekdays' }, buildWeekdays())));
  303.                 this.calendarBody = buildNode('tbody');
  304.                 this.calendarBody.appendChild(buildDays(firstOfMonth, numDays, this.currentMonthView, this.currentYearView));
  305.                 calendar.appendChild(this.calendarBody);
  306.                
  307.                 calendarContainer.appendChild(months);
  308.                 calendarContainer.appendChild(calendar);
  309.                
  310.                 document.body.appendChild(calendarContainer);
  311.                
  312.                 addEvent(calendarContainer, 'click', function(e) { handlers.calendarClick.call(self, e); });
  313.                
  314.                 return calendarContainer;
  315.         }
  316.        
  317.         return function(elementId, userConfig) {
  318.                 var self = this;
  319.                
  320.                 this.element = document.getElementById(elementId);
  321.                 this.config = {
  322.                         fullCurrentMonth: true,
  323.                         dateFormat: 'F jS, Y'
  324.                 };
  325.                 this.currentYearView = date.current.year();
  326.                 this.currentMonthView = date.current.month.integer();
  327.                
  328.                 if(userConfig) {
  329.                         for(var key in userConfig) {
  330.                                 if(this.config.hasOwnProperty(key)) {
  331.                                         this.config[key] = userConfig[key];
  332.                                 }
  333.                         }
  334.                 }
  335.                
  336.                 this.documentClick = function(e) { handlers.documentClick.call(self, e); }
  337.                
  338.                 this.open = function(e) {
  339.                         addEvent(document, 'click', self.documentClick);
  340.                        
  341.                         foreach(datepickrs, function(datepickr) {
  342.                                 if(datepickr != self) {
  343.                                         datepickr.close();
  344.                                 }
  345.                         });
  346.                        
  347.                         self.calendar.style.display = 'block';
  348.                 }
  349.                
  350.                 this.close = function() {
  351.                         removeEvent(document, 'click', self.documentClick);
  352.                         self.calendar.style.display = 'none';
  353.                 }
  354.                
  355.                 this.calendar = buildCalendar.call(this);
  356.                
  357.                 datepickrs.push(this);
  358.                
  359.                 if(this.element.nodeName == 'INPUT') {
  360.                         addEvent(this.element, 'focus', this.open);
  361.                 } else {
  362.                         addEvent(this.element, 'click', this.open);
  363.                 }
  364.         }
  365. })();

Raw Paste


Login or Register to edit or fork this paste. It's free.