tail.datetime
Advanced tools
Comparing version 0.3.4 to 0.4.0
CHANGELOG | ||
========= | ||
Version 0.4.0 - Beta | ||
-------------------- | ||
- Info: This is the first BETA version! :3 | ||
- Info: This Repository is now completely independent, due to the removal of the last original | ||
lines of MrGuiseppes pureJSCalendar script! | ||
- Add: Russian translation (ru). | ||
- Add: Designs in LESS Format (I'm new at this Pre-Processing Stuff :/). | ||
- Add: Support as Asynchronous Module Definition. | ||
- Add: The default design has 3 new, and the "harx" design has one additional color schemes. | ||
- Add: The new option `animate` to enable and disable the fade and tooltip animations. | ||
- Add: The new option `dateBlacklist` to turn the `dateRange` from a blacklist to a whitelist. | ||
- Add: The new option `dateStart` to limit the calendar. | ||
- Add: The new option `dateEnd` to limit the calendar. | ||
- Add: The new option `locale` to change the used locale by the calendar. | ||
- Add: The new option `timeHours` to set the default Hours on init (pass null for current). | ||
- Add: The new option `timeMintes` to set the default Minutes on init (pass null for current). | ||
- Add: The new option `timeSeconds` to set the default Seconds on init (pass null for current). | ||
- Add: The new option `today` to mark the current day within the calendar script. | ||
- Add: The new option `tooltips` to create tooltips on specific dates. | ||
- Add: The new option `viewDefault` to select the default view, when the calendar gets opened. | ||
- Add: The new option `viewDecades` enables the view "Decades" (Show different Decades). | ||
- Add: The new option `viewYears` enables the view "Years" (Show 12 Years - One Decade). | ||
- Add: The new option `viewMonths` enables the view "Months" (January - December). | ||
- Add: The new option `viewDays` enables the view "Days" (01 - 28|29|30|31). | ||
- Add: The new internal event trigger method `.trigger()`. | ||
- Add: A new custom event listener, using `.on()` and `.trigger()`. | ||
- Add: The new internal render and view methods `.renderCalendar()`, `.renderDatePicker()`, | ||
`.renderTimePicker()`,`.viewDecades()`, `.viewYears()`, `.viewMonths()`, `.viewDays()`, | ||
`.handleLabel()`, `.showTooltip()` and `.hideTooltip()`. | ||
- Add: The new public method `.config()` to get and set settings during the runtime. | ||
- Add: The new public methods `.switchView()`, `.browseView()`, `.switchDate()` and `.fetchDate()` | ||
to control the calendar interface and fetch the current Date. | ||
- Add: The new public methods `.appendTooltip()` and `.appendRange()` to append tooltips and date | ||
ranges during the runtime. | ||
- Update: The translations itself, as well as the translation / locale system behind. | ||
- Update: Both designs has been updated to the new structure. | ||
- Update: The main helper methods. | ||
- Update: The calendar render process has been re-written, now it will always show 6 rows of | ||
dates, including days from the previous and next month! | ||
- Update: The locale system is now usable per instance, the strings doesn't get replaced! | ||
- Update: The option `classNames` allows now `true` to copy the class names from the main | ||
element and false, to do nothing. | ||
- Update: The option `position` and `static` has been merged, so use "top", "left", "right" or | ||
or "bottom" to show the calendar on an absolute position relative to the passed element | ||
or pass any selector, which should be used as container. | ||
- Update: The option `weekStart` supports now also numbers (SUN = 0, MON = 1, ... SAT = 6)! | ||
- Update: The option `dateRange` requires now a new range format, the old one is NOT supported! | ||
- Update: The public methods `.switchMonth()` and `switchYear()` now just aliases for the main | ||
public method `.switchDate()`. | ||
- Update: The public methods `.open()` and `.close()` now using `setTimeout()` instead of an | ||
interval. | ||
- Update: The public methods `.reload()` reloads the same instance instead of creating a new one. | ||
- Update: The public event method `.on()` has been updated and supports now a third argument. | ||
- Remove: The option `static` has been removed (use `position` instead). | ||
- Remove: The option `zeroSeconds` has been removed (use `timeSeconds` instead). | ||
- Remove: The option `static` has been removed (use `position` instead). | ||
- Remove: The `isIE11` and `tail.IE` variables. | ||
- Remove: The old render functions `.renderDay()`, `.renderMonth()` and `.renderTime()` has been | ||
replaced by the new `.view*()` and `.render*()` methods! | ||
- Remove: The `.createCalendar()` method has been replaced by the new `.view*()` methods. | ||
- Bugfix: The `tbdy` typo has been fixed. | ||
- Bugfix: Incorrect `colspan` value on the thead element (on the Months View). | ||
Version 0.3.4 - Alpha | ||
@@ -5,0 +68,0 @@ --------------------- |
/* | ||
| tail.DateTime - A pure, vanilla JavaScript DateTime Picker | ||
| @author SamBrishes <https://github.com/pytesNET/tail.DateTime/> | ||
| MrGuiseppe <https://github.com/MrGuiseppe/pureJSCalendar/> | ||
| @version 0.3.4 [0.1.0] - Alpha | ||
| @file ./js/tail.datetime.js | ||
| @author SamBrishes <https://github.com/pytesNET/tail.DateTime/> | ||
| @version 0.4.0 - Alpha | ||
| | ||
| @license X11 / MIT License | ||
| @copyright Copyright © 2018 - SamBrishes, pytesNET <pytes@gmx.net> | ||
| Copyright © 2018 - MrGuiseppe <https://github.com/MrGuiseppe> | ||
| @fork MrGuiseppe <https://github.com/MrGuiseppe/pureJSCalendar/> | ||
| This script started as fork and is now completely independent! | ||
| | ||
| @license X11 / MIT License | ||
| @copyright Copyright © 2018 - SamBrishes, pytesNET <pytes@gmx.net> | ||
*/ | ||
;(function(window){ | ||
;(function(factory){ | ||
if(typeof(define) == "function" && define.amd){ | ||
define(function(){ return factory(window); }); | ||
} else { | ||
if(typeof(window.tail) == "undefined"){ | ||
window.tail = {}; | ||
} | ||
window.tail.DateTime = factory(window); | ||
} | ||
}(function(root){ | ||
"use strict"; | ||
var w = window, d = window.document; | ||
var w = root, d = root.document; | ||
/* | ||
| HELPER METHODs | ||
*/ | ||
var tail = { | ||
hasClass: function(element, name){ | ||
return (new RegExp("(|\s+)" + name + "(\s+|)")).test(element.className); | ||
}, | ||
addClass: function(element, name){ | ||
if(!(new RegExp("(|\s+)" + name + "(\s+|)")).test(element.className)){ | ||
element.className = (element.className.trim() + " " + name.trim()).trim(); | ||
} | ||
return element; | ||
}, | ||
removeClass: function(element, name){ | ||
var regex = new RegExp("(|\s+)(" + name + ")(\s+|)"); | ||
if(regex.test(element.className)){ | ||
element.className = (element.className.replace(regex, "$1$3")).trim(); | ||
} | ||
return element; | ||
}, | ||
trigger: function(element, event, options){ | ||
if(CustomEvent && CustomEvent.name){ | ||
var e = new CustomEvent(event, options); | ||
return element.dispatchEvent(e); | ||
} | ||
var e = d.createEvent("CustomEvent"); | ||
e.initCustomEvent(event, ((options.bubbles)? true: false), ((options.cancelable)? true: false), options.detail); | ||
return element.dispatchEvent(e); | ||
}, | ||
clone: function(object, replace){ | ||
replace = (typeof(replace) == "object")? replace: {}; | ||
var clone = object.constructor(); | ||
for(var key in object){ | ||
if(replace.hasOwnProperty(key)){ | ||
clone[key] = replace[key]; | ||
} else if(object.hasOwnProperty(key)){ | ||
clone[key] = object[key]; | ||
} | ||
} | ||
return clone; | ||
// Internal Helper Methods | ||
function cHAS(e, name){ | ||
return (new RegExp("\\b" + name + "\\b")).test((e.className || "")); | ||
} | ||
function cADD(e, name){ | ||
if(!(new RegExp("\\b" + name + "\\b")).test(e.className || name)){ | ||
e.className += " " + name; | ||
} | ||
return e; | ||
} | ||
function cREM(e, name, regex){ | ||
if((regex = new RegExp("\\b(" + name + ")\\b")) && regex.test(e.className || "")){ | ||
e.className = e.className.replace(regex, ""); | ||
} | ||
return e; | ||
} | ||
function trigger(e, event, opt){ | ||
if(CustomEvent && CustomEvent.name){ | ||
var ev = new CustomEvent(event, opt); | ||
} else { | ||
var ev = d.createEvent("CustomEvent"); | ||
ev.initCustomEvent(event, !!opt.bubbles, !!opt.cancelable, opt.detail); | ||
} | ||
return e.dispatchEvent(ev); | ||
} | ||
function clone(obj, rep){ | ||
if(Object.assign){ | ||
return Object.assign({}, obj, rep || {}); | ||
} | ||
var clone = Object.constructor(); | ||
for(var key in obj){ | ||
clone[key] = (key in rep)? rep[key]: obj[key]; | ||
} | ||
return clone; | ||
} | ||
function first(str){ return str.charAt(0).toUpperCase() + str.slice(1); }; | ||
function parse(str, time, reset){ | ||
var date = (str instanceof Date)? str: (str)? new Date(str): false; | ||
if(!(date instanceof Date) || isNaN(date.getDate())){ | ||
return false; | ||
} | ||
(reset)? date.setHours(0, 0, 0, 0): date; | ||
return (time === true)? date.getTime(): date; | ||
}; | ||
tail.IE = (w.navigator.userAgent.indexOf("MSIE") > -1 || w.navigator.userAgent.indexOf("Edge") > -1); | ||
@@ -62,3 +74,3 @@ /* | ||
| @since 0.1.0 | ||
| @update 0.3.4 | ||
| @update 0.4.0 | ||
*/ | ||
@@ -69,13 +81,11 @@ var tailDateTime = function(element, config){ | ||
} | ||
if(element instanceof NodeList || element instanceof HTMLCollection){ | ||
if(element.length == 0){ | ||
return false; | ||
if(element instanceof NodeList || element instanceof HTMLCollection || element instanceof Array){ | ||
for(var _r = [], l = element.length, i = 0; i < l; i++){ | ||
_r.push(new tailDateTime(element[i], config)); | ||
} | ||
var _return = new Array(); | ||
for(var i = 0; i < element.length; i++){ | ||
_return.push(new tailDateTime(element[i], config)); | ||
} | ||
return (_return.length == 1)? _return[0]: _return; | ||
return (_r.length === 1)? _r[0]: ((_r.length === 0)? false: _r); | ||
} | ||
if(typeof(this) == "undefined"){ | ||
if(!(element instanceof Element)){ | ||
return false; | ||
} else if(!(this instanceof tailDateTime)){ | ||
return new tailDateTime(element, config); | ||
@@ -85,55 +95,23 @@ } | ||
// Check Element | ||
if(!(element instanceof Element)){ | ||
return false; | ||
if(tailDateTime.inst[element.getAttribute("data-tail-datetime")]){ | ||
return tailDateTime.inst[element.getAttribute("data-tail-datetime")]; | ||
} | ||
if(element.hasAttribute("data-tail-calendar") && tailDateTime.instances[element.getAttribute("data-tail-calendar")]){ | ||
return tailDateTime.instances[element.getAttribute("data-tail-calendar")]; | ||
} | ||
// Vaildate DateRange | ||
if(config.dateRanges && config.dateRanges.length > 0){ | ||
for(var t, i = 0; i < config.dateRanges.length; i++){ | ||
t = config.dateRanges[i]; | ||
// Week-Day | ||
if(typeof(t[0]) == "string" && __("shorts").indexOf(t[0]) >= 0){ | ||
t[0] = __("shorts").indexOf(t[0]); | ||
t[1] = (t.length >= 2 && __("shorts").indexOf(t[1]) >= 0)? __("shorts").indexOf(t[1]): 6; | ||
continue; | ||
} | ||
// Date Object | ||
if(typeof(t[0]) == "string"){ | ||
t[0] = new Date(Date.parse(t[0])); | ||
if(t.length == 2 && typeof(t[1]) == "string"){ | ||
t[1] = new Date(Date.parse(t[1])); | ||
} else if(t.length == 1){ | ||
t[1] = new Date(t[0].getFullYear(), t[0].getMonth(), 0); | ||
} | ||
} | ||
if(!(t[0] instanceof Date && !isNaN(t[0].getDate()))){ | ||
t[0] = new Date(); | ||
} | ||
if(t.length < 2 || !(t[1] instanceof Date && !isNaN(t[1].getDate()))){ | ||
t[1] = new Date(t[0].getFullYear(), t[0].getMonth(), 0); | ||
} | ||
if(element.getAttribute("data-datetime")){ | ||
var test = JSON.parse(element.getAttribute("data-datetime").replace(/\'/g, '"')); | ||
if(test instanceof Object){ | ||
config = clone(config, test); | ||
} | ||
} | ||
// Init Prototype Instance | ||
// Init Instance | ||
this.e = element; | ||
config = (typeof(config) == "object")? config: {}; | ||
if(Object.assign){ | ||
this.con = Object.assign({}, tailDateTime.defaults, config); | ||
} else { | ||
this.con = tail.clone(tailDateTime.defaults, config); | ||
} | ||
this.id = ++tailDateTime.count; | ||
this.con = clone(tailDateTime.defaults, config); | ||
tailDateTime.inst["tail-" + this.id] = this; | ||
return this.init(); | ||
}; | ||
tailDateTime.version = "0.3.4"; | ||
tailDateTime.status = "alpha"; | ||
tailDateTime.version = "0.4.0"; | ||
tailDateTime.status = "beta"; | ||
tailDateTime.count = 0; | ||
tailDateTime.isIE11 = !!w.MSInputMethodContext && !!d.documentMode; | ||
tailDateTime.cache = {}; | ||
tailDateTime.instances = {}; | ||
tailDateTime.inst = {}; | ||
@@ -144,12 +122,25 @@ /* | ||
tailDateTime.defaults = { | ||
static: null, | ||
position: "bottom", | ||
classNames: "", | ||
animate: true, | ||
classNames: false, | ||
dateFormat: "YYYY-mm-dd", | ||
timeFormat: "HH:ii:ss", | ||
dateStart: false, | ||
dateRanges: [], | ||
weekStart: "SUN", | ||
dateBlacklist: true, | ||
dateEnd: false, | ||
locale: "en", | ||
position: "bottom", | ||
startOpen: false, | ||
stayOpen: false, | ||
zeroSeconds: false | ||
timeFormat: "HH:ii:ss", | ||
timeHours: null, | ||
timeMinutes: null, | ||
timeSeconds: 0, | ||
today: true, | ||
tooltips: [], | ||
viewDefault: "days", | ||
viewDecades: true, | ||
viewYears: true, | ||
viewMonths: true, | ||
viewDays: true, | ||
weekStart: 0 | ||
}; | ||
@@ -161,17 +152,13 @@ | ||
tailDateTime.strings = { | ||
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], | ||
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], | ||
shorts: ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"], | ||
time: ["Hours", "Minutes", "Seconds"], | ||
header: ["Select a Month", "Select a Year", "Select a Time"], | ||
"en": { | ||
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], | ||
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], | ||
shorts: ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"], | ||
time: ["Hours", "Minutes", "Seconds"], | ||
header: ["Select a Month", "Select a Year", "Select a Decade", "Select a Time"] | ||
} | ||
}; | ||
var __ = function(string, number){ | ||
if(string in w.tail.DateTime.strings){ | ||
if(number !== undefined){ | ||
return w.tail.DateTime.strings[string][number]; | ||
} | ||
return w.tail.DateTime.strings[string]; | ||
} | ||
return false; | ||
} | ||
tailDateTime.strings.register = function(locale, object){ | ||
tailDateTime.strings[locale] = object; | ||
}; | ||
@@ -182,254 +169,277 @@ /* | ||
tailDateTime.prototype = { | ||
e: null, // The Input Element | ||
dt: null, // The DateTime Picker | ||
con: {}, // The Configuration Object | ||
view: {}, // The current DateTime View | ||
select: null, // The current selected Date (Object) | ||
/* | ||
| HANDLE :: INIT CALENDAR | ||
| INTERNAL :: INIT CALENDAR | ||
| @since 0.1.0 | ||
| @update 0.3.3 | ||
| @update 0.4.0 | ||
*/ | ||
init: function(){ | ||
if(this.dt){ | ||
return this.dt; | ||
} | ||
var _static = d.querySelector(this.con.static); | ||
var self = this, temp; | ||
this.__ = tailDateTime.strings[this.con.locale] || tailDateTime.strings["en"]; | ||
// Create DateTime Picker | ||
this.dt = d.createElement("DIV"); | ||
this.dt.id = "data-tail-calendar-" + ++tailDateTime.count; | ||
this.dt.className = "tail-datetime-calendar calendar-close" + ((_static)? " calendar-static": ""); | ||
if(this.con.stayOpen){ | ||
this.dt.className += " calendar-stay"; | ||
// Options | ||
this.con.dateStart = parse(this.con.dateStart, true, true) || 0; | ||
this.con.dateEnd = parse(this.con.dateEnd, true, true) || 9999999999999; | ||
this.con.viewDefault = (!this.con.dateFormat)? "time": this.con.viewDefault; | ||
if(typeof(this.con.weekStart) == "string"){ | ||
this.con.weekStart = tailDateTime.strings.en.shorts.indexOf(this.con.weekStart); | ||
} | ||
if(this.con.classNames){ | ||
this.dt.className += " " + ((this.con.classNames instanceof Array)? this.con.classNames.join(" "): this.con.classNames); | ||
if(this.con.weekStart < 0 && this.con.weekStart > 6){ | ||
this.con.weekStart = 0; | ||
} | ||
// Create Calendar Structure | ||
if(this.con.dateFormat){ | ||
this.dt.innerHTML = '' + | ||
'<div class="calendar-navi">' + | ||
' <span data-tail-navi="prev" class="calendar-button button-prev"></span>' + | ||
' <span data-tail-navi="switch" class="calendar-label"></span>' + | ||
' <span data-tail-navi="next" class="calendar-button button-next"></span>' + | ||
'</div>' + | ||
'<div class="calendar-date"></div>' + | ||
((this.con.timeFormat)? '<div class="calendar-time">' + this.renderTime() + '</div>': ''); | ||
} else { | ||
this.dt.innerHTML = '' + | ||
'<div class="calendar-navi">' + | ||
' <span data-tail-navi="check" class="calendar-button button-check"></span>' + | ||
' <span data-tail-navi="switch" class="calendar-label">' + __("header", 2) + '</span>' + | ||
' <span data-tail-navi="close" class="calendar-button button-close"></span>' + | ||
'</div>' + | ||
((this.con.timeFormat)? '<div class="calendar-time">' + this.renderTime() + '</div>': ''); | ||
// Prepare Date Ranges | ||
if(this.con.dateRanges.length > 0){ | ||
for(var r = [], e = this.con.dateRanges, l = e.length, i = 0; i < l; i++){ | ||
if(!(e[i] instanceof Object) || (!e[i].start && !e[i].days)){ | ||
continue; | ||
} | ||
// Prepare Dates | ||
if((e[i].start = parse(e[i].start || false, true, true)) === false){ | ||
e[i].start = e[i].end = Infinity; | ||
} else { | ||
if((e[i].end = parse(e[i].end || false, true, true)) === false){ | ||
e[i].end = e[i].start; | ||
} | ||
e[i].start = (e[i].start > e[i].end)? [e[i].end, e[i].end = e[i].start][0]: e[i].start; | ||
} | ||
// Prepare Days | ||
e[i].days = (!e[i].days)? true: e[i].days; | ||
e[i].days = (typeof(days) !== "boolean")? (function(days){ | ||
for(var _r = [], _l = days.length, _i = 0; _i < _l; _i++){ | ||
if(typeof(days[_i]) == "string"){ | ||
days[_i] = tailDateTime.strings.en.shorts.indexOf(days[_i]); | ||
} | ||
if(days[_i] >= 0 && days[_i] <= 6){ _r.push(days[_i]); } | ||
} | ||
return _r; | ||
}((e[i].days instanceof Array)? e[i].days: [e[i].days])): [0, 1, 2, 3, 4, 5, 6]; | ||
// Append | ||
r.push({start: e[i].start, end: e[i].end, days: e[i].days}); | ||
} | ||
this.con.dateRanges = r; | ||
} | ||
// Set Calendar Data | ||
var select = new Date(Date.parse(this.e.getAttribute("data-tail-value") || this.e.value)); | ||
this.view = { | ||
type: "date", | ||
date: new Date(), | ||
content: "", | ||
render: function(){ return this.content.querySelector("tbody").innerHTML; } | ||
}; | ||
if(!isNaN(select.getDate())){ | ||
this.select = select; | ||
if(this.con.zeroSeconds){ | ||
this.select.setSeconds(0); | ||
// Prepare Tooltips | ||
if(this.con.tooltips.length > 0){ | ||
for(var r = [], t = this.con.tooltips, l = t.length, i = 0, s, e; i < l; i++){ | ||
if(!(t[i] instanceof Object) || !t[i].date){ | ||
continue; | ||
} | ||
// Prepare Dates | ||
if(t[i].date instanceof Array){ | ||
s = parse(t[i].date[0] || false, true, true); | ||
e = parse(t[i].date[0] || false, true, true) || s; | ||
} else { | ||
s = e = parse(t[i].date || false, true, true); | ||
} | ||
if(!s){ continue; } | ||
// Append | ||
r.push({ | ||
date: (s !== e)? [s, e]: s, | ||
text: t[i].text || "Tooltip", | ||
color: t[i].color || "#202428", | ||
element: t[i].element || (function(tooltip){ | ||
tooltip.className = "calendar-tooltip"; | ||
tooltip.innerHTML = '<div class="tooltip-inner">' + t[i].text || "Tooltip" + '</div>'; | ||
return tooltip; | ||
}(d.createElement("DIV"))) | ||
}); | ||
} | ||
this.view.date = new Date(this.select.getTime()); | ||
this.con.tooltips = r; | ||
} | ||
if(this.con.timeFormat){ | ||
this.dt.querySelector(".calendar-field-h > input").value = this.view.date.getHours(); | ||
this.dt.querySelector(".calendar-field-m > input").value = this.view.date.getMinutes(); | ||
this.dt.querySelector(".calendar-field-s > input").value = this.view.date.getSeconds(); | ||
// Prepare WeekDays | ||
var week = this.__["shorts"].slice(this.con.weekStart).concat(this.__["shorts"].slice(0, this.con.weekStart)); | ||
this.weekdays = "<thead>\n<tr>\n"; | ||
for(var i = 0; i < 7; i++){ | ||
this.weekdays += '<th class="calendar-week">' + week[i] + '</th>'; | ||
} | ||
this.weekdays += "\n</tr>\n</thead>" | ||
this.switchMonth(this.view.date.getMonth(), this.view.date.getFullYear()); | ||
if(this.e.hasAttribute("data-tail-value")){ | ||
this.selectDate(); | ||
} else { | ||
this.e.setAttribute("data-tail-value", this.convertDate(this.view.date, "YYYY-mm-dd HH:ii:ss")); | ||
// Set Main Data and Render | ||
this.select = parse(this.e.getAttribute("data-value") || this.e.value); | ||
if(!this.select || this.select < this.con.dateStart || this.select > this.con.dateEnd){ | ||
this.select = null; | ||
} | ||
if(this.view == undefined){ | ||
this.view = { | ||
type: this.con.viewDefault, | ||
date: this.select || new Date() | ||
}; | ||
} | ||
for(var l = ["Hours", "Minutes", "Seconds"], i = 0; i < 3; i++){ | ||
if(typeof(this.con["time" + l[i]]) == "number"){ | ||
this.view.date["set" + l[i]](this.con["time" + l[i]]); | ||
} | ||
} | ||
this.events = {}; | ||
this.dt = this.renderCalendar(); | ||
// Configure Calendar Widget | ||
this.dt.style.top = 0; | ||
this.dt.style.left = 0; | ||
this.dt.style.zIndex = 99; | ||
this.dt.style.position = (_static)? "static": "absolute"; | ||
this.dt.style.visibility = (_static)? "visible": "hidden"; | ||
if(_static){ | ||
_static.appendChild(this.dt); | ||
} else { | ||
d.getElementsByTagName("body")[0].appendChild(this.dt); | ||
// Hook Events | ||
if(this._bind == undefined){ | ||
var e = "addEventListener"; | ||
this.e[e]("focusin", function(event){ | ||
self.open.call(self); | ||
}); | ||
this.e[e]("keyup", function(event){ | ||
self.bind.call(self, event); | ||
}); | ||
d[e]("keyup", function(event){ | ||
self.bind.call(self, event); | ||
}); | ||
d[e]("click", function(event){ | ||
if(self.dt.contains(event.target)){ | ||
self.bind.call(self, event); | ||
} else if(!self.e.contains(event.target) && cHAS(self.dt, "calendar-open")){ | ||
if(event.target != self.dt && event.target != self.e && !self.con.stayOpen){ | ||
self.close.call(self); | ||
} | ||
} | ||
}); | ||
d[e]("mouseover", function(event){ | ||
if(self.dt.contains(event.target)){ | ||
self.bind.call(self, event); | ||
} | ||
}); | ||
this._bind = true; | ||
} | ||
// Listen Header | ||
var self = this, navi = this.dt.querySelectorAll("[data-tail-navi]"); | ||
if(navi.length > 0){ | ||
for(var i = 0; i < navi.length; i++){ | ||
navi[i].addEventListener("click", function(event){ | ||
var action = this.getAttribute("data-tail-navi"); | ||
// Store Instance and Return | ||
this.e.setAttribute("data-tail-datetime", "tail-" + this.id); | ||
if(this.con.startOpen){ | ||
this.open(); | ||
} | ||
if(this.select){ | ||
this.selectDate(this.select); | ||
} | ||
return this; | ||
}, | ||
if(self.con.dateFormat){ | ||
if(self.view.type == "month"){ | ||
if(action == "prev" || action == "next"){ | ||
self.switchYear.call(self, action); | ||
} else { | ||
self.switchView.call(self, "day"); | ||
} | ||
} else { | ||
if(action == "prev" || action == "next"){ | ||
self.switchMonth.call(self, action); | ||
} else { | ||
self.switchView.call(self, "month"); | ||
} | ||
} | ||
} else if(self.con.timeFormat){ | ||
if(action == "check"){ | ||
self.selectTime.call(self, | ||
parseInt(self.dt.querySelector(".calendar-field-h > input").value), | ||
parseInt(self.dt.querySelector(".calendar-field-m > input").value), | ||
parseInt(self.dt.querySelector(".calendar-field-s > input").value) | ||
); | ||
} | ||
if(!self.con.stayOpen){ | ||
self.close.call(self); | ||
} | ||
} | ||
}); | ||
/* | ||
| INTERNAL :: EVENT LISTENER | ||
| @since 0.4.0 | ||
*/ | ||
bind: function(event){ | ||
var self = event.target, a = "getAttribute", d = "data-action", v = "data-view", | ||
elem = self[a](d)? self: self.parentElement[a](d)? self.parentElement: self; | ||
// Hover Events | ||
var t = "data-tooltip", tip; | ||
if(event.type == "mouseover"){ | ||
if((tip = self[a](t)? self: elem[a](t)? elem: false) !== false){ | ||
if(!this.dt.querySelector("#tooltip-" + tip[a](t) + "-" + tip[a](t + "-time"))){ | ||
this.showTooltip(tip[a](t), tip, tip[a](t + "-time")); | ||
} | ||
} else if(this.dt.querySelector(".calendar-tooltip:not(.remove)")){ | ||
this.hideTooltip(this.dt.querySelector(".calendar-tooltip").id.slice(8)); | ||
} | ||
} | ||
// Listen Input | ||
this.e.addEventListener("focusin", function(event){ | ||
self.open.call(self); | ||
}); | ||
this.e.addEventListener("focusout", function(event){ | ||
var select = new Date(Date.parse(this.value)); | ||
if(!isNaN(select.getDate())){ | ||
self.selectDate.call(self, | ||
select.getFullYear(), select.getMonth(), select.getDate(), | ||
select.getHours(), select.getMinutes(), select.getSeconds() | ||
); | ||
self.switchMonth.call(self, select.getMonth(), select.getFullYear()); | ||
// Click Events | ||
if(event.type == "click"){ | ||
if(!elem || (event.buttons != 1 && (event.which || event.button) != 1)){ | ||
return; | ||
} | ||
}); | ||
this.e.addEventListener("keyup", function(event){ | ||
if(event.keyCode == 13){ | ||
var select = new Date(Date.parse(this.value)); | ||
if(!isNaN(select.getDate())){ | ||
self.selectDate.call(self, | ||
select.getFullYear(), select.getMonth(), select.getDate(), | ||
select.getHours(), select.getMinutes(), select.getSeconds() | ||
); | ||
self.switchMonth.call(self, select.getMonth(), select.getFullYear()); | ||
} | ||
event.stopPropagation(); | ||
switch(elem[a](d)){ | ||
case "prev": | ||
return this.browseView("prev"); | ||
case "next": | ||
return this.browseView("next"); | ||
case "submit": | ||
return this.selectDate(this.fetchDate(elem[a]("data-date"))); | ||
case "cancel": | ||
if(!this.con.stayOpen){ | ||
this.close(); | ||
} | ||
break; | ||
case "view": | ||
this.switchDate(elem[a]("data-year") || null, elem[a]("data-month") || null, elem[a]("data-day") || null); | ||
return this.switchView(elem[a](v)); | ||
} | ||
}); | ||
d.addEventListener("keyup", function(event){ | ||
if(tail.hasClass(self.dt, "calendar-open") && event.keyCode == 27){ | ||
if(!self.con.stayOpen){ | ||
self.close.call(self); | ||
} | ||
// KeyEvents | ||
if(event.type == "keyup"){ | ||
if(event.target !== this.e){ | ||
if(/calendar-(static|close)/i.test(this.dt.className)){ | ||
return false; | ||
} | ||
self.e.blur(); | ||
} | ||
if(tail.hasClass(self.dt, "calendar-open") && event.keyCode == 13){ | ||
if(self.con.dateFormat){ | ||
var day = self.dt.children[1].querySelector("td.today") || self.dt.children[1].querySelector("td:not(.empty)"), | ||
time = !!self.con.timeFormat; | ||
if(!tail.hasClass(day, "disabled")){ | ||
self.selectDate.call(self, | ||
self.view.year, self.view.month, parseInt(day.value), | ||
(time)? parseInt(self.dt.querySelector(".calendar-field-h > input").value): 0, | ||
(time)? parseInt(self.dt.querySelector(".calendar-field-m > input").value): 0, | ||
(time)? parseInt(self.dt.querySelector(".calendar-field-s > input").value): 0 | ||
); | ||
} | ||
} else { | ||
self.selectTime.call(self, | ||
parseInt(self.dt.querySelector(".calendar-field-h > input").value), | ||
parseInt(self.dt.querySelector(".calendar-field-m > input").value), | ||
parseInt(self.dt.querySelector(".calendar-field-s > input").value) | ||
); | ||
} | ||
if(!self.con.stayOpen){ | ||
self.close.call(self); | ||
} | ||
self.e.blur(); | ||
if((event.keyCode || event.which) == 13){ // Enter || Return | ||
this.selectDate(this.fetchDate()); | ||
event.stopPropagation(); | ||
if(!this.con.stayOpen){ this.close(); } | ||
} | ||
}); | ||
d.addEventListener("click", function(event){ | ||
if(!tail.hasClass(self.dt, "calendar-open")){ | ||
return; | ||
if((event.keyCode || event.which) == 27){ // ESC | ||
if(!this.con.stayOpen){ this.close(); } | ||
} | ||
if(!self.dt.contains(event.target) && !self.e.contains(event.target)){ | ||
if(event.target != self.dt && event.target != self.e){ | ||
if(!self.con.stayOpen){ | ||
self.close.call(self); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
}, | ||
// Store Instance and Return | ||
this.e.setAttribute("data-tail-calendar", "tail-" + tailDateTime.count); | ||
if(this.con.startOpen){ | ||
this.open(); | ||
/* | ||
| INTERNAL :: EVENT TRIGGER | ||
| @since 0.4.0 | ||
*/ | ||
trigger: function(event){ | ||
var obj = {bubbles: false, cancelable: true, detail: {args: arguments, self: this}}; | ||
if(event == "change"){ | ||
trigger(this.e, "input", obj); | ||
trigger(this.e, "change", obj); | ||
} | ||
tailDateTime.instances["tail-" + tailDateTime.count] = this; | ||
return this; | ||
trigger(this.dt, "tail::" + event, obj); | ||
for(var l = (this.events[event] || []).length, i = 0; i < l; i++){ | ||
this.events[event][i].cb.apply(this, (function(args, a, b){ | ||
for(var l = a.length, i = 0; i < l; ++i){ | ||
args[i-1] = a[i]; | ||
} | ||
args[i] = b; | ||
return args; | ||
}(new Array(arguments.length), arguments, this.events[event][i].args))); | ||
} | ||
}, | ||
/* | ||
| HANDLE :: CALCULATE POSITION | ||
| HELPER :: CALCULATE POSITION | ||
| @since 0.3.1 | ||
| @update 0.4.0 | ||
*/ | ||
calcPosition: function(){ | ||
if(tail.hasClass(this.dt, "calendar-static")){ | ||
return this; | ||
} | ||
var style = w.getComputedStyle(this.dt), | ||
marginX = parseInt(style.marginLeft)+parseInt(style.marginRight), | ||
marginY = parseInt(style.marginTop)+parseInt(style.marginBottom), | ||
position = (function(element){ | ||
var position = { | ||
top: element.offsetTop || 0, | ||
left: element.offsetLeft || 0, | ||
width: element.offsetWidth || 0, | ||
height: element.offsetHeight || 0 | ||
}; | ||
while(element = element.offsetParent){ | ||
position.top += element.offsetTop; | ||
position.left += element.offsetLeft; | ||
} | ||
return position; | ||
})(this.e); | ||
var a = this.dt.style, b = w.getComputedStyle(this.dt), | ||
x = parseInt(b.marginLeft)+parseInt(b.marginRight), | ||
y = parseInt(b.marginTop) +parseInt(b.marginBottom), | ||
p = (function(e, r){ | ||
r = { | ||
top: e.offsetTop || 0, left: e.offsetLeft || 0, | ||
width: e.offsetWidth || 0, height: e.offsetHeight || 0 | ||
}; | ||
while(e = e.offsetParent){ r.top += e.offsetTop; r.left += e.offsetLeft; } | ||
return r; | ||
})(this.e, {}); | ||
// Set Position | ||
this.dt.style.visibility = "hidden"; | ||
a.visibility = "hidden"; | ||
switch(this.con.position){ | ||
case "top": | ||
this.dt.style.top = position.top - (this.dt.offsetHeight + marginY) + "px"; | ||
this.dt.style.left = (position.left + (position.width / 2)) - (this.dt.offsetWidth / 2 + marginX / 2) + "px"; | ||
a.top = p.top - (this.dt.offsetHeight + y) + "px"; | ||
a.left = (p.left + (p.width / 2)) - (this.dt.offsetWidth / 2 + x / 2) + "px"; | ||
break; | ||
case "left": | ||
this.dt.style.top = (position.top + position.height/2) - (this.dt.offsetHeight / 2 + marginY) + "px"; | ||
this.dt.style.left = position.left - (this.dt.offsetWidth + marginX) + "px"; | ||
a.top = (p.top + p.height/2) - (this.dt.offsetHeight / 2 + y) + "px"; | ||
a.left = p.left - (this.dt.offsetWidth + x) + "px"; | ||
break; | ||
case "right": | ||
this.dt.style.top = (position.top + position.height/2) - (this.dt.offsetHeight / 2 + marginY) + "px"; | ||
this.dt.style.left = position.left + position.width + "px"; | ||
a.top = (p.top + p.height/2) - (this.dt.offsetHeight / 2 + y) + "px"; | ||
a.left = p.left + p.width + "px"; | ||
break; | ||
default: | ||
this.dt.style.top = position.top + position.height + "px"; | ||
this.dt.style.left = (position.left + (position.width / 2)) - (this.dt.offsetWidth / 2 + marginX / 2) + "px"; | ||
case "bottom": | ||
a.top = p.top + p.height + "px"; | ||
a.left = (p.left + (p.width / 2)) - (this.dt.offsetWidth / 2 + x / 2) + "px"; | ||
break; | ||
} | ||
this.dt.style.visibility = "visible"; | ||
a.visibility = "visible"; | ||
return this; | ||
@@ -439,485 +449,658 @@ }, | ||
/* | ||
| HANDLE :: SWITCH VIEW | ||
| HELPER :: CONVERT DATE | ||
| @since 0.1.0 | ||
| @update 0.3.3 | ||
| @update 0.4.0 | ||
*/ | ||
switchView: function(view){ | ||
if(!this.con.dateFormat){ | ||
return false; | ||
} | ||
convertDate: function(inDate, format){ | ||
var dateObject = { | ||
H: String("00" + inDate.getHours()).toString().slice(-2), | ||
G: function(hours){ return (hours % 12)? hours % 12: 12; }(inDate.getHours()), | ||
A: inDate.getHours() >= 12? "PM": "AM", | ||
a: inDate.getHours() >= 12? "pm": "am", | ||
i: String("00" + inDate.getMinutes()).toString().slice(-2), | ||
s: String("00" + inDate.getSeconds()).toString().slice(-2), | ||
Y: inDate.getFullYear(), | ||
y: parseInt(inDate.getFullYear().toString().slice(2)), | ||
m: String("00" + (inDate.getMonth() + 1)).toString().slice(-2), | ||
M: this.__["months"][inDate.getMonth()].slice(0, 3), | ||
F: this.__["months"][inDate.getMonth()], | ||
d: String("00" + inDate.getDate()).toString().slice(-2), | ||
D: this.__["days"][inDate.getDay()], | ||
l: this.__["shorts"][inDate.getDay()].toLowerCase() | ||
}; | ||
return format.replace(/([HGismd]{1,2}|[Y]{2,4}|y{2})/g, function(token){ | ||
if(token.length == 4 || token.length == 2){ | ||
return dateObject[token.slice(-1)].toString().slice(-Math.abs(token.length)); | ||
} else if(token.length == 1 && datePart[0] == "0"){ | ||
return dateObject[token.slice(-1)].toString().slice(-1) | ||
} | ||
return dateObject[token.slice(-1)].toString(); | ||
}).replace(/(A|a|M|F|D|l)/g, function(token){ return dateObject[token]; }); | ||
}, | ||
// Render View | ||
this.view.type = view; | ||
if(view == "month"){ | ||
this.dt.children[1].innerHTML = ""; | ||
this.dt.children[1].insertAdjacentHTML("afterbegin", this.renderMonth()); | ||
this.dt.querySelector(".calendar-label").innerText = this.view.date.getFullYear(); | ||
} else { | ||
this.dt.children[1].innerHTML = this.renderDay(); | ||
this.dt.querySelector(".calendar-label").innerText = __("months", this.view.date.getMonth()) + " " + this.view.date.getFullYear(); | ||
/* | ||
| RENDER :: CALENDAR | ||
| @since 0.4.0 | ||
*/ | ||
renderCalendar: function(){ | ||
var _s, _c = ["tail-datetime-calendar", "calendar-close"], dt = d.createElement("DIV"), | ||
_t = (this.con.classNames === true)? this.e.className: this.con.classNames; | ||
// Disable on Ranges | ||
var ranges = this.con.dateRanges, current = this.view.date, | ||
fields = this.dt.querySelectorAll("tbody td:not(.empty)"), | ||
compare = new Date(current.getFullYear(), current.getMonth(), current.getDate(), 0, 0, 0); | ||
if(ranges.length > 0){ | ||
for(var enable = [], i = 0; i < ranges.length; i++){ | ||
if(ranges[i][0] instanceof Date){ | ||
if(current.getYear() >= ranges[i][0].getYear() && current.getYear() <= ranges[i][1].getYear()){ | ||
if(current.getMonth() >= ranges[i][0].getMonth() && current.getMonth() <= ranges[i][1].getMonth()){ | ||
for(var f = 0; f < fields.length; f++){ | ||
compare.setDate(parseInt(fields[f].innerText)); | ||
if(compare >= ranges[i][0] && compare <= ranges[i][1]){ | ||
enable.push(fields[f].innerText); | ||
} | ||
} | ||
} | ||
} | ||
} else { | ||
for(var f = 0; f < fields.length; f++){ | ||
compare.setDate(parseInt(fields[f].innerText)); | ||
if(ranges[i].length == 3 && ranges[i][3] == true){ | ||
if(compare.getDay() >= ranges[i][0] && compare.getDay() <= ranges[i][1]){ | ||
if(enable.indexOf(fields[f].innerText) == -1){ | ||
enable.push(fields[f].innerText); | ||
} | ||
} | ||
} | ||
if(compare.getDay() < ranges[i][0] || compare.getDay() > ranges[i][1]){ | ||
if(enable.indexOf(fields[f].innerText) >= 0){ | ||
enable.splice(enable.indexOf(fields[f].innerText), 1); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
for(var f = 0; f < fields.length; f++){ | ||
if(enable.indexOf(fields[f].innerText) == -1){ | ||
tail.addClass(fields[f], "disable"); | ||
} | ||
} | ||
} | ||
// Configure Calendar | ||
if(["top", "left", "right", "bottom"].indexOf(this.con.position) < 0){ | ||
_s = d.querySelector(this.con.position); | ||
_c.push("calendar-static"); | ||
} | ||
if(typeof(_t) == "string" || _t instanceof Array){ | ||
_c = _c.concat(((typeof(_t) == "string")? _t.split(" "): _t)); | ||
} | ||
if(this.con.stayOpen){ | ||
_c.push("calendar-stay"); | ||
} | ||
dt.id = "tail-datetime-" + this.id; | ||
dt.className = _c.join(" "); | ||
// Select Current | ||
if(this.select instanceof Date && this.select.getYear() == this.view.date.getYear() && this.select.getMonth() == this.view.date.getMonth()){ | ||
tail.addClass(this.dt.querySelectorAll("tbody td:not(.empty)")[this.select.getDate()-1], "current"); | ||
} else { | ||
if(this.dt.querySelector("tbody td.current")){ | ||
tail.removeClass(this.dt.querySelector("tbody td.current"), "current"); | ||
} | ||
} | ||
// Render Action | ||
if(this.con.dateFormat){ | ||
var _a = '<span class="action action-prev" data-action="prev"></span>' | ||
+ '<span class="label" data-action="view" data-view="up"></span>' | ||
+ '<span class="action action-next" data-action="next"></span>' | ||
} else if(this.con.timeFormat){ | ||
var _a = '<span class="action action-submit" data-action="submit"></span>' | ||
+ '<span class="label"></span>' | ||
+ '<span class="action action-cancel" data-action="cancel"></span>' | ||
} | ||
if(typeof(_a) != "undefined"){ | ||
dt.innerHTML = '<div class="calendar-actions">' + _a + '</div>'; | ||
} | ||
// Handle View | ||
var self = this; | ||
// Render Date and Time Picker | ||
if(this.con.dateFormat){ | ||
var listen = this.dt.querySelectorAll("tbody td:not(.empty)"); | ||
for(var i = 0; i < listen.length; i++){ | ||
listen[i].addEventListener("click", function(event){ | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
this.renderDatePicker(dt, this.con.viewDefault); | ||
} | ||
if(this.con.timeFormat){ | ||
this.renderTimePicker(dt); | ||
} | ||
if(tail.hasClass(this, "disable")){ | ||
return false; | ||
} | ||
var time = !!self.con.timeFormat; | ||
// Append Calendar | ||
if(_s){ | ||
dt.style.cssText = 'position:static;visibility:visible;'; | ||
} else { | ||
dt.style.cssText = 'top:0;left:0;z-index:999;position:absolute;visibility:hidden;'; | ||
} | ||
(_s || document.body).appendChild(dt); | ||
return dt; | ||
}, | ||
if(self.view.type == "month"){ | ||
self.switchMonth.call(self, parseInt(this.getAttribute("data-tail-month")), self.view.date.getFullYear()); | ||
} else { | ||
self.selectDate.call(self, | ||
self.view.date.getFullYear(), self.view.date.getMonth(), parseInt(this.innerText), | ||
(time)? parseInt(self.dt.querySelector(".calendar-field-h > input").value): 0, | ||
(time)? parseInt(self.dt.querySelector(".calendar-field-m > input").value): 0, | ||
(time)? parseInt(self.dt.querySelector(".calendar-field-s > input").value): 0 | ||
); | ||
if(!self.con.stayOpen){ | ||
self.close.call(self); | ||
} | ||
} | ||
}); | ||
} | ||
/* | ||
| RENDER :: DATE PICKER | ||
| @since 0.4.0 | ||
*/ | ||
renderDatePicker: function(dt, view){ | ||
if(!view || ["decades", "years", "months", "days"].indexOf(view) < 0){ | ||
view = this.con.viewDays? "days": this.con.viewMonths? "months": | ||
this.con.viewYears? "years": this.con.viewDecades? "decades": false; | ||
} | ||
if(!view || !this.con["view" + first(view)] || !this.con.dateFormat){ return false; } | ||
// Render View | ||
var content = d.createElement("DIV"); | ||
content.className = "calendar-datepicker calendar-view-" + view; | ||
content.innerHTML = this["view" + first(view)](); | ||
// Append Element | ||
if(dt.querySelector(".calendar-datepicker")){ | ||
dt.replaceChild(content, dt.querySelector(".calendar-datepicker")); | ||
} else { | ||
dt.appendChild(content); | ||
} | ||
this.view.type = view; | ||
return this.handleLabel(dt); | ||
}, | ||
/* | ||
| RENDER :: DAY VIEW | ||
| @since 0.1.0 | ||
| @update 0.3.3 | ||
| RENDER :: TIME PICKER | ||
| @since 0.4.0 | ||
*/ | ||
renderDay: function(){ | ||
var start = __("shorts").indexOf(this.con.weekStart), | ||
week = __("shorts").slice(start); | ||
week = week.concat(__("shorts").slice(0, start)); | ||
renderTimePicker: function(dt){ | ||
if(!this.con.timeFormat){ return false; } | ||
var content = '<table class="calendar-day"><thead><tr>'; | ||
for(var i = 0; i < 7; i++){ | ||
content += '<th data-tail-day="' + __("shorts").indexOf(week[i]) + '">' + week[i] + '</th>'; | ||
// Render View | ||
var div = d.createElement("DIV"), inp; | ||
div.className = "calendar-timepicker"; | ||
div.innerHTML = '<div class="timepicker-field timepicker-hours">' | ||
+ '<input type="number" name="dt[h]" value="" min="00" max="23" step="1" />' | ||
+ '<label>' + this.__["time"][0] + '</label>' | ||
+ '</div>' | ||
+ '<div class="timepicker-field timepicker-minutes">' | ||
+ '<input type="number" name="dt[m]" value="" min="00" max="59" step="5" />' | ||
+ '<label>' + this.__["time"][1] + '</label>' | ||
+ '</div>' | ||
+ '<div class="timepicker-field timepicker-seconds">' | ||
+ '<input type="number" name="dt[s]" value="" min="00" max="59" step="5" />' | ||
+ '<label>' + this.__["time"][2] + '</label>' | ||
+ '</div>', | ||
// Set Data | ||
inp = div.querySelectorAll("input"); | ||
inp[0].value = this.view.date.getHours(), | ||
inp[1].value = this.view.date.getMinutes(); | ||
inp[2].value = this.view.date.getSeconds(); | ||
// Append Element | ||
if(dt.querySelector(".calendar-timepicker")){ | ||
dt.replaceChild(div, dt.querySelector(".calendar-timepicker")); | ||
} else { | ||
dt.appendChild(div); | ||
} | ||
content += "</tr></thead><tbody>"; | ||
content += this.createCalendar(this.view.date.getMonth(), this.view.date.getFullYear()).render(); | ||
content += "</tbody></table>"; | ||
return content; | ||
return this.handleLabel(dt); | ||
}, | ||
/* | ||
| RENDER :: MONTH VIEW | ||
| @since 0.1.0 | ||
| @update 0.3.3 | ||
| VIEW :: HANDLE LABEL | ||
| @since 0.4.0 | ||
*/ | ||
renderMonth: function(){ | ||
var strings = __("months"); | ||
var content = '<table class="calendar-month"><thead><tr><th colspan="4">' + __("header", 0) + '</th></tr></thead><tbody>'; | ||
for(var i = 0; i < 12; i++){ | ||
content += '<tr>'; | ||
content += '<td class="calendar-month" data-tail-month="0"><span>' + strings[i++] + '</span></td>'; | ||
content += '<td class="calendar-month" data-tail-month="1"><span>' + strings[i++] + '</span></td>'; | ||
content += '<td class="calendar-month" data-tail-month="2"><span>' + strings[i] + '</span></td>'; | ||
content += '</tr>'; | ||
handleLabel: function(dt){ | ||
var label = dt.querySelector(".label"), text, year; | ||
switch(this.view.type){ | ||
case "days": | ||
text = this.__["months"][this.view.date.getMonth()] + ", " + this.view.date.getFullYear(); break; | ||
case "months": | ||
text = this.view.date.getFullYear(); break; | ||
case "years": | ||
year = parseInt((this.view.date.getFullYear()).toString().slice(0, 3) + "0"); | ||
text = year + " - " + (year+10); break; | ||
case "decades": | ||
year = parseInt((this.view.date.getFullYear()).toString().slice(0, 2) + "00"); | ||
text = year + " - " + (year+100); break; | ||
} | ||
content += "</tbody></table>"; | ||
return content; | ||
label.innerText = text; | ||
return dt; | ||
}, | ||
/* | ||
| RENDER :: TIME VIEW | ||
| @since 0.1.0 | ||
| @update 0.3.3 | ||
| VIEW :: SHOW DECADEs | ||
| @since 0.4.0 | ||
*/ | ||
renderTime: function(){ | ||
return '' + | ||
'<div class="calendar-field calendar-field-h">' + | ||
' <input type="number" value="' + new Date().getHours() + '" min="00" max="23" step="1" />' + | ||
' <label>' + __("time", 0) + '</label>' + | ||
'</div>' + | ||
'<div class="calendar-field calendar-field-m">' + | ||
' <input type="number" value="' + new Date().getMinutes() + '" min="00" max="59" step="1" />' + | ||
' <label>' + __("time", 1) + '</label>' + | ||
'</div>' + | ||
'<div class="calendar-field calendar-field-s">' + | ||
' <input type="number" value="' + new Date().getSeconds() + '" min="00" max="59" step="1" />' + | ||
' <label>' + __("time", 2) + '</label>' + | ||
'</div>'; | ||
viewDecades: function(){ | ||
var year = this.view.date.getFullYear(), | ||
date = new Date(this.view.date.getTime()), | ||
today = this.con.today? (new Date()).getYear(): 0; | ||
date.setFullYear(year-parseInt(year.toString()[3])-30); | ||
for(var c, a, t = [], r = [], i = 1; i <= 16; i++){ | ||
c = 'calendar-decade' + (today >= date.getYear() && today <= (date.getYear()+10)? ' date-today': ''); | ||
a = 'data-action="view" data-view="down" data-year="' + date.getFullYear() + '"'; | ||
t.push('<td class="' + c + '" ' + a + '><span class="inner">' + date.getFullYear() + " - " + (date.getFullYear()+10) + '</span></td>'); | ||
if(i >= 4 && i%4 == 0){ | ||
r.push("<tr>\n" + t.join("\n") + "\n</tr>"); t = []; | ||
} | ||
date.setFullYear(date.getFullYear() + 10); | ||
} | ||
return '<table class="calendar-decades">' | ||
+ '<thead><tr><th colspan="4">' + this.__["header"][2] + '</th></tr></thead>' | ||
+ '<tbody>' + r.join("\n") + '</tbody></table>'; | ||
}, | ||
/* | ||
| ACTION :: ADD EVENT LISTENER | ||
| @since 0.3.0 | ||
| VIEW :: SHOW YEARs | ||
| @since 0.4.0 | ||
*/ | ||
on: function(event, func){ | ||
this.dt.addEventListener(event, func); | ||
viewYears: function(){ | ||
var year = this.view.date.getFullYear(), | ||
date = new Date(this.view.date.getTime()), | ||
today = this.con.today? (new Date()).getYear(): 0; | ||
date.setFullYear(year-parseInt(year.toString()[3])-2); | ||
for(var c, a, t = [], r = [], i = 1; i <= 16; i++){ | ||
c = 'calendar-year' + ((date.getYear() == today)? ' date-today': ''); | ||
a = 'data-action="view" data-view="down" data-year="' + date.getFullYear() + '"'; | ||
t.push('<td class="' + c + '" ' + a + '><span class="inner">' + date.getFullYear() + '</span></td>'); | ||
if(i >= 4 && i%4 == 0){ | ||
r.push("<tr>\n" + t.join("\n") + "\n</tr>"); t = []; | ||
} | ||
date.setFullYear(date.getFullYear() + 1); | ||
} | ||
return '<table class="calendar-years">' | ||
+ '<thead><tr><th colspan="4">' + this.__["header"][1] + '</th></tr></thead>' | ||
+ '<tbody>' + r.join("\n") + '</tbody></table>'; | ||
}, | ||
/* | ||
| ACTION :: OPEN CALENDAR | ||
| @since 0.1.0 | ||
| @update 0.3.4 | ||
| VIEW :: SHOW MONTHs | ||
| @since 0.4.0 | ||
*/ | ||
open: function(){ | ||
if(!tail.hasClass(this.dt, "calendar-close")){ | ||
return this; | ||
viewMonths: function(){ | ||
var strings = this.__["months"], today = this.con.today? (new Date()).getMonth(): -1; | ||
today = (this.view.date.getYear() == (new Date()).getYear())? today: -1; | ||
for(var c, a, t = [], r = [], i = 0; i < 12; i++){ | ||
c = 'calendar-month' + ((today == i)? ' date-today': ''); | ||
a = 'data-action="view" data-view="down" data-month="' + i + '"'; | ||
t.push('<td class="' + c + '" ' + a + '><span class="inner">' + strings[i] + '</span></td>'); | ||
if(t.length == 3){ | ||
r.push("<tr>\n" + t.join("\n") + "\n</tr>"); t = []; | ||
} | ||
} | ||
tail.removeClass(this.dt, "calendar-close"); | ||
tail.addClass(this.dt, "calendar-idle"); | ||
return '<table class="calendar-months">' | ||
+ '<thead><tr><th colspan="3">' + this.__["header"][0] + '</th></tr></thead>' | ||
+ '<tbody>' + r.join("\n") + '</tbody></table>'; | ||
}, | ||
this.dt.style.opacity = 0; | ||
this.dt.style.display = "block"; | ||
this.calcPosition(); | ||
(function(self){ | ||
self.animate = setInterval(function(){ | ||
self.dt.style.opacity = parseFloat(self.dt.style.opacity) + 0.1; | ||
if(parseFloat(self.dt.style.opacity) >= 1){ | ||
tail.removeClass(self.dt, "calendar-idle"); | ||
tail.addClass(self.dt, "calendar-open"); | ||
tail.trigger(self.dt, "tail.DateTime::open", { | ||
bubbles: false, | ||
cancelable: true, | ||
detail: self | ||
}); | ||
clearInterval(self.animate); | ||
} | ||
}, 10); | ||
})(this); | ||
return this; | ||
/* | ||
| VIEW :: SHOW DAYs | ||
| @since 0.4.0 | ||
*/ | ||
viewDays: function(){ | ||
var date = new Date(this.view.date.getTime()), time, | ||
today = new Date().toDateString(), | ||
month = date.getMonth(), c, a, t = [], r = [], i, | ||
disabled = [0, []], check, ranges = [].concat(this.con.dateRanges), | ||
tooltips = [].concat(this.con.tooltips), tooltip = [0, 0]; | ||
// Reset Date | ||
date.setHours(0, 0, 0, 0); | ||
date.setDate(1); | ||
date.setDate((1 - (date.getDay() - this.con.weekStart))); | ||
// Create Table | ||
while(r.length < 6){ | ||
time = date.getTime(); | ||
// Attributes and ClassNames | ||
a = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate(); | ||
a = 'data-action="submit" data-date="' + a + '"'; | ||
c = 'calendar-day date-' + ((date.getMonth() > month)? 'next': | ||
(date.getMonth() < month)? 'previous': 'current'); | ||
if(this.con.today && today == date.toDateString()){ | ||
c += ' date-today'; | ||
} | ||
// Calc Disabled | ||
if(this.con.dateBlacklist && ((time) < this.con.dateStart || time > this.con.dateEnd)){ | ||
disabled = [(time < this.con.dateStart)? this.con.dateStart: Infinity, [0, 1, 2, 3, 4, 5, 6], true]; | ||
} else if(disabled[0] == 0){ | ||
ranges = ranges.filter(function(obj){ | ||
if(obj.start == Infinity || (time >= obj.start && time <= obj.end)){ | ||
disabled = [obj.end, obj.days]; | ||
return false; | ||
} | ||
return obj.start > time; | ||
}, this); | ||
} else if(disabled.length == 3){ | ||
disabled = [0, [0, 1, 2, 3, 4, 5, 6]]; | ||
} | ||
// Calc Tooltips | ||
if(this.con.tooltips.length > 0){ | ||
tooltips = this.con.tooltips.filter(function(obj, index){ | ||
if(obj.date instanceof Array){ | ||
if(obj.date[0] <= time && obj.date[1] >= time){ | ||
tooltip = [obj.date[1], index, obj.color]; | ||
} | ||
} else if(obj.date == time){ | ||
tooltip = [obj.date, index, obj.color] | ||
} | ||
}, this); | ||
} | ||
if(tooltip[0] < time){ | ||
tooltip = [0, 0]; | ||
} | ||
// Disabled | ||
check = disabled[0] >= time && disabled[1].indexOf(date.getDay()) >= 0; | ||
if((check && this.con.dateBlacklist) || (!check && !this.con.dateBlacklist)){ | ||
c += ' date-disabled'; | ||
a += ' data-disabled="true"'; | ||
} else if(disabled[0] !== 0 && disabled[0] <= time){ | ||
disabled = [0, []]; | ||
} | ||
// Curent | ||
if(this.select && this.select.toDateString() == date.toDateString()){ | ||
c += ' date-select'; | ||
} | ||
// Create Calendar Item | ||
i = '<span class="inner">' + date.getDate() + '</span>'; | ||
if(tooltip[0] > 0){ | ||
c += ' date-tooltip'; | ||
a += ' data-tooltip="' + tooltip[1] + '" data-tooltip-time="' + time + '"'; | ||
i += '<span class="tooltip-tick" style="background:' + tooltip[2] + ';"></span>'; | ||
} | ||
t.push('<td class="' + c + '" ' + a + '>' + i + '</td>') | ||
// Next | ||
if(t.length == 7){ | ||
r.push("<tr>\n" + t.join("\n") + "\n</tr>"); t = []; | ||
} | ||
date.setDate(date.getDate()+1); | ||
} | ||
r = "<tbody>" + r.join("\n") + "</tbody>"; | ||
// Create Table Header | ||
return '<table class="calendar-days">' + this.weekdays + r + '</table>'; | ||
}, | ||
/* | ||
| ACTION :: CLOSE CALENDAR | ||
| @since 0.1.0 | ||
| @update 0.3.4 | ||
| VIEW :: SHOW TOOLTIP | ||
| @since 0.4.0 | ||
*/ | ||
close: function(){ | ||
if(!tail.hasClass(this.dt, "calendar-open")){ | ||
return this; | ||
showTooltip: function(id, field, time){ | ||
var t = this.con.tooltips[id].element, e = t.style, w, h, | ||
d = this.dt.querySelector(".calendar-datepicker"); | ||
// Calc Tooltip Rect | ||
e.cssText = "opacity:0;visibility:hidden;"; | ||
t.id = "tooltip-" + id + "-" + time; | ||
d.appendChild(t); | ||
w = t.offsetWidth; h = t.offsetHeight; | ||
// Set Tooltip Rect | ||
e.top = field.offsetTop + field.offsetHeight + "px"; | ||
e.left = (field.offsetLeft + (field.offsetWidth/2)) - (w/2) + "px" | ||
e.visibility = "visible"; | ||
// Animate Tooltip | ||
if(this.con.animate){ | ||
t.setAttribute("data-top", parseInt(e.top)); | ||
e.top = (parseInt(e.top) + 5) + "px"; | ||
(function fade(){ | ||
if(parseFloat(e.top) > t.getAttribute("data-top")){ | ||
e.top = (parseFloat(e.top) - 0.5) + "px"; | ||
} | ||
if((e.opacity = parseFloat(e.opacity)+0.125) < 1){ | ||
setTimeout(fade, 20); | ||
} | ||
})(); | ||
} else { | ||
e.opacity = 1; | ||
} | ||
tail.removeClass(this.dt, "calendar-open"); | ||
tail.addClass(this.dt, "calendar-idle"); | ||
(function(self){ | ||
self.animate = setInterval(function(){ | ||
self.dt.style.opacity = parseFloat(self.dt.style.opacity) - 0.1; | ||
if(parseFloat(self.dt.style.opacity) <= 0){ | ||
tail.removeClass(self.dt, "calendar-idle"); | ||
tail.addClass(self.dt, "calendar-close"); | ||
tail.trigger(self.dt, "tail.DateTime::close", { | ||
bubbles: false, | ||
cancelable: true, | ||
detail: self | ||
}); | ||
self.dt.style.display = "none"; | ||
clearInterval(self.animate); | ||
} | ||
}, 10); | ||
})(this); | ||
return this; | ||
}, | ||
/* | ||
| ACTION :: CLOSE CALENDAR | ||
| @since 0.1.0 | ||
| @update 0.3.0 | ||
| VIEW :: HIDE TOOLTIP | ||
| @since 0.4.0 | ||
*/ | ||
toggle: function(){ | ||
if(tail.hasClass(this.dt, "calendar-open")){ | ||
return this.close(); | ||
} else if(tail.hasClass(this.dt, "calendar-close")){ | ||
return this.open(); | ||
hideTooltip: function(id){ | ||
var t = this.dt.querySelector("#tooltip-" + id), e = t.style; | ||
// Animate Tooltip | ||
if(this.con.animate){ | ||
t.className += " remove"; | ||
(function fade(){ | ||
if(parseFloat(e.top) < (parseInt(t.getAttribute("data-top"))+5)){ | ||
e.top = (parseFloat(e.top) + 0.5) + "px"; | ||
} | ||
if((e.opacity -= 0.125) < 0){ | ||
return (t.className = "calendar-tooltip")? t.parentElement.removeChild(t): ""; | ||
} | ||
setTimeout(fade, 20); | ||
})(); | ||
} else { | ||
t.parentElement.removeChild(t); | ||
} | ||
return this; | ||
}, | ||
/* | ||
| ACTION :: REMOVE CALENDAR | ||
| @since 0.3.0 | ||
| PUBLIC :: SWITCH VIEW | ||
| @since 0.1.0 | ||
| @update 0.4.0 | ||
*/ | ||
remove: function(){ | ||
this.e.removeAttribute("data-tail-calendar"); | ||
this.e.removeAttribute("data-tail-value"); | ||
this.dt.parentElement.removeChild(this.dt); | ||
return null; | ||
switchView: function(view){ | ||
var order = [null, "days", "months", "years", "decades", null]; | ||
if(order.indexOf(view) == -1){ | ||
if(view == "up"){ | ||
view = order[(order.indexOf(this.view.type) || 5)+1] || null; | ||
} else if(view == "down"){ | ||
view = order[(order.indexOf(this.view.type) || 1)-1] || null; | ||
} | ||
if(!(view && this.con["view" + first(view)])){ | ||
view = false; | ||
} | ||
} | ||
return (!view)? false: !!this.renderDatePicker(this.dt, view); | ||
}, | ||
/* | ||
| ACTION :: REMOVE CALENDAR | ||
| @since 0.3.3 | ||
| PUBLIC :: SWITCH DATE | ||
| @since 0.4.0 | ||
*/ | ||
reload: function(){ | ||
this.remove(); | ||
return new tailDateTime(this.e, this.con); | ||
switchDate: function(year, month, day, none){ | ||
this.view.date.setFullYear(year || this.view.date.getFullYear()); | ||
this.view.date.setMonth(month || this.view.date.getMonth()); | ||
if(day == "auto"){ | ||
var test = this.view.date, now = new Date(); | ||
if(test.getMonth() == now.getMonth() && test.getYear() == now.getYear()){ | ||
day = now.getDate(); | ||
} else { | ||
day = 1; | ||
} | ||
} | ||
this.view.date.setDate(day || this.view.date.getDate()); | ||
return (none === true)? true: this.switchView(this.view.type); | ||
}, | ||
/* | ||
| ACTION :: SWITCH MONTH | ||
| PUBLIC :: SWITCH MONTH | ||
| @since 0.1.0 | ||
| @update 0.1.2 | ||
| @update 0.4.0 - Alias for `.switchDate()` | ||
*/ | ||
switchMonth: function(month, year){ | ||
if(month == "prev"){ | ||
this.view.date.setMonth(this.view.date.getMonth()-1) | ||
} else if(month == "next"){ | ||
this.view.date.setMonth(this.view.date.getMonth()+1); | ||
} else { | ||
this.view.date.setMonth(month); | ||
this.view.date.setFullYear(year); | ||
if(typeof(month) == "string"){ | ||
month = ["previous", "prev"].indexOf(month) >= 0? -1: 1; | ||
month = this.view.date.getMonth() + type; | ||
} | ||
this.switchView("day"); | ||
return this; | ||
return this.switchDate(year || this.getFullYear(), month); | ||
}, | ||
/* | ||
| ACTION :: SWITCH YEAR | ||
| PUBLIC :: SWITCH YEAR | ||
| @since 0.1.0 | ||
| @update 0.1.2 | ||
| @update 0.4.0 - Alias for `.switchDate()` | ||
*/ | ||
switchYear: function(year){ | ||
if(year == "prev"){ | ||
this.view.date.setFullYear(this.view.date.getFullYear()-1); | ||
} else if(year == "next"){ | ||
this.view.date.setFullYear(this.view.date.getFullYear()+1); | ||
} else { | ||
this.view.date.setFullYear(year); | ||
if(typeof(year) == "string"){ | ||
year = ["previous", "prev"].indexOf(year) >= 0? -1: 1; | ||
year = this.view.date.getFullYear() + type; | ||
} | ||
this.switchView("month"); | ||
return this; | ||
return this.switchDate(year); | ||
}, | ||
/* | ||
| ACTION :: SELECT A DATE | ||
| PUBLIC :: BROWSE VIEW | ||
| @since 0.4.0 - Helper for `switchDate()` | ||
*/ | ||
browseView: function(type){ | ||
type = (["previous", "prev"].indexOf(type) >= 0)? -1: 1; | ||
switch(this.view.type){ | ||
case "days": | ||
return this.switchDate(null, this.view.date.getMonth() + type, "auto"); | ||
case "months": | ||
return this.switchDate(this.view.date.getFullYear() + type, null, "auto"); | ||
case "years": | ||
return this.switchDate(this.view.date.getFullYear() + (type*10), null, "auto"); | ||
case "decades": | ||
return this.switchDate(this.view.date.getFullYear() + (type*100), null, "auto"); | ||
} | ||
return false; | ||
}, | ||
/* | ||
| PUBLIC :: FETCH DATE / DTIME | ||
| @since 0.4.0 | ||
*/ | ||
fetchDate: function(date){ | ||
date = parse(date || false) || this.view.date; | ||
var inp = this.dt.querySelectorAll("input[type=number]"); | ||
if(inp && inp.length == 3){ | ||
date.setHours(inp[0].value || 0, inp[1].value || 0, inp[2].value || 0, 0); | ||
} | ||
return date; | ||
}, | ||
/* | ||
| PUBLIC :: SELECT DATE / TIME | ||
| @since 0.1.0 | ||
| @update 0.3.0 | ||
| @update 0.4.0 | ||
*/ | ||
selectDate: function(Y, M, D, h, i, s){ | ||
var n = new Date(); | ||
selectDate: function(Y, M, D, H, I, S){ | ||
var n = new Date(), f = []; | ||
(this.con.dateFormat)? f.push(this.con.dateFormat): null; | ||
(this.con.timeFormat)? f.push(this.con.timeFormat): null; | ||
// Format | ||
var f = [ | ||
(this.con.dateFormat)? this.con.dateFormat: "", | ||
(this.con.timeFormat)? this.con.timeFormat: "", | ||
].join(" ").trim(); | ||
// Date | ||
this.select = new Date( | ||
((Y)? Y: ((Y == undefined)? this.view.date.getFullYear(): n.getFullYear())), | ||
((M)? M: ((M == undefined)? this.view.date.getMonth(): n.getMonth())), | ||
((D)? D: ((D == undefined)? this.view.date.getDate(): n.getDate())), | ||
((h)? h: ((h == undefined)? this.view.date.getHours(): 0)), | ||
((i)? i: ((i == undefined)? this.view.date.getMinutes(): 0)), | ||
((s)? s: ((s == undefined)? this.view.date.getSeconds(): 0)) | ||
// Set Value | ||
this.select = (Y instanceof Date)? Y: new Date( | ||
Y? Y: (Y == undefined)? this.view.date.getFullYear(): n.getFullYear(), | ||
M? M: (M == undefined)? this.view.date.getMonth(): n.getMonth(), | ||
D? D: (D == undefined)? this.view.date.getDate(): n.getDate(), | ||
H? H: (H == undefined)? this.view.date.getHours(): 0, | ||
I? I: (I == undefined)? this.view.date.getMinutes(): 0, | ||
S? S: (S == undefined)? this.view.date.getSeconds(): 0 | ||
); | ||
// Trigger | ||
tail.trigger(this.dt, "tail.DateTime::select", { | ||
bubbles: false, | ||
cancelable: true, | ||
detail: self | ||
}); | ||
// Value | ||
this.e.value = this.convertDate(this.select, f); | ||
this.e.setAttribute("data-tail-value", this.convertDate(this.select, "YYYY-mm-dd HH:ii:ss")); | ||
return this.switchView(this.view.type); | ||
this.e.value = this.convertDate(this.select, f.join(" ")); | ||
this.e.setAttribute("data-value", this.select.getTime()); | ||
this.trigger("change"); | ||
return this.switchView("days"); | ||
}, | ||
selectTime: function(h, i, s){ | ||
return this.selectDate(false, false, false, h, i, s); | ||
selectTime: function(H, I, S){ | ||
return this.selectDate(false, false, false, H, I, S); | ||
}, | ||
/* | ||
| ACTION :: SELECT CALENDAR | ||
| PUBLIC :: OPEN CALENDAR | ||
| @since 0.1.0 | ||
| @update 0.3.4 | ||
| @update 0.4.0 | ||
*/ | ||
createCalendar: function(month, year){ | ||
var day = 1, haveDays = true, | ||
startDay = new Date(year, month, day).getDay(), | ||
daysInMonths = [31, (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], | ||
calendar = []; | ||
// Calc start Day | ||
startDay = startDay-__("shorts").indexOf(this.con.weekStart); | ||
if(startDay < 0){ | ||
startDay = 7 + startDay; | ||
open: function(){ | ||
if(!cHAS(this.dt, "calendar-close")){ | ||
return this; | ||
} | ||
var self = this, e = this.dt.style; | ||
// Cache | ||
if(tailDateTime.cache[this.con.weekStart + "_" + year] && !tailDateTime.isIE11){ | ||
if(tailDateTime.cache[this.con.weekStart + "_" + year][month]){ | ||
return tailDateTime.cache[this.con.weekStart + "_" + year][month]; | ||
// Animate | ||
e.opacity = this.con.animate? 0: 1; e.display = "block"; | ||
cADD(cREM(this.dt, "calendar-close"), "calender-idle"); | ||
cHAS(this.dt, "calendar-static")? null: this.calcPosition(); | ||
(function fade(){ | ||
if((e.opacity = parseFloat(e.opacity)+0.125) >= 1){ | ||
cADD(cREM(self.dt, "calendar-idle"), "calendar-open"); | ||
return self.trigger("open"); | ||
} | ||
} else { | ||
tailDateTime.cache[this.con.weekStart + "_" + year] = {}; | ||
setTimeout(fade, 20); | ||
})(); | ||
return this; | ||
}, | ||
/* | ||
| PUBLIC :: CLOSE CALENDAR | ||
| @since 0.1.0 | ||
| @update 0.4.0 | ||
*/ | ||
close: function(){ | ||
if(!cHAS(this.dt, "calendar-open")){ | ||
return this; | ||
} | ||
var self = this, e = this.dt.style; | ||
// Calculate | ||
var i = 0; | ||
while(haveDays){ | ||
calendar[i] = []; | ||
for(var j = 0; j < 7; j++){ | ||
if(i === 0){ | ||
if(j === startDay){ | ||
calendar[i][j] = '<span>' + day++ + '</span>'; | ||
startDay++; | ||
} | ||
} else if(day <= daysInMonths[month]){ | ||
calendar[i][j] = '<span>' + day++ + '</span>'; | ||
} else { | ||
calendar[i][j] = ""; | ||
haveDays = false; | ||
} | ||
if(day > daysInMonths[month]){ | ||
haveDays = false; | ||
} | ||
// Animate | ||
cADD(cREM(this.dt, "calendar-open"), "calender-idle"); | ||
e.opacity = this.con.animate? 1: 0; e.display = "block"; | ||
(function fade(){ | ||
if((e.opacity -= 0.125) <= 0){ | ||
cADD(cREM(self.dt, "calendar-idle"), "calendar-close"); | ||
e.display = "none"; | ||
return self.trigger("close"); | ||
} | ||
i++; | ||
} | ||
setTimeout(fade, 20); | ||
})(); | ||
return this; | ||
}, | ||
// Render | ||
for(var i = 0; i < calendar.length; i++){ | ||
calendar[i] = '<tr>\n<td class="calendar-day">' + calendar[i].join('</td>\n<td class="calendar-day">') + '</td>\n</tr>'; | ||
/* | ||
| PUBLIC :: CLOSE CALENDAR | ||
| @since 0.1.0 | ||
| @update 0.4.0 | ||
*/ | ||
toggle: function(){ | ||
if(cHAS(this.dt, "calendar-open")){ | ||
return this.close(); | ||
} | ||
if(tail.IE){ | ||
var inner = "<table><tbdy>" + calendar.join("") + "</tbody></table>"; | ||
var render = d.createElement("div"); | ||
render.innerHTML = inner; | ||
render = render.getElementsByTagName("table")[0]; | ||
} else { | ||
var render = d.createElement("table"); | ||
render.className = "calendar-current"; | ||
render.innerHTML = calendar.join(""); | ||
} | ||
return cHAS(this.dt, "calendar-close")? this.open(): this; | ||
}, | ||
// Empty Fields | ||
var empty = render.querySelectorAll("td:empty"); | ||
for(var i = 0; i < empty.length; ++i){ | ||
empty[i].className += " empty"; | ||
/* | ||
| PUBLIC :: ADD EVENT LISTENER | ||
| @since 0.3.0 | ||
| @update 0.4.0 | ||
*/ | ||
on: function(event, func, args){ | ||
if(["open", "close", "change"].indexOf(event) < 0 || typeof(func) != "function"){ | ||
return false; | ||
} | ||
// Today Field | ||
if(month == new Date().getMonth() && year == new Date().getFullYear()){ | ||
var today = Array.prototype.slice.call(render.querySelectorAll("td")); | ||
today.forEach(function(current, index, array){ | ||
if(current.innerText === new Date().getDate().toString()){ | ||
current.className += " today"; | ||
} | ||
}); | ||
if(!(event in this.events)){ | ||
this.events[event] = []; | ||
} | ||
this.events[event].push({cb: func, args: (args instanceof Array)? args: []}); | ||
return this; | ||
}, | ||
// Return | ||
this.view.date.setMonth(month); | ||
this.view.date.setFullYear(year); | ||
this.view = tail.clone(this.view, {content: render}); | ||
tailDateTime.cache[this.con.weekStart + "_" + year][month] = this.view; | ||
return tailDateTime.cache[this.con.weekStart + "_" + year][month]; | ||
/* | ||
| PUBLIC :: REMOVE CALENDAR | ||
| @since 0.3.0 | ||
| @update 0.4.0 | ||
*/ | ||
remove: function(){ | ||
this.e.removeAttribute("data-tail-datetime"); | ||
this.e.removeAttribute("data-value"); | ||
this.dt.parentElement.removeChild(this.dt); | ||
return this; | ||
}, | ||
/* | ||
| CONVERT DATE | ||
| @since 0.1.0 | ||
| @update 0.3.3 | ||
| PUBLIC :: REMOVE CALENDAR | ||
| @since 0.3.3 | ||
| @update 0.4.0 | ||
*/ | ||
convertDate: function(inDate, format){ | ||
var dateObject = { | ||
H: String("00" + inDate.getHours()).toString().slice(-2), | ||
G: function(hours){ | ||
return (hours % 12)? hours % 12: 12; | ||
}(inDate.getHours()), | ||
A: inDate.getHours() >= 12? "PM": "AM", | ||
a: inDate.getHours() >= 12? "pm": "am", | ||
i: String("00" + inDate.getMinutes()).toString().slice(-2), | ||
s: String("00" + inDate.getSeconds()).toString().slice(-2), | ||
reload: function(){ | ||
this.remove(); | ||
return this.init(); | ||
}, | ||
Y: inDate.getFullYear(), | ||
y: parseInt(inDate.getFullYear().toString().slice(2)), | ||
m: String("00" + (inDate.getMonth() + 1)).toString().slice(-2), | ||
M: __("months", [inDate.getMonth()]).slice(0, 3), | ||
F: __("months", [inDate.getMonth()]), | ||
d: String("00" + inDate.getDate()).toString().slice(-2), | ||
D: __("days", [inDate.getDay()]), | ||
l: __("shorts", [inDate.getDay()]).toLowerCase() | ||
}; | ||
/* | ||
| PUBLIC :: (G|S)ET OPOTION | ||
| @since 0.4.0 | ||
*/ | ||
config: function(key, value, rebuild){ | ||
if(key instanceof Object){ | ||
for(var k in key){ | ||
this.config(k, key[k], false); | ||
} | ||
this.reload(); | ||
return this.con; | ||
} | ||
if(typeof(key) == "undefined"){ | ||
return this.con; | ||
} else if(!(key in this.con)){ | ||
return false; | ||
} | ||
var regex = new RegExp("(H{1,2}|G{1,2}|i{1,2}|s{1,2}|Y{2,4}|y{2}|m{1,2}|d{1,2})", "g"); | ||
format = format.replace(regex, function(token){ | ||
var datePart = dateObject[token.slice(-1)].toString(), | ||
tokenlen = token.length, zeroPad | ||
if(tokenlen == 4 || tokenlen == 2){ | ||
return datePart.slice(-Math.abs(tokenlen)); | ||
} | ||
if(tokenlen == 1 && datePart[0] == "0"){ | ||
return datePart.slice(-1) | ||
} | ||
return datePart; | ||
}); | ||
format = format.replace(/(A|a|M|F|D|l)/g, function(token){ | ||
return dateObject[token]; | ||
}); | ||
return format; | ||
// Set | Return | ||
if(typeof(value) == "undefined"){ | ||
return this.con[key]; | ||
} | ||
this.con[key] = value; | ||
if(this.rebuild !== false){ | ||
this.reload(); | ||
} | ||
return this; | ||
} | ||
} | ||
// Assign to Window | ||
if(typeof(w.tail) == "undefined"){ | ||
w.tail = {}; | ||
} | ||
w.tail.DateTime = tailDateTime; | ||
return w.tail.DateTime | ||
})(this); | ||
// Return | ||
return tailDateTime; | ||
})); |
@@ -1,2 +0,2 @@ | ||
/* tail.DateTime 0.3.4 @ https://github.com/pytesNET/tail.DateTime */ | ||
!function(t){"use strict";var n=t,u=t.document,g={hasClass:function(t,e){return new RegExp("(|s+)"+e+"(s+|)").test(t.className)},addClass:function(t,e){return new RegExp("(|s+)"+e+"(s+|)").test(t.className)||(t.className=(t.className.trim()+" "+e.trim()).trim()),t},removeClass:function(t,e){var a=new RegExp("(|s+)("+e+")(s+|)");return a.test(t.className)&&(t.className=t.className.replace(a,"$1$3").trim()),t},trigger:function(t,e,a){if(CustomEvent&&CustomEvent.name){var s=new CustomEvent(e,a);return t.dispatchEvent(s)}return(s=u.createEvent("CustomEvent")).initCustomEvent(e,!!a.bubbles,!!a.cancelable,a.detail),t.dispatchEvent(s)},clone:function(t,e){e="object"==typeof e?e:{};var a=t.constructor();for(var s in t)e.hasOwnProperty(s)?a[s]=e[s]:t.hasOwnProperty(s)&&(a[s]=t[s]);return a}};g.IE=-1<n.navigator.userAgent.indexOf("MSIE")||-1<n.navigator.userAgent.indexOf("Edge");var v=function(t,e){if("string"==typeof t&&(t=u.querySelectorAll(t)),t instanceof NodeList||t instanceof HTMLCollection){if(0==t.length)return!1;for(var a=new Array,s=0;s<t.length;s++)a.push(new v(t[s],e));return 1==a.length?a[0]:a}if(void 0===this)return new v(t,e);if(!(t instanceof Element))return!1;if(t.hasAttribute("data-tail-calendar")&&v.instances[t.getAttribute("data-tail-calendar")])return v.instances[t.getAttribute("data-tail-calendar")];if(e.dateRanges&&0<e.dateRanges.length){var n;for(s=0;s<e.dateRanges.length;s++)"string"==typeof(n=e.dateRanges[s])[0]&&0<=p("shorts").indexOf(n[0])?(n[0]=p("shorts").indexOf(n[0]),n[1]=2<=n.length&&0<=p("shorts").indexOf(n[1])?p("shorts").indexOf(n[1]):6):("string"==typeof n[0]&&(n[0]=new Date(Date.parse(n[0])),2==n.length&&"string"==typeof n[1]?n[1]=new Date(Date.parse(n[1])):1==n.length&&(n[1]=new Date(n[0].getFullYear(),n[0].getMonth(),0))),n[0]instanceof Date&&!isNaN(n[0].getDate())||(n[0]=new Date),(n.length<2||!(n[1]instanceof Date)||isNaN(n[1].getDate()))&&(n[1]=new Date(n[0].getFullYear(),n[0].getMonth(),0)))}return this.e=t,e="object"==typeof e?e:{},Object.assign?this.con=Object.assign({},v.defaults,e):this.con=g.clone(v.defaults,e),this.init()};v.version="0.3.4",v.status="alpha",v.count=0,v.isIE11=!!n.MSInputMethodContext&&!!u.documentMode,v.cache={},v.instances={},v.defaults={static:null,position:"bottom",classNames:"",dateFormat:"YYYY-mm-dd",timeFormat:"HH:ii:ss",dateRanges:[],weekStart:"SUN",startOpen:!1,stayOpen:!1,zeroSeconds:!1},v.strings={months:["January","February","March","April","May","June","July","August","September","October","November","December"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shorts:["SUN","MON","TUE","WED","THU","FRI","SAT"],time:["Hours","Minutes","Seconds"],header:["Select a Month","Select a Year","Select a Time"]};var p=function(t,e){return t in n.tail.DateTime.strings&&(void 0!==e?n.tail.DateTime.strings[t][e]:n.tail.DateTime.strings[t])};v.prototype={e:null,dt:null,con:{},view:{},select:null,init:function(){if(this.dt)return this.dt;var t=u.querySelector(this.con.static);this.dt=u.createElement("DIV"),this.dt.id="data-tail-calendar-"+ ++v.count,this.dt.className="tail-datetime-calendar calendar-close"+(t?" calendar-static":""),this.con.stayOpen&&(this.dt.className+=" calendar-stay"),this.con.classNames&&(this.dt.className+=" "+(this.con.classNames instanceof Array?this.con.classNames.join(" "):this.con.classNames)),this.con.dateFormat?this.dt.innerHTML='<div class="calendar-navi"> <span data-tail-navi="prev" class="calendar-button button-prev"></span> <span data-tail-navi="switch" class="calendar-label"></span> <span data-tail-navi="next" class="calendar-button button-next"></span></div><div class="calendar-date"></div>'+(this.con.timeFormat?'<div class="calendar-time">'+this.renderTime()+"</div>":""):this.dt.innerHTML='<div class="calendar-navi"> <span data-tail-navi="check" class="calendar-button button-check"></span> <span data-tail-navi="switch" class="calendar-label">'+p("header",2)+'</span> <span data-tail-navi="close" class="calendar-button button-close"></span></div>'+(this.con.timeFormat?'<div class="calendar-time">'+this.renderTime()+"</div>":"");var e=new Date(Date.parse(this.e.getAttribute("data-tail-value")||this.e.value));this.view={type:"date",date:new Date,content:"",render:function(){return this.content.querySelector("tbody").innerHTML}},isNaN(e.getDate())||(this.select=e,this.con.zeroSeconds&&this.select.setSeconds(0),this.view.date=new Date(this.select.getTime())),this.con.timeFormat&&(this.dt.querySelector(".calendar-field-h > input").value=this.view.date.getHours(),this.dt.querySelector(".calendar-field-m > input").value=this.view.date.getMinutes(),this.dt.querySelector(".calendar-field-s > input").value=this.view.date.getSeconds()),this.switchMonth(this.view.date.getMonth(),this.view.date.getFullYear()),this.e.hasAttribute("data-tail-value")?this.selectDate():this.e.setAttribute("data-tail-value",this.convertDate(this.view.date,"YYYY-mm-dd HH:ii:ss")),this.dt.style.top=0,this.dt.style.left=0,this.dt.style.zIndex=99,this.dt.style.position=t?"static":"absolute",this.dt.style.visibility=t?"visible":"hidden",t?t.appendChild(this.dt):u.getElementsByTagName("body")[0].appendChild(this.dt);var s=this,a=this.dt.querySelectorAll("[data-tail-navi]");if(0<a.length)for(var n=0;n<a.length;n++)a[n].addEventListener("click",function(t){var e=this.getAttribute("data-tail-navi");s.con.dateFormat?"month"==s.view.type?"prev"==e||"next"==e?s.switchYear.call(s,e):s.switchView.call(s,"day"):"prev"==e||"next"==e?s.switchMonth.call(s,e):s.switchView.call(s,"month"):s.con.timeFormat&&("check"==e&&s.selectTime.call(s,parseInt(s.dt.querySelector(".calendar-field-h > input").value),parseInt(s.dt.querySelector(".calendar-field-m > input").value),parseInt(s.dt.querySelector(".calendar-field-s > input").value)),s.con.stayOpen||s.close.call(s))});return this.e.addEventListener("focusin",function(t){s.open.call(s)}),this.e.addEventListener("focusout",function(t){var e=new Date(Date.parse(this.value));isNaN(e.getDate())||(s.selectDate.call(s,e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds()),s.switchMonth.call(s,e.getMonth(),e.getFullYear()))}),this.e.addEventListener("keyup",function(t){if(13==t.keyCode){var e=new Date(Date.parse(this.value));isNaN(e.getDate())||(s.selectDate.call(s,e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds()),s.switchMonth.call(s,e.getMonth(),e.getFullYear())),t.stopPropagation()}}),u.addEventListener("keyup",function(t){if(g.hasClass(s.dt,"calendar-open")&&27==t.keyCode&&(s.con.stayOpen||s.close.call(s),s.e.blur()),g.hasClass(s.dt,"calendar-open")&&13==t.keyCode){if(s.con.dateFormat){var e=s.dt.children[1].querySelector("td.today")||s.dt.children[1].querySelector("td:not(.empty)"),a=!!s.con.timeFormat;g.hasClass(e,"disabled")||s.selectDate.call(s,s.view.year,s.view.month,parseInt(e.value),a?parseInt(s.dt.querySelector(".calendar-field-h > input").value):0,a?parseInt(s.dt.querySelector(".calendar-field-m > input").value):0,a?parseInt(s.dt.querySelector(".calendar-field-s > input").value):0)}else s.selectTime.call(s,parseInt(s.dt.querySelector(".calendar-field-h > input").value),parseInt(s.dt.querySelector(".calendar-field-m > input").value),parseInt(s.dt.querySelector(".calendar-field-s > input").value));s.con.stayOpen||s.close.call(s),s.e.blur()}}),u.addEventListener("click",function(t){g.hasClass(s.dt,"calendar-open")&&(s.dt.contains(t.target)||s.e.contains(t.target)||t.target!=s.dt&&t.target!=s.e&&(s.con.stayOpen||s.close.call(s)))}),this.e.setAttribute("data-tail-calendar","tail-"+v.count),this.con.startOpen&&this.open(),v.instances["tail-"+v.count]=this},calcPosition:function(){if(g.hasClass(this.dt,"calendar-static"))return this;var t=n.getComputedStyle(this.dt),e=parseInt(t.marginLeft)+parseInt(t.marginRight),a=parseInt(t.marginTop)+parseInt(t.marginBottom),s=function(t){for(var e={top:t.offsetTop||0,left:t.offsetLeft||0,width:t.offsetWidth||0,height:t.offsetHeight||0};t=t.offsetParent;)e.top+=t.offsetTop,e.left+=t.offsetLeft;return e}(this.e);switch(this.dt.style.visibility="hidden",this.con.position){case"top":this.dt.style.top=s.top-(this.dt.offsetHeight+a)+"px",this.dt.style.left=s.left+s.width/2-(this.dt.offsetWidth/2+e/2)+"px";break;case"left":this.dt.style.top=s.top+s.height/2-(this.dt.offsetHeight/2+a)+"px",this.dt.style.left=s.left-(this.dt.offsetWidth+e)+"px";break;case"right":this.dt.style.top=s.top+s.height/2-(this.dt.offsetHeight/2+a)+"px",this.dt.style.left=s.left+s.width+"px";break;default:this.dt.style.top=s.top+s.height+"px",this.dt.style.left=s.left+s.width/2-(this.dt.offsetWidth/2+e/2)+"px"}return this.dt.style.visibility="visible",this},switchView:function(t){if(!this.con.dateFormat)return!1;if("month"==(this.view.type=t))this.dt.children[1].innerHTML="",this.dt.children[1].insertAdjacentHTML("afterbegin",this.renderMonth()),this.dt.querySelector(".calendar-label").innerText=this.view.date.getFullYear();else{this.dt.children[1].innerHTML=this.renderDay(),this.dt.querySelector(".calendar-label").innerText=p("months",this.view.date.getMonth())+" "+this.view.date.getFullYear();var e=this.con.dateRanges,a=this.view.date,s=this.dt.querySelectorAll("tbody td:not(.empty)"),n=new Date(a.getFullYear(),a.getMonth(),a.getDate(),0,0,0);if(0<e.length){for(var i=[],l=0;l<e.length;l++)if(e[l][0]instanceof Date){if(a.getYear()>=e[l][0].getYear()&&a.getYear()<=e[l][1].getYear()&&a.getMonth()>=e[l][0].getMonth()&&a.getMonth()<=e[l][1].getMonth())for(var r=0;r<s.length;r++)n.setDate(parseInt(s[r].innerText)),n>=e[l][0]&&n<=e[l][1]&&i.push(s[r].innerText)}else for(r=0;r<s.length;r++)n.setDate(parseInt(s[r].innerText)),3==e[l].length&&1==e[l][3]&&n.getDay()>=e[l][0]&&n.getDay()<=e[l][1]&&-1==i.indexOf(s[r].innerText)&&i.push(s[r].innerText),(n.getDay()<e[l][0]||n.getDay()>e[l][1])&&0<=i.indexOf(s[r].innerText)&&i.splice(i.indexOf(s[r].innerText),1);for(r=0;r<s.length;r++)-1==i.indexOf(s[r].innerText)&&g.addClass(s[r],"disable")}this.select instanceof Date&&this.select.getYear()==this.view.date.getYear()&&this.select.getMonth()==this.view.date.getMonth()?g.addClass(this.dt.querySelectorAll("tbody td:not(.empty)")[this.select.getDate()-1],"current"):this.dt.querySelector("tbody td.current")&&g.removeClass(this.dt.querySelector("tbody td.current"),"current")}var d=this;if(this.con.dateFormat){var o=this.dt.querySelectorAll("tbody td:not(.empty)");for(l=0;l<o.length;l++)o[l].addEventListener("click",function(t){if(t.preventDefault(),t.stopPropagation(),g.hasClass(this,"disable"))return!1;var e=!!d.con.timeFormat;"month"==d.view.type?d.switchMonth.call(d,parseInt(this.getAttribute("data-tail-month")),d.view.date.getFullYear()):(d.selectDate.call(d,d.view.date.getFullYear(),d.view.date.getMonth(),parseInt(this.innerText),e?parseInt(d.dt.querySelector(".calendar-field-h > input").value):0,e?parseInt(d.dt.querySelector(".calendar-field-m > input").value):0,e?parseInt(d.dt.querySelector(".calendar-field-s > input").value):0),d.con.stayOpen||d.close.call(d))})}},renderDay:function(){var t=p("shorts").indexOf(this.con.weekStart),e=p("shorts").slice(t);e=e.concat(p("shorts").slice(0,t));for(var a='<table class="calendar-day"><thead><tr>',s=0;s<7;s++)a+='<th data-tail-day="'+p("shorts").indexOf(e[s])+'">'+e[s]+"</th>";return a+="</tr></thead><tbody>",a+=this.createCalendar(this.view.date.getMonth(),this.view.date.getFullYear()).render(),a+="</tbody></table>"},renderMonth:function(){for(var t=p("months"),e='<table class="calendar-month"><thead><tr><th colspan="4">'+p("header",0)+"</th></tr></thead><tbody>",a=0;a<12;a++)e+="<tr>",e+='<td class="calendar-month" data-tail-month="0"><span>'+t[a++]+"</span></td>",e+='<td class="calendar-month" data-tail-month="1"><span>'+t[a++]+"</span></td>",e+='<td class="calendar-month" data-tail-month="2"><span>'+t[a]+"</span></td>",e+="</tr>";return e+="</tbody></table>"},renderTime:function(){return'<div class="calendar-field calendar-field-h"> <input type="number" value="'+(new Date).getHours()+'" min="00" max="23" step="1" /> <label>'+p("time",0)+'</label></div><div class="calendar-field calendar-field-m"> <input type="number" value="'+(new Date).getMinutes()+'" min="00" max="59" step="1" /> <label>'+p("time",1)+'</label></div><div class="calendar-field calendar-field-s"> <input type="number" value="'+(new Date).getSeconds()+'" min="00" max="59" step="1" /> <label>'+p("time",2)+"</label></div>"},on:function(t,e){this.dt.addEventListener(t,e)},open:function(){return g.hasClass(this.dt,"calendar-close")&&(g.removeClass(this.dt,"calendar-close"),g.addClass(this.dt,"calendar-idle"),this.dt.style.opacity=0,this.dt.style.display="block",this.calcPosition(),(t=this).animate=setInterval(function(){t.dt.style.opacity=parseFloat(t.dt.style.opacity)+.1,1<=parseFloat(t.dt.style.opacity)&&(g.removeClass(t.dt,"calendar-idle"),g.addClass(t.dt,"calendar-open"),g.trigger(t.dt,"tail.DateTime::open",{bubbles:!1,cancelable:!0,detail:t}),clearInterval(t.animate))},10)),this;var t},close:function(){return g.hasClass(this.dt,"calendar-open")&&(g.removeClass(this.dt,"calendar-open"),g.addClass(this.dt,"calendar-idle"),(t=this).animate=setInterval(function(){t.dt.style.opacity=parseFloat(t.dt.style.opacity)-.1,parseFloat(t.dt.style.opacity)<=0&&(g.removeClass(t.dt,"calendar-idle"),g.addClass(t.dt,"calendar-close"),g.trigger(t.dt,"tail.DateTime::close",{bubbles:!1,cancelable:!0,detail:t}),t.dt.style.display="none",clearInterval(t.animate))},10)),this;var t},toggle:function(){return g.hasClass(this.dt,"calendar-open")?this.close():g.hasClass(this.dt,"calendar-close")?this.open():this},remove:function(){return this.e.removeAttribute("data-tail-calendar"),this.e.removeAttribute("data-tail-value"),this.dt.parentElement.removeChild(this.dt),null},reload:function(){return this.remove(),new v(this.e,this.con)},switchMonth:function(t,e){return"prev"==t?this.view.date.setMonth(this.view.date.getMonth()-1):"next"==t?this.view.date.setMonth(this.view.date.getMonth()+1):(this.view.date.setMonth(t),this.view.date.setFullYear(e)),this.switchView("day"),this},switchYear:function(t){return"prev"==t?this.view.date.setFullYear(this.view.date.getFullYear()-1):"next"==t?this.view.date.setFullYear(this.view.date.getFullYear()+1):this.view.date.setFullYear(t),this.switchView("month"),this},selectDate:function(t,e,a,s,n,i){var l=new Date,r=[this.con.dateFormat?this.con.dateFormat:"",this.con.timeFormat?this.con.timeFormat:""].join(" ").trim();return this.select=new Date(t||(null==t?this.view.date.getFullYear():l.getFullYear()),e||(null==e?this.view.date.getMonth():l.getMonth()),a||(null==a?this.view.date.getDate():l.getDate()),s||(null==s?this.view.date.getHours():0),n||(null==n?this.view.date.getMinutes():0),i||(null==i?this.view.date.getSeconds():0)),g.trigger(this.dt,"tail.DateTime::select",{bubbles:!1,cancelable:!0,detail:self}),this.e.value=this.convertDate(this.select,r),this.e.setAttribute("data-tail-value",this.convertDate(this.select,"YYYY-mm-dd HH:ii:ss")),this.switchView(this.view.type)},selectTime:function(t,e,a){return this.selectDate(!1,!1,!1,t,e,a)},createCalendar:function(t,e){var a=1,s=!0,n=new Date(e,t,a).getDay(),i=[31,e%4==0&&e%100!=0||e%400==0?29:28,31,30,31,30,31,31,30,31,30,31],l=[];if((n-=p("shorts").indexOf(this.con.weekStart))<0&&(n=7+n),v.cache[this.con.weekStart+"_"+e]&&!v.isIE11){if(v.cache[this.con.weekStart+"_"+e][t])return v.cache[this.con.weekStart+"_"+e][t]}else v.cache[this.con.weekStart+"_"+e]={};for(var r=0;s;){l[r]=[];for(var d=0;d<7;d++)0===r?d===n&&(l[r][d]="<span>"+a+++"</span>",n++):a<=i[t]?l[r][d]="<span>"+a+++"</span>":(l[r][d]="",s=!1),i[t]<a&&(s=!1);r++}for(r=0;r<l.length;r++)l[r]='<tr>\n<td class="calendar-day">'+l[r].join('</td>\n<td class="calendar-day">')+"</td>\n</tr>";if(g.IE){var o="<table><tbdy>"+l.join("")+"</tbody></table>";(c=u.createElement("div")).innerHTML=o,c=c.getElementsByTagName("table")[0]}else{var c;(c=u.createElement("table")).className="calendar-current",c.innerHTML=l.join("")}var h=c.querySelectorAll("td:empty");for(r=0;r<h.length;++r)h[r].className+=" empty";t==(new Date).getMonth()&&e==(new Date).getFullYear()&&Array.prototype.slice.call(c.querySelectorAll("td")).forEach(function(t,e,a){t.innerText===(new Date).getDate().toString()&&(t.className+=" today")});return this.view.date.setMonth(t),this.view.date.setFullYear(e),this.view=g.clone(this.view,{content:c}),v.cache[this.con.weekStart+"_"+e][t]=this.view,v.cache[this.con.weekStart+"_"+e][t]},convertDate:function(t,e){var a,s={H:String("00"+t.getHours()).toString().slice(-2),G:(a=t.getHours(),a%12?a%12:12),A:12<=t.getHours()?"PM":"AM",a:12<=t.getHours()?"pm":"am",i:String("00"+t.getMinutes()).toString().slice(-2),s:String("00"+t.getSeconds()).toString().slice(-2),Y:t.getFullYear(),y:parseInt(t.getFullYear().toString().slice(2)),m:String("00"+(t.getMonth()+1)).toString().slice(-2),M:p("months",[t.getMonth()]).slice(0,3),F:p("months",[t.getMonth()]),d:String("00"+t.getDate()).toString().slice(-2),D:p("days",[t.getDay()]),l:p("shorts",[t.getDay()]).toLowerCase()},n=new RegExp("(H{1,2}|G{1,2}|i{1,2}|s{1,2}|Y{2,4}|y{2}|m{1,2}|d{1,2})","g");return e=(e=e.replace(n,function(t){var e=s[t.slice(-1)].toString(),a=t.length;return 4==a||2==a?e.slice(-Math.abs(a)):1==a&&"0"==e[0]?e.slice(-1):e})).replace(/(A|a|M|F|D|l)/g,function(t){return s[t]})}},void 0===n.tail&&(n.tail={}),n.tail.DateTime=v,n.tail.DateTime}(this); | ||
/* tail.DateTime 0.4.0 @ https://github.com/pytesNET/tail.DateTime */ | ||
!function(t){"function"==typeof define&&define.amd?define(function(){return t(window)}):(void 0===window.tail&&(window.tail={}),window.tail.DateTime=t(window))}(function(t){"use strict";var n=t,c=t.document;function d(t,e){return new RegExp("\\b"+e+"\\b").test(t.className||"")}function a(t,e){return new RegExp("\\b"+e+"\\b").test(t.className||e)||(t.className+=" "+e),t}function s(t,e,i){return(i=new RegExp("\\b("+e+")\\b"))&&i.test(t.className||"")&&(t.className=t.className.replace(i,"")),t}function r(t,e,i){if(CustomEvent&&CustomEvent.name)var a=new CustomEvent(e,i);else(a=c.createEvent("CustomEvent")).initCustomEvent(e,!!i.bubbles,!!i.cancelable,i.detail);return t.dispatchEvent(a)}function o(t,e){if(Object.assign)return Object.assign({},t,e||{});var i=Object.constructor();for(var a in t)i[a]=a in e?e[a]:t[a];return i}function l(t){return t.charAt(0).toUpperCase()+t.slice(1)}function h(t,e,i){var a=t instanceof Date?t:!!t&&new Date(t);return a instanceof Date&&!isNaN(a.getDate())&&(i&&a.setHours(0,0,0,0),!0===e?a.getTime():a)}var u=function(t,e){if("string"==typeof t&&(t=c.querySelectorAll(t)),t instanceof NodeList||t instanceof HTMLCollection||t instanceof Array){for(var i=[],a=t.length,s=0;s<a;s++)i.push(new u(t[s],e));return 1===i.length?i[0]:0!==i.length&&i}if(!(t instanceof Element))return!1;if(!(this instanceof u))return new u(t,e);if(u.inst[t.getAttribute("data-tail-datetime")])return u.inst[t.getAttribute("data-tail-datetime")];if(t.getAttribute("data-datetime")){var n=JSON.parse(t.getAttribute("data-datetime").replace(/\'/g,'"'));n instanceof Object&&(e=o(e,n))}return this.e=t,this.id=++u.count,this.con=o(u.defaults,e),(u.inst["tail-"+this.id]=this).init()};return u.version="0.4.0",u.status="beta",u.count=0,u.inst={},u.defaults={animate:!0,classNames:!1,dateFormat:"YYYY-mm-dd",dateStart:!1,dateRanges:[],dateBlacklist:!0,dateEnd:!1,locale:"en",position:"bottom",startOpen:!1,stayOpen:!1,timeFormat:"HH:ii:ss",timeHours:null,timeMinutes:null,timeSeconds:0,today:!0,tooltips:[],viewDefault:"days",viewDecades:!0,viewYears:!0,viewMonths:!0,viewDays:!0,weekStart:0},u.strings={en:{months:["January","February","March","April","May","June","July","August","September","October","November","December"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shorts:["SUN","MON","TUE","WED","THU","FRI","SAT"],time:["Hours","Minutes","Seconds"],header:["Select a Month","Select a Year","Select a Decade","Select a Time"]}},u.strings.register=function(t,e){u.strings[t]=e},u.prototype={init:function(){var t,e=this;if(this.__=u.strings[this.con.locale]||u.strings.en,this.con.dateStart=h(this.con.dateStart,!0,!0)||0,this.con.dateEnd=h(this.con.dateEnd,!0,!0)||9999999999999,this.con.viewDefault=this.con.dateFormat?this.con.viewDefault:"time","string"==typeof this.con.weekStart&&(this.con.weekStart=u.strings.en.shorts.indexOf(this.con.weekStart)),this.con.weekStart<0&&6<this.con.weekStart&&(this.con.weekStart=0),0<this.con.dateRanges.length){for(var i=[],a=(l=this.con.dateRanges).length,s=0;s<a;s++)l[s]instanceof Object&&(l[s].start||l[s].days)&&(!1===(l[s].start=h(l[s].start||!1,!0,!0))?l[s].start=l[s].end=1/0:(!1===(l[s].end=h(l[s].end||!1,!0,!0))&&(l[s].end=l[s].start),l[s].start=l[s].start>l[s].end?[l[s].end,l[s].end=l[s].start][0]:l[s].start),l[s].days=!l[s].days||l[s].days,l[s].days="boolean"!=typeof days?function(t){for(var e=[],i=t.length,a=0;a<i;a++)"string"==typeof t[a]&&(t[a]=u.strings.en.shorts.indexOf(t[a])),0<=t[a]&&t[a]<=6&&e.push(t[a]);return e}(l[s].days instanceof Array?l[s].days:[l[s].days]):[0,1,2,3,4,5,6],i.push({start:l[s].start,end:l[s].end,days:l[s].days}));this.con.dateRanges=i}if(0<this.con.tooltips.length){i=[];var n,r=this.con.tooltips;for(a=r.length,s=0;s<a;s++)r[s]instanceof Object&&r[s].date&&(r[s].date instanceof Array?(n=h(r[s].date[0]||!1,!0,!0),l=h(r[s].date[0]||!1,!0,!0)||n):n=l=h(r[s].date||!1,!0,!0),n&&i.push({date:n!==l?[n,l]:n,text:r[s].text||"Tooltip",color:r[s].color||"#202428",element:r[s].element||(t=c.createElement("DIV"),t.className="calendar-tooltip",t.innerHTML='<div class="tooltip-inner">'+r[s].text||"Tooltip</div>",t)}));this.con.tooltips=i}var o=this.__.shorts.slice(this.con.weekStart).concat(this.__.shorts.slice(0,this.con.weekStart));this.weekdays="<thead>\n<tr>\n";for(s=0;s<7;s++)this.weekdays+='<th class="calendar-week">'+o[s]+"</th>";this.weekdays+="\n</tr>\n</thead>",this.select=h(this.e.getAttribute("data-value")||this.e.value),(!this.select||this.select<this.con.dateStart||this.select>this.con.dateEnd)&&(this.select=null),null==this.view&&(this.view={type:this.con.viewDefault,date:this.select||new Date});for(a=["Hours","Minutes","Seconds"],s=0;s<3;s++)"number"==typeof this.con["time"+a[s]]&&this.view.date["set"+a[s]](this.con["time"+a[s]]);if(this.events={},this.dt=this.renderCalendar(),null==this._bind){var l="addEventListener";this.e[l]("focusin",function(t){e.open.call(e)}),this.e[l]("keyup",function(t){e.bind.call(e,t)}),c[l]("keyup",function(t){e.bind.call(e,t)}),c[l]("click",function(t){e.dt.contains(t.target)?e.bind.call(e,t):!e.e.contains(t.target)&&d(e.dt,"calendar-open")&&(t.target==e.dt||t.target==e.e||e.con.stayOpen||e.close.call(e))}),c[l]("mouseover",function(t){e.dt.contains(t.target)&&e.bind.call(e,t)}),this._bind=!0}return this.e.setAttribute("data-tail-datetime","tail-"+this.id),this.con.startOpen&&this.open(),this.select&&this.selectDate(this.select),this},bind:function(t){var e,i=t.target,a="getAttribute",s="data-action",n=i[a](s)?i:i.parentElement[a](s)?i.parentElement:i,r="data-tooltip";if("mouseover"==t.type&&(!1!==(e=i[a](r)?i:!!n[a](r)&&n)?this.dt.querySelector("#tooltip-"+e[a](r)+"-"+e[a](r+"-time"))||this.showTooltip(e[a](r),e,e[a](r+"-time")):this.dt.querySelector(".calendar-tooltip:not(.remove)")&&this.hideTooltip(this.dt.querySelector(".calendar-tooltip").id.slice(8))),"click"==t.type){if(!n||1!=t.buttons&&1!=(t.which||t.button))return;switch(n[a](s)){case"prev":return this.browseView("prev");case"next":return this.browseView("next");case"submit":return this.selectDate(this.fetchDate(n[a]("data-date")));case"cancel":this.con.stayOpen||this.close();break;case"view":return this.switchDate(n[a]("data-year")||null,n[a]("data-month")||null,n[a]("data-day")||null),this.switchView(n[a]("data-view"))}}if("keyup"==t.type){if(t.target!==this.e&&/calendar-(static|close)/i.test(this.dt.className))return!1;13==(t.keyCode||t.which)&&(this.selectDate(this.fetchDate()),t.stopPropagation(),this.con.stayOpen||this.close()),27==(t.keyCode||t.which)&&(this.con.stayOpen||this.close())}},trigger:function(t){var e={bubbles:!1,cancelable:!0,detail:{args:arguments,self:this}};"change"==t&&(r(this.e,"input",e),r(this.e,"change",e)),r(this.dt,"tail::"+t,e);for(var i=(this.events[t]||[]).length,a=0;a<i;a++)this.events[t][a].cb.apply(this,function(t,e,i){for(var a=e.length,s=0;s<a;++s)t[s-1]=e[s];return t[s]=i,t}(new Array(arguments.length),arguments,this.events[t][a].args))},calcPosition:function(){var t=this.dt.style,e=n.getComputedStyle(this.dt),i=parseInt(e.marginLeft)+parseInt(e.marginRight),a=parseInt(e.marginTop)+parseInt(e.marginBottom),s=function(t,e){for(e={top:t.offsetTop||0,left:t.offsetLeft||0,width:t.offsetWidth||0,height:t.offsetHeight||0};t=t.offsetParent;)e.top+=t.offsetTop,e.left+=t.offsetLeft;return e}(this.e,{});switch(t.visibility="hidden",this.con.position){case"top":t.top=s.top-(this.dt.offsetHeight+a)+"px",t.left=s.left+s.width/2-(this.dt.offsetWidth/2+i/2)+"px";break;case"left":t.top=s.top+s.height/2-(this.dt.offsetHeight/2+a)+"px",t.left=s.left-(this.dt.offsetWidth+i)+"px";break;case"right":t.top=s.top+s.height/2-(this.dt.offsetHeight/2+a)+"px",t.left=s.left+s.width+"px";break;case"bottom":t.top=s.top+s.height+"px",t.left=s.left+s.width/2-(this.dt.offsetWidth/2+i/2)+"px"}return t.visibility="visible",this},convertDate:function(t,e){var i,a={H:String("00"+t.getHours()).toString().slice(-2),G:(i=t.getHours(),i%12?i%12:12),A:12<=t.getHours()?"PM":"AM",a:12<=t.getHours()?"pm":"am",i:String("00"+t.getMinutes()).toString().slice(-2),s:String("00"+t.getSeconds()).toString().slice(-2),Y:t.getFullYear(),y:parseInt(t.getFullYear().toString().slice(2)),m:String("00"+(t.getMonth()+1)).toString().slice(-2),M:this.__.months[t.getMonth()].slice(0,3),F:this.__.months[t.getMonth()],d:String("00"+t.getDate()).toString().slice(-2),D:this.__.days[t.getDay()],l:this.__.shorts[t.getDay()].toLowerCase()};return e.replace(/([HGismd]{1,2}|[Y]{2,4}|y{2})/g,function(t){return 4==t.length||2==t.length?a[t.slice(-1)].toString().slice(-Math.abs(t.length)):1==t.length&&"0"==datePart[0]?a[t.slice(-1)].toString().slice(-1):a[t.slice(-1)].toString()}).replace(/(A|a|M|F|D|l)/g,function(t){return a[t]})},renderCalendar:function(){var t,e=["tail-datetime-calendar","calendar-close"],i=c.createElement("DIV"),a=!0===this.con.classNames?this.e.className:this.con.classNames;if(["top","left","right","bottom"].indexOf(this.con.position)<0&&(t=c.querySelector(this.con.position),e.push("calendar-static")),("string"==typeof a||a instanceof Array)&&(e=e.concat("string"==typeof a?a.split(" "):a)),this.con.stayOpen&&e.push("calendar-stay"),i.id="tail-datetime-"+this.id,i.className=e.join(" "),this.con.dateFormat)var s='<span class="action action-prev" data-action="prev"></span><span class="label" data-action="view" data-view="up"></span><span class="action action-next" data-action="next"></span>';else if(this.con.timeFormat)s='<span class="action action-submit" data-action="submit"></span><span class="label"></span><span class="action action-cancel" data-action="cancel"></span>';return void 0!==s&&(i.innerHTML='<div class="calendar-actions">'+s+"</div>"),this.con.dateFormat&&this.renderDatePicker(i,this.con.viewDefault),this.con.timeFormat&&this.renderTimePicker(i),i.style.cssText=t?"position:static;visibility:visible;":"top:0;left:0;z-index:999;position:absolute;visibility:hidden;",(t||document.body).appendChild(i),i},renderDatePicker:function(t,e){if((!e||["decades","years","months","days"].indexOf(e)<0)&&(e=this.con.viewDays?"days":this.con.viewMonths?"months":this.con.viewYears?"years":!!this.con.viewDecades&&"decades"),!e||!this.con["view"+l(e)]||!this.con.dateFormat)return!1;var i=c.createElement("DIV");return i.className="calendar-datepicker calendar-view-"+e,i.innerHTML=this["view"+l(e)](),t.querySelector(".calendar-datepicker")?t.replaceChild(i,t.querySelector(".calendar-datepicker")):t.appendChild(i),this.view.type=e,this.handleLabel(t)},renderTimePicker:function(t){if(!this.con.timeFormat)return!1;var e,i=c.createElement("DIV");return i.className="calendar-timepicker",i.innerHTML='<div class="timepicker-field timepicker-hours"><input type="number" name="dt[h]" value="" min="00" max="23" step="1" /><label>'+this.__.time[0]+'</label></div><div class="timepicker-field timepicker-minutes"><input type="number" name="dt[m]" value="" min="00" max="59" step="5" /><label>'+this.__.time[1]+'</label></div><div class="timepicker-field timepicker-seconds"><input type="number" name="dt[s]" value="" min="00" max="59" step="5" /><label>'+this.__.time[2]+"</label></div>",(e=i.querySelectorAll("input"))[0].value=this.view.date.getHours(),e[1].value=this.view.date.getMinutes(),e[2].value=this.view.date.getSeconds(),t.querySelector(".calendar-timepicker")?t.replaceChild(i,t.querySelector(".calendar-timepicker")):t.appendChild(i),this.handleLabel(t)},handleLabel:function(t){var e,i,a=t.querySelector(".label");switch(this.view.type){case"days":e=this.__.months[this.view.date.getMonth()]+", "+this.view.date.getFullYear();break;case"months":e=this.view.date.getFullYear();break;case"years":e=(i=parseInt(this.view.date.getFullYear().toString().slice(0,3)+"0"))+" - "+(i+10);break;case"decades":e=(i=parseInt(this.view.date.getFullYear().toString().slice(0,2)+"00"))+" - "+(i+100)}return a.innerText=e,t},viewDecades:function(){var t=this.view.date.getFullYear(),e=new Date(this.view.date.getTime()),i=this.con.today?(new Date).getYear():0;e.setFullYear(t-parseInt(t.toString()[3])-30);for(var a,s,n=[],r=[],o=1;o<=16;o++)a="calendar-decade"+(i>=e.getYear()&&i<=e.getYear()+10?" date-today":""),s='data-action="view" data-view="down" data-year="'+e.getFullYear()+'"',n.push('<td class="'+a+'" '+s+'><span class="inner">'+e.getFullYear()+" - "+(e.getFullYear()+10)+"</span></td>"),4<=o&&o%4==0&&(r.push("<tr>\n"+n.join("\n")+"\n</tr>"),n=[]),e.setFullYear(e.getFullYear()+10);return'<table class="calendar-decades"><thead><tr><th colspan="4">'+this.__.header[2]+"</th></tr></thead><tbody>"+r.join("\n")+"</tbody></table>"},viewYears:function(){var t=this.view.date.getFullYear(),e=new Date(this.view.date.getTime()),i=this.con.today?(new Date).getYear():0;e.setFullYear(t-parseInt(t.toString()[3])-2);for(var a,s,n=[],r=[],o=1;o<=16;o++)a="calendar-year"+(e.getYear()==i?" date-today":""),s='data-action="view" data-view="down" data-year="'+e.getFullYear()+'"',n.push('<td class="'+a+'" '+s+'><span class="inner">'+e.getFullYear()+"</span></td>"),4<=o&&o%4==0&&(r.push("<tr>\n"+n.join("\n")+"\n</tr>"),n=[]),e.setFullYear(e.getFullYear()+1);return'<table class="calendar-years"><thead><tr><th colspan="4">'+this.__.header[1]+"</th></tr></thead><tbody>"+r.join("\n")+"</tbody></table>"},viewMonths:function(){var t=this.__.months,e=this.con.today?(new Date).getMonth():-1;e=this.view.date.getYear()==(new Date).getYear()?e:-1;for(var i,a,s=[],n=[],r=0;r<12;r++)i="calendar-month"+(e==r?" date-today":""),a='data-action="view" data-view="down" data-month="'+r+'"',s.push('<td class="'+i+'" '+a+'><span class="inner">'+t[r]+"</span></td>"),3==s.length&&(n.push("<tr>\n"+s.join("\n")+"\n</tr>"),s=[]);return'<table class="calendar-months"><thead><tr><th colspan="3">'+this.__.header[0]+"</th></tr></thead><tbody>"+n.join("\n")+"</tbody></table>"},viewDays:function(){var i,t,e,a,s,n=new Date(this.view.date.getTime()),r=(new Date).toDateString(),o=n.getMonth(),l=[],c=[],d=[0,[]],h=[].concat(this.con.dateRanges),u=([].concat(this.con.tooltips),[0,0]);for(n.setHours(0,0,0,0),n.setDate(1),n.setDate(1-(n.getDay()-this.con.weekStart));c.length<6;)i=n.getTime(),e='data-action="submit" data-date="'+(e=n.getFullYear()+"-"+(n.getMonth()+1)+"-"+n.getDate())+'"',t="calendar-day date-"+(n.getMonth()>o?"next":n.getMonth()<o?"previous":"current"),this.con.today&&r==n.toDateString()&&(t+=" date-today"),this.con.dateBlacklist&&(i<this.con.dateStart||i>this.con.dateEnd)?d=[i<this.con.dateStart?this.con.dateStart:1/0,[0,1,2,3,4,5,6],!0]:0==d[0]?h=h.filter(function(t){return t.start==1/0||i>=t.start&&i<=t.end?!(d=[t.end,t.days]):t.start>i},this):3==d.length&&(d=[0,[0,1,2,3,4,5,6]]),0<this.con.tooltips.length&&this.con.tooltips.filter(function(t,e){t.date instanceof Array?t.date[0]<=i&&t.date[1]>=i&&(u=[t.date[1],e,t.color]):t.date==i&&(u=[t.date,e,t.color])},this),u[0]<i&&(u=[0,0]),(s=d[0]>=i&&0<=d[1].indexOf(n.getDay()))&&this.con.dateBlacklist||!s&&!this.con.dateBlacklist?(t+=" date-disabled",e+=' data-disabled="true"'):0!==d[0]&&d[0]<=i&&(d=[0,[]]),this.select&&this.select.toDateString()==n.toDateString()&&(t+=" date-select"),a='<span class="inner">'+n.getDate()+"</span>",0<u[0]&&(t+=" date-tooltip",e+=' data-tooltip="'+u[1]+'" data-tooltip-time="'+i+'"',a+='<span class="tooltip-tick" style="background:'+u[2]+';"></span>'),l.push('<td class="'+t+'" '+e+">"+a+"</td>"),7==l.length&&(c.push("<tr>\n"+l.join("\n")+"\n</tr>"),l=[]),n.setDate(n.getDate()+1);return c="<tbody>"+c.join("\n")+"</tbody>",'<table class="calendar-days">'+this.weekdays+c+"</table>"},showTooltip:function(t,e,i){var a,s=this.con.tooltips[t].element,n=s.style,r=this.dt.querySelector(".calendar-datepicker");n.cssText="opacity:0;visibility:hidden;",s.id="tooltip-"+t+"-"+i,r.appendChild(s),a=s.offsetWidth,s.offsetHeight,n.top=e.offsetTop+e.offsetHeight+"px",n.left=e.offsetLeft+e.offsetWidth/2-a/2+"px",n.visibility="visible",this.con.animate?(s.setAttribute("data-top",parseInt(n.top)),n.top=parseInt(n.top)+5+"px",function t(){parseFloat(n.top)>s.getAttribute("data-top")&&(n.top=parseFloat(n.top)-.5+"px"),(n.opacity=parseFloat(n.opacity)+.125)<1&&setTimeout(t,20)}()):n.opacity=1},hideTooltip:function(t){var e=this.dt.querySelector("#tooltip-"+t),i=e.style;this.con.animate?(e.className+=" remove",function t(){if(parseFloat(i.top)<parseInt(e.getAttribute("data-top"))+5&&(i.top=parseFloat(i.top)+.5+"px"),(i.opacity-=.125)<0)return(e.className="calendar-tooltip")?e.parentElement.removeChild(e):"";setTimeout(t,20)}()):e.parentElement.removeChild(e)},switchView:function(t){var e=[null,"days","months","years","decades",null];return-1==e.indexOf(t)&&("up"==t?t=e[(e.indexOf(this.view.type)||5)+1]||null:"down"==t&&(t=e[(e.indexOf(this.view.type)||1)-1]||null),t&&this.con["view"+l(t)]||(t=!1)),!!t&&!!this.renderDatePicker(this.dt,t)},switchDate:function(t,e,i,a){if(this.view.date.setFullYear(t||this.view.date.getFullYear()),this.view.date.setMonth(e||this.view.date.getMonth()),"auto"==i){var s=this.view.date,n=new Date;i=s.getMonth()==n.getMonth()&&s.getYear()==n.getYear()?n.getDate():1}return this.view.date.setDate(i||this.view.date.getDate()),!0===a||this.switchView(this.view.type)},switchMonth:function(t,e){return"string"==typeof t&&(t=0<=["previous","prev"].indexOf(t)?-1:1,t=this.view.date.getMonth()+type),this.switchDate(e||this.getFullYear(),t)},switchYear:function(t){return"string"==typeof t&&(t=0<=["previous","prev"].indexOf(t)?-1:1,t=this.view.date.getFullYear()+type),this.switchDate(t)},browseView:function(t){switch(t=0<=["previous","prev"].indexOf(t)?-1:1,this.view.type){case"days":return this.switchDate(null,this.view.date.getMonth()+t,"auto");case"months":return this.switchDate(this.view.date.getFullYear()+t,null,"auto");case"years":return this.switchDate(this.view.date.getFullYear()+10*t,null,"auto");case"decades":return this.switchDate(this.view.date.getFullYear()+100*t,null,"auto")}return!1},fetchDate:function(t){t=h(t||!1)||this.view.date;var e=this.dt.querySelectorAll("input[type=number]");return e&&3==e.length&&t.setHours(e[0].value||0,e[1].value||0,e[2].value||0,0),t},selectDate:function(t,e,i,a,s,n){var r=new Date,o=[];return this.con.dateFormat&&o.push(this.con.dateFormat),this.con.timeFormat&&o.push(this.con.timeFormat),this.select=t instanceof Date?t:new Date(t||(null==t?this.view.date.getFullYear():r.getFullYear()),e||(null==e?this.view.date.getMonth():r.getMonth()),i||(null==i?this.view.date.getDate():r.getDate()),a||(null==a?this.view.date.getHours():0),s||(null==s?this.view.date.getMinutes():0),n||(null==n?this.view.date.getSeconds():0)),this.e.value=this.convertDate(this.select,o.join(" ")),this.e.setAttribute("data-value",this.select.getTime()),this.trigger("change"),this.switchView("days")},selectTime:function(t,e,i){return this.selectDate(!1,!1,!1,t,e,i)},open:function(){if(!d(this.dt,"calendar-close"))return this;var e=this,i=this.dt.style;return i.opacity=this.con.animate?0:1,i.display="block",a(s(this.dt,"calendar-close"),"calender-idle"),!d(this.dt,"calendar-static")&&this.calcPosition(),function t(){if(1<=(i.opacity=parseFloat(i.opacity)+.125))return a(s(e.dt,"calendar-idle"),"calendar-open"),e.trigger("open");setTimeout(t,20)}(),this},close:function(){if(!d(this.dt,"calendar-open"))return this;var e=this,i=this.dt.style;return a(s(this.dt,"calendar-open"),"calender-idle"),i.opacity=this.con.animate?1:0,i.display="block",function t(){if((i.opacity-=.125)<=0)return a(s(e.dt,"calendar-idle"),"calendar-close"),i.display="none",e.trigger("close");setTimeout(t,20)}(),this},toggle:function(){return d(this.dt,"calendar-open")?this.close():d(this.dt,"calendar-close")?this.open():this},on:function(t,e,i){return!(["open","close","change"].indexOf(t)<0||"function"!=typeof e)&&(t in this.events||(this.events[t]=[]),this.events[t].push({cb:e,args:i instanceof Array?i:[]}),this)},remove:function(){return this.e.removeAttribute("data-tail-datetime"),this.e.removeAttribute("data-value"),this.dt.parentElement.removeChild(this.dt),this},reload:function(){return this.remove(),this.init()},config:function(t,e,i){if(t instanceof Object){for(var a in t)this.config(a,t[a],!1);return this.reload(),this.con}return void 0===t?this.con:t in this.con&&(void 0===e?this.con[t]:(this.con[t]=e,!1!==this.rebuild&&this.reload(),this))}},u}); |
@@ -1,3 +0,25 @@ | ||
;(function(w){ | ||
w.tail.DateTime.strings = { | ||
/* | ||
| tail.DateTime - A pure, vanilla JavaScript DateTime Picker | ||
| @file ./langs/tail.datetime-de_AT.js | ||
| @author SamBrishes <https://github.com/pytesNET/tail.DateTime/> | ||
| @version 0.4.0 - Alpha | ||
| | ||
| @fork MrGuiseppe <https://github.com/MrGuiseppe/pureJSCalendar/> | ||
| This script started as fork and is now completely independent! | ||
| | ||
| @license X11 / MIT License | ||
| @copyright Copyright © 2018 - SamBrishes, pytesNET <pytes@gmx.net> | ||
*/ | ||
;(function(factory){ | ||
if(typeof(define) == "function" && define.amd){ | ||
define(function(){ | ||
return function(datetime){ factory(datetime); }; | ||
}); | ||
} else { | ||
if(typeof(window.tail) != "undefined" && window.tail.DateTime){ | ||
factory(window.tail.DateTime); | ||
} | ||
} | ||
}(function(datetime){ | ||
datetime.strings.register("de_AT", { | ||
months: ["Jänner", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], | ||
@@ -7,4 +29,5 @@ days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], | ||
time: ["Stunden", "Minuten", "Sekunden"], | ||
header: ["Wähle einen Monat", "Wähle ein Jahr", "Wähle eine Uhrzeit"], | ||
}; | ||
})(this); | ||
header: ["Wähle einen Monat", "Wähle ein Jahr", "Wähle ein Jahrzehnt", "Wähle eine Uhrzeit"] | ||
}); | ||
return datetime; | ||
})); |
@@ -1,3 +0,25 @@ | ||
;(function(w){ | ||
w.tail.DateTime.strings = { | ||
/* | ||
| tail.DateTime - A pure, vanilla JavaScript DateTime Picker | ||
| @file ./langs/tail.datetime-de.js | ||
| @author SamBrishes <https://github.com/pytesNET/tail.DateTime/> | ||
| @version 0.4.0 - Alpha | ||
| | ||
| @fork MrGuiseppe <https://github.com/MrGuiseppe/pureJSCalendar/> | ||
| This script started as fork and is now completely independent! | ||
| | ||
| @license X11 / MIT License | ||
| @copyright Copyright © 2018 - SamBrishes, pytesNET <pytes@gmx.net> | ||
*/ | ||
;(function(factory){ | ||
if(typeof(define) == "function" && define.amd){ | ||
define(function(){ | ||
return function(datetime){ factory(datetime); }; | ||
}); | ||
} else { | ||
if(typeof(window.tail) != "undefined" && window.tail.DateTime){ | ||
factory(window.tail.DateTime); | ||
} | ||
} | ||
}(function(datetime){ | ||
datetime.strings.register("de", { | ||
months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], | ||
@@ -7,4 +29,5 @@ days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], | ||
time: ["Stunden", "Minuten", "Sekunden"], | ||
header: ["Wähle einen Monat", "Wähle ein Jahr", "Wähle eine Uhrzeit"], | ||
}; | ||
})(this); | ||
header: ["Wähle einen Monat", "Wähle ein Jahr", "Wähle ein Jahrzehnt", "Wähle eine Uhrzeit"] | ||
}); | ||
return datetime; | ||
})); |
@@ -1,3 +0,25 @@ | ||
;(function(w){ | ||
w.tail.DateTime.strings = { | ||
/* | ||
| tail.DateTime - A pure, vanilla JavaScript DateTime Picker | ||
| @file ./langs/tail.datetime-es.js | ||
| @author SamBrishes <https://github.com/pytesNET/tail.DateTime/> | ||
| @version 0.4.0 - Alpha | ||
| | ||
| @fork MrGuiseppe <https://github.com/MrGuiseppe/pureJSCalendar/> | ||
| This script started as fork and is now completely independent! | ||
| | ||
| @license X11 / MIT License | ||
| @copyright Copyright © 2018 - SamBrishes, pytesNET <pytes@gmx.net> | ||
*/ | ||
;(function(factory){ | ||
if(typeof(define) == "function" && define.amd){ | ||
define(function(){ | ||
return function(datetime){ factory(datetime); }; | ||
}); | ||
} else { | ||
if(typeof(window.tail) != "undefined" && window.tail.DateTime){ | ||
factory(window.tail.DateTime); | ||
} | ||
} | ||
}(function(datetime){ | ||
datetime.strings.register("es", { | ||
months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], | ||
@@ -7,4 +29,5 @@ days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"], | ||
time: ["Horas", "Minutos", "Segundos"], | ||
header: ["Selecciona un mes", "Seleccione un año", "Seleccione una hora"], | ||
}; | ||
})(this); | ||
header: ["Selecciona un mes", "Seleccione un año", "Seleccione un década", "Seleccione una hora"] | ||
}); | ||
return datetime; | ||
})); |
{ | ||
"name": "tail.datetime", | ||
"version": "0.3.4", | ||
"version": "0.4.0", | ||
"description": "A light-weight, translat- and configurable Open Source DateTime Picker, written in pure vanilla JavaScript!", | ||
@@ -12,3 +12,3 @@ "main": "js/tail.datetime.js", | ||
"keywords": [ | ||
"datetime-picker", "datetime", "date", "time", "picker", "calendar", "form", "tail" | ||
"datetime-picker", "datetime", "date", "time", "picker", "calendar", "tail" | ||
], | ||
@@ -15,0 +15,0 @@ "author": "SamBrishes, pytesNET", |
313
README.md
tail.DateTime | ||
============= | ||
[![npm](https://img.shields.io/npm/v/tail.datetime.svg?style=flat-square)](https://www.npmjs.com/package/tail.datetime) | ||
[![npm](https://img.shields.io/npm/dt/tail.datetime.svg?style=flat-square)](https://www.npmjs.com/package/tail.datetime) | ||
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) | ||
[![Author](https://img.shields.io/badge/Author-SamBrishes@pytesNET-lightgrey.svg?style=flat-square)](https://www.github.com/pytesNET) | ||
[![npm](https://s.pytes.net/4afcd19c)](https://s.pytes.net/64a7f3a3) | ||
[![npm](https://s.pytes.net/2f3f75c4)](https://s.pytes.net/64a7f3a3) | ||
[![Software License](https://s.pytes.net/8257ac72)](LICENSE.md) | ||
[![Author](https://s.pytes.net/5542d1fa)](https://www.github.com/pytesNET) | ||
**The tail.DateTime script is a fork of the [Pure JS Calendar](https://github.com/MrGuiseppe/pureJSCalendar), written by [MrGuiseppe](https://github.com/MrGuiseppe).** It is specially designed for the new, yet unpublished, backend theme for the FoxCMS. The tail.DateTime script offers the following changes compared to the Pure JS Calendar: | ||
The **tail.DateTime** Calendar Interface is written in pure vanilla JavaScript and doesn't require | ||
any additional dependencies. It was originally a fork of MrGuiseppes [Pure JS Calendar](https://github.com/MrGuiseppe/pureJSCalendar), | ||
however version 0.4.0 has separated from the last origin lines and is now completely independent. | ||
- A Time Picker (Hours, Minutes, Seconds) | ||
- A Month-Based browse view | ||
- A slightly different date/time output format | ||
- A slightly different HTML class/id layout | ||
- A different JS structure / implementation / constructur (Prototyping) | ||
- Key Listener for 'Escape' (Close) and 'Enter' (Use Today / First Day of the month) | ||
- Auto-Close on click outside of the calendar popup / input element | ||
- Instance Caching + Calendar Caching with the first day in the week | ||
- Default value depending on the input field | ||
- "Translatable" Strings through the global variable | ||
- And many more... Check out the Changelog for details. | ||
[Wanna see **tail.DateTime** in action?](https://github.pytes.net/tail.DateTime) | ||
[Demonstration](https://github.pytes.net/tail.DateTime) | ||
[Wanna translate **tail.DateTime** in your language?](https://github.com/pytesNET/tail.DateTime/wiki/Help-Translating) | ||
Work in Progress | ||
---------------- | ||
The script is still **Work in Progress** and hasn't been tested much! | ||
Features | ||
-------- | ||
- A beautiful Date/Time Picker (in 2 Designs + 6 Color Schemes) | ||
- Definable ranges of selectable dates (Blacklist / Whitelist) | ||
- Colorable Tooltips with an cute animation | ||
- Different Views to navigate quickly: Days, Months, Years & Decades | ||
- Completely Translatable and available in 5 languages (de, de_AT, en, es, ru) | ||
- Extendable and Bindable through different Events | ||
- Compatible with AMD, tested with requireJS | ||
- Many Settings to adapt and configure the design and behavior | ||
- Compatible with all modern browsers **(including IE 9+)** | ||
- No Dependencies, just embed and use | ||
- Free/To/Use - MIT Licensed | ||
Thanks to [MrGuiseppe](https://github.com/MrGuiseppe) and to [Octicons](https://octicons.github.com/) for the Vector Graphics. | ||
Install & Embed | ||
--------------- | ||
The master branch will always contain the latest Release, which you can download directly here | ||
as [.tar](https://github.com/pytesNET/tail.DateTime/tarball/master) or as [.zip](https://github.com/pytesNET/tail.DateTime/zipball/master) | ||
archive, or just visit the [Releases](https://github.com/pytesNET/tail.DateTime/releases) Page | ||
on GitHub directly. You can also be cool and using NPM (or YARN): | ||
Options | ||
------- | ||
```javascript | ||
tail.DateTime(document.getElementById("my-input-field"), { | ||
static: null, | ||
position: "bottom", | ||
classNames: "", | ||
dateFormat: "YYYY-mm-dd", | ||
timeFormat: "HH:ii:ss", | ||
dateRanges: [], | ||
weekStart: "SUN", | ||
startOpen: false, | ||
stayOpen: false, | ||
zeroSeconds: false | ||
}); | ||
```markup | ||
npm install tail.DateTime --save | ||
``` | ||
### static | ||
`string`<br /> | ||
Pass an valid selector of an element where the Calendar Popup should be append to, leave it on | ||
null to use the absolute position calculation. | ||
```markup | ||
yarn add tail.DateTime --save | ||
``` | ||
### position | ||
`string`<br /> | ||
Sets the position of the DateTime popup field to `"top"`, `"left"`, `"right"` or `"bottom"`. This | ||
option **does not** work if you pass an valid selector on `static`! | ||
```markup | ||
bower install tail.DateTime --save | ||
``` | ||
### classNames | ||
`string` or `array`<br /> | ||
Adds custom class names to the main DateTime container element, pass and array or an space-separated | ||
list! | ||
### Using a CDN | ||
You can also use the awesome CDN services from jsDelivr or UNPKG. | ||
### dateFormat | ||
`string` or `false`<br /> | ||
Pass an valid Date/Time Format (see below) or pass `false` to disable the Date picker. | ||
```markup | ||
https://cdn.jsdelivr.net/npm/tail.DateTime@latest/ | ||
``` | ||
### timeFormat | ||
`string` or `false`<br /> | ||
Pass an valid Date/Time Format (see below) or pass `false` to disable the Time picker. | ||
```markup | ||
https://unpkg.com/tail.DateTime/ | ||
``` | ||
### dateRanges | ||
`array`<br /> | ||
This option allows you to create one or more selectable periods of time. Each period defines itself | ||
through an array, where the first value if the start-point and the last one the end-point (which is | ||
also optional). You can use a `Date` object as value, a string as `YYYY-MM-DD` or the (translated) | ||
name of a weekday (See `tailDateTime.strings.shorts`). | ||
Thanks To | ||
--------- | ||
- [MrGuiseppe](https://github.com/MrGuiseppe) for the Inspiration | ||
- [Octicons](https://octicons.github.com/) for the cute Icons | ||
- [jsCompress](https://jscompress.com/) for the Compressor | ||
- [prismJS](https://prismjs.com) for the Syntax highlighting library | ||
- [MenuSpy](https://github.com/lcdsantos/menuspy) for the Menu Navigation | ||
#### Example: | ||
The following Example limits the selectable area to: | ||
Documentation | ||
------------- | ||
The Documentation has been moved to [GitHubs Wiki Pages](https://github.com/pytesNET/tail.DateTime/wiki), | ||
but I will keep a table of contents list here and some basic instructions. | ||
- From 2018-10-12 up to 2018-10-26 | ||
- From 2018-11-04 up to 2018-11-30 | ||
- From 2018-12-01 up to 2018-12-31 | ||
- **In all cases only from Monday up to Friday** (Sunday and Saturday are not selectable) | ||
- [Instructions]() | ||
- [Default Usage]() | ||
- [Public Options]() | ||
- [Public Methods]() | ||
- [Events & Callbacks]() | ||
- [Help Translating]() | ||
- [Internal]() | ||
The last array `["MON", "FRI"]` limits **only** all selections before! If you want to just use a | ||
selection between Monday and Friday in general, add a third parameters with `true`. | ||
### Basic Instructions | ||
You can pass up to 2 arguments to the **tail.DateTime** constructor, the first parameter is required | ||
and need to be an `Element`, a `NodeList`, a `HTMLCollection`, an Array with `Element` objects or | ||
just a single selector as `string`, which calls the `querySelectorAll()` method on its own. The | ||
second parameter is optional and, if set, MUST be an object with your *tail.DateTime* options. | ||
```javascript | ||
tail.DateTime("#datetime", { | ||
dateRanges: [ | ||
[new Date(2018, 9, 12), new Date(2018, 9, 26)], | ||
["2018-11-4", "2018-11-30"], | ||
[new Date(2018, 11, 1), new Date(2018, 11, 31)], | ||
["MON", "FRI"] | ||
] | ||
}); | ||
``` | ||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
### weekStart | ||
`string`<br /> | ||
Pass the (translated) string of the global variable `tailDateTime.strings.shorts` to change the | ||
shown first day in the week. (If no translation has been made, you can choose between: "SUN", "MON", | ||
"TUE", "WED", "THU", "FRI" and "SAT") | ||
<link type="text/css" rel="stylesheet" href="css/tail.datetime-default.css" /> | ||
<!-- Additional Stylesheets --> | ||
</head> | ||
<body> | ||
<script type="text/javascript" src="js/tail.datetime.min.js"></script> | ||
<!-- <script type="text/javascript" src="langs/tail.datetime-{lang}.js"></script> --> | ||
### startOpen | ||
`boolean`<br /> | ||
Use true to show the DateTime Picker directly after the initialization. | ||
<input type="text" class="tail-datetime-field" /> | ||
### stayOpen | ||
`boolean`<br /> | ||
Use true to keep the DateTime Picker open, even if an selection has been made or any other closing | ||
event has been triggered! (You can still close the DateTime Picker with the `close()` method!) | ||
<script type="text/javascript"> | ||
document.addEventListener("DOMContentLoaded", function(){ | ||
tail.DateTime(".tail-datetime-field", { /* Your Options */ }); | ||
}); | ||
</script> | ||
</body> | ||
</html> | ||
``` | ||
### zeroSeconds | ||
`boolean`<br /> | ||
Use true to set the seconds to `00`. This would be happen once, during the initialization. | ||
### Default Settings | ||
Please check out [GitHubs Wiki Pages](https://github.com/pytesNET/tail.DateTime/wiki) to read more | ||
about each single option! | ||
Date/Time Format | ||
---------------- | ||
<table> | ||
<tr> | ||
<th>Code</th> | ||
<th>Description</th> | ||
</tr> | ||
<tr> | ||
<th>H</th> | ||
<td>24-hour format of an hour, use `HH` for leading zeros!</td> | ||
</tr> | ||
<tr> | ||
<th>G</th> | ||
<td>12-hour format of an hour, use `GG` for leading zeros!</td> | ||
</tr> | ||
<tr> | ||
<th>A</th> | ||
<td>Uppercase Ante meridiem and Post meridiem (AM or PM).</td> | ||
</tr> | ||
<tr> | ||
<th>a</th> | ||
<td>Lowercase Ante meridiem and Post meridiem (am or om).</td> | ||
</tr> | ||
<tr> | ||
<th>i</th> | ||
<td>Minutes, use `ii` for leading zeros.</td> | ||
</tr> | ||
<tr> | ||
<th>s</th> | ||
<td>Seconds, use `ss` for leading zeros.</td> | ||
</tr> | ||
<tr> | ||
<th>Y</th> | ||
<td>A (4-digit) numeric representation of a year, used as `YY` or `YYYY`.</td> | ||
</tr> | ||
<tr> | ||
<th>y</th> | ||
<td>A (2-digit) numeric representation of a year, used as `yy`.</td> | ||
</tr> | ||
<tr> | ||
<th>m</th> | ||
<td>Numeric representation of a month, use `mm` for leading zeros.</td> | ||
</tr> | ||
<tr> | ||
<th>M</th> | ||
<td>A short textual representation of a month, three letters.</td> | ||
</tr> | ||
<tr> | ||
<th>F</th> | ||
<td>A full textual representation of a month, such as March.</td> | ||
</tr> | ||
<tr> | ||
<th>d</th> | ||
<td>Day of the month, use `dd` for leading zeros.</td> | ||
</tr> | ||
<tr> | ||
<th>D</th> | ||
<td>A textual representation of a day, three letters.</td> | ||
</tr> | ||
<tr> | ||
<th>l</th> | ||
<td>(Lower `L`) A full textual representation of the day of the week.</td> | ||
</tr> | ||
</table> | ||
Methods | ||
------- | ||
```javascript | ||
tail.DateTime(".tail-datetime-field", { | ||
animate: true, // New in 0.4.0 | ||
classNames: false, | ||
dateFormat: "YYYY-mm-dd", | ||
dateStart: false, // New in 0.4.0 | ||
dateRanges: [], // New Syntax in 0.4.0 | ||
dateBlacklist: true, // New in 0.4.0 | ||
dateEnd: false, // New in 0.4.0 | ||
locale: "en", // New in 0.4.0 | ||
position: "bottom", | ||
startOpen: false, | ||
stayOpen: false, | ||
timeFormat: "HH:ii:ss", | ||
timeHours: null, // New in 0.4.0 | ||
timeMinutes: null, // New in 0.4.0 | ||
timeSeconds: 0, // New in 0.4.0 | ||
today: true, // New in 0.4.0 | ||
tooltips: [], // New in 0.4.0 | ||
viewDefault: "days", // New in 0.4.0 | ||
viewDecades: true, // New in 0.4.0 | ||
viewYears: true, // New in 0.4.0 | ||
viewMonths: true, // New in 0.4.0 | ||
viewDays: true, // New in 0.4.0 | ||
weekStart: 0 | ||
}); | ||
``` | ||
var calendar = tail.DateTime(document.getElementById("my-input-field")); | ||
calendar.<method>(); | ||
``` | ||
### on(event, callback) | ||
This method hooks an event with an respective callback function to the DateTime object. Available | ||
Events: | ||
- `tail.DateTime::open`, when the DateTime Picker opens. | ||
- `tail.DateTime::close`, when the DateTime Picker closes. | ||
- `tail.DateTime::select`, the a selection has been made. | ||
### open() | ||
This method opens the calendar popup, if it isn't already open! | ||
### close() | ||
This method closes the calendar popup, if it is still open! | ||
### toggle() | ||
This method toggles the open/close option of the calendar popup. | ||
### remove() | ||
This method removes the DateTime Picker elments and destroys the tail.DateTime picker instance. | ||
### switchMonth(monthNum, year) | ||
This method changes the shown month (monthNum starts with 0). You can also use "prev" or "next" to just browse forward and back. | ||
### switchYear(year) | ||
This method changes the year within the month view. You can also use "prev" or "next" to just browse forward and back. | ||
### selectDate(Y, M, D, H, i, s) | ||
Select a date with year, month, day, hours, minutes and seconds. | ||
### selectTime(H, i, s) | ||
Select a time (alias for `selectDate`) with hours, minutes and seconds. | ||
Copyright & License | ||
------------------- | ||
Licensed under the MIT-License; Copyright © 2018 SamBrishes, pytesNET |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
235753
24
3497
146
1