vendor/assets/javascripts/bootstrap/bootstrap-datepicker.js in bootstrap-rails-engine-1.2.0 vs vendor/assets/javascripts/bootstrap/bootstrap-datepicker.js in bootstrap-rails-engine-1.2.1

- old
+ new

@@ -35,45 +35,42 @@ this.element = $(element); this.language = options.language||this.element.data('date-language')||"en"; this.language = this.language in dates ? this.language : "en"; this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy'); - this.picker = $(DPGlobal.template) - .appendTo('body') - .on({ - click: $.proxy(this.click, this) - }); + this.isInline = false; this.isInput = this.element.is('input'); this.component = this.element.is('.date') ? this.element.find('.add-on') : false; this.hasInput = this.component && this.element.find('input').length; if(this.component && this.component.length === 0) this.component = false; - if (this.isInput) { - this.element.on({ - focus: $.proxy(this.show, this), - keyup: $.proxy(this.update, this), - keydown: $.proxy(this.keydown, this) - }); - } else { - if (this.component && this.hasInput){ - // For components that are not readonly, allow keyboard nav - this.element.find('input').on({ - focus: $.proxy(this.show, this), - keyup: $.proxy(this.update, this), - keydown: $.proxy(this.keydown, this) - }); + this._attachEvents(); - this.component.on('click', $.proxy(this.show, this)); - } else { - this.element.on('click', $.proxy(this.show, this)); - } + this.forceParse = true; + if ('forceParse' in options) { + this.forceParse = options.forceParse; + } else if ('dateForceParse' in this.element.data()) { + this.forceParse = this.element.data('date-force-parse'); } + + this.picker = $(DPGlobal.template) + .appendTo(this.isInline ? this.element : 'body') + .on({ + click: $.proxy(this.click, this), + mousedown: $.proxy(this.mousedown, this) + }); + + if(this.isInline) { + this.picker.addClass('datepicker-inline'); + } else { + this.picker.addClass('datepicker-dropdown dropdown-menu'); + } $(document).on('mousedown', function (e) { // Clicked outside the datepicker, hide it - if ($(e.target).closest('.datepicker').length == 0) { + if ($(e.target).closest('.datepicker').length === 0) { that.hide(); } }); this.autoclose = false; @@ -88,44 +85,96 @@ this.keyboardNavigation = options.keyboardNavigation; } else if ('dateKeyboardNavigation' in this.element.data()) { this.keyboardNavigation = this.element.data('date-keyboard-navigation'); } + this.viewMode = this.startViewMode = 0; switch(options.startView || this.element.data('date-start-view')){ case 2: case 'decade': this.viewMode = this.startViewMode = 2; break; case 1: case 'year': this.viewMode = this.startViewMode = 1; break; - case 0: - case 'month': - default: - this.viewMode = this.startViewMode = 0; - break; } this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false); this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false); this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7); this.weekEnd = ((this.weekStart + 6) % 7); this.startDate = -Infinity; this.endDate = Infinity; + this.daysOfWeekDisabled = []; this.setStartDate(options.startDate||this.element.data('date-startdate')); this.setEndDate(options.endDate||this.element.data('date-enddate')); + this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled')); this.fillDow(); this.fillMonths(); this.update(); this.showMode(); + + if(this.isInline) { + this.show(); + } }; Datepicker.prototype = { constructor: Datepicker, + _events: [], + _attachEvents: function(){ + this._detachEvents(); + if (this.isInput) { // single input + this._events = [ + [this.element, { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }] + ]; + } + else if (this.component && this.hasInput){ // component: input + button + this._events = [ + // For components that are not readonly, allow keyboard nav + [this.element.find('input'), { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }], + [this.component, { + click: $.proxy(this.show, this) + }] + ]; + } + else if (this.element.is('div')) { // inline datepicker + this.isInline = true; + } + else { + this._events = [ + [this.element, { + click: $.proxy(this.show, this) + }] + ]; + } + for (var i=0, el, ev; i<this._events.length; i++){ + el = this._events[i][0]; + ev = this._events[i][1]; + el.on(ev); + } + }, + _detachEvents: function(){ + for (var i=0, el, ev; i<this._events.length; i++){ + el = this._events[i][0]; + ev = this._events[i][1]; + el.off(ev); + } + this._events = []; + }, + show: function(e) { this.picker.show(); this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); this.update(); this.place(); @@ -139,28 +188,42 @@ date: this.date }); }, hide: function(e){ + if(this.isInline) return; this.picker.hide(); $(window).off('resize', this.place); this.viewMode = this.startViewMode; this.showMode(); if (!this.isInput) { $(document).off('mousedown', this.hide); } - if (e && e.currentTarget.value) + + if ( + this.forceParse && + ( + this.isInput && this.element.val() || + this.hasInput && this.element.find('input').val() + ) + ) this.setValue(); this.element.trigger({ type: 'hide', date: this.date }); }, + remove: function() { + this._detachEvents(); + this.picker.remove(); + delete this.element.data().datepicker; + }, + getDate: function() { var d = this.getUTCDate(); - return new Date(d.getTime() + (d.getTimezoneOffset()*60000)) + return new Date(d.getTime() + (d.getTimezoneOffset()*60000)); }, getUTCDate: function() { return this.date; }, @@ -173,21 +236,26 @@ this.date = d; this.setValue(); }, setValue: function() { - var formatted = DPGlobal.formatDate(this.date, this.format, this.language); + var formatted = this.getFormattedDate(); if (!this.isInput) { if (this.component){ this.element.find('input').prop('value', formatted); } this.element.data('date', formatted); } else { this.element.prop('value', formatted); } }, + getFormattedDate: function(format) { + if(format == undefined) format = this.format; + return DPGlobal.formatDate(this.date, format, this.language); + }, + setStartDate: function(startDate){ this.startDate = startDate||-Infinity; if (this.startDate !== -Infinity) { this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language); } @@ -202,11 +270,24 @@ } this.update(); this.updateNavArrows(); }, + setDaysOfWeekDisabled: function(daysOfWeekDisabled){ + this.daysOfWeekDisabled = daysOfWeekDisabled||[]; + if (!$.isArray(this.daysOfWeekDisabled)) { + this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/); + } + this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) { + return parseInt(d, 10); + }); + this.update(); + this.updateNavArrows(); + }, + place: function(){ + if(this.isInline) return; var zIndex = parseInt(this.element.parents().filter(function() { return $(this).css('z-index') != 'auto'; }).first().css('z-index'))+10; var offset = this.component ? this.component.offset() : this.element.offset(); this.picker.css({ @@ -215,14 +296,22 @@ zIndex: zIndex }); }, update: function(){ - this.date = DPGlobal.parseDate( - this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'), - this.format, this.language - ); + var date, fromArgs = false; + if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { + date = arguments[0]; + fromArgs = true; + } else { + date = this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'); + } + + this.date = DPGlobal.parseDate(date, this.format, this.language); + + if(fromArgs) this.setValue(); + if (this.date < this.startDate) { this.viewDate = new Date(this.startDate); } else if (this.date > this.endDate) { this.viewDate = new Date(this.endDate); } else { @@ -230,22 +319,22 @@ } this.fill(); }, fillDow: function(){ - var dowCnt = this.weekStart; - var html = '<tr>'; + var dowCnt = this.weekStart, + html = '<tr>'; while (dowCnt < this.weekStart + 7) { html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>'; } html += '</tr>'; this.picker.find('.datepicker-days thead').append(html); }, fillMonths: function(){ - var html = ''; - var i = 0 + var html = '', + i = 0; while (i < 12) { html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>'; } this.picker.find('.datepicker-months td').html(html); }, @@ -262,11 +351,11 @@ today = new Date(); this.picker.find('.datepicker-days thead th:eq(1)') .text(dates[this.language].months[month]+' '+year); this.picker.find('tfoot th.today') .text(dates[this.language].today) - .toggle(this.todayBtn); + .toggle(this.todayBtn !== false); this.updateNavArrows(); this.fillMonths(); var prevMonth = UTCDate(year, month-1, 28,0,0,0,0), day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); prevMonth.setUTCDate(day); @@ -294,11 +383,12 @@ clsName += ' today'; } if (prevMonth.valueOf() == currentDate) { clsName += ' active'; } - if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) { + if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate || + $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) { clsName += ' disabled'; } html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>'); if (prevMonth.getUTCDay() == this.weekEnd) { html.push('</tr>'); @@ -399,14 +489,11 @@ } this.fill(); break; case 'today': var date = new Date(); - date.setUTCHours(0); - date.setUTCMinutes(0); - date.setUTCSeconds(0); - date.setUTCMilliseconds(0); + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); this.showMode(-2); var which = this.todayBtn == 'linked' ? null : 'view'; this._setDate(date, which); break; @@ -438,11 +525,11 @@ if (target.is('.day') && !target.is('.disabled')){ var day = parseInt(target.text(), 10)||1; var year = this.viewDate.getUTCFullYear(), month = this.viewDate.getUTCMonth(); if (target.is('.old')) { - if (month == 0) { + if (month === 0) { month = 11; year -= 1; } else { month -= 1; } @@ -478,12 +565,12 @@ } else if (this.component){ element = this.element.find('input'); } if (element) { element.change(); - if (this.autoclose) { - this.hide(); + if (this.autoclose && (!which || which == 'date')) { + this.hide(); } } }, moveMonth: function(date, dir){ @@ -625,11 +712,21 @@ showMode: function(dir) { if (dir) { this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir)); } - this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + /* + vitalets: fixing bug of very special conditions: + jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover. + Method show() does not set display css correctly and datepicker is not shown. + Changed to .css('display', 'block') solve the problem. + See https://github.com/vitalets/x-editable/issues/37 + + In jquery 1.7.2+ everything works fine. + */ + //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); this.updateNavArrows(); } }; $.fn.datepicker = function ( option ) { @@ -658,11 +755,11 @@ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], today: "Today" } - } + }; var DPGlobal = { modes: [ { clsName: 'days', @@ -808,11 +905,11 @@ '</tr>'+ '</thead>', contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>', footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>' }; - DPGlobal.template = '<div class="datepicker dropdown-menu">'+ + DPGlobal.template = '<div class="datepicker">'+ '<div class="datepicker-days">'+ '<table class=" table-condensed">'+ DPGlobal.headTemplate+ '<tbody></tbody>'+ DPGlobal.footTemplate+ @@ -831,6 +928,9 @@ DPGlobal.contTemplate+ DPGlobal.footTemplate+ '</table>'+ '</div>'+ '</div>'; + + $.fn.datepicker.DPGlobal = DPGlobal; + }( window.jQuery );