glDatePicker-2.0 日历插件

昨天用的日历插件在绑定数据的时候出现了问题,所以今天换了这个glDatePicker-2.0 日历插件

 

这是我修改后的样式

 

 

默认样式是这样的。

 

我的代码

index.html

 1 <!doctype html>
 2 <html>
 3 <head>
 4     <meta charset="utf-8">
 5     <title>glDatePicker</title>
 6     <link href="styles/glDatePicker.default.css" rel="stylesheet" type="text/css">
 7 </head>
 8 
 9 <body>
10     <input type="text" id="mydate" style=" visibility: visible;height: 20px;width:300px;" />
11     <script src="jquery-1.10.2.min.js"></script>
12     <script src="glDatePicker.js"></script>
13     <script>
14         $('input').glDatePicker({
15             showAlways: true,
16             selectedDate: new Date(),
17             specialDates: [
18                 {
19                     date: new Date(2016,05,25),
20                     data: { message: 'Happy New Year!' },
21                     repeatYear: true
22                 },
23                 {
24                     date: new Date(2016,06,01),
25                     data: { message: 'Happy New Year!' },
26                     repeatYear: true
27                 }
28             ]
29         });
30     </script>
31 </body>
32 </html>

 

glDatePicker.default.css

1 .gldp-default{position:absolute;font-family:'helvetica'}.gldp-default .core{box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;position:relative;float:left;padding:0;margin:0;font-size:14px;text-align:center;cursor:pointer;color:#777;background:#e1e1e1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#dadada',GradientType=0)}.gldp-default .dow{box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;position:relative;float:left;padding:0;margin:0;font-size:14px;text-align:center;cursor:pointer;color:#777;background:#e1e1e1;border:0;border-radius:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#dadada',GradientType=0)}.gldp-default .monyear{box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;position:relative;float:left;padding:0;margin:0;font-size:14px;text-align:center;cursor:pointer;color:#777;background:#e1e1e1;border:0;border-radius:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#dadada',GradientType=0)}.gldp-default .border{border:1px solid #e1e1e1}.gldp-default .monyear,.gldp-default .monyear select{font-size:16px!important;font-weight:bold;text-shadow:1px 1px 0 rgba(255,255,255,0.75)}.gldp-default .monyear span{margin:0 5px 0 5px}.gldp-default .prev-arrow,.gldp-default .next-arrow{color:#222;text-shadow:1px 1px 0 rgba(255,255,255,0.75)}.gldp-default .prev-arrow:active,.gldp-default .next-arrow:active{color:#f00}.gldp-default .prev-arrow-off,.gldp-default .next-arrow-off{color:#222;opacity:.15}.gldp-default .dow{color:#363636;font-weight:bold;cursor:wait!important;background:#fff;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000',endColorstr='#880000',GradientType=0)}.gldp-default .mon,.gldp-default .tue,.gldp-default .wed,.gldp-default .thu,.gldp-default .fri{font-weight:bold;text-shadow:1px 1px 0 rgba(255,255,255,0.75)}.gldp-default .sat,.gldp-default .sun{color:#3858a8;font-weight:bold;text-shadow:1px 1px 0 rgba(255,255,255,0.75)}.gldp-default .outday{color:#d9d9d9!important;background:#f2f2f2}.gldp-default .mon:hover,.gldp-default .tue:hover,.gldp-default .wed:hover,.gldp-default .thu:hover,.gldp-default .fri:hover,.gldp-default .sat:hover,.gldp-default .sun:hover{background:#fcfff4;background:-moz-linear-gradient(top,#fcfff4 0,#e9e9ce 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#fcfff4),color-stop(100%,#e9e9ce));background:-webkit-linear-gradient(top,#fcfff4 0,#e9e9ce 100%);background:-o-linear-gradient(top,#fcfff4 0,#e9e9ce 100%);background:-ms-linear-gradient(top,#fcfff4 0,#e9e9ce 100%);background:linear-gradient(to bottom,#fcfff4 0,#e9e9ce 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fcfff4',endColorstr='#e9e9ce',GradientType=0)}.gldp-default .noday{color:#444;font-weight:normal;cursor:wait!important;background:#aaa;background:-moz-linear-gradient(top,#aaa 0,#8a8a8a 98%,#aaa 99%,#8a8a8a 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#aaa),color-stop(98%,#8a8a8a),color-stop(99%,#aaa),color-stop(100%,#8a8a8a));background:-webkit-linear-gradient(top,#aaa 0,#8a8a8a 98%,#aaa 99%,#8a8a8a 100%);background:-o-linear-gradient(top,#aaa 0,#8a8a8a 98%,#aaa 99%,#8a8a8a 100%);background:-ms-linear-gradient(top,#aaa 0,#8a8a8a 98%,#aaa 99%,#8a8a8a 100%);background:linear-gradient(to bottom,#aaa 0,#8a8a8a 98%,#aaa 99%,#8a8a8a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#aaaaaa',endColorstr='#8a8a8a',GradientType=0)}.gldp-default .selected{color:#fff;font-weight:bold;border-color:#3d9fe1;background:#3d9fe1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e8bf88',endColorstr='#ef753f',GradientType=0)}.gldp-default .today{color:#fff;font-weight:bold;border-color:#3d9fe1;background:#3d9fe1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88bfe8',endColorstr='#3775ef',GradientType=0)}.gldp-default .special{color:#3d9fe1;font-weight:bold;border-color:#dbdbdb;background:#fff;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88e888',endColorstr='#37ef37',GradientType=0)}

 

glDatePicker.js

  1 /*!
  2  * glDatePicker v2.0
  3  * http://glad.github.com/glDatePicker/
  4  *
  5  * Copyright (c) 2013 Gautam Lad.  All rights reserved.
  6  * Released under the MIT license.
  7  *
  8  * Date: Tue Jan 1 2013
  9  */
 10  ;(function() {
 11     $.fn.glDatePicker = function(options) {
 12         var pluginName = 'glDatePicker';
 13 
 14         // Find the plugin attached to the element
 15         var instance = this.data(pluginName);
 16 
 17         // If the instance wasn't found, create it...
 18         if(!instance) {
 19             // Return the element being bound to
 20             return this.each(function() {
 21                 return $(this).data(pluginName, new glDatePicker(this, options));
 22             });
 23         }
 24 
 25         // ...otherwise if the user passes true to the plugin (on the second call),
 26         // then return the instance of the plugin itself
 27         return (options === true) ? instance : this;
 28     };
 29 
 30     // Default options
 31     $.fn.glDatePicker.defaults =
 32     {
 33         // Style to use for the calendar.  This name must match the name used in
 34         // the stylesheet, using the class naming convention "gldp-cssName".
 35         cssName: 'default',
 36 
 37         // The z-index for the calendar control.
 38         zIndex: 1000,
 39 
 40         // Thickness of border (in pixels)
 41         borderSize: 1,
 42 
 43         // The number of pixels to offset the calendar's position on the page.
 44         calendarOffset: { x: 0, y: 1 },
 45 
 46         // Set to true if you want the calendar to be visible at all times.
 47         // NOTE: If your target element is hidden, the calendar will be hidden as well.
 48         showAlways: false,
 49 
 50         // Hide the calendar when a date is selected (only if showAlways is set to false).
 51         hideOnClick: true,
 52 
 53         // Allow selection of months by clicking on the month in the title.
 54         allowMonthSelect: true,
 55 
 56         // Allow selection of years by clicking on the year in the title.
 57         allowYearSelect: true,
 58 
 59         // The date that will be treated as 'today'.
 60         todayDate: new Date(),
 61 
 62         // The date that will appear selected when the calendar renders.
 63         // By default it will be set to todayDate.
 64         selectedDate: null,
 65 
 66         // Arrows used for the Previous and Next month buttons on the title.
 67         // Set these to blank to hide the arrows completely.
 68         prevArrow: '\u25c4',
 69         nextArrow: '\u25ba',
 70 
 71         // A collection of dates that can be selectable by the user.
 72         // The dates can be a one-time selection or made repeatable by setting
 73         // the repeatYear or repeatMonth flag to true.
 74         // By default repeatYear and repeatMonth are false.
 75         //
 76         // This example creates 4-individual dates that can be selected;
 77         // The first date will repeat every year, the second date will repeat every
 78         // month and year, the third date will repeat every month and the fourth date
 79         // will only be selectable one-time and not repeat:
 80         //
 81         //    selectableDates: [
 82         //        { date: new Date(0, 8, 5), repeatYear: true },
 83         //        { date: new Date(0, 0, 14), repeatMonth: true, repeatYear: true },
 84         //        { date: new Date(2013, 0, 24), repeatMonth: true },
 85         //        { date: new Date(2013, 11, 25) },
 86         //    ]
 87         selectableDates: null,
 88 
 89         // A collection of date ranges that are selectable by the user.
 90         // The ranges can be made to repeat by setting repeatYear to true
 91         // (repeatMonth is not supported).
 92         //
 93         // This example will create 3-sets of selectable date ranges with
 94         // specific from and to ranges.  The 4th and 5th ranges don't specify
 95         // the "to" date in which case the "to" date will be the maximum days for
 96         // the month specified in "from".  The 4th and 5th ranges also repeat every year:
 97         //
 98         //     selectableDateRange: [
 99         //         { from: new Date(2013, 1, 1), to: newDate (2013, 2, 1) },
100         //         { from: new Date(2013, 4, 1), to: newDate (2013, 8, 1) },
101         //         { from: new Date(2013, 7, 10), to: newDate (2013, 9, 10) },
102         //         { from: new Date(0, 8, 10), repeatYear: true }
103         //         { from: new Date(0, 9, 1), repeatYear: true }
104         //     ]
105         selectableDateRange: null,
106 
107         // Mark certain dates as special dates.  Similar to selectableDates, this
108         // property supports both repeatYear and repeatMonth flags.
109         // Each special date can be styled using custom style names and can have
110         // data attached to it that will be returned in the onClick callback.
111         // The data field can be any custom (JSON style) object.
112         //
113         // This example creates two (repeatable by year) dates with special data in them.
114         // The first date also assigns a special class (which you will have to define).
115         //    specialDates: [
116         //        {
117         //            date: new Date(0, 8, 5),
118         //            data: { message: 'Happy Birthday!' },
119         //            repeatYear: true,
120         //            cssClass: 'special-bday'
121         //        },
122         //        {
123         //            date: new Date(2013, 0, 8),
124         //            data: { message: 'Meeting every day 8 of the month' },
125         //            repeatMonth: true
126         //        }
127         //    ]
128         specialDates: null,
129 
130         // List of months that can be selectable, including when the user clicks
131         // on the title to select from the dropdown.
132         // This example only makes two months visible; September and December:
133         //    selectableMonths: [8, 11]
134         selectableMonths : null,
135 
136         // List of selectable years.  If not provided, will default to 5-years
137         // back and forward.
138         // This example only allows selection of dates that have year 2012, 2013, 2015
139         //    selectableYears: [2012, 2013, 2015]
140         selectableYears: null,
141 
142         // List of selectable days of the week.  0 is Sunday, 1 is Monday, and so on.
143         // This example allows only Sunday, Tuesday, Thursday:
144         //    selectableDOW: [0, 2, 4]
145         selectableDOW : null,
146 
147         // Names of the month that will be shown in the title.
148         // Will default to long-form names:
149         //     January, February, March, April, May, June, July,
150         //     August, September, October, November, December
151         monthNames: null,
152 
153         // Names of the days of the Week that will be shown below the title.
154         // Will default to short-form names:
155         //     Sun, Mon, Tue, Wed, Thu, Fri, Sat
156         dowNames: null,
157 
158         // The day of the week to start the calendar on.  0 is Sunday, 1 is Monday and so on.
159         dowOffset: 0,
160 
161         // Callback that will trigger when the user clicks a selectable date.
162         // Parameters that are passed to the callback:
163         //     el : The input element the date picker is bound to
164         //   cell : The cell on the calendar that triggered this event
165         //   date : The date associated with the cell
166         //   data : Special data associated with the cell (if available, otherwise, null)
167         onClick: (function(el, cell, date, data) {
168             el.val(date.toLocaleDateString());
169         }),
170 
171         // Callback that will trigger when the user hovers over a selectable date.
172         // This callback receives the same set of parameters as onClick.
173         onHover: function(el, cell, date, data) {},
174 
175         // Callback that will trigger when the calendar needs to show.
176         // You can use this callback to animate the opening of the calendar.
177         onShow: function(calendar) { calendar.show(); },
178 
179         // Callback that will trigger when the calendar needs to hide.
180         // You can use this callback to animate the hiding of the calendar.
181         onHide: function(calendar) { calendar.hide(); },
182 
183         // First date of the month.
184         firstDate: null
185     };
186 
187     // Our plugin object
188     var glDatePicker = (function() {
189         // Main entry point.  Initialize the plugin
190         function glDatePicker(element, userOptions) {
191             // Grab handle to this
192             var self = this;
193 
194             // Save bound element to el
195             self.el = $(element);
196             var el = self.el;
197 
198             // Merge user options into default options
199             self.options = $.extend(true, {}, $.fn.glDatePicker.defaults, userOptions);
200             var options = self.options;
201 
202             // Find the calendar element if the user provided one
203             self.calendar = $($.find('[gldp-el=' + el.attr('gldp-id') + ' ]'));
204 
205             // Default first date to selected
206             options.selectedDate = options.selectedDate || options.todayDate;
207             options.firstDate = (new Date((options.firstDate || options.selectedDate)))._first();
208 
209             if(!(el.attr('gldp-id') || '').length) {
210                 el.attr('gldp-id', 'gldp-' + Math.round(Math.random() * 1e10))
211             }
212 
213             // Show the plugin on focus
214             el
215                 .addClass('gldp-el')
216                 .bind('click', function(e) { self.show(e); })
217                 .bind('focus', function(e) { self.show(e); });
218 
219             // If the user is defining the container and it exists, hide it on initial creation.
220             // The update function will handle showing if it's showAlways = true
221             if(self.calendar.length && !options.showAlways) {
222                 self.calendar.hide();
223             }
224 
225             // Hide the plugin on mouse up outside of the plugin
226             $(document).bind('mouseup', function(e) {
227                 var target = e.target;
228                 var calendar = self.calendar;
229 
230                 if(!el.is(target) && !calendar.is(target) && calendar.has(target).length === 0 && calendar.is(':visible')) {
231                     self.hide();
232                 }
233             });
234 
235             // Render calendar
236             self.render();
237         };
238 
239         // Public methods
240         glDatePicker.prototype =
241         {
242             show: function() {
243                 // Hide others and show this calendar
244                 $.each($('.gldp-el').not(this.el), function(i, o) {
245                     if(o.length) { o.options.onHide(o.calendar) ; }
246                 });
247 
248                 // Show this calendar
249                 this.options.onShow(this.calendar);
250             },
251 
252             hide: function() {
253                 if(this.options && !this.options.showAlways) {
254                     this.options.onHide(this.calendar);
255                 }
256             },
257 
258             // Render the calendar
259             render: function(renderCalback) {
260                 var self = this;
261                 var el = self.el;
262                 var options = self.options;
263                 var calendar = self.calendar;
264 
265                 // Build a core class (with border) that every element would have
266                 var coreClass = ' core border ';
267                 var cssName = 'gldp-' + options.cssName;
268 
269                 // Get today
270                 var todayVal = options.todayDate._val();
271                 var todayTime = todayVal.time;
272 
273                 // Constants
274                 var maxRow = 6;
275                 var maxCol = 7;
276                 var borderSize = options.borderSize + 'px';
277 
278                 // Helper function to build selectable list
279                 var getSelectableList = function(min, max, userList) {
280                     // Build a default list using min/max
281                     var resultList = [];
282                     for(var i = min; i <= max; i++) { resultList.push(i); }
283 
284                     // If user provided a collection, sanitize list by ensuring it's within range and unique
285                     if(userList) {
286                         var newList = [];
287                         $.each(userList, function(i, v) {
288                             if(v >= min && v <= max && newList._indexOf(v) < 0) {
289                                 newList.push(v);
290                             }
291                         });
292 
293                         resultList = newList.length ? newList : resultList;
294                     };
295 
296                     // Sort the values before returning it
297                     resultList.sort();
298 
299                     return resultList;
300                 };
301 
302                 // Selectable (constants)
303                 var selectableMonths = getSelectableList(0, 11, options.selectableMonths);
304                 var selectableYears = getSelectableList(todayVal.year - 5, todayVal.year + 5, options.selectableYears);
305                 var selectableDOW = getSelectableList(0, 6, options.selectableDOW);
306                 var dowNames = options.dowNames || [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ];
307                 var monthNames = options.monthNames || [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ];
308 
309                 // Create cell width based on el size
310                 var containerWidth = el.outerWidth();
311                 var containerHeight = containerWidth;
312 
313                 // Create cell size based on container size
314                 var getCellSize = function(_size, _count) {
315                     return (_size / _count) + ((options.borderSize / _count) * (_count - 1));
316                 };
317                 var cellWidth = getCellSize(containerWidth, maxCol);
318                 var cellHeight = getCellSize(containerHeight, maxRow + 2);
319 
320                 // If calendar doesn't exist, create it and re-assign it to self
321                 if(!calendar.length) {
322                     self.calendar = calendar = $('<div/>')
323                         .attr('gldp-el', el.attr('gldp-id'))
324                         .data('is', true)
325                         .css(
326                         {
327                             display: (options.showAlways ? undefined : 'none'),
328                             zIndex: options.zIndex,
329                             width: (cellWidth * maxCol) + 'px'
330                         });
331 
332                     $('body').append(calendar);
333                 }
334                 else {
335                     if(!eval(calendar.data('is'))) {
336                         containerWidth = calendar.outerWidth();
337                         containerHeight = calendar.outerHeight();
338 
339                         cellWidth = getCellSize(containerWidth, maxCol);
340                         cellHeight = getCellSize(containerHeight, maxRow + 2);
341                     }
342                 }
343 
344                 // Hide calendar if the target element isn't visible
345                 if(!el.is(':visible')) { calendar.hide(); }
346 
347                 // Add core classes and remove calendar's children
348                 calendar
349                     .removeClass()
350                     .addClass(cssName)
351                     .children().remove();
352 
353                 // Bind to resize event to position calendar
354                 var onResize = function() {
355                     var elPos = el.offset();
356                     calendar.css(
357                     {
358                         top: (elPos.top + el.outerHeight() + options.calendarOffset.y) + 'px',
359                         left: (elPos.left + options.calendarOffset.x) + 'px'
360                     });
361                 };
362                 $(window).resize(onResize);
363                 onResize();
364 
365                 // Create variables for cells
366                 var cellCSS =
367                 {
368                     width: cellWidth + 'px',
369                     height: cellHeight + 'px',
370                     lineHeight: cellHeight + 'px'
371                 };
372 
373                 // Helper function to setDate
374                 var setFirstDate = function(_date) {
375                     if(_date) {
376                         // Get first date
377                         options.firstDate = _date;
378 
379                         // Update the calendar
380                         self.render();
381                     }
382                 };
383 
384                 var getFirstDate = function(_offset) {
385                     // Create start date as the first date of the month
386                     var _date = new Date(options.firstDate);
387 
388                     // Default to no offset
389                     _offset = _offset || 0;
390 
391                     // Find out which months are selectable
392                     while(true) {
393                         // Adjust date for month offset
394                         _date.setMonth(_date.getMonth() + _offset);
395                         _date.setDate(Math.min(1, _date._max()));
396 
397                         // If not an offset, break out of the loop
398                         if(_offset == 0) { break; }
399 
400                         // Get _date's value
401                         var dateVal = _date._val();
402 
403                         // Get local vars
404                         var dateMonth = dateVal.month;
405                         var dateYear = dateVal.year;
406 
407                         // Find the month first
408                         if(selectableMonths._indexOf(dateMonth) != -1) {
409                             // If year is in our collection, break...
410                             if(selectableYears._indexOf(dateYear) != -1) {
411                                 break;
412                             }
413                             else {
414                                 // ...otherwise, if it's out of bounds, exit loop
415                                 if(dateYear < selectableYears[0] || dateYear > selectableYears[selectableYears.length - 1]) {
416                                     return null;
417                                 }
418                             }
419                         }
420                     }
421 
422                     return _date;
423                 };
424 
425                 // Get the previous, next first dates
426                 var prevFirstDate = getFirstDate(-1);
427                 var nextFirstDate = getFirstDate(1);
428 
429                 // Get the first date for the current month being rendered
430                 var firstDate = (options.firstDate = getFirstDate());
431                 var firstDateVal = firstDate._val();
432                 var firstDateMonth = firstDateVal.month;
433                 var firstDateYear = firstDateVal.year;
434 
435                 // Get the start date in the calendar
436                 var startDate = new Date(firstDate);
437 
438                 // Sanitize days of the week offset
439                 var dowOffset = Math.abs(Math.min(6, Math.max(0, options.dowOffset)));
440 
441                 // Offset weekdays
442                 var startOffset = startDate.getDay() - dowOffset;
443                     startOffset = startOffset < 1 ? -7 - startOffset : -startOffset;
444                     dowNames = (dowNames.concat(dowNames))
445                                 .slice(dowOffset, dowOffset + 7);
446 
447                 // Offset the start date
448                 startDate._add(startOffset);
449 
450                 // Gather flags for prev/next arrows
451                 var showPrev = (prevFirstDate);
452                 var showNext = (nextFirstDate);
453 
454                 // Create the arrows and title
455                 var monyearClass = coreClass + 'monyear ';
456 
457                 var prevCell = $('<div/>')
458                                 .addClass(monyearClass)
459                                 .css(
460                                     $.extend({}, cellCSS,
461                                     {
462                                         borderWidth: borderSize + ' 0 0 ' + borderSize
463                                     })
464                                 )
465                                 .append(
466                                     $('<a/>')
467                                         .addClass('prev-arrow' + (showPrev ? '' : '-off'))
468                                         .html(options.prevArrow)
469                                 )
470                                 .mousedown(function() { return false; })
471                                 .click(function(e) {
472                                     if(options.prevArrow != '' && showPrev) {
473                                         e.stopPropagation();
474                                         setFirstDate(prevFirstDate);
475                                     }
476                                 });
477 
478                 var titleCellCount = maxCol - 2;
479                 var titleWidth = (cellWidth * titleCellCount) - (titleCellCount * options.borderSize) + (options.borderSize);
480                 var titleCell = $('<div/>')
481                                 .addClass(monyearClass + 'title')
482                                 .css(
483                                     $.extend({}, cellCSS,
484                                     {
485                                         width: titleWidth + 'px',
486                                         borderTopWidth: borderSize,
487                                         marginLeft: '-' + (borderSize)
488                                     })
489                                 );
490 
491                 var nextCell = $('<div/>')
492                                 .addClass(monyearClass)
493                                 .css(
494                                     $.extend({}, cellCSS,
495                                     {
496                                         marginLeft: '-' + (borderSize),
497                                         borderWidth: borderSize + ' ' + borderSize + ' 0 0'
498                                     })
499                                 )
500                                 .append(
501                                     $('<a/>')
502                                         .addClass('next-arrow' + (showNext ? '' : '-off'))
503                                         .html(options.nextArrow)
504                                 )
505                                 .mousedown(function() { return false; })
506                                 .click(function(e) {
507                                     if(options.nextArrow != '' && showNext) {
508                                         e.stopPropagation();
509                                         setFirstDate(nextFirstDate);
510                                     }
511                                 });
512 
513                 // Add cells for prev/title/next
514                 calendar
515                     .append(prevCell)
516                     .append(titleCell)
517                     .append(nextCell);
518 
519                 // Add all the cells to the calendar
520                 for(var row = 0, cellIndex = 0; row < maxRow + 1; row++) {
521                     for(var col = 0; col < maxCol; col++, cellIndex++) {
522                         var cellDate = new Date(startDate);
523                         var cellClass = 'day';
524                         var cellZIndex = options.zIndex + (cellIndex);
525                         var cell = $('<div/>')
526 
527                         if(!row) {
528                             cellClass = 'dow';
529                             cell.html(dowNames[col]);
530                             cellDate = null;
531                         }
532                         else {
533                             // Get the new date for this cell
534                             cellDate._add(col + ((row - 1) * maxCol));
535 
536                             // Get value for this date
537                             var cellDateVal = cellDate._val();
538                             var cellDateTime = cellDateVal.time;
539 
540                             // Variable to hold special data
541                             var specialData = null;
542 
543                             // Determine if this date is selectable
544                             var isSelectable = true;
545 
546                             // Helper function to get repeat friendly date against current date
547                             var getRepeatDate = function(v, date) {
548                                 // If repeating, set the date's year and month accordingly
549                                 if(v.repeatYear === true) { date.setYear(cellDateVal.year); }
550                                 if(v.repeatMonth === true) { date.setMonth(cellDateVal.month); }
551 
552                                 return date._val();
553                             };
554 
555                             // Assign date for the cell
556                             cell.html(cellDateVal.date);
557 
558                             // If we have selectable date ranges
559                             if(options.selectableDateRange) {
560                                 isSelectable = false;
561                                 $.each(options.selectableDateRange, function(i, v) {
562                                     var dateFrom = v.from;
563                                     var dateTo = (v.to || null);
564 
565                                     // If to is not specified, default to max days in the from month
566                                     dateTo = dateTo || new Date(v.from.getFullYear(), v.from.getMonth(), v.from._max());
567 
568                                     // If repeating year, set the from and two to the current date's year
569                                     dateFrom = getRepeatDate(v, dateFrom);
570                                     dateTo = getRepeatDate(v, dateTo);
571 
572                                     // Test to see if this date is selectable
573                                     if(cellDateTime >= dateFrom.time && cellDateTime <= dateTo.time) {
574                                         isSelectable = true;
575                                         return true;
576                                     }
577                                 });
578                             }
579 
580                             // Handle date ranges and collections
581                             if(options.selectableDates) {
582                                 if((options.selectableDateRange && !isSelectable) || (isSelectable && !options.selectableDateRange)) {
583                                     isSelectable = false;
584                                 }
585                                 $.each(options.selectableDates, function(i, v) {
586                                     var vDate = getRepeatDate(v, v.date);
587 
588                                     if(vDate.time == cellDateTime) {
589                                         return (isSelectable = true);
590                                     }
591                                 });
592                             }
593 
594                             // If not active or if not within selectableMonths, set to noday otherwise evaluate accordingly
595                             if(!isSelectable ||
596                                 selectableYears._indexOf(cellDateVal.year) < 0 ||
597                                 selectableMonths._indexOf(cellDateVal.month) < 0 ||
598                                 selectableDOW._indexOf(cellDateVal.day) < 0) {
599                                 cellClass = 'noday';
600                             }
601                             else {
602                                 // Handle active dates and weekends
603                                 cellClass = ([ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ])[cellDateVal.day];
604 
605                                 // Handle today or selected dates
606                                 if(firstDateMonth != cellDateVal.month) { cellClass += ' outday'; }
607                                 if(todayTime == cellDateTime) { cellClass = 'today'; cellZIndex += 50; }
608                                 if(options.selectedDate._time() == cellDateTime) { cellClass = 'selected'; cellZIndex += 51; }
609 
610                                 // Handle special dates
611                                 if(options.specialDates) {
612                                     $.each(options.specialDates, function(i, v) {
613                                         var vDate = getRepeatDate(v, v.date);
614 
615                                         if(vDate.time == cellDateTime) {
616                                             cellClass = (v.cssClass || 'special');
617                                             cellZIndex += 52;
618                                             specialData = v.data;
619                                         }
620                                     });
621                                 }
622 
623                                 cell
624                                     .mousedown(function() { return false; })
625                                     .hover(function(e) {
626                                         e.stopPropagation();
627 
628                                         // Get the data from this cell
629                                         var hoverData = $(this).data('data');
630 
631                                         // Call callback
632                                         options.onHover(el, cell, hoverData.date, hoverData.data);
633                                     })
634                                     .click(function(e) {
635                                         e.stopPropagation();
636 
637                                         // Get the data from this cell
638                                         var clickedData = $(this).data('data');
639 
640                                         // Save date to selected and first
641                                         options.selectedDate = options.firstDate = clickedData.date;
642 
643                                         // Update calendar (and auto-hide if necessary)
644                                         self.render(function() {
645                                             if(!options.showAlways && options.hideOnClick) {
646                                                 self.hide();
647                                             }
648                                         });
649 
650                                         // Call callback
651                                         options.onClick(el, $(this), clickedData.date, clickedData.data);
652                                     });
653                             }
654                         }
655 
656                         // Update the css for the cell
657                         $.extend(cellCSS,
658                         {
659                             borderTopWidth: borderSize,
660                             borderBottomWidth: borderSize,
661                             borderLeftWidth: (row > 0 || (!row && !col)) ? borderSize : 0,
662                             borderRightWidth: (row > 0 || (!row && col == 6)) ? borderSize : 0,
663                             marginLeft: (col > 0) ? '-' + (borderSize) : 0,
664                             marginTop: (row > 0) ? '-' + (borderSize) : 0,
665                             zIndex: cellZIndex
666                         });
667 
668                         // Assign other properties to the cell
669                         cell
670                             .data('data', { date: cellDate, data: specialData})
671                             .addClass(coreClass + cellClass)
672                             .css(cellCSS);
673 
674                         // Add cell to calendar
675                         calendar.append(cell);
676                     }
677                 }
678 
679                 // Render the month / year title
680 
681                 // Helper function for toggling select and text
682                 var toggleYearMonthSelect = function(showYear) {
683                     var show = 'inline-block';
684                     var hide = 'none';
685 
686                     if(options.allowMonthSelect) {
687                         monthText.css({ display: !showYear ? hide : show });
688                         monthSelect.css({ display: !showYear ? show : hide });
689                     }
690 
691                     if(options.allowYearSelect) {
692                         yearText.css({ display: showYear ? hide : show });
693                         yearSelect.css({ display: showYear ? show : hide });
694                     }
695                 };
696 
697                 // Helper function when select is updated
698                 var onYearMonthSelect = function() {
699                     options.firstDate = new Date(yearSelect.val(), monthSelect.val(), 1);
700                     self.render();
701                 };
702 
703                 // Build month selector
704                 var monthSelect = $('<select/>')
705                                     .hide()
706                                     .change(onYearMonthSelect);
707 
708                 // Build year selector
709                 var yearSelect = $('<select/>')
710                                     .hide()
711                                     .change(onYearMonthSelect);
712 
713                 // Build month label
714                 var monthText = $('<span/>')
715                                     .html(monthNames[firstDateMonth])
716                                     .mousedown(function() { return false; })
717                                     .click(function(e) {
718                                         e.stopPropagation();
719                                         toggleYearMonthSelect(false);
720                                     });
721 
722                 // Build year label
723                 var yearText = $('<span/>')
724                                     .html(firstDateYear)
725                                     .mousedown(function() { return false; })
726                                     .click(function(e) {
727                                         e.stopPropagation();
728                                         toggleYearMonthSelect(true);
729                                     });
730 
731                 // Populate month select
732                 $.each(monthNames, function(i, v) {
733                     if(options.allowMonthSelect && selectableMonths._indexOf(i) != -1) {
734                         var o = $('<option/>').html(v).attr('value', i);
735                         if(i == firstDateMonth) { o.attr('selected', 'selected');}
736                         monthSelect.append(o);
737                     }
738                 });
739 
740                 // Populate year select
741                 $.each(selectableYears, function(i, v) {
742                     if(options.allowYearSelect) {
743                         var o = $('<option/>').html(v).attr('value', v);
744                         if(v == firstDateYear) { o.attr('selected', 'selected'); }
745                         yearSelect.append(o);
746                     }
747                 });
748 
749                 var titleYearMonth = $('<div/>')
750                                         .append(monthText)
751                                         .append(monthSelect)
752                                         .append(yearText)
753                                         .append(yearSelect);
754 
755                 // Add to title
756                 titleCell.children().remove();
757                 titleCell.append(titleYearMonth);
758 
759                 // Run the callback signaling end of the render
760                 renderCalback = renderCalback || (function() {});
761                 renderCalback();
762             }
763         };
764 
765         // Return the plugin
766         return glDatePicker;
767     })();
768 
769     // One time initialization of useful prototypes
770     (function() {
771         Date.prototype._clear = function() {
772             this.setHours(0);
773             this.setMinutes(0);
774             this.setSeconds(0);
775             this.setMilliseconds(0);
776 
777             return this;
778         };
779 
780         Date.prototype._time = function() {
781             return this._clear().getTime();
782         };
783 
784         Date.prototype._max = function() {
785             var isLeapYear = (new Date(this.getYear(), 1, 29).getMonth() == 1) ? 1 : 0;
786             var days = [31, 28 + isLeapYear, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
787 
788             return days[this.getMonth()];
789         };
790 
791         Date.prototype._add = function(days) {
792             this.setDate(this.getDate() + days);
793         };
794 
795         Date.prototype._first = function() {
796             var date = new Date(this);
797                 date.setDate(1);
798 
799             return date;
800         };
801 
802         Date.prototype._val = function() {
803             this._clear();
804 
805             return {
806                 year: this.getFullYear(),
807                 month: this.getMonth(),
808                 date: this.getDate(),
809                 time: this.getTime(),
810                 day: this.getDay()
811             };
812         };
813 
814         Array.prototype._indexOf = function(value) {
815             return $.inArray(value, this);
816         }
817     })();
818 })();

 

 

在线演示地址

http://runjs.cn/detail/bx3qgacr

 

posted @ 2016-07-06 11:28  sonicwater  阅读(748)  评论(0编辑  收藏  举报