1 /* =========================================================
2 * bootstrap-datepicker.js
3 * http://www.eyecon.ro/bootstrap-datepicker
4 * =========================================================
5 * Copyright 2012 Stefan Petre
6 * Improvements by Andrew Rowls
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ========================================================= */
24 return new Date(Date.UTC.apply(Date, arguments));
27 var today = new Date();
28 return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
33 var Datepicker = function(element, options) {
36 this.element = $(element);
37 this.language = options.language||this.element.data('date-language')||"en";
38 this.language = this.language in dates ? this.language : "en";
39 this.isRTL = dates[this.language].rtl||false;
40 this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
41 this.isInline = false;
42 this.isInput = this.element.is('input');
43 this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
44 this.hasInput = this.component && this.element.find('input').length;
45 if(this.component && this.component.length === 0)
46 this.component = false;
50 this.forceParse = true;
51 if ('forceParse' in options) {
52 this.forceParse = options.forceParse;
53 } else if ('dateForceParse' in this.element.data()) {
54 this.forceParse = this.element.data('date-force-parse');
58 this.picker = $(DPGlobal.template)
59 .appendTo(this.isInline ? this.element : 'body')
61 click: $.proxy(this.click, this),
62 mousedown: $.proxy(this.mousedown, this)
66 this.picker.addClass('datepicker-inline');
68 this.picker.addClass('datepicker-dropdown dropdown-menu');
71 this.picker.addClass('datepicker-rtl');
72 this.picker.find('.prev i, .next i')
73 .toggleClass('icon-arrow-left icon-arrow-right');
75 $(document).on('mousedown', function (e) {
76 // Clicked outside the datepicker, hide it
77 if ($(e.target).closest('.datepicker').length === 0) {
82 this.autoclose = false;
83 if ('autoclose' in options) {
84 this.autoclose = options.autoclose;
85 } else if ('dateAutoclose' in this.element.data()) {
86 this.autoclose = this.element.data('date-autoclose');
89 this.keyboardNavigation = true;
90 if ('keyboardNavigation' in options) {
91 this.keyboardNavigation = options.keyboardNavigation;
92 } else if ('dateKeyboardNavigation' in this.element.data()) {
93 this.keyboardNavigation = this.element.data('date-keyboard-navigation');
96 this.viewMode = this.startViewMode = 0;
97 switch(options.startView || this.element.data('date-start-view')){
100 this.viewMode = this.startViewMode = 2;
104 this.viewMode = this.startViewMode = 1;
108 this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false);
109 this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false);
111 this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
112 this.weekEnd = ((this.weekStart + 6) % 7);
113 this.startDate = -Infinity;
114 this.endDate = Infinity;
115 this.daysOfWeekDisabled = [];
116 this.setStartDate(options.startDate||this.element.data('date-startdate'));
117 this.setEndDate(options.endDate||this.element.data('date-enddate'));
118 this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled'));
129 Datepicker.prototype = {
130 constructor: Datepicker,
133 _attachEvents: function(){
134 this._detachEvents();
135 if (this.isInput) { // single input
138 focus: $.proxy(this.show, this),
139 keyup: $.proxy(this.update, this),
140 keydown: $.proxy(this.keydown, this)
144 else if (this.component && this.hasInput){ // component: input + button
146 // For components that are not readonly, allow keyboard nav
147 [this.element.find('input'), {
148 focus: $.proxy(this.show, this),
149 keyup: $.proxy(this.update, this),
150 keydown: $.proxy(this.keydown, this)
153 click: $.proxy(this.show, this)
157 else if (this.element.is('div')) { // inline datepicker
158 this.isInline = true;
163 click: $.proxy(this.show, this)
167 for (var i=0, el, ev; i<this._events.length; i++){
168 el = this._events[i][0];
169 ev = this._events[i][1];
173 _detachEvents: function(){
174 for (var i=0, el, ev; i<this._events.length; i++){
175 el = this._events[i][0];
176 ev = this._events[i][1];
184 this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
187 $(window).on('resize', $.proxy(this.place, this));
192 this.element.trigger({
199 if(this.isInline) return;
201 $(window).off('resize', this.place);
202 this.viewMode = this.startViewMode;
205 $(document).off('mousedown', this.hide);
211 this.isInput && this.element.val() ||
212 this.hasInput && this.element.find('input').val()
216 this.element.trigger({
223 this._detachEvents();
224 this.picker.remove();
225 delete this.element.data().datepicker;
228 getDate: function() {
229 var d = this.getUTCDate();
230 return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
233 getUTCDate: function() {
237 setDate: function(d) {
238 this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
241 setUTCDate: function(d) {
246 setValue: function() {
247 var formatted = this.getFormattedDate();
250 this.element.find('input').val(formatted);
252 this.element.data('date', formatted);
254 this.element.val(formatted);
258 getFormattedDate: function(format) {
259 if (format === undefined)
260 format = this.format;
261 return DPGlobal.formatDate(this.date, format, this.language);
264 setStartDate: function(startDate){
265 this.startDate = startDate||-Infinity;
266 if (this.startDate !== -Infinity) {
267 this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
270 this.updateNavArrows();
273 setEndDate: function(endDate){
274 this.endDate = endDate||Infinity;
275 if (this.endDate !== Infinity) {
276 this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
279 this.updateNavArrows();
282 setDaysOfWeekDisabled: function(daysOfWeekDisabled){
283 this.daysOfWeekDisabled = daysOfWeekDisabled||[];
284 if (!$.isArray(this.daysOfWeekDisabled)) {
285 this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
287 this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
288 return parseInt(d, 10);
291 this.updateNavArrows();
295 if(this.isInline) return;
296 var zIndex = parseInt(this.element.parents().filter(function() {
297 return $(this).css('z-index') != 'auto';
298 }).first().css('z-index'))+10;
299 var offset = this.component ? this.component.offset() : this.element.offset();
300 var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(true);
302 top: offset.top + height,
309 var date, fromArgs = false;
310 if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
314 date = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
317 this.date = DPGlobal.parseDate(date, this.format, this.language);
319 if(fromArgs) this.setValue();
321 var oldViewDate = this.viewDate;
322 if (this.date < this.startDate) {
323 this.viewDate = new Date(this.startDate);
324 } else if (this.date > this.endDate) {
325 this.viewDate = new Date(this.endDate);
327 this.viewDate = new Date(this.date);
330 if (oldViewDate && oldViewDate.getTime() != this.viewDate.getTime()){
331 this.element.trigger({
340 var dowCnt = this.weekStart,
342 while (dowCnt < this.weekStart + 7) {
343 html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
346 this.picker.find('.datepicker-days thead').append(html);
349 fillMonths: function(){
353 html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
355 this.picker.find('.datepicker-months td').html(html);
359 var d = new Date(this.viewDate),
360 year = d.getUTCFullYear(),
361 month = d.getUTCMonth(),
362 startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
363 startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
364 endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
365 endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
366 currentDate = this.date && this.date.valueOf(),
368 this.picker.find('.datepicker-days thead th:eq(1)')
369 .text(dates[this.language].months[month]+' '+year);
370 this.picker.find('tfoot th.today')
371 .text(dates[this.language].today)
372 .toggle(this.todayBtn !== false);
373 this.updateNavArrows();
375 var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
376 day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
377 prevMonth.setUTCDate(day);
378 prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
379 var nextMonth = new Date(prevMonth);
380 nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
381 nextMonth = nextMonth.valueOf();
384 while(prevMonth.valueOf() < nextMonth) {
385 if (prevMonth.getUTCDay() == this.weekStart) {
389 if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
391 } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
394 // Compare internal UTC date with local today, not UTC today
395 if (this.todayHighlight &&
396 prevMonth.getUTCFullYear() == today.getFullYear() &&
397 prevMonth.getUTCMonth() == today.getMonth() &&
398 prevMonth.getUTCDate() == today.getDate()) {
401 if (currentDate && prevMonth.valueOf() == currentDate) {
402 clsName += ' active';
404 if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate ||
405 $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) {
406 clsName += ' disabled';
408 html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
409 if (prevMonth.getUTCDay() == this.weekEnd) {
412 prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
414 this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
415 var currentYear = this.date && this.date.getUTCFullYear();
417 var months = this.picker.find('.datepicker-months')
421 .find('span').removeClass('active');
422 if (currentYear && currentYear == year) {
423 months.eq(this.date.getUTCMonth()).addClass('active');
425 if (year < startYear || year > endYear) {
426 months.addClass('disabled');
428 if (year == startYear) {
429 months.slice(0, startMonth).addClass('disabled');
431 if (year == endYear) {
432 months.slice(endMonth+1).addClass('disabled');
436 year = parseInt(year/10, 10) * 10;
437 var yearCont = this.picker.find('.datepicker-years')
439 .text(year + '-' + (year + 9))
443 for (var i = -1; i < 11; i++) {
444 html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
450 updateNavArrows: function() {
451 var d = new Date(this.viewDate),
452 year = d.getUTCFullYear(),
453 month = d.getUTCMonth();
454 switch (this.viewMode) {
456 if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
457 this.picker.find('.prev').css({visibility: 'hidden'});
459 this.picker.find('.prev').css({visibility: 'visible'});
461 if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
462 this.picker.find('.next').css({visibility: 'hidden'});
464 this.picker.find('.next').css({visibility: 'visible'});
469 if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
470 this.picker.find('.prev').css({visibility: 'hidden'});
472 this.picker.find('.prev').css({visibility: 'visible'});
474 if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
475 this.picker.find('.next').css({visibility: 'hidden'});
477 this.picker.find('.next').css({visibility: 'visible'});
486 var target = $(e.target).closest('span, td, th');
487 if (target.length == 1) {
488 switch(target[0].nodeName.toLowerCase()) {
490 switch(target[0].className) {
496 var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
497 switch(this.viewMode){
499 this.viewDate = this.moveMonth(this.viewDate, dir);
503 this.viewDate = this.moveYear(this.viewDate, dir);
509 var date = new Date();
510 date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
513 var which = this.todayBtn == 'linked' ? null : 'view';
514 this._setDate(date, which);
519 if (!target.is('.disabled')) {
520 this.viewDate.setUTCDate(1);
521 if (target.is('.month')) {
522 var month = target.parent().find('span').index(target);
523 this.viewDate.setUTCMonth(month);
524 this.element.trigger({
529 var year = parseInt(target.text(), 10)||0;
530 this.viewDate.setUTCFullYear(year);
531 this.element.trigger({
541 if (target.is('.day') && !target.is('.disabled')){
542 var day = parseInt(target.text(), 10)||1;
543 var year = this.viewDate.getUTCFullYear(),
544 month = this.viewDate.getUTCMonth();
545 if (target.is('.old')) {
552 } else if (target.is('.new')) {
560 this._setDate(UTCDate(year, month, day,0,0,0,0));
567 _setDate: function(date, which){
568 if (!which || which == 'date')
570 if (!which || which == 'view')
571 this.viewDate = date;
574 this.element.trigger({
580 element = this.element;
581 } else if (this.component){
582 element = this.element.find('input');
586 if (this.autoclose && (!which || which == 'date')) {
592 moveMonth: function(date, dir){
593 if (!dir) return date;
594 var new_date = new Date(date.valueOf()),
595 day = new_date.getUTCDate(),
596 month = new_date.getUTCMonth(),
599 dir = dir > 0 ? 1 : -1;
602 // If going back one month, make sure month is not current month
603 // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
604 ? function(){ return new_date.getUTCMonth() == month; }
605 // If going forward one month, make sure month is as expected
606 // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
607 : function(){ return new_date.getUTCMonth() != new_month; };
608 new_month = month + dir;
609 new_date.setUTCMonth(new_month);
610 // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
611 if (new_month < 0 || new_month > 11)
612 new_month = (new_month + 12) % 12;
614 // For magnitudes >1, move one month at a time...
615 for (var i=0; i<mag; i++)
616 // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
617 new_date = this.moveMonth(new_date, dir);
618 // ...then reset the day, keeping it in the new month
619 new_month = new_date.getUTCMonth();
620 new_date.setUTCDate(day);
621 test = function(){ return new_month != new_date.getUTCMonth(); };
623 // Common date-resetting loop -- if date is beyond end of month, make it
626 new_date.setUTCDate(--day);
627 new_date.setUTCMonth(new_month);
632 moveYear: function(date, dir){
633 return this.moveMonth(date, dir*12);
636 dateWithinRange: function(date){
637 return date >= this.startDate && date <= this.endDate;
640 keydown: function(e){
641 if (this.picker.is(':not(:visible)')){
642 if (e.keyCode == 27) // allow escape to hide and re-show picker
646 var dateChanged = false,
648 newDate, newViewDate;
656 if (!this.keyboardNavigation) break;
657 dir = e.keyCode == 37 ? -1 : 1;
659 newDate = this.moveYear(this.date, dir);
660 newViewDate = this.moveYear(this.viewDate, dir);
661 } else if (e.shiftKey){
662 newDate = this.moveMonth(this.date, dir);
663 newViewDate = this.moveMonth(this.viewDate, dir);
665 newDate = new Date(this.date);
666 newDate.setUTCDate(this.date.getUTCDate() + dir);
667 newViewDate = new Date(this.viewDate);
668 newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
670 if (this.dateWithinRange(newDate)){
672 this.viewDate = newViewDate;
681 if (!this.keyboardNavigation) break;
682 dir = e.keyCode == 38 ? -1 : 1;
684 newDate = this.moveYear(this.date, dir);
685 newViewDate = this.moveYear(this.viewDate, dir);
686 } else if (e.shiftKey){
687 newDate = this.moveMonth(this.date, dir);
688 newViewDate = this.moveMonth(this.viewDate, dir);
690 newDate = new Date(this.date);
691 newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
692 newViewDate = new Date(this.viewDate);
693 newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
695 if (this.dateWithinRange(newDate)){
697 this.viewDate = newViewDate;
713 this.element.trigger({
719 element = this.element;
720 } else if (this.component){
721 element = this.element.find('input');
729 showMode: function(dir) {
731 this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
734 vitalets: fixing bug of very special conditions:
735 jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
736 Method show() does not set display css correctly and datepicker is not shown.
737 Changed to .css('display', 'block') solve the problem.
738 See https://github.com/vitalets/x-editable/issues/37
740 In jquery 1.7.2+ everything works fine.
742 //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
743 this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
744 this.updateNavArrows();
748 $.fn.datepicker = function ( option ) {
749 var args = Array.apply(null, arguments);
751 return this.each(function () {
753 data = $this.data('datepicker'),
754 options = typeof option == 'object' && option;
756 $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
758 if (typeof option == 'string' && typeof data[option] == 'function') {
759 data[option].apply(data, args);
764 $.fn.datepicker.defaults = {
766 $.fn.datepicker.Constructor = Datepicker;
767 var dates = $.fn.datepicker.dates = {
769 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
770 daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
771 daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
772 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
773 monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
795 isLeapYear: function (year) {
796 return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
798 getDaysInMonth: function (year, month) {
799 return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
801 validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
802 nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
803 parseFormat: function(format){
804 // IE treats \0 as a string end in inputs (truncating the value),
805 // so it's a bad format delimiter, anyway
806 var separators = format.replace(this.validParts, '\0').split('\0'),
807 parts = format.match(this.validParts);
808 if (!separators || !separators.length || !parts || parts.length === 0){
809 throw new Error("Invalid date format.");
811 return {separators: separators, parts: parts};
813 parseDate: function(date, format, language) {
814 if (date instanceof Date) return date;
815 if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) {
816 var part_re = /([\-+]\d+)([dmwy])/,
817 parts = date.match(/([\-+]\d+)([dmwy])/g),
820 for (var i=0; i<parts.length; i++) {
821 part = part_re.exec(parts[i]);
822 dir = parseInt(part[1]);
825 date.setUTCDate(date.getUTCDate() + dir);
828 date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
831 date.setUTCDate(date.getUTCDate() + dir * 7);
834 date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
838 return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
840 var parts = date && date.match(this.nonpunctuation) || [],
843 setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
845 yyyy: function(d,v){ return d.setUTCFullYear(v); },
846 yy: function(d,v){ return d.setUTCFullYear(2000+v); },
852 while (d.getUTCMonth() != v)
853 d.setUTCDate(d.getUTCDate()-1);
856 d: function(d,v){ return d.setUTCDate(v); }
859 setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
860 setters_map['dd'] = setters_map['d'];
861 date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
862 var fparts = format.parts.slice();
864 if (parts.length != fparts.length) {
865 fparts = $(fparts).filter(function(i,p){
866 return $.inArray(p, setters_order) !== -1;
870 if (parts.length == fparts.length) {
871 for (var i=0, cnt = fparts.length; i < cnt; i++) {
872 val = parseInt(parts[i], 10);
877 filtered = $(dates[language].months).filter(function(){
878 var m = this.slice(0, parts[i].length),
879 p = parts[i].slice(0, m.length);
882 val = $.inArray(filtered[0], dates[language].months) + 1;
885 filtered = $(dates[language].monthsShort).filter(function(){
886 var m = this.slice(0, parts[i].length),
887 p = parts[i].slice(0, m.length);
890 val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
896 for (var i=0, s; i<setters_order.length; i++){
897 s = setters_order[i];
898 if (s in parsed && !isNaN(parsed[s]))
899 setters_map[s](date, parsed[s]);
904 formatDate: function(date, format, language){
906 d: date.getUTCDate(),
907 D: dates[language].daysShort[date.getUTCDay()],
908 DD: dates[language].days[date.getUTCDay()],
909 m: date.getUTCMonth() + 1,
910 M: dates[language].monthsShort[date.getUTCMonth()],
911 MM: dates[language].months[date.getUTCMonth()],
912 yy: date.getUTCFullYear().toString().substring(2),
913 yyyy: date.getUTCFullYear()
915 val.dd = (val.d < 10 ? '0' : '') + val.d;
916 val.mm = (val.m < 10 ? '0' : '') + val.m;
918 seps = $.extend([], format.separators);
919 for (var i=0, cnt = format.parts.length; i < cnt; i++) {
921 date.push(seps.shift());
922 date.push(val[format.parts[i]]);
924 return date.join('');
926 headTemplate: '<thead>'+
928 '<th class="prev"><i class="icon-arrow-left"/></th>'+
929 '<th colspan="5" class="switch"></th>'+
930 '<th class="next"><i class="icon-arrow-right"/></th>'+
933 contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
934 footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
936 DPGlobal.template = '<div class="datepicker">'+
937 '<div class="datepicker-days">'+
938 '<table class=" table-condensed">'+
939 DPGlobal.headTemplate+
941 DPGlobal.footTemplate+
944 '<div class="datepicker-months">'+
945 '<table class="table-condensed">'+
946 DPGlobal.headTemplate+
947 DPGlobal.contTemplate+
948 DPGlobal.footTemplate+
951 '<div class="datepicker-years">'+
952 '<table class="table-condensed">'+
953 DPGlobal.headTemplate+
954 DPGlobal.contTemplate+
955 DPGlobal.footTemplate+
960 $.fn.datepicker.DPGlobal = DPGlobal;