From 059e0d95d0c28bc5060e87e146eaf7411f51bf90 Mon Sep 17 00:00:00 2001 From: George Halkiadakis Date: Thu, 27 Apr 2023 03:47:30 +0300 Subject: skeleton commit; based on an anom project --- .../DateTime-1.4.0/css/dataTables.dateTime.css | 218 +++ .../DateTime-1.4.0/css/dataTables.dateTime.min.css | 1 + .../DateTime-1.4.0/js/dataTables.dateTime.js | 1708 ++++++++++++++++++++ .../DateTime-1.4.0/js/dataTables.dateTime.min.js | 6 + 4 files changed, 1933 insertions(+) create mode 100644 public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.css create mode 100644 public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.min.css create mode 100644 public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.js create mode 100644 public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.min.js (limited to 'public/assets/js/DataTables/DateTime-1.4.0') diff --git a/public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.css b/public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.css new file mode 100644 index 0000000..768efed --- /dev/null +++ b/public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.css @@ -0,0 +1,218 @@ +div.dt-datetime { + position: absolute; + background-color: white; + z-index: 2050; + border: 1px solid #ccc; + box-shadow: 0 5px 15px -5px rgba(0, 0, 0, 0.5); + padding: 0 20px 6px 20px; + width: 275px; +} +div.dt-datetime.inline { + position: relative; + box-shadow: none; +} +div.dt-datetime div.dt-datetime-title { + text-align: center; + padding: 5px 0px 3px; +} +div.dt-datetime div.dt-datetime-buttons { + text-align: center; +} +div.dt-datetime div.dt-datetime-buttons a { + display: inline-block; + padding: 0 0.5em 0.5em 0.5em; + margin: 0; + font-size: 0.9em; +} +div.dt-datetime div.dt-datetime-buttons a:hover { + text-decoration: underline; +} +div.dt-datetime table { + border-spacing: 0; + margin: 12px 0; + width: 100%; +} +div.dt-datetime table.dt-datetime-table-nospace { + margin-top: -12px; +} +div.dt-datetime table th { + font-size: 0.8em; + color: #777; + font-weight: normal; + width: 14.285714286%; + padding: 0 0 4px 0; + text-align: center; +} +div.dt-datetime table td { + font-size: 0.9em; + color: #444; + padding: 0; +} +div.dt-datetime table td.selectable { + text-align: center; + background: #f5f5f5; +} +div.dt-datetime table td.selectable.disabled { + color: #aaa; + background: white; +} +div.dt-datetime table td.selectable.disabled button:hover { + color: #aaa; + background: white; +} +div.dt-datetime table td.selectable.now { + background-color: #ddd; +} +div.dt-datetime table td.selectable.now button { + font-weight: bold; +} +div.dt-datetime table td.selectable.selected button { + background: #4E6CA3; + color: white; + border-radius: 2px; +} +div.dt-datetime table td.selectable button:hover { + background: #ff8000; + color: white; + border-radius: 2px; +} +div.dt-datetime table td.dt-datetime-week { + font-size: 0.7em; +} +div.dt-datetime table button { + width: 100%; + box-sizing: border-box; + border: none; + background: transparent; + font-size: inherit; + color: inherit; + text-align: center; + padding: 4px 0; + cursor: pointer; + margin: 0; +} +div.dt-datetime table button span { + display: inline-block; + min-width: 14px; + text-align: right; +} +div.dt-datetime table.weekNumber th { + width: 12.5%; +} +div.dt-datetime div.dt-datetime-calendar table { + margin-top: 0; +} +div.dt-datetime div.dt-datetime-label { + position: relative; + display: inline-block; + height: 30px; + padding: 5px 6px; + border: 1px solid transparent; + box-sizing: border-box; + cursor: pointer; +} +div.dt-datetime div.dt-datetime-label:hover { + border: 1px solid #ddd; + border-radius: 2px; + background-color: #f5f5f5; +} +div.dt-datetime div.dt-datetime-label select { + position: absolute; + top: 6px; + left: 0; + cursor: pointer; + opacity: 0; +} +div.dt-datetime.horizontal { + width: 550px; +} +div.dt-datetime.horizontal div.dt-datetime-date, +div.dt-datetime.horizontal div.dt-datetime-time { + width: 48%; +} +div.dt-datetime.horizontal div.dt-datetime-time { + margin-left: 4%; +} +div.dt-datetime div.dt-datetime-date { + position: relative; + float: left; + width: 100%; +} +div.dt-datetime div.dt-datetime-time { + position: relative; + float: left; + width: 100%; + text-align: center; +} +div.dt-datetime div.dt-datetime-time > span { + vertical-align: middle; +} +div.dt-datetime div.dt-datetime-time th { + text-align: left; +} +div.dt-datetime div.dt-datetime-time div.dt-datetime-timeblock { + display: inline-block; + vertical-align: middle; +} +div.dt-datetime div.dt-datetime-iconLeft, +div.dt-datetime div.dt-datetime-iconRight, +div.dt-datetime div.dt-datetime-iconUp, +div.dt-datetime div.dt-datetime-iconDown { + width: 30px; + height: 30px; + background-position: center; + background-repeat: no-repeat; + opacity: 0.3; + overflow: hidden; + box-sizing: border-box; +} +div.dt-datetime div.dt-datetime-iconLeft:hover, +div.dt-datetime div.dt-datetime-iconRight:hover, +div.dt-datetime div.dt-datetime-iconUp:hover, +div.dt-datetime div.dt-datetime-iconDown:hover { + border: 1px solid #ccc; + border-radius: 2px; + background-color: #f0f0f0; + opacity: 0.6; +} +div.dt-datetime div.dt-datetime-iconLeft button, +div.dt-datetime div.dt-datetime-iconRight button, +div.dt-datetime div.dt-datetime-iconUp button, +div.dt-datetime div.dt-datetime-iconDown button { + border: none; + background: transparent; + text-indent: 30px; + height: 100%; + width: 100%; + cursor: pointer; +} +div.dt-datetime div.dt-datetime-iconLeft { + position: absolute; + top: 5px; + left: 5px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg=="); +} +div.dt-datetime div.dt-datetime-iconRight { + position: absolute; + top: 5px; + right: 5px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII="); +} +div.dt-datetime div.dt-datetime-iconUp { + height: 20px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAALCAMAAABf9c24AAAAFVBMVEX///99fX1+fn57e3t6enoAAAAAAAC73bqPAAAABnRSTlMAYmJkZt92bnysAAAAL0lEQVR4AWOgJmBhxCvLyopHnpmVjY2VCadeoCxIHrcsWJ4RlyxCHlMWCTBRJxwAjrIBDMWSiM0AAAAASUVORK5CYII="); +} +div.dt-datetime div.dt-datetime-iconDown { + height: 20px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAALCAMAAABf9c24AAAAFVBMVEX///99fX1+fn57e3t6enoAAAAAAAC73bqPAAAABnRSTlMAYmJkZt92bnysAAAAMElEQVR4AWOgDmBiRQIsmPKMrGxQgJDFlEfIYpoPk8Utz8qM232MYFfhkQfKUg8AANefAQxecJ58AAAAAElFTkSuQmCC"); +} + +div.dt-datetime-error { + clear: both; + padding: 0 1em; + max-width: 240px; + font-size: 11px; + line-height: 1.25em; + text-align: center; + color: #b11f1f; +} \ No newline at end of file diff --git a/public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.min.css b/public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.min.css new file mode 100644 index 0000000..94b9fa1 --- /dev/null +++ b/public/assets/js/DataTables/DateTime-1.4.0/css/dataTables.dateTime.min.css @@ -0,0 +1 @@ +div.dt-datetime{position:absolute;background-color:white;z-index:2050;border:1px solid #ccc;box-shadow:0 5px 15px -5px rgba(0, 0, 0, 0.5);padding:0 20px 6px 20px;width:275px}div.dt-datetime.inline{position:relative;box-shadow:none}div.dt-datetime div.dt-datetime-title{text-align:center;padding:5px 0px 3px}div.dt-datetime div.dt-datetime-buttons{text-align:center}div.dt-datetime div.dt-datetime-buttons a{display:inline-block;padding:0 .5em .5em .5em;margin:0;font-size:.9em}div.dt-datetime div.dt-datetime-buttons a:hover{text-decoration:underline}div.dt-datetime table{border-spacing:0;margin:12px 0;width:100%}div.dt-datetime table.dt-datetime-table-nospace{margin-top:-12px}div.dt-datetime table th{font-size:.8em;color:#777;font-weight:normal;width:14.285714286%;padding:0 0 4px 0;text-align:center}div.dt-datetime table td{font-size:.9em;color:#444;padding:0}div.dt-datetime table td.selectable{text-align:center;background:#f5f5f5}div.dt-datetime table td.selectable.disabled{color:#aaa;background:white}div.dt-datetime table td.selectable.disabled button:hover{color:#aaa;background:white}div.dt-datetime table td.selectable.now{background-color:#ddd}div.dt-datetime table td.selectable.now button{font-weight:bold}div.dt-datetime table td.selectable.selected button{background:#4e6ca3;color:white;border-radius:2px}div.dt-datetime table td.selectable button:hover{background:#ff8000;color:white;border-radius:2px}div.dt-datetime table td.dt-datetime-week{font-size:.7em}div.dt-datetime table button{width:100%;box-sizing:border-box;border:none;background:transparent;font-size:inherit;color:inherit;text-align:center;padding:4px 0;cursor:pointer;margin:0}div.dt-datetime table button span{display:inline-block;min-width:14px;text-align:right}div.dt-datetime table.weekNumber th{width:12.5%}div.dt-datetime div.dt-datetime-calendar table{margin-top:0}div.dt-datetime div.dt-datetime-label{position:relative;display:inline-block;height:30px;padding:5px 6px;border:1px solid transparent;box-sizing:border-box;cursor:pointer}div.dt-datetime div.dt-datetime-label:hover{border:1px solid #ddd;border-radius:2px;background-color:#f5f5f5}div.dt-datetime div.dt-datetime-label select{position:absolute;top:6px;left:0;cursor:pointer;opacity:0}div.dt-datetime.horizontal{width:550px}div.dt-datetime.horizontal div.dt-datetime-date,div.dt-datetime.horizontal div.dt-datetime-time{width:48%}div.dt-datetime.horizontal div.dt-datetime-time{margin-left:4%}div.dt-datetime div.dt-datetime-date{position:relative;float:left;width:100%}div.dt-datetime div.dt-datetime-time{position:relative;float:left;width:100%;text-align:center}div.dt-datetime div.dt-datetime-time>span{vertical-align:middle}div.dt-datetime div.dt-datetime-time th{text-align:left}div.dt-datetime div.dt-datetime-time div.dt-datetime-timeblock{display:inline-block;vertical-align:middle}div.dt-datetime div.dt-datetime-iconLeft,div.dt-datetime div.dt-datetime-iconRight,div.dt-datetime div.dt-datetime-iconUp,div.dt-datetime div.dt-datetime-iconDown{width:30px;height:30px;background-position:center;background-repeat:no-repeat;opacity:.3;overflow:hidden;box-sizing:border-box}div.dt-datetime div.dt-datetime-iconLeft:hover,div.dt-datetime div.dt-datetime-iconRight:hover,div.dt-datetime div.dt-datetime-iconUp:hover,div.dt-datetime div.dt-datetime-iconDown:hover{border:1px solid #ccc;border-radius:2px;background-color:#f0f0f0;opacity:.6}div.dt-datetime div.dt-datetime-iconLeft button,div.dt-datetime div.dt-datetime-iconRight button,div.dt-datetime div.dt-datetime-iconUp button,div.dt-datetime div.dt-datetime-iconDown button{border:none;background:transparent;text-indent:30px;height:100%;width:100%;cursor:pointer}div.dt-datetime div.dt-datetime-iconLeft{position:absolute;top:5px;left:5px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg==")}div.dt-datetime div.dt-datetime-iconRight{position:absolute;top:5px;right:5px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII=")}div.dt-datetime div.dt-datetime-iconUp{height:20px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAALCAMAAABf9c24AAAAFVBMVEX///99fX1+fn57e3t6enoAAAAAAAC73bqPAAAABnRSTlMAYmJkZt92bnysAAAAL0lEQVR4AWOgJmBhxCvLyopHnpmVjY2VCadeoCxIHrcsWJ4RlyxCHlMWCTBRJxwAjrIBDMWSiM0AAAAASUVORK5CYII=")}div.dt-datetime div.dt-datetime-iconDown{height:20px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAALCAMAAABf9c24AAAAFVBMVEX///99fX1+fn57e3t6enoAAAAAAAC73bqPAAAABnRSTlMAYmJkZt92bnysAAAAMElEQVR4AWOgDmBiRQIsmPKMrGxQgJDFlEfIYpoPk8Utz8qM232MYFfhkQfKUg8AANefAQxecJ58AAAAAElFTkSuQmCC")}div.dt-datetime-error{clear:both;padding:0 1em;max-width:240px;font-size:11px;line-height:1.25em;text-align:center;color:#b11f1f} diff --git a/public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.js b/public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.js new file mode 100644 index 0000000..5d81543 --- /dev/null +++ b/public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.js @@ -0,0 +1,1708 @@ +/*! DateTime picker for DataTables.net v1.4.0 + * + * © SpryMedia Ltd, all rights reserved. + * License: MIT datatables.net/license/mit + */ + +(function( factory ){ + if ( typeof define === 'function' && define.amd ) { + // AMD + define( ['jquery'], function ( $ ) { + return factory( $, window, document ); + } ); + } + else if ( typeof exports === 'object' ) { + // CommonJS + var jq = require('jquery'); + var cjsRequires = function (root, $) { }; + + if (typeof window !== 'undefined') { + module.exports = function (root, $) { + if ( ! root ) { + // CommonJS environments without a window global must pass a + // root. This will give an error otherwise + root = window; + } + + if ( ! $ ) { + $ = jq( root ); + } + + cjsRequires( root, $ ); + return factory( $, root, root.document ); + }; + } + else { + cjsRequires( window, jq ); + module.exports = factory( jq, window, window.document ); + } + } + else { + // Browser + factory( jQuery, window, document ); + } +}(function( $, window, document, undefined ) { +'use strict'; + + + +/** + * @summary DateTime picker for DataTables.net + * @version 1.4.0 + * @file dataTables.dateTime.js + * @author SpryMedia Ltd + * @contact www.datatables.net/contact + */ + +// Supported formatting and parsing libraries: +// * Moment +// * Luxon +// * DayJS +var dateLib; + +/* + * This file provides a DateTime GUI picker (calendar and time input). Only the + * format YYYY-MM-DD is supported without additional software, but the end user + * experience can be greatly enhanced by including the momentjs, dayjs or luxon library + * which provide date / time parsing and formatting options. + * + * This functionality is required because the HTML5 date and datetime input + * types are not widely supported in desktop browsers. + * + * Constructed by using: + * + * new DateTime( input, opts ) + * + * where `input` is the HTML input element to use and `opts` is an object of + * options based on the `DateTime.defaults` object. + */ +var DateTime = function ( input, opts ) { + // Check if called with a window or jQuery object for DOM less applications + // This is for backwards compatibility with CommonJS loader + if (DateTime.factory(input, opts)) { + return DateTime; + } + + // Attempt to auto detect the formatting library (if there is one). Having it in + // the constructor allows load order independence. + if (typeof dateLib === 'undefined') { + dateLib = window.moment + ? window.moment + : window.dayjs + ? window.dayjs + : window.luxon + ? window.luxon + : null; + } + + this.c = $.extend( true, {}, DateTime.defaults, opts ); + var classPrefix = this.c.classPrefix; + var i18n = this.c.i18n; + + // Only IS8601 dates are supported without moment, dayjs or luxon + if ( ! dateLib && this.c.format !== 'YYYY-MM-DD' ) { + throw "DateTime: Without momentjs, dayjs or luxon only the format 'YYYY-MM-DD' can be used"; + } + + // Min and max need to be `Date` objects in the config + if (typeof this.c.minDate === 'string') { + this.c.minDate = new Date(this.c.minDate); + } + if (typeof this.c.maxDate === 'string') { + this.c.maxDate = new Date(this.c.maxDate); + } + + // DOM structure + var structure = $( + '
'+ + '
'+ + '
'+ + '
'+ + ''+ + '
'+ + '
'+ + ''+ + '
'+ + '
'+ + ''+ + ''+ + '
'+ + '
'+ + ''+ + ''+ + '
'+ + '
'+ + '
'+ + ''+ + ''+ + '
'+ + '
'+ + '
'+ + '
'+ + '
'+ + '
'+ + '
'+ + '
'+ + '
'+ + '
' + ); + + this.dom = { + container: structure, + date: structure.find( '.'+classPrefix+'-date' ), + title: structure.find( '.'+classPrefix+'-title' ), + calendar: structure.find( '.'+classPrefix+'-calendar' ), + time: structure.find( '.'+classPrefix+'-time' ), + error: structure.find( '.'+classPrefix+'-error' ), + buttons: structure.find( '.'+classPrefix+'-buttons' ), + clear: structure.find( '.'+classPrefix+'-clear' ), + today: structure.find( '.'+classPrefix+'-today' ), + previous: structure.find( '.'+classPrefix+'-iconLeft' ), + next: structure.find( '.'+classPrefix+'-iconRight' ), + input: $(input) + }; + + this.s = { + /** @type {Date} Date value that the picker has currently selected */ + d: null, + + /** @type {Date} Date of the calendar - might not match the value */ + display: null, + + /** @type {number} Used to select minutes in a range where the range base is itself unavailable */ + minutesRange: null, + + /** @type {number} Used to select minutes in a range where the range base is itself unavailable */ + secondsRange: null, + + /** @type {String} Unique namespace string for this instance */ + namespace: 'dateime-'+(DateTime._instance++), + + /** @type {Object} Parts of the picker that should be shown */ + parts: { + date: this.c.format.match( /[YMD]|L(?!T)|l/ ) !== null, + time: this.c.format.match( /[Hhm]|LT|LTS/ ) !== null, + seconds: this.c.format.indexOf( 's' ) !== -1, + hours12: this.c.format.match( /[haA]/ ) !== null + } + }; + + this.dom.container + .append( this.dom.date ) + .append( this.dom.time ) + .append( this.dom.error ); + + this.dom.date + .append( this.dom.title ) + .append( this.dom.buttons ) + .append( this.dom.calendar ); + + this._constructor(); +}; + +$.extend( DateTime.prototype, { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public + */ + + /** + * Destroy the control + */ + destroy: function () { + this._hide(true); + this.dom.container.off().empty(); + this.dom.input + .removeAttr('autocomplete') + .off('.datetime'); + }, + + errorMsg: function ( msg ) { + var error = this.dom.error; + + if ( msg ) { + error.html( msg ); + } + else { + error.empty(); + } + + return this; + }, + + hide: function () { + this._hide(); + + return this; + }, + + max: function ( date ) { + this.c.maxDate = typeof date === 'string' + ? new Date(date) + : date; + + this._optionsTitle(); + this._setCalander(); + + return this; + }, + + min: function ( date ) { + this.c.minDate = typeof date === 'string' + ? new Date(date) + : date; + + this._optionsTitle(); + this._setCalander(); + + return this; + }, + + /** + * Check if an element belongs to this control + * + * @param {node} node Element to check + * @return {boolean} true if owned by this control, false otherwise + */ + owns: function ( node ) { + return $(node).parents().filter( this.dom.container ).length > 0; + }, + + /** + * Get / set the value + * + * @param {string|Date} set Value to set + * @param {boolean} [write=true] Flag to indicate if the formatted value + * should be written into the input element + */ + val: function ( set, write ) { + if ( set === undefined ) { + return this.s.d; + } + + if ( set instanceof Date ) { + this.s.d = this._dateToUtc( set ); + } + else if ( set === null || set === '' ) { + this.s.d = null; + } + else if ( set === '--now' ) { + this.s.d = this._dateToUtc(new Date()); + } + else if ( typeof set === 'string' ) { + this.s.d = this._dateToUtc( + this._convert(set, this.c.format, null) + ); + } + + if ( write || write === undefined ) { + if ( this.s.d ) { + this._writeOutput(); + } + else { + // The input value was not valid... + this.dom.input.val( set ); + } + } + + // Need something to display + this.s.display = this.s.d + ? new Date( this.s.d.toString() ) + : new Date(); + + // Set the day of the month to be 1 so changing between months doesn't + // run into issues when going from day 31 to 28 (for example) + this.s.display.setUTCDate( 1 ); + + // Update the display elements for the new value + this._setTitle(); + this._setCalander(); + this._setTime(); + + return this; + }, + + /** + * Similar to `val()` but uses a given date / time format + * + * @param format Format to get the data as (getter) or that is input (setter) + * @param val Value to write (if undefined, used as a getter) + * @returns + */ + valFormat: function (format, val) { + if (! val) { + return this._convert(this.val(), null, format); + } + + // Convert from the format given here to the instance's configured format + this.val( + this._convert(val, format, null) + ); + + return this; + }, + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Constructor + */ + + /** + * Build the control and assign initial event handlers + * + * @private + */ + _constructor: function () { + var that = this; + var classPrefix = this.c.classPrefix; + var last = this.dom.input.val(); + + var onChange = function () { + var curr = that.dom.input.val(); + + if (curr !== last) { + that.c.onChange.call( that, curr, that.s.d, that.dom.input ); + last = curr; + } + }; + + if ( ! this.s.parts.date ) { + this.dom.date.css( 'display', 'none' ); + } + + if ( ! this.s.parts.time ) { + this.dom.time.css( 'display', 'none' ); + } + + if ( ! this.s.parts.seconds ) { + this.dom.time.children('div.'+classPrefix+'-seconds').remove(); + this.dom.time.children('span').eq(1).remove(); + } + + if ( ! this.c.buttons.clear ) { + this.dom.clear.css( 'display', 'none' ); + } + + if ( ! this.c.buttons.today ) { + this.dom.today.css( 'display', 'none' ); + } + + // Render the options + this._optionsTitle(); + + $(document).on('i18n.dt', function (e, settings) { + if (settings.oLanguage.datetime) { + $.extend(true, that.c.i18n, settings.oLanguage.datetime); + that._optionsTitle(); + } + }); + + // When attached to a hidden input, we always show the input picker, and + // do so inline + if (this.dom.input.attr('type') === 'hidden') { + this.dom.container.addClass('inline'); + this.c.attachTo = 'input'; + + this.val( this.dom.input.val(), false ); + this._show(); + } + + // Set the initial value + if (last) { + this.val( last, false ); + } + + // Trigger the display of the widget when clicking or focusing on the + // input element + this.dom.input + .attr('autocomplete', 'off') + .on('focus.datetime click.datetime', function () { + // If already visible - don't do anything + if ( that.dom.container.is(':visible') || that.dom.input.is(':disabled') ) { + return; + } + + // In case the value has changed by text + that.val( that.dom.input.val(), false ); + + that._show(); + } ) + .on('keyup.datetime', function () { + // Update the calendar's displayed value as the user types + if ( that.dom.container.is(':visible') ) { + that.val( that.dom.input.val(), false ); + } + } ); + + // Main event handlers for input in the widget + this.dom.container + .on( 'change', 'select', function () { + var select = $(this); + var val = select.val(); + + if ( select.hasClass(classPrefix+'-month') ) { + // Month select + that._correctMonth( that.s.display, val ); + that._setTitle(); + that._setCalander(); + } + else if ( select.hasClass(classPrefix+'-year') ) { + // Year select + that.s.display.setUTCFullYear( val ); + that._setTitle(); + that._setCalander(); + } + else if ( select.hasClass(classPrefix+'-hours') || select.hasClass(classPrefix+'-ampm') ) { + // Hours - need to take account of AM/PM input if present + if ( that.s.parts.hours12 ) { + var hours = $(that.dom.container).find('.'+classPrefix+'-hours').val() * 1; + var pm = $(that.dom.container).find('.'+classPrefix+'-ampm').val() === 'pm'; + + that.s.d.setUTCHours( hours === 12 && !pm ? + 0 : + pm && hours !== 12 ? + hours + 12 : + hours + ); + } + else { + that.s.d.setUTCHours( val ); + } + + that._setTime(); + that._writeOutput( true ); + + onChange(); + } + else if ( select.hasClass(classPrefix+'-minutes') ) { + // Minutes select + that.s.d.setUTCMinutes( val ); + that._setTime(); + that._writeOutput( true ); + + onChange(); + } + else if ( select.hasClass(classPrefix+'-seconds') ) { + // Seconds select + that.s.d.setSeconds( val ); + that._setTime(); + that._writeOutput( true ); + + onChange(); + } + + that.dom.input.focus(); + that._position(); + } ) + .on( 'click', function (e) { + var d = that.s.d; + var nodeName = e.target.nodeName.toLowerCase(); + var target = nodeName === 'span' ? + e.target.parentNode : + e.target; + + nodeName = target.nodeName.toLowerCase(); + + if ( nodeName === 'select' ) { + return; + } + + e.stopPropagation(); + + if ( nodeName === 'a' ) { + e.preventDefault(); + + if ($(target).hasClass(classPrefix+'-clear')) { + // Clear the value and don't change the display + that.s.d = null; + that.dom.input.val(''); + that._writeOutput(); + that._setCalander(); + that._setTime(); + + onChange(); + } + else if ($(target).hasClass(classPrefix+'-today')) { + // Don't change the value, but jump to the month + // containing today + that.s.display = new Date(); + + that._setTitle(); + that._setCalander(); + } + } + if ( nodeName === 'button' ) { + var button = $(target); + var parent = button.parent(); + + if ( parent.hasClass('disabled') && ! parent.hasClass('range') ) { + button.blur(); + return; + } + + if ( parent.hasClass(classPrefix+'-iconLeft') ) { + // Previous month + that.s.display.setUTCMonth( that.s.display.getUTCMonth()-1 ); + that._setTitle(); + that._setCalander(); + + that.dom.input.focus(); + } + else if ( parent.hasClass(classPrefix+'-iconRight') ) { + // Next month + that._correctMonth( that.s.display, that.s.display.getUTCMonth()+1 ); + that._setTitle(); + that._setCalander(); + + that.dom.input.focus(); + } + else if ( button.parents('.'+classPrefix+'-time').length ) { + var val = button.data('value'); + var unit = button.data('unit'); + + d = that._needValue(); + + if ( unit === 'minutes' ) { + if ( parent.hasClass('disabled') && parent.hasClass('range') ) { + that.s.minutesRange = val; + that._setTime(); + return; + } + else { + that.s.minutesRange = null; + } + } + + if ( unit === 'seconds' ) { + if ( parent.hasClass('disabled') && parent.hasClass('range') ) { + that.s.secondsRange = val; + that._setTime(); + return; + } + else { + that.s.secondsRange = null; + } + } + + // Specific to hours for 12h clock + if ( val === 'am' ) { + if ( d.getUTCHours() >= 12 ) { + val = d.getUTCHours() - 12; + } + else { + return; + } + } + else if ( val === 'pm' ) { + if ( d.getUTCHours() < 12 ) { + val = d.getUTCHours() + 12; + } + else { + return; + } + } + + var set = unit === 'hours' ? + 'setUTCHours' : + unit === 'minutes' ? + 'setUTCMinutes' : + 'setSeconds'; + + d[set]( val ); + that._setCalander(); + that._setTime(); + that._writeOutput( true ); + onChange(); + } + else { + // Calendar click + d = that._needValue(); + + // Can't be certain that the current day will exist in + // the new month, and likewise don't know that the + // new day will exist in the old month, But 1 always + // does, so we can change the month without worry of a + // recalculation being done automatically by `Date` + d.setUTCDate( 1 ); + d.setUTCFullYear( button.data('year') ); + d.setUTCMonth( button.data('month') ); + d.setUTCDate( button.data('day') ); + + that._writeOutput( true ); + + // Don't hide if there is a time picker, since we want to + // be able to select a time as well. + if ( ! that.s.parts.time ) { + // This is annoying but IE has some kind of async + // behaviour with focus and the focus from the above + // write would occur after this hide - resulting in the + // calendar opening immediately + setTimeout( function () { + that._hide(); + }, 10 ); + } + else { + that._setCalander(); + that._setTime(); + } + + onChange(); + } + } + else { + // Click anywhere else in the widget - return focus to the + // input element + that.dom.input.focus(); + } + } ); + }, + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Private + */ + + /** + * Compare the date part only of two dates - this is made super easy by the + * toDateString method! + * + * @param {Date} a Date 1 + * @param {Date} b Date 2 + * @private + */ + _compareDates: function( a, b ) { + // Can't use toDateString as that converts to local time + // luxon uses different method names so need to be able to call them + return this._isLuxon() + ? dateLib.DateTime.fromJSDate(a).toUTC().toISODate() === dateLib.DateTime.fromJSDate(b).toUTC().toISODate() + : this._dateToUtcString(a) === this._dateToUtcString(b); + }, + + /** + * Convert from one format to another + * + * @param {string|Date} val Value + * @param {string|null} from Format to convert from. If null a `Date` must be given + * @param {string|null} to Format to convert to. If null a `Date` will be returned + * @returns {string|Date} Converted value + */ + _convert(val, from, to) { + if (! val) { + return val; + } + + if (! dateLib) { + // Note that in here from and to can either be null or YYYY-MM-DD + // They cannot be anything else + if ((! from && ! to) || (from && to)) { + // No conversion + return val; + } + else if (! from) { + // Date in, string back + return val.getUTCFullYear() +'-'+ + this._pad(val.getUTCMonth() + 1) +'-'+ + this._pad(val.getUTCDate()); + } + else { // (! to) + // String in, date back + var match = val.match(/(\d{4})\-(\d{2})\-(\d{2})/ ); + return match ? + new Date( match[1], match[2]-1, match[3] ) : + null; + } + } + else if (this._isLuxon()) { + // Luxon + var dtLux = val instanceof Date + ? dateLib.DateTime.fromJSDate(val).toUTC() + : dateLib.DateTime.fromFormat(val, from); + + if (! dtLux.isValid) { + return null; + } + + return to + ? dtLux.toFormat(to) + : dtLux.toJSDate(); + } + else { + // Moment / DayJS + var dtMo = val instanceof Date + ? dateLib.utc( val, undefined, this.c.locale, this.c.strict ) + : dateLib( val, from, this.c.locale, this.c.strict ); + + if (! dtMo.isValid()) { + return null; + } + + return to + ? dtMo.format(to) + : dtMo.toDate(); + } + }, + + /** + * When changing month, take account of the fact that some months don't have + * the same number of days. For example going from January to February you + * can have the 31st of Jan selected and just add a month since the date + * would still be 31, and thus drop you into March. + * + * @param {Date} date Date - will be modified + * @param {integer} month Month to set + * @private + */ + _correctMonth: function ( date, month ) { + var days = this._daysInMonth( date.getUTCFullYear(), month ); + var correctDays = date.getUTCDate() > days; + + date.setUTCMonth( month ); + + if ( correctDays ) { + date.setUTCDate( days ); + date.setUTCMonth( month ); + } + }, + + /** + * Get the number of days in a method. Based on + * http://stackoverflow.com/a/4881951 by Matti Virkkunen + * + * @param {integer} year Year + * @param {integer} month Month (starting at 0) + * @private + */ + _daysInMonth: function ( year, month ) { + // + var isLeap = ((year % 4) === 0 && ((year % 100) !== 0 || (year % 400) === 0)); + var months = [31, (isLeap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + + return months[month]; + }, + + /** + * Create a new date object which has the UTC values set to the local time. + * This allows the local time to be used directly for the library which + * always bases its calculations and display on UTC. + * + * @param {Date} s Date to "convert" + * @return {Date} Shifted date + */ + _dateToUtc: function ( s ) { + if (! s) { + return s; + } + + return new Date( Date.UTC( + s.getFullYear(), s.getMonth(), s.getDate(), + s.getHours(), s.getMinutes(), s.getSeconds() + ) ); + }, + + /** + * Create a UTC ISO8601 date part from a date object + * + * @param {Date} d Date to "convert" + * @return {string} ISO formatted date + */ + _dateToUtcString: function ( d ) { + // luxon uses different method names so need to be able to call them + return this._isLuxon() + ? dateLib.DateTime.fromJSDate(d).toUTC().toISODate() + : d.getUTCFullYear()+'-'+ + this._pad(d.getUTCMonth()+1)+'-'+ + this._pad(d.getUTCDate()); + }, + + /** + * Hide the control and remove events related to its display + * + * @private + */ + _hide: function (destroy) { + if (! destroy && this.dom.input.attr('type') === 'hidden') { + return; + } + + var namespace = this.s.namespace; + + this.dom.container.detach(); + + $(window).off( '.'+namespace ); + $(document).off( 'keydown.'+namespace ); + $('div.dataTables_scrollBody').off( 'scroll.'+namespace ); + $('div.DTE_Body_Content').off( 'scroll.'+namespace ); + $('body').off( 'click.'+namespace ); + $(this.dom.input[0].offsetParent).off('.'+namespace); + }, + + /** + * Convert a 24 hour value to a 12 hour value + * + * @param {integer} val 24 hour value + * @return {integer} 12 hour value + * @private + */ + _hours24To12: function ( val ) { + return val === 0 ? + 12 : + val > 12 ? + val - 12 : + val; + }, + + /** + * Generate the HTML for a single day in the calendar - this is basically + * and HTML cell with a button that has data attributes so we know what was + * clicked on (if it is clicked on) and a bunch of classes for styling. + * + * @param {object} day Day object from the `_htmlMonth` method + * @return {string} HTML cell + */ + _htmlDay: function( day ) + { + if ( day.empty ) { + return ''; + } + + var classes = [ 'selectable' ]; + var classPrefix = this.c.classPrefix; + + if ( day.disabled ) { + classes.push( 'disabled' ); + } + + if ( day.today ) { + classes.push( 'now' ); + } + + if ( day.selected ) { + classes.push( 'selected' ); + } + + return '' + + '' + + ''; + }, + + + /** + * Create the HTML for a month to be displayed in the calendar table. + * + * Based upon the logic used in Pikaday - MIT licensed + * Copyright (c) 2014 David Bushell + * https://github.com/dbushell/Pikaday + * + * @param {integer} year Year + * @param {integer} month Month (starting at 0) + * @return {string} Calendar month HTML + * @private + */ + _htmlMonth: function ( year, month ) { + var now = this._dateToUtc( new Date() ), + days = this._daysInMonth( year, month ), + before = new Date( Date.UTC(year, month, 1) ).getUTCDay(), + data = [], + row = []; + + if ( this.c.firstDay > 0 ) { + before -= this.c.firstDay; + + if (before < 0) { + before += 7; + } + } + + var cells = days + before, + after = cells; + + while ( after > 7 ) { + after -= 7; + } + + cells += 7 - after; + + var minDate = this.c.minDate; + var maxDate = this.c.maxDate; + + if ( minDate ) { + minDate.setUTCHours(0); + minDate.setUTCMinutes(0); + minDate.setSeconds(0); + } + + if ( maxDate ) { + maxDate.setUTCHours(23); + maxDate.setUTCMinutes(59); + maxDate.setSeconds(59); + } + + for ( var i=0, r=0 ; i= (days + before), + disabled = (minDate && day < minDate) || + (maxDate && day > maxDate); + + var disableDays = this.c.disableDays; + if ( Array.isArray( disableDays ) && $.inArray( day.getUTCDay(), disableDays ) !== -1 ) { + disabled = true; + } + else if ( typeof disableDays === 'function' && disableDays( day ) === true ) { + disabled = true; + } + + var dayConfig = { + day: 1 + (i - before), + month: month, + year: year, + selected: selected, + today: today, + disabled: disabled, + empty: empty + }; + + row.push( this._htmlDay(dayConfig) ); + + if ( ++r === 7 ) { + if ( this.c.showWeekNumber ) { + row.unshift( this._htmlWeekOfYear(i - before, month, year) ); + } + + data.push( ''+row.join('')+'' ); + row = []; + r = 0; + } + } + + var classPrefix = this.c.classPrefix; + var className = classPrefix+'-table'; + if ( this.c.showWeekNumber ) { + className += ' weekNumber'; + } + + // Show / hide month icons based on min/max + if ( minDate ) { + var underMin = minDate >= new Date( Date.UTC(year, month, 1, 0, 0, 0 ) ); + + this.dom.title.find('div.'+classPrefix+'-iconLeft') + .css( 'display', underMin ? 'none' : 'block' ); + } + + if ( maxDate ) { + var overMax = maxDate < new Date( Date.UTC(year, month+1, 1, 0, 0, 0 ) ); + + this.dom.title.find('div.'+classPrefix+'-iconRight') + .css( 'display', overMax ? 'none' : 'block' ); + } + + return '' + + ''+ + this._htmlMonthHead() + + ''+ + ''+ + data.join('') + + ''+ + '
'; + }, + + /** + * Create the calendar table's header (week days) + * + * @return {string} HTML cells for the row + * @private + */ + _htmlMonthHead: function () { + var a = []; + var firstDay = this.c.firstDay; + var i18n = this.c.i18n; + + // Take account of the first day shift + var dayName = function ( day ) { + day += firstDay; + + while (day >= 7) { + day -= 7; + } + + return i18n.weekdays[day]; + }; + + // Empty cell in the header + if ( this.c.showWeekNumber ) { + a.push( '' ); + } + + for ( var i=0 ; i<7 ; i++ ) { + a.push( ''+dayName( i )+'' ); + } + + return a.join(''); + }, + + /** + * Create a cell that contains week of the year - ISO8601 + * + * Based on https://stackoverflow.com/questions/6117814/ and + * http://techblog.procurios.nl/k/n618/news/view/33796/14863/ + * + * @param {integer} d Day of month + * @param {integer} m Month of year (zero index) + * @param {integer} y Year + * @return {string} + * @private + */ + _htmlWeekOfYear: function ( d, m, y ) { + var date = new Date( y, m, d, 0, 0, 0, 0 ); + + // First week of the year always has 4th January in it + date.setDate( date.getDate() + 4 - (date.getDay() || 7) ); + + var oneJan = new Date( y, 0, 1 ); + var weekNum = Math.ceil( ( ( (date - oneJan) / 86400000) + 1)/7 ); + + return '' + weekNum + ''; + }, + + /** + * Determine if Luxon is being used + * + * @returns Flag for Luxon + */ + _isLuxon: function () { + return dateLib && dateLib.DateTime && dateLib.Duration && dateLib.Settings + ? true + : false; + }, + + /** + * Check if the instance has a date object value - it might be null. + * If is doesn't set one to now. + * @returns A Date object + * @private + */ + _needValue: function () { + if ( ! this.s.d ) { + this.s.d = this._dateToUtc( new Date() ); + + if (! this.s.parts.time) { + this.s.d.setUTCHours(0); + this.s.d.setUTCMinutes(0); + this.s.d.setSeconds(0); + this.s.d.setMilliseconds(0); + } + } + + return this.s.d; + }, + + /** + * Create option elements from a range in an array + * + * @param {string} selector Class name unique to the select element to use + * @param {array} values Array of values + * @param {array} [labels] Array of labels. If given must be the same + * length as the values parameter. + * @private + */ + _options: function ( selector, values, labels ) { + if ( ! labels ) { + labels = values; + } + + var select = this.dom.container.find('select.'+this.c.classPrefix+'-'+selector); + select.empty(); + + for ( var i=0, ien=values.length ; i'+labels[i]+'' ); + } + }, + + /** + * Set an option and update the option's span pair (since the select element + * has opacity 0 for styling) + * + * @param {string} selector Class name unique to the select element to use + * @param {*} val Value to set + * @private + */ + _optionSet: function ( selector, val ) { + var select = this.dom.container.find('select.'+this.c.classPrefix+'-'+selector); + var span = select.parent().children('span'); + + select.val( val ); + + var selected = select.find('option:selected'); + span.html( selected.length !== 0 ? + selected.text() : + this.c.i18n.unknown + ); + }, + + /** + * Create time options list. + * + * @param {string} unit Time unit - hours, minutes or seconds + * @param {integer} count Count range - 12, 24 or 60 + * @param {integer} val Existing value for this unit + * @param {integer[]} allowed Values allow for selection + * @param {integer} range Override range + * @private + */ + _optionsTime: function ( unit, count, val, allowed, range ) { + var classPrefix = this.c.classPrefix; + var container = this.dom.container.find('div.'+classPrefix+'-'+unit); + var i, j; + var render = count === 12 ? + function (i) { return i; } : + this._pad; + var classPrefix = this.c.classPrefix; + var className = classPrefix+'-table'; + var i18n = this.c.i18n; + + if ( ! container.length ) { + return; + } + + var a = ''; + var span = 10; + var button = function (value, label, className) { + // Shift the value for PM + if ( count === 12 && typeof value === 'number' ) { + if (val >= 12 ) { + value += 12; + } + + if (value == 12) { + value = 0; + } + else if (value == 24) { + value = 12; + } + } + + var selected = val === value || (value === 'am' && val < 12) || (value === 'pm' && val >= 12) ? + 'selected' : + ''; + + if (typeof value === 'number' && allowed && $.inArray(value, allowed) === -1) { + selected += ' disabled'; + } + + if ( className ) { + selected += ' '+className; + } + + return '' + + '' + + ''; + } + + if ( count === 12 ) { + // Hours with AM/PM + a += ''; + + for ( i=1 ; i<=6 ; i++ ) { + a += button(i, render(i)); + } + a += button('am', i18n.amPm[0]); + + a += ''; + a += ''; + + for ( i=7 ; i<=12 ; i++ ) { + a += button(i, render(i)); + } + a += button('pm', i18n.amPm[1]); + a += ''; + + span = 7; + } + else if ( count === 24 ) { + // Hours - 24 + var c = 0; + for (j=0 ; j<4 ; j++ ) { + a += ''; + for ( i=0 ; i<6 ; i++ ) { + a += button(c, render(c)); + c++; + } + a += ''; + } + + span = 6; + } + else { + // Minutes and seconds + a += ''; + for (j=0 ; j<60 ; j+=10 ) { + a += button(j, render(j), 'range'); + } + a += ''; + + // Slight hack to allow for the different number of columns + a += ''; + + var start = range !== null + ? range + : val === -1 + ? 0 + : Math.floor( val / 10 )*10; + + a += ''; + for (j=start+1 ; j'+ + ''+ + ''+ + a+ + ''+ + '
'+ + i18n[unit] + + '
' + ); + }, + + /** + * Create the options for the month and year + * + * @param {integer} year Year + * @param {integer} month Month (starting at 0) + * @private + */ + _optionsTitle: function () { + var i18n = this.c.i18n; + var min = this.c.minDate; + var max = this.c.maxDate; + var minYear = min ? min.getFullYear() : null; + var maxYear = max ? max.getFullYear() : null; + + var i = minYear !== null ? minYear : new Date().getFullYear() - this.c.yearRange; + var j = maxYear !== null ? maxYear : new Date().getFullYear() + this.c.yearRange; + + this._options( 'month', this._range( 0, 11 ), i18n.months ); + this._options( 'year', this._range( i, j ) ); + + // Set the language strings in case any have changed + this.dom.today.text(i18n.today).text(i18n.today); + this.dom.clear.text(i18n.clear).text(i18n.clear); + this.dom.previous + .attr('title', i18n.previous) + .children('button') + .text(i18n.previous); + this.dom.next + .attr('title', i18n.next) + .children('button') + .text(i18n.next); + }, + + /** + * Simple two digit pad + * + * @param {integer} i Value that might need padding + * @return {string|integer} Padded value + * @private + */ + _pad: function ( i ) { + return i<10 ? '0'+i : i; + }, + + /** + * Position the calendar to look attached to the input element + * @private + */ + _position: function () { + var offset = this.c.attachTo === 'input' ? this.dom.input.position() : this.dom.input.offset(); + var container = this.dom.container; + var inputHeight = this.dom.input.outerHeight(); + + if (container.hasClass('inline')) { + container.insertAfter( this.dom.input ); + return; + } + + if ( this.s.parts.date && this.s.parts.time && $(window).width() > 550 ) { + container.addClass('horizontal'); + } + else { + container.removeClass('horizontal'); + } + + if(this.c.attachTo === 'input') { + container + .css( { + top: offset.top + inputHeight, + left: offset.left + } ) + .insertAfter( this.dom.input ); + } + else { + container + .css( { + top: offset.top + inputHeight, + left: offset.left + } ) + .appendTo( 'body' ); + } + + var calHeight = container.outerHeight(); + var calWidth = container.outerWidth(); + var scrollTop = $(window).scrollTop(); + + // Correct to the bottom + if ( offset.top + inputHeight + calHeight - scrollTop > $(window).height() ) { + var newTop = offset.top - calHeight; + + container.css( 'top', newTop < 0 ? 0 : newTop ); + } + + // Correct to the right + if ( calWidth + offset.left > $(window).width() ) { + var newLeft = $(window).width() - calWidth; + + // Account for elements which are inside a position absolute element + if (this.c.attachTo === 'input') { + newLeft -= $(container).offsetParent().offset().left; + } + + container.css( 'left', newLeft < 0 ? 0 : newLeft ); + } + }, + + /** + * Create a simple array with a range of values + * + * @param {integer} start Start value (inclusive) + * @param {integer} end End value (inclusive) + * @param {integer} [inc=1] Increment value + * @return {array} Created array + * @private + */ + _range: function ( start, end, inc ) { + var a = []; + + if ( ! inc ) { + inc = 1; + } + + for ( var i=start ; i<=end ; i+=inc ) { + a.push( i ); + } + + return a; + }, + + /** + * Redraw the calendar based on the display date - this is a destructive + * operation + * + * @private + */ + _setCalander: function () { + if ( this.s.display ) { + this.dom.calendar + .empty() + .append( this._htmlMonth( + this.s.display.getUTCFullYear(), + this.s.display.getUTCMonth() + ) ); + } + }, + + /** + * Set the month and year for the calendar based on the current display date + * + * @private + */ + _setTitle: function () { + this._optionSet( 'month', this.s.display.getUTCMonth() ); + this._optionSet( 'year', this.s.display.getUTCFullYear() ); + }, + + /** + * Set the time based on the current value of the widget + * + * @private + */ + _setTime: function () { + var that = this; + var d = this.s.d; + + // luxon uses different method names so need to be able to call them. This happens a few time later in this method too + var luxDT = null + if (this._isLuxon()) { + luxDT = dateLib.DateTime.fromJSDate(d).toUTC(); + } + + var hours = luxDT != null + ? luxDT.hour + : d + ? d.getUTCHours() + : -1; + + var allowed = function ( prop ) { // Backwards compt with `Increment` option + return that.c[prop+'Available'] ? + that.c[prop+'Available'] : + that._range( 0, 59, that.c[prop+'Increment'] ); + } + + this._optionsTime( 'hours', this.s.parts.hours12 ? 12 : 24, hours, this.c.hoursAvailable ) + this._optionsTime( + 'minutes', + 60, + luxDT != null + ? luxDT.minute + : d + ? d.getUTCMinutes() + : -1, + allowed('minutes'), + this.s.minutesRange + ); + this._optionsTime( + 'seconds', + 60, + luxDT != null + ? luxDT.second + : d + ? d.getSeconds() + : -1, + allowed('seconds'), + this.s.secondsRange + ); + }, + + /** + * Show the widget and add events to the document required only while it + * is displayed + * + * @private + */ + _show: function () { + var that = this; + var namespace = this.s.namespace; + + this._position(); + + // Need to reposition on scroll + $(window).on( 'scroll.'+namespace+' resize.'+namespace, function () { + that._position(); + } ); + + $('div.DTE_Body_Content').on( 'scroll.'+namespace, function () { + that._position(); + } ); + + $('div.dataTables_scrollBody').on( 'scroll.'+namespace, function () { + that._position(); + } ); + + var offsetParent = this.dom.input[0].offsetParent; + + if ( offsetParent !== document.body ) { + $(offsetParent).on( 'scroll.'+namespace, function () { + that._position(); + } ); + } + + // On tab focus will move to a different field (no keyboard navigation + // in the date picker - this might need to be changed). + $(document).on( 'keydown.'+namespace, function (e) { + if ( + e.keyCode === 9 || // tab + e.keyCode === 27 || // esc + e.keyCode === 13 // return + ) { + that._hide(); + } + } ); + + // Hide if clicking outside of the widget - but in a different click + // event from the one that was used to trigger the show (bubble and + // inline) + setTimeout( function () { + $('body').on( 'click.'+namespace, function (e) { + var parents = $(e.target).parents(); + + if ( ! parents.filter( that.dom.container ).length && e.target !== that.dom.input[0] ) { + that._hide(); + } + } ); + }, 10 ); + }, + + /** + * Write the formatted string to the input element this control is attached + * to + * + * @private + */ + _writeOutput: function ( focus ) { + var date = this.s.d; + var out = ''; + + if (date) { + out = this._convert(date, null, this.c.format); + } + + this.dom.input + .val( out ) + .trigger('change', {write: date}); + + if ( this.dom.input.attr('type') === 'hidden' ) { + this.val(out, false); + } + + if ( focus ) { + this.dom.input.focus(); + } + } +} ); + +/** + * Use a specificmoment compatible date library + */ +DateTime.use = function (lib) { + dateLib = lib; +}; + +/** + * For generating unique namespaces + * + * @type {Number} + * @private + */ +DateTime._instance = 0; + +/** + * Defaults for the date time picker + * + * @type {Object} + */ +DateTime.defaults = { + attachTo: 'body', + + buttons: { + clear: false, + today: false + }, + + // Not documented - could be an internal property + classPrefix: 'dt-datetime', + + // function or array of ints + disableDays: null, + + // first day of the week (0: Sunday, 1: Monday, etc) + firstDay: 1, + + format: 'YYYY-MM-DD', + + hoursAvailable: null, + + i18n: { + clear: 'Clear', + previous: 'Previous', + next: 'Next', + months: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ], + weekdays: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ], + amPm: [ 'am', 'pm' ], + hours: 'Hour', + minutes: 'Minute', + seconds: 'Second', + unknown: '-', + today: 'Today' + }, + + maxDate: null, + + minDate: null, + + minutesAvailable: null, + + minutesIncrement: 1, // deprecated + + strict: true, + + locale: 'en', + + onChange: function () {}, + + secondsAvailable: null, + + secondsIncrement: 1, // deprecated + + // show the ISO week number at the head of the row + showWeekNumber: false, + + // overruled by max / min date + yearRange: 25 +}; + +DateTime.version = '1.4.0'; + +/** + * CommonJS factory function pass through. Matches DataTables. + * @param {*} root Window + * @param {*} jq jQUery + * @returns {boolean} Indicator + */ +DateTime.factory = function (root, jq) { + var is = false; + + // Test if the first parameter is a window object + if (root && root.document) { + window = root; + document = root.document; + } + + // Test if the second parameter is a jQuery object + if (jq && jq.fn && jq.fn.jquery) { + $ = jq; + is = true; + } + + return is; +} + +// Global export - if no conflicts +if (! window.DateTime) { + window.DateTime = DateTime; +} + +// Global DataTable +if (window.DataTable) { + window.DataTable.DateTime = DateTime; +} + +// Make available via jQuery +$.fn.dtDateTime = function (options) { + return this.each(function() { + new DateTime(this, options); + }); +} + +// Attach to DataTables if present +if ($.fn.dataTable) { + $.fn.dataTable.DateTime = DateTime; + $.fn.DataTable.DateTime = DateTime; + + if ($.fn.dataTable.Editor) { + $.fn.dataTable.Editor.DateTime = DateTime; + } +} + + +return DateTime; +})); diff --git a/public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.min.js b/public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.min.js new file mode 100644 index 0000000..4f83e33 --- /dev/null +++ b/public/assets/js/DataTables/DateTime-1.4.0/js/dataTables.dateTime.min.js @@ -0,0 +1,6 @@ +/*! DateTime picker for DataTables.net v1.4.0 + * + * © SpryMedia Ltd, all rights reserved. + * License: MIT datatables.net/license/mit + */ +!function(s){var i;"function"==typeof define&&define.amd?define(["jquery"],function(t){return s(t,window,document)}):"object"==typeof exports?(i=require("jquery"),"undefined"!=typeof window?module.exports=function(t,e){return t=t||window,e=e||i(t),s(e,t,t.document)}:(window,module.exports=s(i,window,window.document))):s(jQuery,window,document)}(function(C,o,i,n){"use strict";function a(t,e){if(a.factory(t,e))return a;if(void 0===r&&(r=o.moment||o.dayjs||o.luxon||null),this.c=C.extend(!0,{},a.defaults,e),e=this.c.classPrefix,this.c.i18n,!r&&"YYYY-MM-DD"!==this.c.format)throw"DateTime: Without momentjs, dayjs or luxon only the format 'YYYY-MM-DD' can be used";"string"==typeof this.c.minDate&&(this.c.minDate=new Date(this.c.minDate)),"string"==typeof this.c.maxDate&&(this.c.maxDate=new Date(this.c.maxDate));var s=C('
');this.dom={container:s,date:s.find("."+e+"-date"),title:s.find("."+e+"-title"),calendar:s.find("."+e+"-calendar"),time:s.find("."+e+"-time"),error:s.find("."+e+"-error"),buttons:s.find("."+e+"-buttons"),clear:s.find("."+e+"-clear"),today:s.find("."+e+"-today"),previous:s.find("."+e+"-iconLeft"),next:s.find("."+e+"-iconRight"),input:C(t)},this.s={d:null,display:null,minutesRange:null,secondsRange:null,namespace:"dateime-"+a._instance++,parts:{date:null!==this.c.format.match(/[YMD]|L(?!T)|l/),time:null!==this.c.format.match(/[Hhm]|LT|LTS/),seconds:-1!==this.c.format.indexOf("s"),hours12:null!==this.c.format.match(/[haA]/)}},this.dom.container.append(this.dom.date).append(this.dom.time).append(this.dom.error),this.dom.date.append(this.dom.title).append(this.dom.buttons).append(this.dom.calendar),this._constructor()}var r;return C.extend(a.prototype,{destroy:function(){this._hide(!0),this.dom.container.off().empty(),this.dom.input.removeAttr("autocomplete").off(".datetime")},errorMsg:function(t){var e=this.dom.error;return t?e.html(t):e.empty(),this},hide:function(){return this._hide(),this},max:function(t){return this.c.maxDate="string"==typeof t?new Date(t):t,this._optionsTitle(),this._setCalander(),this},min:function(t){return this.c.minDate="string"==typeof t?new Date(t):t,this._optionsTitle(),this._setCalander(),this},owns:function(t){return 0s;t.setUTCMonth(e),i&&(t.setUTCDate(s),t.setUTCMonth(e))},_daysInMonth:function(t,e){return[31,t%4==0&&(t%100!=0||t%400==0)?29:28,31,30,31,30,31,31,30,31,30,31][e]},_dateToUtc:function(t){return t&&new Date(Date.UTC(t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),t.getMinutes(),t.getSeconds()))},_dateToUtcString:function(t){return this._isLuxon()?r.DateTime.fromJSDate(t).toUTC().toISODate():t.getUTCFullYear()+"-"+this._pad(t.getUTCMonth()+1)+"-"+this._pad(t.getUTCDate())},_hide:function(t){!t&&"hidden"===this.dom.input.attr("type")||(t=this.s.namespace,this.dom.container.detach(),C(o).off("."+t),C(i).off("keydown."+t),C("div.dataTables_scrollBody").off("scroll."+t),C("div.DTE_Body_Content").off("scroll."+t),C("body").off("click."+t),C(this.dom.input[0].offsetParent).off("."+t))},_hours24To12:function(t){return 0===t?12:12':(e=["selectable"],s=this.c.classPrefix,t.disabled&&e.push("disabled"),t.today&&e.push("now"),t.selected&&e.push("selected"),'")},_htmlMonth:function(t,e){for(var s=this._dateToUtc(new Date),i=this._daysInMonth(t,e),n=new Date(Date.UTC(t,e,1)).getUTCDay(),a=[],o=[],r=(0"+o.join("")+""),o=[],u=0)}var v,D=this.c.classPrefix,g=D+"-table";return this.c.showWeekNumber&&(g+=" weekNumber"),l&&(v=l>=new Date(Date.UTC(t,e,1,0,0,0)),this.dom.title.find("div."+D+"-iconLeft").css("display",v?"none":"block")),h&&(v=h'+this._htmlMonthHead()+""+a.join("")+""},_htmlMonthHead:function(){var t=[],e=this.c.firstDay,s=this.c.i18n;this.c.showWeekNumber&&t.push("");for(var i=0;i<7;i++)t.push(""+function(t){for(t+=e;7<=t;)t-=7;return s.weekdays[t]}(i)+"");return t.join("")},_htmlWeekOfYear:function(t,e,s){e=new Date(s,e,t,0,0,0,0),e.setDate(e.getDate()+4-(e.getDay()||7)),t=new Date(s,0,1),s=Math.ceil(((e-t)/864e5+1)/7);return''+s+""},_isLuxon:function(){return!!(r&&r.DateTime&&r.Duration&&r.Settings)},_needValue:function(){return this.s.d||(this.s.d=this._dateToUtc(new Date),this.s.parts.time)||(this.s.d.setUTCHours(0),this.s.d.setUTCMinutes(0),this.s.d.setSeconds(0),this.s.d.setMilliseconds(0)),this.s.d},_options:function(t,e,s){s=s||e;var i=this.dom.container.find("select."+this.c.classPrefix+"-"+t);i.empty();for(var n=0,a=e.length;n'+s[n]+"")},_optionSet:function(t,e){var t=this.dom.container.find("select."+this.c.classPrefix+"-"+t),s=t.parent().children("span"),e=(t.val(e),t.find("option:selected"));s.html(0!==e.length?e.text():this.c.i18n.unknown)},_optionsTime:function(n,a,o,r,t){var e,d=this.c.classPrefix,s=this.dom.container.find("div."+d+"-"+n),i=12===a?function(t){return t}:this._pad,l=(d=this.c.classPrefix)+"-table",h=this.c.i18n;if(s.length){var c="",u=10,m=function(t,e,s){12===a&&"number"==typeof t&&(12<=o&&(t+=12),12==t?t=0:24==t&&(t=12));var i=o===t||"am"===t&&o<12||"pm"===t&&12<=o?"selected":"";return"number"==typeof t&&r&&-1===C.inArray(t,r)&&(i+=" disabled"),s&&(i+=" "+s),'"};if(12===a){for(c+="",e=1;e<=6;e++)c+=m(e,i(e));for(c=(c+=m("am",h.amPm[0]))+""+"",e=7;e<=12;e++)c+=m(e,i(e));c=c+m("pm",h.amPm[1])+"",u=7}else{if(24===a)for(var f=0,p=0;p<4;p++){for(c+="",e=0;e<6;e++)c+=m(f,i(f)),f++;c+=""}else{for(c+="",p=0;p<60;p+=10)c+=m(p,i(p),"range");var c=c+""+(''),y=null!==t?t:-1===o?0:10*Math.floor(o/10);for(c+="",p=y+1;p"}u=6}s.empty().append('
"+c+"
'+h[n]+"
")}},_optionsTitle:function(){var t=this.c.i18n,e=this.c.minDate,s=this.c.maxDate,e=e?e.getFullYear():null,s=s?s.getFullYear():null,e=null!==e?e:(new Date).getFullYear()-this.c.yearRange,s=null!==s?s:(new Date).getFullYear()+this.c.yearRange;this._options("month",this._range(0,11),t.months),this._options("year",this._range(e,s)),this.dom.today.text(t.today).text(t.today),this.dom.clear.text(t.clear).text(t.clear),this.dom.previous.attr("title",t.previous).children("button").text(t.previous),this.dom.next.attr("title",t.next).children("button").text(t.next)},_pad:function(t){return t<10?"0"+t:t},_position:function(){var t,e,s,i="input"===this.c.attachTo?this.dom.input.position():this.dom.input.offset(),n=this.dom.container,a=this.dom.input.outerHeight();n.hasClass("inline")?n.insertAfter(this.dom.input):(this.s.parts.date&&this.s.parts.time&&550C(o).height()&&(a=i.top-t,n.css("top",a<0?0:a)),e+i.left>C(o).width()&&(s=C(o).width()-e,"input"===this.c.attachTo&&(s-=C(n).offsetParent().offset().left),n.css("left",s<0?0:s)))},_range:function(t,e,s){var i=[];s=s||1;for(var n=t;n<=e;n+=s)i.push(n);return i},_setCalander:function(){this.s.display&&this.dom.calendar.empty().append(this._htmlMonth(this.s.display.getUTCFullYear(),this.s.display.getUTCMonth()))},_setTitle:function(){this._optionSet("month",this.s.display.getUTCMonth()),this._optionSet("year",this.s.display.getUTCFullYear())},_setTime:function(){function t(t){return e.c[t+"Available"]||e._range(0,59,e.c[t+"Increment"])}var e=this,s=this.s.d,i=null,n=null!=(i=this._isLuxon()?r.DateTime.fromJSDate(s).toUTC():i)?i.hour:s?s.getUTCHours():-1;this._optionsTime("hours",this.s.parts.hours12?12:24,n,this.c.hoursAvailable),this._optionsTime("minutes",60,null!=i?i.minute:s?s.getUTCMinutes():-1,t("minutes"),this.s.minutesRange),this._optionsTime("seconds",60,null!=i?i.second:s?s.getSeconds():-1,t("seconds"),this.s.secondsRange)},_show:function(){var e=this,t=this.s.namespace,s=(this._position(),C(o).on("scroll."+t+" resize."+t,function(){e._position()}),C("div.DTE_Body_Content").on("scroll."+t,function(){e._position()}),C("div.dataTables_scrollBody").on("scroll."+t,function(){e._position()}),this.dom.input[0].offsetParent);s!==i.body&&C(s).on("scroll."+t,function(){e._position()}),C(i).on("keydown."+t,function(t){9!==t.keyCode&&27!==t.keyCode&&13!==t.keyCode||e._hide()}),setTimeout(function(){C("body").on("click."+t,function(t){C(t.target).parents().filter(e.dom.container).length||t.target===e.dom.input[0]||e._hide()})},10)},_writeOutput:function(t){var e=this.s.d,s="";e&&(s=this._convert(e,null,this.c.format)),this.dom.input.val(s).trigger("change",{write:e}),"hidden"===this.dom.input.attr("type")&&this.val(s,!1),t&&this.dom.input.focus()}}),a.use=function(t){r=t},a._instance=0,a.defaults={attachTo:"body",buttons:{clear:!1,today:!1},classPrefix:"dt-datetime",disableDays:null,firstDay:1,format:"YYYY-MM-DD",hoursAvailable:null,i18n:{clear:"Clear",previous:"Previous",next:"Next",months:["January","February","March","April","May","June","July","August","September","October","November","December"],weekdays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],amPm:["am","pm"],hours:"Hour",minutes:"Minute",seconds:"Second",unknown:"-",today:"Today"},maxDate:null,minDate:null,minutesAvailable:null,minutesIncrement:1,strict:!0,locale:"en",onChange:function(){},secondsAvailable:null,secondsIncrement:1,showWeekNumber:!1,yearRange:25},a.version="1.4.0",a.factory=function(t,e){var s=!1;return t&&t.document&&(i=(o=t).document),e&&e.fn&&e.fn.jquery&&(C=e,s=!0),s},o.DateTime||(o.DateTime=a),o.DataTable&&(o.DataTable.DateTime=a),C.fn.dtDateTime=function(t){return this.each(function(){new a(this,t)})},C.fn.dataTable&&(C.fn.dataTable.DateTime=a,C.fn.DataTable.DateTime=a,C.fn.dataTable.Editor)&&(C.fn.dataTable.Editor.DateTime=a),a}); \ No newline at end of file -- cgit v1.2.3