1273 lines
37 KiB
JavaScript
1273 lines
37 KiB
JavaScript
/**
|
|
* @license =========================================================
|
|
* bootstrap-datetimepicker.js
|
|
* http://www.eyecon.ro/bootstrap-datepicker
|
|
* ========================================================= Copyright
|
|
* 2012 Stefan Petre
|
|
*
|
|
* Contributions: - Andrew Rowls - Thiago de Arruda
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
* use this file except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations under
|
|
* the License. =========================================================
|
|
*/
|
|
(function($) {
|
|
var smartPhone = window.orientation != undefined;
|
|
var DateTimePicker = function(element, options) {
|
|
this.id = dpgId++;
|
|
this.init(element, options)
|
|
};
|
|
var dateToDate = function(dt) {
|
|
if (typeof dt === "string") {
|
|
return new Date(dt)
|
|
}
|
|
return dt
|
|
};
|
|
DateTimePicker.prototype = {
|
|
constructor : DateTimePicker,
|
|
init : function(element, options) {
|
|
var icon;
|
|
if (!(options.pickTime || options.pickDate))
|
|
throw new Error("Must choose at least one picker");
|
|
this.options = options;
|
|
this.$element = $(element);
|
|
this.language = options.language in dates ? options.language : "en";
|
|
this.pickDate = options.pickDate;
|
|
this.pickTime = options.pickTime;
|
|
this.isInput = this.$element.is("input");
|
|
this.component = false;
|
|
if (this.$element.is(".input-append")
|
|
|| this.$element.is(".input-prepend"))
|
|
this.component = this.$element.find(".add-on");
|
|
this.format = options.format;
|
|
if (!this.format) {
|
|
if (this.isInput)
|
|
this.format = this.$element.data("format");
|
|
else
|
|
this.format = this.$element.find("input").data("format");
|
|
if (!this.format)
|
|
this.format = "MM/dd/yyyy"
|
|
}
|
|
this._compileFormat();
|
|
if (this.component) {
|
|
icon = this.component.find("i")
|
|
}
|
|
if (this.pickTime) {
|
|
if (icon && icon.length)
|
|
this.timeIcon = icon.data("time-icon");
|
|
if (!this.timeIcon)
|
|
this.timeIcon = "icon-time";
|
|
icon.addClass(this.timeIcon)
|
|
}
|
|
if (this.pickDate) {
|
|
if (icon && icon.length)
|
|
this.dateIcon = icon.data("date-icon");
|
|
if (!this.dateIcon)
|
|
this.dateIcon = "icon-calendar";
|
|
icon.removeClass(this.timeIcon);
|
|
icon.addClass(this.dateIcon)
|
|
}
|
|
this.widget = $(
|
|
getTemplate(this.timeIcon, options.pickDate,
|
|
options.pickTime, options.pick12HourFormat,
|
|
options.pickSeconds)).appendTo("body");
|
|
this.minViewMode = options.minViewMode
|
|
|| this.$element.data("date-minviewmode") || 0;
|
|
if (typeof this.minViewMode === "string") {
|
|
switch (this.minViewMode) {
|
|
case "months":
|
|
this.minViewMode = 1;
|
|
break;
|
|
case "years":
|
|
this.minViewMode = 2;
|
|
break;
|
|
default:
|
|
this.minViewMode = 0;
|
|
break
|
|
}
|
|
}
|
|
this.viewMode = options.viewMode
|
|
|| this.$element.data("date-viewmode") || 0;
|
|
if (typeof this.viewMode === "string") {
|
|
switch (this.viewMode) {
|
|
case "months":
|
|
this.viewMode = 1;
|
|
break;
|
|
case "years":
|
|
this.viewMode = 2;
|
|
break;
|
|
default:
|
|
this.viewMode = 0;
|
|
break
|
|
}
|
|
}
|
|
this.startViewMode = this.viewMode;
|
|
this.weekStart = options.weekStart
|
|
|| this.$element.data("date-weekstart") || 0;
|
|
this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
|
|
this.setStartDate(options.startDate
|
|
|| this.$element.data("date-startdate"));
|
|
this.setEndDate(options.endDate
|
|
|| this.$element.data("date-enddate"));
|
|
this.fillDow();
|
|
this.fillMonths();
|
|
this.fillHours();
|
|
this.fillMinutes();
|
|
this.fillSeconds();
|
|
this.update();
|
|
this.showMode();
|
|
this._attachDatePickerEvents()
|
|
},
|
|
show : function(e) {
|
|
this.widget.show();
|
|
this.height = this.component ? this.component.outerHeight()
|
|
: this.$element.outerHeight();
|
|
this.place();
|
|
this.$element.trigger({
|
|
type : "show",
|
|
date : this._date
|
|
});
|
|
this._attachDatePickerGlobalEvents();
|
|
if (e) {
|
|
e.stopPropagation();
|
|
e.preventDefault()
|
|
}
|
|
},
|
|
disable : function() {
|
|
this.$element.find("input").prop("disabled", true);
|
|
this._detachDatePickerEvents()
|
|
},
|
|
enable : function() {
|
|
this.$element.find("input").prop("disabled", false);
|
|
this._attachDatePickerEvents()
|
|
},
|
|
hide : function() {
|
|
var collapse = this.widget.find(".collapse");
|
|
for ( var i = 0; i < collapse.length; i++) {
|
|
var collapseData = collapse.eq(i).data("collapse");
|
|
if (collapseData && collapseData.transitioning)
|
|
return
|
|
|
|
}
|
|
this.widget.hide();
|
|
this.viewMode = this.startViewMode;
|
|
this.showMode();
|
|
this.set();
|
|
this.$element.trigger({
|
|
type : "hide",
|
|
date : this._date
|
|
});
|
|
this._detachDatePickerGlobalEvents()
|
|
},
|
|
set : function() {
|
|
var formatted = "";
|
|
if (!this._unset)
|
|
formatted = this.formatDate(this._date);
|
|
if (!this.isInput) {
|
|
if (this.component) {
|
|
var input = this.$element.find("input");
|
|
input.val(formatted);
|
|
this._resetMaskPos(input)
|
|
}
|
|
this.$element.data("date", formatted)
|
|
} else {
|
|
this.$element.val(formatted);
|
|
this._resetMaskPos(this.$element)
|
|
}
|
|
},
|
|
setValue : function(newDate) {
|
|
if (!newDate) {
|
|
this._unset = true
|
|
} else {
|
|
this._unset = false
|
|
}
|
|
if (typeof newDate === "string") {
|
|
this._date = this.parseDate(newDate)
|
|
} else if (newDate) {
|
|
this._date = new Date(newDate)
|
|
}
|
|
this.set();
|
|
this.viewDate = UTCDate(this._date.getUTCFullYear(), this._date
|
|
.getUTCMonth(), 1, 0, 0, 0, 0);
|
|
this.fillDate();
|
|
this.fillTime()
|
|
},
|
|
getDate : function() {
|
|
if (this._unset)
|
|
return null;
|
|
return new Date(this._date.valueOf())
|
|
},
|
|
setDate : function(date) {
|
|
if (!date)
|
|
this.setValue(null);
|
|
else
|
|
this.setValue(date.valueOf())
|
|
},
|
|
setStartDate : function(date) {
|
|
if (date instanceof Date) {
|
|
this.startDate = date
|
|
} else if (typeof date === "string") {
|
|
this.startDate = new UTCDate(date);
|
|
if (!this.startDate.getUTCFullYear()) {
|
|
this.startDate = -Infinity
|
|
}
|
|
} else {
|
|
this.startDate = -Infinity
|
|
}
|
|
if (this.viewDate) {
|
|
this.update()
|
|
}
|
|
},
|
|
setEndDate : function(date) {
|
|
if (date instanceof Date) {
|
|
this.endDate = date
|
|
} else if (typeof date === "string") {
|
|
this.endDate = new UTCDate(date);
|
|
if (!this.endDate.getUTCFullYear()) {
|
|
this.endDate = Infinity
|
|
}
|
|
} else {
|
|
this.endDate = Infinity
|
|
}
|
|
if (this.viewDate) {
|
|
this.update()
|
|
}
|
|
},
|
|
getLocalDate : function() {
|
|
if (this._unset)
|
|
return null;
|
|
var d = this._date;
|
|
return new Date(d.getUTCFullYear(), d.getUTCMonth(),
|
|
d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d
|
|
.getUTCSeconds(), d.getUTCMilliseconds())
|
|
},
|
|
setLocalDate : function(localDate) {
|
|
if (!localDate)
|
|
this.setValue(null);
|
|
else
|
|
this.setValue(Date.UTC(localDate.getFullYear(), localDate
|
|
.getMonth(), localDate.getDate(), localDate.getHours(),
|
|
localDate.getMinutes(), localDate.getSeconds(),
|
|
localDate.getMilliseconds()))
|
|
},
|
|
place : function() {
|
|
var offset = this.component ? this.component.offset()
|
|
: this.$element.offset();
|
|
this.widget.css({
|
|
top : offset.top + this.height,
|
|
left : offset.left
|
|
})
|
|
},
|
|
notifyChange : function() {
|
|
this.$element.trigger({
|
|
type : "changeDate",
|
|
date : this.getDate(),
|
|
localDate : this.getLocalDate()
|
|
})
|
|
},
|
|
update : function(newDate) {
|
|
var dateStr = newDate;
|
|
if (!dateStr) {
|
|
if (this.isInput) {
|
|
dateStr = this.$element.val()
|
|
} else {
|
|
dateStr = this.$element.find("input").val()
|
|
}
|
|
if (!dateStr) {
|
|
var tmp = new Date;
|
|
this._date = UTCDate(tmp.getFullYear(), tmp.getMonth(), tmp
|
|
.getDate(), tmp.getHours(), tmp.getMinutes(), tmp
|
|
.getSeconds(), tmp.getMilliseconds())
|
|
} else {
|
|
this._date = this.parseDate(dateStr)
|
|
}
|
|
}
|
|
this.viewDate = UTCDate(this._date.getUTCFullYear(), this._date
|
|
.getUTCMonth(), 1, 0, 0, 0, 0);
|
|
this.fillDate();
|
|
this.fillTime()
|
|
},
|
|
fillDow : function() {
|
|
var dowCnt = this.weekStart;
|
|
var html = "<tr>";
|
|
while (dowCnt < this.weekStart + 7) {
|
|
html += '<th class="dow">'
|
|
+ dates[this.language].daysMin[dowCnt++ % 7] + "</th>"
|
|
}
|
|
html += "</tr>";
|
|
this.widget.find(".datepicker-days thead").append(html)
|
|
},
|
|
fillMonths : function() {
|
|
var html = "";
|
|
var i = 0;
|
|
while (i < 12) {
|
|
html += '<span class="month">'
|
|
+ dates[this.language].monthsShort[i++] + "</span>"
|
|
}
|
|
this.widget.find(".datepicker-months td").append(html)
|
|
},
|
|
fillDate : function() {
|
|
var year = this.viewDate.getUTCFullYear();
|
|
var month = this.viewDate.getUTCMonth();
|
|
var currentDate = UTCDate(this._date.getUTCFullYear(), this._date
|
|
.getUTCMonth(), this._date.getUTCDate(), 0, 0, 0, 0);
|
|
var startYear = typeof this.startDate === "object" ? this.startDate
|
|
.getUTCFullYear() : -Infinity;
|
|
var startMonth = typeof this.startDate === "object" ? this.startDate
|
|
.getUTCMonth()
|
|
: -1;
|
|
var endYear = typeof this.endDate === "object" ? this.endDate
|
|
.getUTCFullYear() : Infinity;
|
|
var endMonth = typeof this.endDate === "object" ? this.endDate
|
|
.getUTCMonth() : 12;
|
|
this.widget.find(".datepicker-days").find(".disabled").removeClass(
|
|
"disabled");
|
|
this.widget.find(".datepicker-months").find(".disabled")
|
|
.removeClass("disabled");
|
|
this.widget.find(".datepicker-years").find(".disabled")
|
|
.removeClass("disabled");
|
|
this.widget.find(".datepicker-days th:eq(1)").text(
|
|
dates[this.language].months[month] + " " + year);
|
|
var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0);
|
|
var day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(),
|
|
prevMonth.getUTCMonth());
|
|
prevMonth.setUTCDate(day);
|
|
prevMonth.setUTCDate(day
|
|
- (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
|
|
if (year == startYear && month <= startMonth || year < startYear) {
|
|
this.widget.find(".datepicker-days th:eq(0)").addClass(
|
|
"disabled")
|
|
}
|
|
if (year == endYear && month >= endMonth || year > endYear) {
|
|
this.widget.find(".datepicker-days th:eq(2)").addClass(
|
|
"disabled")
|
|
}
|
|
var nextMonth = new Date(prevMonth.valueOf());
|
|
nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
|
|
nextMonth = nextMonth.valueOf();
|
|
var html = [];
|
|
var clsName;
|
|
while (prevMonth.valueOf() < nextMonth) {
|
|
if (prevMonth.getUTCDay() === this.weekStart) {
|
|
html.push("<tr>")
|
|
}
|
|
clsName = "";
|
|
if (prevMonth.getUTCFullYear() < year
|
|
|| prevMonth.getUTCFullYear() == year
|
|
&& prevMonth.getUTCMonth() < month) {
|
|
clsName += " old"
|
|
} else if (prevMonth.getUTCFullYear() > year
|
|
|| prevMonth.getUTCFullYear() == year
|
|
&& prevMonth.getUTCMonth() > month) {
|
|
clsName += " new"
|
|
}
|
|
if (prevMonth.valueOf() === currentDate.valueOf()) {
|
|
clsName += " active"
|
|
}
|
|
if (prevMonth.valueOf() + 864e5 <= this.startDate) {
|
|
clsName += " disabled"
|
|
}
|
|
if (prevMonth.valueOf() > this.endDate) {
|
|
clsName += " disabled"
|
|
}
|
|
html.push('<td class="day' + clsName + '">'
|
|
+ prevMonth.getUTCDate() + "</td>");
|
|
if (prevMonth.getUTCDay() === this.weekEnd) {
|
|
html.push("</tr>")
|
|
}
|
|
prevMonth.setUTCDate(prevMonth.getUTCDate() + 1)
|
|
}
|
|
this.widget.find(".datepicker-days tbody").empty().append(
|
|
html.join(""));
|
|
var currentYear = this._date.getUTCFullYear();
|
|
var months = this.widget.find(".datepicker-months")
|
|
.find("th:eq(1)").text(year).end().find("span")
|
|
.removeClass("active");
|
|
if (currentYear === year) {
|
|
months.eq(this._date.getUTCMonth()).addClass("active")
|
|
}
|
|
if (currentYear - 1 < startYear) {
|
|
this.widget.find(".datepicker-months th:eq(0)").addClass(
|
|
"disabled")
|
|
}
|
|
if (currentYear + 1 > endYear) {
|
|
this.widget.find(".datepicker-months th:eq(2)").addClass(
|
|
"disabled")
|
|
}
|
|
for ( var i = 0; i < 12; i++) {
|
|
if (year == startYear && startMonth > i || year < startYear) {
|
|
$(months[i]).addClass("disabled")
|
|
} else if (year == endYear && endMonth < i || year > endYear) {
|
|
$(months[i]).addClass("disabled")
|
|
}
|
|
}
|
|
html = "";
|
|
year = parseInt(year / 10, 10) * 10;
|
|
var yearCont = this.widget.find(".datepicker-years").find(
|
|
"th:eq(1)").text(year + "-" + (year + 9)).end().find("td");
|
|
this.widget.find(".datepicker-years").find("th").removeClass(
|
|
"disabled");
|
|
if (startYear > year) {
|
|
this.widget.find(".datepicker-years").find("th:eq(0)")
|
|
.addClass("disabled")
|
|
}
|
|
if (endYear < year + 9) {
|
|
this.widget.find(".datepicker-years").find("th:eq(2)")
|
|
.addClass("disabled")
|
|
}
|
|
year -= 1;
|
|
for ( var i = -1; i < 11; i++) {
|
|
html += '<span class="year'
|
|
+ (i === -1 || i === 10 ? " old" : "")
|
|
+ (currentYear === year ? " active" : "")
|
|
+ (year < startYear || year > endYear ? " disabled"
|
|
: "") + '">' + year + "</span>";
|
|
year += 1
|
|
}
|
|
yearCont.html(html)
|
|
},
|
|
fillHours : function() {
|
|
var table = this.widget.find(".timepicker .timepicker-hours table");
|
|
table.parent().hide();
|
|
var html = "";
|
|
if (this.options.pick12HourFormat) {
|
|
var current = 1;
|
|
for ( var i = 0; i < 3; i += 1) {
|
|
html += "<tr>";
|
|
for ( var j = 0; j < 4; j += 1) {
|
|
var c = current.toString();
|
|
html += '<td class="hour">' + padLeft(c, 2, "0")
|
|
+ "</td>";
|
|
current++
|
|
}
|
|
html += "</tr>"
|
|
}
|
|
} else {
|
|
var current = 0;
|
|
for ( var i = 0; i < 6; i += 1) {
|
|
html += "<tr>";
|
|
for ( var j = 0; j < 4; j += 1) {
|
|
var c = current.toString();
|
|
html += '<td class="hour">' + padLeft(c, 2, "0")
|
|
+ "</td>";
|
|
current++
|
|
}
|
|
html += "</tr>"
|
|
}
|
|
}
|
|
table.html(html)
|
|
},
|
|
fillMinutes : function() {
|
|
var table = this.widget
|
|
.find(".timepicker .timepicker-minutes table");
|
|
table.parent().hide();
|
|
var html = "";
|
|
var current = 0;
|
|
for ( var i = 0; i < 5; i++) {
|
|
html += "<tr>";
|
|
for ( var j = 0; j < 4; j += 1) {
|
|
var c = current.toString();
|
|
html += '<td class="minute">' + padLeft(c, 2, "0")
|
|
+ "</td>";
|
|
current += 3
|
|
}
|
|
html += "</tr>"
|
|
}
|
|
table.html(html)
|
|
},
|
|
fillSeconds : function() {
|
|
var table = this.widget
|
|
.find(".timepicker .timepicker-seconds table");
|
|
table.parent().hide();
|
|
var html = "";
|
|
var current = 0;
|
|
for ( var i = 0; i < 5; i++) {
|
|
html += "<tr>";
|
|
for ( var j = 0; j < 4; j += 1) {
|
|
var c = current.toString();
|
|
html += '<td class="second">' + padLeft(c, 2, "0")
|
|
+ "</td>";
|
|
current += 3
|
|
}
|
|
html += "</tr>"
|
|
}
|
|
table.html(html)
|
|
},
|
|
fillTime : function() {
|
|
if (!this._date)
|
|
return;
|
|
var timeComponents = this.widget
|
|
.find(".timepicker span[data-time-component]");
|
|
var table = timeComponents.closest("table");
|
|
var is12HourFormat = this.options.pick12HourFormat;
|
|
var hour = this._date.getUTCHours();
|
|
var period = "AM";
|
|
if (is12HourFormat) {
|
|
if (hour >= 12)
|
|
period = "PM";
|
|
if (hour === 0)
|
|
hour = 12;
|
|
else if (hour != 12)
|
|
hour = hour % 12;
|
|
this.widget.find(".timepicker [data-action=togglePeriod]")
|
|
.text(period)
|
|
}
|
|
hour = padLeft(hour.toString(), 2, "0");
|
|
var minute = padLeft(this._date.getUTCMinutes().toString(), 2, "0");
|
|
var second = padLeft(this._date.getUTCSeconds().toString(), 2, "0");
|
|
timeComponents.filter("[data-time-component=hours]").text(hour);
|
|
timeComponents.filter("[data-time-component=minutes]").text(minute);
|
|
timeComponents.filter("[data-time-component=seconds]").text(second)
|
|
},
|
|
click : function(e) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
this._unset = false;
|
|
var target = $(e.target).closest("span, td, th");
|
|
if (target.length === 1) {
|
|
if (!target.is(".disabled")) {
|
|
switch (target[0].nodeName.toLowerCase()) {
|
|
case "th":
|
|
switch (target[0].className) {
|
|
case "switch":
|
|
this.showMode(1);
|
|
break;
|
|
case "prev":
|
|
case "next":
|
|
var vd = this.viewDate;
|
|
var navFnc = DPGlobal.modes[this.viewMode].navFnc;
|
|
var step = DPGlobal.modes[this.viewMode].navStep;
|
|
if (target[0].className === "prev")
|
|
step = step * -1;
|
|
vd["set" + navFnc](vd["get" + navFnc]() + step);
|
|
this.fillDate();
|
|
this.set();
|
|
break
|
|
}
|
|
break;
|
|
case "span":
|
|
if (target.is(".month")) {
|
|
var month = target.parent().find("span").index(
|
|
target);
|
|
this.viewDate.setUTCMonth(month)
|
|
} else {
|
|
var year = parseInt(target.text(), 10) || 0;
|
|
this.viewDate.setUTCFullYear(year)
|
|
}
|
|
if (this.viewMode !== 0) {
|
|
this._date = UTCDate(
|
|
this.viewDate.getUTCFullYear(),
|
|
this.viewDate.getUTCMonth(), this.viewDate
|
|
.getUTCDate(), this._date
|
|
.getUTCHours(), this._date
|
|
.getUTCMinutes(), this._date
|
|
.getUTCSeconds(), this._date
|
|
.getUTCMilliseconds());
|
|
this.notifyChange()
|
|
}
|
|
this.showMode(-1);
|
|
this.fillDate();
|
|
this.set();
|
|
break;
|
|
case "td":
|
|
if (target.is(".day")) {
|
|
var day = parseInt(target.text(), 10) || 1;
|
|
var month = this.viewDate.getUTCMonth();
|
|
var year = this.viewDate.getUTCFullYear();
|
|
if (target.is(".old")) {
|
|
if (month === 0) {
|
|
month = 11;
|
|
year -= 1
|
|
} else {
|
|
month -= 1
|
|
}
|
|
} else if (target.is(".new")) {
|
|
if (month == 11) {
|
|
month = 0;
|
|
year += 1
|
|
} else {
|
|
month += 1
|
|
}
|
|
}
|
|
this._date = UTCDate(year, month, day, this._date
|
|
.getUTCHours(), this._date.getUTCMinutes(),
|
|
this._date.getUTCSeconds(), this._date
|
|
.getUTCMilliseconds());
|
|
this.viewDate = UTCDate(year, month, Math.min(28,
|
|
day), 0, 0, 0, 0);
|
|
this.fillDate();
|
|
this.set();
|
|
this.notifyChange()
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
},
|
|
actions : {
|
|
incrementHours : function(e) {
|
|
this._date.setUTCHours(this._date.getUTCHours() + 1)
|
|
},
|
|
incrementMinutes : function(e) {
|
|
this._date.setUTCMinutes(this._date.getUTCMinutes() + 1)
|
|
},
|
|
incrementSeconds : function(e) {
|
|
this._date.setUTCSeconds(this._date.getUTCSeconds() + 1)
|
|
},
|
|
decrementHours : function(e) {
|
|
this._date.setUTCHours(this._date.getUTCHours() - 1)
|
|
},
|
|
decrementMinutes : function(e) {
|
|
this._date.setUTCMinutes(this._date.getUTCMinutes() - 1)
|
|
},
|
|
decrementSeconds : function(e) {
|
|
this._date.setUTCSeconds(this._date.getUTCSeconds() - 1)
|
|
},
|
|
togglePeriod : function(e) {
|
|
var hour = this._date.getUTCHours();
|
|
if (hour >= 12)
|
|
hour -= 12;
|
|
else
|
|
hour += 12;
|
|
this._date.setUTCHours(hour)
|
|
},
|
|
showPicker : function() {
|
|
this.widget.find(".timepicker > div:not(.timepicker-picker)")
|
|
.hide();
|
|
this.widget.find(".timepicker .timepicker-picker").show()
|
|
},
|
|
showHours : function() {
|
|
this.widget.find(".timepicker .timepicker-picker").hide();
|
|
this.widget.find(".timepicker .timepicker-hours").show()
|
|
},
|
|
showMinutes : function() {
|
|
this.widget.find(".timepicker .timepicker-picker").hide();
|
|
this.widget.find(".timepicker .timepicker-minutes").show()
|
|
},
|
|
showSeconds : function() {
|
|
this.widget.find(".timepicker .timepicker-picker").hide();
|
|
this.widget.find(".timepicker .timepicker-seconds").show()
|
|
},
|
|
selectHour : function(e) {
|
|
var tgt = $(e.target);
|
|
var value = parseInt(tgt.text(), 10);
|
|
if (this.options.pick12HourFormat) {
|
|
var current = this._date.getUTCHours();
|
|
if (current >= 12) {
|
|
if (value != 12)
|
|
value = (value + 12) % 24
|
|
} else {
|
|
if (value === 12)
|
|
value = 0;
|
|
else
|
|
value = value % 12
|
|
}
|
|
}
|
|
this._date.setUTCHours(value);
|
|
this.actions.showPicker.call(this)
|
|
},
|
|
selectMinute : function(e) {
|
|
var tgt = $(e.target);
|
|
var value = parseInt(tgt.text(), 10);
|
|
this._date.setUTCMinutes(value);
|
|
this.actions.showPicker.call(this)
|
|
},
|
|
selectSecond : function(e) {
|
|
var tgt = $(e.target);
|
|
var value = parseInt(tgt.text(), 10);
|
|
this._date.setUTCSeconds(value);
|
|
this.actions.showPicker.call(this)
|
|
}
|
|
},
|
|
doAction : function(e) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
if (!this._date)
|
|
this._date = UTCDate(1970, 0, 0, 0, 0, 0, 0);
|
|
var action = $(e.currentTarget).data("action");
|
|
var rv = this.actions[action].apply(this, arguments);
|
|
this.set();
|
|
this.fillTime();
|
|
this.notifyChange();
|
|
return rv
|
|
},
|
|
stopEvent : function(e) {
|
|
e.stopPropagation();
|
|
e.preventDefault()
|
|
},
|
|
keydown : function(e) {
|
|
var self = this, k = e.which, input = $(e.target);
|
|
if (k == 8 || k == 46) {
|
|
setTimeout(function() {
|
|
self._resetMaskPos(input)
|
|
})
|
|
}
|
|
},
|
|
keypress : function(e) {
|
|
var k = e.which;
|
|
if (k == 8 || k == 46) {
|
|
return
|
|
|
|
}
|
|
var input = $(e.target);
|
|
var c = String.fromCharCode(k);
|
|
var val = input.val() || "";
|
|
val += c;
|
|
var mask = this._mask[this._maskPos];
|
|
if (!mask) {
|
|
return false
|
|
}
|
|
if (mask.end != val.length) {
|
|
return
|
|
|
|
}
|
|
if (!mask.pattern.test(val.slice(mask.start))) {
|
|
val = val.slice(0, val.length - 1);
|
|
while ((mask = this._mask[this._maskPos]) && mask.character) {
|
|
val += mask.character;
|
|
this._maskPos++
|
|
}
|
|
val += c;
|
|
if (mask.end != val.length) {
|
|
input.val(val);
|
|
return false
|
|
} else {
|
|
if (!mask.pattern.test(val.slice(mask.start))) {
|
|
input.val(val.slice(0, mask.start));
|
|
return false
|
|
} else {
|
|
input.val(val);
|
|
this._maskPos++;
|
|
return false
|
|
}
|
|
}
|
|
} else {
|
|
this._maskPos++
|
|
}
|
|
},
|
|
change : function(e) {
|
|
var input = $(e.target);
|
|
var val = input.val();
|
|
if (this._formatPattern.test(val)) {
|
|
this.update();
|
|
this.setValue(this._date.getTime());
|
|
this.notifyChange();
|
|
this.set()
|
|
} else if (val && val.trim()) {
|
|
this.setValue(this._date.getTime());
|
|
if (this._date)
|
|
this.set();
|
|
else
|
|
input.val("")
|
|
} else {
|
|
if (this._date) {
|
|
this.setValue(null);
|
|
this.notifyChange();
|
|
this._unset = true
|
|
}
|
|
}
|
|
this._resetMaskPos(input)
|
|
},
|
|
showMode : function(dir) {
|
|
if (dir) {
|
|
this.viewMode = Math.max(this.minViewMode, Math.min(2,
|
|
this.viewMode + dir))
|
|
}
|
|
this.widget.find(".datepicker > div").hide().filter(
|
|
".datepicker-" + DPGlobal.modes[this.viewMode].clsName)
|
|
.show()
|
|
},
|
|
destroy : function() {
|
|
this._detachDatePickerEvents();
|
|
this._detachDatePickerGlobalEvents();
|
|
this.widget.remove();
|
|
this.$element.removeData("datetimepicker");
|
|
this.component.removeData("datetimepicker")
|
|
},
|
|
formatDate : function(d) {
|
|
return this.format.replace(formatReplacer, function(match) {
|
|
var methodName, property, rv, len = match.length;
|
|
if (match === "ms")
|
|
len = 1;
|
|
property = dateFormatComponents[match].property;
|
|
if (property === "Hours12") {
|
|
rv = d.getUTCHours();
|
|
if (rv === 0)
|
|
rv = 12;
|
|
else if (rv !== 12)
|
|
rv = rv % 12
|
|
} else if (property === "Period12") {
|
|
if (d.getUTCHours() >= 12)
|
|
return "PM";
|
|
else
|
|
return "AM"
|
|
} else {
|
|
methodName = "get" + property;
|
|
rv = d[methodName]()
|
|
}
|
|
if (methodName === "getUTCMonth")
|
|
rv = rv + 1;
|
|
if (methodName === "getUTCYear")
|
|
rv = rv + 1900 - 2e3;
|
|
return padLeft(rv.toString(), len, "0")
|
|
})
|
|
},
|
|
parseDate : function(str) {
|
|
var match, i, property, methodName, value, parsed = {};
|
|
if (!(match = this._formatPattern.exec(str)))
|
|
return null;
|
|
for (i = 1; i < match.length; i++) {
|
|
property = this._propertiesByIndex[i];
|
|
if (!property)
|
|
continue;
|
|
value = match[i];
|
|
if (/^\d+$/.test(value))
|
|
value = parseInt(value, 10);
|
|
parsed[property] = value
|
|
}
|
|
return this._finishParsingDate(parsed)
|
|
},
|
|
_resetMaskPos : function(input) {
|
|
var val = input.val();
|
|
for ( var i = 0; i < this._mask.length; i++) {
|
|
if (this._mask[i].end > val.length) {
|
|
this._maskPos = i;
|
|
break
|
|
} else if (this._mask[i].end === val.length) {
|
|
this._maskPos = i + 1;
|
|
break
|
|
}
|
|
}
|
|
},
|
|
_finishParsingDate : function(parsed) {
|
|
var year, month, date, hours, minutes, seconds, milliseconds;
|
|
year = parsed.UTCFullYear;
|
|
if (parsed.UTCYear)
|
|
year = 2e3 + parsed.UTCYear;
|
|
if (!year)
|
|
year = 1970;
|
|
if (parsed.UTCMonth)
|
|
month = parsed.UTCMonth - 1;
|
|
else
|
|
month = 0;
|
|
date = parsed.UTCDate || 1;
|
|
hours = parsed.UTCHours || 0;
|
|
minutes = parsed.UTCMinutes || 0;
|
|
seconds = parsed.UTCSeconds || 0;
|
|
milliseconds = parsed.UTCMilliseconds || 0;
|
|
if (parsed.Hours12) {
|
|
hours = parsed.Hours12
|
|
}
|
|
if (parsed.Period12) {
|
|
if (/pm/i.test(parsed.Period12)) {
|
|
if (hours != 12)
|
|
hours = (hours + 12) % 24
|
|
} else {
|
|
hours = hours % 12
|
|
}
|
|
}
|
|
return UTCDate(year, month, date, hours, minutes, seconds,
|
|
milliseconds)
|
|
},
|
|
_compileFormat : function() {
|
|
var match, component, components = [], mask = [], str = this.format, propertiesByIndex = {}, i = 0, pos = 0;
|
|
while (match = formatComponent.exec(str)) {
|
|
component = match[0];
|
|
if (component in dateFormatComponents) {
|
|
i++;
|
|
propertiesByIndex[i] = dateFormatComponents[component].property;
|
|
components.push("\\s*"
|
|
+ dateFormatComponents[component].getPattern(this)
|
|
+ "\\s*");
|
|
mask.push({
|
|
pattern : new RegExp(dateFormatComponents[component]
|
|
.getPattern(this)),
|
|
property : dateFormatComponents[component].property,
|
|
start : pos,
|
|
end : pos += component.length
|
|
})
|
|
} else {
|
|
components.push(escapeRegExp(component));
|
|
mask.push({
|
|
pattern : new RegExp(escapeRegExp(component)),
|
|
character : component,
|
|
start : pos,
|
|
end : ++pos
|
|
})
|
|
}
|
|
str = str.slice(component.length)
|
|
}
|
|
this._mask = mask;
|
|
this._maskPos = 0;
|
|
this._formatPattern = new RegExp("^\\s*" + components.join("")
|
|
+ "\\s*$");
|
|
this._propertiesByIndex = propertiesByIndex
|
|
},
|
|
_attachDatePickerEvents : function() {
|
|
var self = this;
|
|
this.widget.on("click", ".datepicker *", $.proxy(this.click, this));
|
|
this.widget.on("click", "[data-action]", $.proxy(this.doAction,
|
|
this));
|
|
this.widget.on("mousedown", $.proxy(this.stopEvent, this));
|
|
if (this.pickDate && this.pickTime) {
|
|
this.widget.on("click.togglePicker", ".accordion-toggle",
|
|
function(e) {
|
|
e.stopPropagation();
|
|
var $this = $(this);
|
|
var $parent = $this.closest("ul");
|
|
var expanded = $parent.find(".collapse.in");
|
|
var closed = $parent.find(".collapse:not(.in)");
|
|
if (expanded && expanded.length) {
|
|
var collapseData = expanded.data("collapse");
|
|
if (collapseData && collapseData.transitioning)
|
|
return;
|
|
expanded.collapse("hide");
|
|
closed.collapse("show");
|
|
$this.find("i").toggleClass(
|
|
self.timeIcon + " " + self.dateIcon);
|
|
self.$element.find(".add-on i").toggleClass(
|
|
self.timeIcon + " " + self.dateIcon)
|
|
}
|
|
})
|
|
}
|
|
if (this.isInput) {
|
|
this.$element.on({
|
|
focus : $.proxy(this.show, this),
|
|
change : $.proxy(this.change, this)
|
|
});
|
|
if (this.options.maskInput) {
|
|
this.$element.on({
|
|
keydown : $.proxy(this.keydown, this),
|
|
keypress : $.proxy(this.keypress, this)
|
|
})
|
|
}
|
|
} else {
|
|
this.$element.on({
|
|
change : $.proxy(this.change, this)
|
|
}, "input");
|
|
if (this.options.maskInput) {
|
|
this.$element.on({
|
|
keydown : $.proxy(this.keydown, this),
|
|
keypress : $.proxy(this.keypress, this)
|
|
}, "input")
|
|
}
|
|
if (this.component) {
|
|
this.component.on("click", $.proxy(this.show, this))
|
|
} else {
|
|
this.$element.on("click", $.proxy(this.show, this))
|
|
}
|
|
}
|
|
},
|
|
_attachDatePickerGlobalEvents : function() {
|
|
$(window).on("resize.datetimepicker" + this.id,
|
|
$.proxy(this.place, this));
|
|
if (!this.isInput) {
|
|
$(document).on("mousedown.datetimepicker" + this.id,
|
|
$.proxy(this.hide, this))
|
|
}
|
|
},
|
|
_detachDatePickerEvents : function() {
|
|
this.widget.off("click", ".datepicker *", this.click);
|
|
this.widget.off("click", "[data-action]");
|
|
this.widget.off("mousedown", this.stopEvent);
|
|
if (this.pickDate && this.pickTime) {
|
|
this.widget.off("click.togglePicker")
|
|
}
|
|
if (this.isInput) {
|
|
this.$element.off({
|
|
focus : this.show,
|
|
change : this.change
|
|
});
|
|
if (this.options.maskInput) {
|
|
this.$element.off({
|
|
keydown : this.keydown,
|
|
keypress : this.keypress
|
|
})
|
|
}
|
|
} else {
|
|
this.$element.off({
|
|
change : this.change
|
|
}, "input");
|
|
if (this.options.maskInput) {
|
|
this.$element.off({
|
|
keydown : this.keydown,
|
|
keypress : this.keypress
|
|
}, "input")
|
|
}
|
|
if (this.component) {
|
|
this.component.off("click", this.show)
|
|
} else {
|
|
this.$element.off("click", this.show)
|
|
}
|
|
}
|
|
},
|
|
_detachDatePickerGlobalEvents : function() {
|
|
$(window).off("resize.datetimepicker" + this.id);
|
|
if (!this.isInput) {
|
|
$(document).off("mousedown.datetimepicker" + this.id)
|
|
}
|
|
}
|
|
};
|
|
$.fn.datetimepicker = function(option, val) {
|
|
return this
|
|
.each(function() {
|
|
var $this = $(this), data = $this.data("datetimepicker"), options = typeof option === "object"
|
|
&& option;
|
|
if (!data) {
|
|
$this
|
|
.data(
|
|
"datetimepicker",
|
|
data = new DateTimePicker(
|
|
this,
|
|
$
|
|
.extend(
|
|
{},
|
|
$.fn.datetimepicker.defaults,
|
|
options)))
|
|
}
|
|
if (typeof option === "string")
|
|
data[option](val)
|
|
})
|
|
};
|
|
$.fn.datetimepicker.defaults = {
|
|
maskInput : false,
|
|
pickDate : true,
|
|
pickTime : true,
|
|
pick12HourFormat : false,
|
|
pickSeconds : true,
|
|
startDate : -Infinity,
|
|
endDate : Infinity
|
|
};
|
|
$.fn.datetimepicker.Constructor = DateTimePicker;
|
|
var dpgId = 0;
|
|
var dates = $.fn.datetimepicker.dates = {
|
|
en : {
|
|
days : [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
|
|
"Friday", "Saturday", "Sunday" ],
|
|
daysShort : [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
|
|
"Sun" ],
|
|
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" ]
|
|
}
|
|
};
|
|
var dateFormatComponents = {
|
|
dd : {
|
|
property : "UTCDate",
|
|
getPattern : function() {
|
|
return "(0?[1-9]|[1-2][0-9]|3[0-1])\\b"
|
|
}
|
|
},
|
|
MM : {
|
|
property : "UTCMonth",
|
|
getPattern : function() {
|
|
return "(0?[1-9]|1[0-2])\\b"
|
|
}
|
|
},
|
|
yy : {
|
|
property : "UTCYear",
|
|
getPattern : function() {
|
|
return "(\\d{2})\\b"
|
|
}
|
|
},
|
|
yyyy : {
|
|
property : "UTCFullYear",
|
|
getPattern : function() {
|
|
return "(\\d{4})\\b"
|
|
}
|
|
},
|
|
hh : {
|
|
property : "UTCHours",
|
|
getPattern : function() {
|
|
return "(0?[0-9]|1[0-9]|2[0-3])\\b"
|
|
}
|
|
},
|
|
mm : {
|
|
property : "UTCMinutes",
|
|
getPattern : function() {
|
|
return "(0?[0-9]|[1-5][0-9])\\b"
|
|
}
|
|
},
|
|
ss : {
|
|
property : "UTCSeconds",
|
|
getPattern : function() {
|
|
return "(0?[0-9]|[1-5][0-9])\\b"
|
|
}
|
|
},
|
|
ms : {
|
|
property : "UTCMilliseconds",
|
|
getPattern : function() {
|
|
return "([0-9]{1,3})\\b"
|
|
}
|
|
},
|
|
HH : {
|
|
property : "Hours12",
|
|
getPattern : function() {
|
|
return "(0?[1-9]|1[0-2])\\b"
|
|
}
|
|
},
|
|
PP : {
|
|
property : "Period12",
|
|
getPattern : function() {
|
|
return "(AM|PM|am|pm|Am|aM|Pm|pM)\\b"
|
|
}
|
|
}
|
|
};
|
|
var keys = [];
|
|
for ( var k in dateFormatComponents)
|
|
keys.push(k);
|
|
keys[keys.length - 1] += "\\b";
|
|
keys.push(".");
|
|
var formatComponent = new RegExp(keys.join("\\b|"));
|
|
keys.pop();
|
|
var formatReplacer = new RegExp(keys.join("\\b|"), "g");
|
|
function escapeRegExp(str) {
|
|
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
|
|
}
|
|
function padLeft(s, l, c) {
|
|
if (l < s.length)
|
|
return s;
|
|
else
|
|
return Array(l - s.length + 1).join(c || " ") + s
|
|
}
|
|
function getTemplate(timeIcon, pickDate, pickTime, is12Hours, showSeconds) {
|
|
if (pickDate && pickTime) {
|
|
return '<div class="bootstrap-datetimepicker-widget dropdown-menu">'
|
|
+ "<ul>"
|
|
+ '<li class="collapse in">'
|
|
+ '<div class="datepicker">'
|
|
+ DPGlobal.template
|
|
+ "</div>"
|
|
+ "</li>"
|
|
+ '<li class="picker-switch"><a class="accordion-toggle"><i class="'
|
|
+ timeIcon
|
|
+ '"></i></a></li>'
|
|
+ '<li class="collapse">'
|
|
+ '<div class="timepicker">'
|
|
+ TPGlobal.getTemplate(is12Hours, showSeconds)
|
|
+ "</div>"
|
|
+ "</li>" + "</ul>" + "</div>"
|
|
} else if (pickTime) {
|
|
return '<div class="bootstrap-datetimepicker-widget dropdown-menu">'
|
|
+ '<div class="timepicker">'
|
|
+ TPGlobal.getTemplate(is12Hours, showSeconds)
|
|
+ "</div>"
|
|
+ "</div>"
|
|
} else {
|
|
return '<div class="bootstrap-datetimepicker-widget dropdown-menu">'
|
|
+ '<div class="datepicker">'
|
|
+ DPGlobal.template
|
|
+ "</div>"
|
|
+ "</div>"
|
|
}
|
|
}
|
|
function UTCDate() {
|
|
return new Date(Date.UTC.apply(Date, arguments))
|
|
}
|
|
var DPGlobal = {
|
|
modes : [ {
|
|
clsName : "days",
|
|
navFnc : "UTCMonth",
|
|
navStep : 1
|
|
}, {
|
|
clsName : "months",
|
|
navFnc : "UTCFullYear",
|
|
navStep : 1
|
|
}, {
|
|
clsName : "years",
|
|
navFnc : "UTCFullYear",
|
|
navStep : 10
|
|
} ],
|
|
isLeapYear : function(year) {
|
|
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0
|
|
},
|
|
getDaysInMonth : function(year, month) {
|
|
return [ 31, DPGlobal.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30,
|
|
31, 31, 30, 31, 30, 31 ][month]
|
|
},
|
|
headTemplate : "<thead>" + "<tr>" + '<th class="prev">‹</th>'
|
|
+ '<th colspan="5" class="switch"></th>'
|
|
+ '<th class="next">›</th>' + "</tr>" + "</thead>",
|
|
contTemplate : '<tbody><tr><td colspan="7"></td></tr></tbody>'
|
|
};
|
|
DPGlobal.template = '<div class="datepicker-days">'
|
|
+ '<table class="table-condensed">' + DPGlobal.headTemplate
|
|
+ "<tbody></tbody>" + "</table>" + "</div>"
|
|
+ '<div class="datepicker-months">'
|
|
+ '<table class="table-condensed">' + DPGlobal.headTemplate
|
|
+ DPGlobal.contTemplate + "</table>" + "</div>"
|
|
+ '<div class="datepicker-years">'
|
|
+ '<table class="table-condensed">' + DPGlobal.headTemplate
|
|
+ DPGlobal.contTemplate + "</table>" + "</div>";
|
|
var TPGlobal = {
|
|
hourTemplate : '<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',
|
|
minuteTemplate : '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',
|
|
secondTemplate : '<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>'
|
|
};
|
|
TPGlobal.getTemplate = function(is12Hours, showSeconds) {
|
|
return '<div class="timepicker-picker">'
|
|
+ '<table class="table-condensed"'
|
|
+ (is12Hours ? ' data-hour-format="12"' : "")
|
|
+ ">"
|
|
+ "<tr>"
|
|
+ '<td><a href="#" class="btn" data-action="incrementHours"><i class="icon-chevron-up"></i></a></td>'
|
|
+ '<td class="separator"></td>'
|
|
+ '<td><a href="#" class="btn" data-action="incrementMinutes"><i class="icon-chevron-up"></i></a></td>'
|
|
+ (showSeconds ? '<td class="separator"></td>'
|
|
+ '<td><a href="#" class="btn" data-action="incrementSeconds"><i class="icon-chevron-up"></i></a></td>'
|
|
: "")
|
|
+ (is12Hours ? '<td class="separator"></td>' : "")
|
|
+ "</tr>"
|
|
+ "<tr>"
|
|
+ "<td>"
|
|
+ TPGlobal.hourTemplate
|
|
+ "</td> "
|
|
+ '<td class="separator">:</td>'
|
|
+ "<td>"
|
|
+ TPGlobal.minuteTemplate
|
|
+ "</td> "
|
|
+ (showSeconds ? '<td class="separator">:</td>' + "<td>"
|
|
+ TPGlobal.secondTemplate + "</td>" : "")
|
|
+ (is12Hours ? '<td class="separator"></td>'
|
|
+ "<td>"
|
|
+ '<button type="button" class="btn btn-primary" data-action="togglePeriod"></button>'
|
|
+ "</td>"
|
|
: "")
|
|
+ "</tr>"
|
|
+ "<tr>"
|
|
+ '<td><a href="#" class="btn" data-action="decrementHours"><i class="icon-chevron-down"></i></a></td>'
|
|
+ '<td class="separator"></td>'
|
|
+ '<td><a href="#" class="btn" data-action="decrementMinutes"><i class="icon-chevron-down"></i></a></td>'
|
|
+ (showSeconds ? '<td class="separator"></td>'
|
|
+ '<td><a href="#" class="btn" data-action="decrementSeconds"><i class="icon-chevron-down"></i></a></td>'
|
|
: "")
|
|
+ (is12Hours ? '<td class="separator"></td>' : "")
|
|
+ "</tr>"
|
|
+ "</table>"
|
|
+ "</div>"
|
|
+ '<div class="timepicker-hours" data-action="selectHour">'
|
|
+ '<table class="table-condensed">'
|
|
+ "</table>"
|
|
+ "</div>"
|
|
+ '<div class="timepicker-minutes" data-action="selectMinute">'
|
|
+ '<table class="table-condensed">'
|
|
+ "</table>"
|
|
+ "</div>"
|
|
+ (showSeconds ? '<div class="timepicker-seconds" data-action="selectSecond">'
|
|
+ '<table class="table-condensed">'
|
|
+ "</table>"
|
|
+ "</div>"
|
|
: "")
|
|
}
|
|
})(window.jQuery); |