1676 lines
44 KiB
JavaScript
Executable File
1676 lines
44 KiB
JavaScript
Executable File
/*!
|
|
* Picker.js v1.2.0
|
|
* https://fengyuanchen.github.io/pickerjs
|
|
*
|
|
* Copyright 2016-present Chen Fengyuan
|
|
* Released under the MIT license
|
|
*
|
|
* Date: 2018-12-16T14:10:26.813Z
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
function _typeof(obj) {
|
|
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
_typeof = function (obj) {
|
|
return typeof obj;
|
|
};
|
|
} else {
|
|
_typeof = function (obj) {
|
|
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
};
|
|
}
|
|
|
|
return _typeof(obj);
|
|
}
|
|
|
|
function _classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
}
|
|
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ("value" in descriptor) descriptor.writable = true;
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
|
|
function _toConsumableArray(arr) {
|
|
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
|
|
}
|
|
|
|
function _arrayWithoutHoles(arr) {
|
|
if (Array.isArray(arr)) {
|
|
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
|
|
|
|
return arr2;
|
|
}
|
|
}
|
|
|
|
function _iterableToArray(iter) {
|
|
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
|
|
}
|
|
|
|
function _nonIterableSpread() {
|
|
throw new TypeError("Invalid attempt to spread non-iterable instance");
|
|
}
|
|
|
|
var DEFAULTS = {
|
|
// Define the container for putting the picker.
|
|
container: null,
|
|
// Indicate whether show the prev and next arrow controls on each column.
|
|
controls: false,
|
|
// The initial date. If not present, use the current date.
|
|
date: null,
|
|
// The date string format, also as the sorting order for columns.
|
|
format: 'YYYY-MM-DD HH:mm',
|
|
// Indicate whether show the column headers.
|
|
headers: false,
|
|
// Define the increment for each date / time part.
|
|
increment: 1,
|
|
// Enable inline mode.
|
|
inline: false,
|
|
// Define the language. (An ISO language code).
|
|
language: '',
|
|
// Months' name.
|
|
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
|
// Shorter months' name.
|
|
monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
// Define the number of rows for showing.
|
|
rows: 5,
|
|
// Define the text of the picker.
|
|
text: {
|
|
title: 'Pick a date and time',
|
|
cancel: 'Cancel',
|
|
confirm: 'OK',
|
|
year: 'Year',
|
|
month: 'Month',
|
|
day: 'Day',
|
|
hour: 'Hour',
|
|
minute: 'Minute',
|
|
second: 'Second',
|
|
millisecond: 'Millisecond'
|
|
},
|
|
// Translate date / time text.
|
|
translate: function translate(type, text) {
|
|
return text;
|
|
},
|
|
// Shortcuts of custom events.
|
|
show: null,
|
|
shown: null,
|
|
hide: null,
|
|
hidden: null,
|
|
pick: null
|
|
};
|
|
|
|
var TEMPLATE = '<div class="picker" data-picker-action="hide" touch-action="none" tabindex="-1" role="dialog">' + '<div class="picker-dialog" role="document">' + '<div class="picker-header">' + '<h4 class="picker-title">{{ title }}</h4>' + '<button type="button" class="picker-close" data-picker-action="hide" aria-label="Close">×</button>' + '</div>' + '<div class="picker-body">' + '<div class="picker-grid"></div>' + '</div>' + '<div class="picker-footer">' + '<button type="button" class="picker-cancel" data-picker-action="hide">{{ cancel }}</button>' + '<button type="button" class="picker-confirm" data-picker-action="pick">{{ confirm }}</button>' + '</div>' + '</div>' + '</div>';
|
|
|
|
var IS_BROWSER = typeof window !== 'undefined';
|
|
var WINDOW = IS_BROWSER ? window : {};
|
|
var IS_TOUCH_DEVICE = IS_BROWSER ? 'ontouchstart' in WINDOW.document.documentElement : false;
|
|
var HAS_POINTER_EVENT = IS_BROWSER ? 'PointerEvent' in WINDOW : false;
|
|
var NAMESPACE = 'picker';
|
|
var LANGUAGES = {}; // Actions
|
|
|
|
var ACTION_HIDE = 'hide';
|
|
var ACTION_NEXT = 'next';
|
|
var ACTION_PICK = 'pick';
|
|
var ACTION_PREV = 'prev'; // Classes
|
|
|
|
var CLASS_OPEN = "".concat(NAMESPACE, "-open");
|
|
var CLASS_OPENED = "".concat(NAMESPACE, "-opened");
|
|
var CLASS_PICKED = "".concat(NAMESPACE, "-picked"); // Data keys
|
|
// Add namespace to avoid to conflict to some other libraries.
|
|
|
|
var DATA_ACTION = "".concat(NAMESPACE, "Action");
|
|
var DATA_TOKEN = 'token';
|
|
var DATA_TYPE = 'type';
|
|
var DATA_NAME = 'name';
|
|
var DATA_VALUE = 'value'; // Events
|
|
|
|
var EVENT_CLICK = 'click';
|
|
var EVENT_FOCUS = 'focus';
|
|
var EVENT_HIDDEN = 'hidden';
|
|
var EVENT_HIDE = 'hide';
|
|
var EVENT_KEY_DOWN = 'keydown';
|
|
var EVENT_PICK = 'pick';
|
|
var EVENT_TOUCH_START = IS_TOUCH_DEVICE ? 'touchstart' : 'mousedown';
|
|
var EVENT_TOUCH_MOVE = IS_TOUCH_DEVICE ? 'touchmove' : 'mousemove';
|
|
var EVENT_TOUCH_END = IS_TOUCH_DEVICE ? 'touchend touchcancel' : 'mouseup';
|
|
var EVENT_POINTER_DOWN = HAS_POINTER_EVENT ? 'pointerdown' : EVENT_TOUCH_START;
|
|
var EVENT_POINTER_MOVE = HAS_POINTER_EVENT ? 'pointermove' : EVENT_TOUCH_MOVE;
|
|
var EVENT_POINTER_UP = HAS_POINTER_EVENT ? 'pointerup pointercancel' : EVENT_TOUCH_END;
|
|
var EVENT_SHOW = 'show';
|
|
var EVENT_SHOWN = 'shown';
|
|
var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll';
|
|
|
|
var _Object$prototype = Object.prototype,
|
|
hasOwnProperty = _Object$prototype.hasOwnProperty,
|
|
toString = _Object$prototype.toString;
|
|
/**
|
|
* Detect the type of the given value.
|
|
* @param {*} value - The value to detect.
|
|
* @returns {string} Returns the type.
|
|
*/
|
|
|
|
function typeOf(value) {
|
|
return toString.call(value).slice(8, -1).toLowerCase();
|
|
}
|
|
/**
|
|
* Check if the given value is a string.
|
|
* @param {*} value - The value to check.
|
|
* @returns {boolean} Returns `true` if the given value is a string, else `false`.
|
|
*/
|
|
|
|
function isString(value) {
|
|
return typeof value === 'string';
|
|
}
|
|
/**
|
|
* Check if the given value is finite.
|
|
*/
|
|
|
|
var isFinite = Number.isFinite || WINDOW.isFinite;
|
|
/**
|
|
* Check if the given value is not a number.
|
|
*/
|
|
|
|
var isNaN = Number.isNaN || WINDOW.isNaN;
|
|
/**
|
|
* Check if the given value is a number.
|
|
* @param {*} value - The value to check.
|
|
* @returns {boolean} Returns `true` if the given value is a number, else `false`.
|
|
*/
|
|
|
|
function isNumber(value) {
|
|
return typeof value === 'number' && !isNaN(value);
|
|
}
|
|
/**
|
|
* Check if the given value is an object.
|
|
* @param {*} value - The value to check.
|
|
* @returns {boolean} Returns `true` if the given value is an object, else `false`.
|
|
*/
|
|
|
|
function isObject(value) {
|
|
return _typeof(value) === 'object' && value !== null;
|
|
}
|
|
/**
|
|
* Check if the given value is a plain object.
|
|
* @param {*} value - The value to check.
|
|
* @returns {boolean} Returns `true` if the given value is a plain object, else `false`.
|
|
*/
|
|
|
|
function isPlainObject(value) {
|
|
if (!isObject(value)) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
var _constructor = value.constructor;
|
|
var prototype = _constructor.prototype;
|
|
return _constructor && prototype && hasOwnProperty.call(prototype, 'isPrototypeOf');
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
}
|
|
/**
|
|
* Check if the given value is a function.
|
|
* @param {*} value - The value to check.
|
|
* @returns {boolean} Returns `true` if the given value is a function, else `false`.
|
|
*/
|
|
|
|
function isFunction(value) {
|
|
return typeof value === 'function';
|
|
}
|
|
/**
|
|
* Check if the given value is a date.
|
|
* @param {*} value - The value to check.
|
|
* @returns {boolean} Returns `true` if the given value is a date, else `false`.
|
|
*/
|
|
|
|
function isDate(value) {
|
|
return typeOf(value) === 'date';
|
|
}
|
|
/**
|
|
* Check if the given value is a valid date.
|
|
* @param {*} value - The value to check.
|
|
* @returns {boolean} Returns `true` if the given value is a valid date, else `false`.
|
|
*/
|
|
|
|
function isValidDate(value) {
|
|
return isDate(value) && value.toString() !== 'Invalid Date';
|
|
}
|
|
/**
|
|
* Iterate the given data.
|
|
* @param {*} data - The data to iterate.
|
|
* @param {Function} callback - The process function for each element.
|
|
* @returns {*} The original data.
|
|
*/
|
|
|
|
function forEach(data, callback) {
|
|
if (data && isFunction(callback)) {
|
|
if (Array.isArray(data) || isNumber(data.length)
|
|
/* array-like */
|
|
) {
|
|
var length = data.length;
|
|
var i;
|
|
|
|
for (i = 0; i < length; i += 1) {
|
|
if (callback.call(data, data[i], i, data) === false) {
|
|
break;
|
|
}
|
|
}
|
|
} else if (isObject(data)) {
|
|
Object.keys(data).forEach(function (key) {
|
|
callback.call(data, data[key], key, data);
|
|
});
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
/**
|
|
* Recursively assigns own enumerable properties of source objects to the target object.
|
|
* @param {Object} target - The target object.
|
|
* @param {Object[]} sources - The source objects.
|
|
* @returns {Object} The target object.
|
|
*/
|
|
|
|
function deepAssign(target) {
|
|
for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
sources[_key - 1] = arguments[_key];
|
|
}
|
|
|
|
if (isObject(target) && sources.length > 0) {
|
|
sources.forEach(function (source) {
|
|
if (isObject(source)) {
|
|
Object.keys(source).forEach(function (key) {
|
|
if (isPlainObject(target[key]) && isPlainObject(source[key])) {
|
|
target[key] = deepAssign({}, target[key], source[key]);
|
|
} else {
|
|
target[key] = source[key];
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
return target;
|
|
}
|
|
/**
|
|
* Add classes to the given element.
|
|
* @param {Element} element - The target element.
|
|
* @param {string} value - The classes to be added.
|
|
*/
|
|
|
|
function addClass(element, value) {
|
|
if (!value) {
|
|
return;
|
|
}
|
|
|
|
if (isNumber(element.length)) {
|
|
forEach(element, function (elem) {
|
|
addClass(elem, value);
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (element.classList) {
|
|
element.classList.add(value);
|
|
return;
|
|
}
|
|
|
|
var className = element.className.trim();
|
|
|
|
if (!className) {
|
|
element.className = value;
|
|
} else if (className.indexOf(value) < 0) {
|
|
element.className = "".concat(className, " ").concat(value);
|
|
}
|
|
}
|
|
/**
|
|
* Remove classes from the given element.
|
|
* @param {Element} element - The target element.
|
|
* @param {string} value - The classes to be removed.
|
|
*/
|
|
|
|
function removeClass(element, value) {
|
|
if (!value) {
|
|
return;
|
|
}
|
|
|
|
if (isNumber(element.length)) {
|
|
forEach(element, function (elem) {
|
|
removeClass(elem, value);
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (element.classList) {
|
|
element.classList.remove(value);
|
|
return;
|
|
}
|
|
|
|
if (element.className.indexOf(value) >= 0) {
|
|
element.className = element.className.replace(value, '');
|
|
}
|
|
}
|
|
var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g;
|
|
/**
|
|
* Transform the given string from camelCase to kebab-case
|
|
* @param {string} value - The value to transform.
|
|
* @returns {string} The transformed value.
|
|
*/
|
|
|
|
function hyphenate(value) {
|
|
return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase();
|
|
}
|
|
/**
|
|
* Get data from the given element.
|
|
* @param {Element} element - The target element.
|
|
* @param {string} name - The data key to get.
|
|
* @returns {string} The data value.
|
|
*/
|
|
|
|
function getData(element, name) {
|
|
if (isObject(element[name])) {
|
|
return element[name];
|
|
}
|
|
|
|
if (element.dataset) {
|
|
return element.dataset[name];
|
|
}
|
|
|
|
return element.getAttribute("data-".concat(hyphenate(name)));
|
|
}
|
|
/**
|
|
* Set data to the given element.
|
|
* @param {Element} element - The target element.
|
|
* @param {string} name - The data key to set.
|
|
* @param {string} data - The data value.
|
|
*/
|
|
|
|
function setData(element, name, data) {
|
|
if (isObject(data)) {
|
|
element[name] = data;
|
|
} else if (element.dataset) {
|
|
element.dataset[name] = data;
|
|
} else {
|
|
element.setAttribute("data-".concat(hyphenate(name)), data);
|
|
}
|
|
}
|
|
/**
|
|
* Remove data from the given element.
|
|
* @param {Element} element - The target element.
|
|
* @param {string} name - The data key to remove.
|
|
*/
|
|
|
|
function removeData(element, name) {
|
|
if (isObject(element[name])) {
|
|
try {
|
|
delete element[name];
|
|
} catch (error) {
|
|
element[name] = undefined;
|
|
}
|
|
} else if (element.dataset) {
|
|
// #128 Safari not allows to delete dataset property
|
|
try {
|
|
delete element.dataset[name];
|
|
} catch (error) {
|
|
element.dataset[name] = undefined;
|
|
}
|
|
} else {
|
|
element.removeAttribute("data-".concat(hyphenate(name)));
|
|
}
|
|
}
|
|
var REGEXP_SPACES = /\s\s*/;
|
|
|
|
var onceSupported = function () {
|
|
var supported = false;
|
|
|
|
if (IS_BROWSER) {
|
|
var once = false;
|
|
|
|
var listener = function listener() {};
|
|
|
|
var options = Object.defineProperty({}, 'once', {
|
|
get: function get() {
|
|
supported = true;
|
|
return once;
|
|
},
|
|
|
|
/**
|
|
* This setter can fix a `TypeError` in strict mode
|
|
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only}
|
|
* @param {boolean} value - The value to set
|
|
*/
|
|
set: function set(value) {
|
|
once = value;
|
|
}
|
|
});
|
|
WINDOW.addEventListener('test', listener, options);
|
|
WINDOW.removeEventListener('test', listener, options);
|
|
}
|
|
|
|
return supported;
|
|
}();
|
|
/**
|
|
* Remove event listener from the target element.
|
|
* @param {Element} element - The event target.
|
|
* @param {string} type - The event type(s).
|
|
* @param {Function} listener - The event listener.
|
|
* @param {Object} options - The event options.
|
|
*/
|
|
|
|
|
|
function removeListener(element, type, listener) {
|
|
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
var handler = listener;
|
|
type.trim().split(REGEXP_SPACES).forEach(function (event) {
|
|
if (!onceSupported) {
|
|
var listeners = element.listeners;
|
|
|
|
if (listeners && listeners[event] && listeners[event][listener]) {
|
|
handler = listeners[event][listener];
|
|
delete listeners[event][listener];
|
|
|
|
if (Object.keys(listeners[event]).length === 0) {
|
|
delete listeners[event];
|
|
}
|
|
|
|
if (Object.keys(listeners).length === 0) {
|
|
delete element.listeners;
|
|
}
|
|
}
|
|
}
|
|
|
|
element.removeEventListener(event, handler, options);
|
|
});
|
|
}
|
|
/**
|
|
* Add event listener to the target element.
|
|
* @param {Element} element - The event target.
|
|
* @param {string} type - The event type(s).
|
|
* @param {Function} listener - The event listener.
|
|
* @param {Object} options - The event options.
|
|
*/
|
|
|
|
function addListener(element, type, listener) {
|
|
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
var _handler = listener;
|
|
type.trim().split(REGEXP_SPACES).forEach(function (event) {
|
|
if (options.once && !onceSupported) {
|
|
var _element$listeners = element.listeners,
|
|
listeners = _element$listeners === void 0 ? {} : _element$listeners;
|
|
|
|
_handler = function handler() {
|
|
delete listeners[event][listener];
|
|
element.removeEventListener(event, _handler, options);
|
|
|
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
args[_key2] = arguments[_key2];
|
|
}
|
|
|
|
listener.apply(element, args);
|
|
};
|
|
|
|
if (!listeners[event]) {
|
|
listeners[event] = {};
|
|
}
|
|
|
|
if (listeners[event][listener]) {
|
|
element.removeEventListener(event, listeners[event][listener], options);
|
|
}
|
|
|
|
listeners[event][listener] = _handler;
|
|
element.listeners = listeners;
|
|
}
|
|
|
|
element.addEventListener(event, _handler, options);
|
|
});
|
|
}
|
|
/**
|
|
* Dispatch event on the target element.
|
|
* @param {Element} element - The event target.
|
|
* @param {string} type - The event type(s).
|
|
* @param {Object} data - The additional event data.
|
|
* @returns {boolean} Indicate if the event is default prevented or not.
|
|
*/
|
|
|
|
function dispatchEvent(element, type, data) {
|
|
var event; // Event and CustomEvent on IE9-11 are global objects, not constructors
|
|
|
|
if (isFunction(Event) && isFunction(CustomEvent)) {
|
|
event = new CustomEvent(type, {
|
|
detail: data,
|
|
bubbles: true,
|
|
cancelable: true
|
|
});
|
|
} else {
|
|
event = document.createEvent('CustomEvent');
|
|
event.initCustomEvent(type, true, true, data);
|
|
}
|
|
|
|
return element.dispatchEvent(event);
|
|
}
|
|
/**
|
|
* Check if the given year is a leap year.
|
|
* @param {number} year - The year to check.
|
|
* @returns {boolean} Returns `true` if the given year is a leap year, else `false`.
|
|
*/
|
|
|
|
function isLeapYear(year) {
|
|
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
}
|
|
/**
|
|
* Get days number of the given month.
|
|
* @param {number} year - The target year.
|
|
* @param {number} month - The target month.
|
|
* @returns {number} Returns days number.
|
|
*/
|
|
|
|
function getDaysInMonth(year, month) {
|
|
return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
|
|
}
|
|
/**
|
|
* Add leading zeroes to the given value
|
|
* @param {number} value - The value to add.
|
|
* @param {number} [length=1] - The number of the leading zeroes.
|
|
* @returns {string} Returns converted value.
|
|
*/
|
|
|
|
function addLeadingZero(value) {
|
|
var length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
var str = String(Math.abs(value));
|
|
var i = str.length;
|
|
var result = '';
|
|
|
|
if (value < 0) {
|
|
result += '-';
|
|
}
|
|
|
|
while (i < length) {
|
|
i += 1;
|
|
result += '0';
|
|
}
|
|
|
|
return result + str;
|
|
}
|
|
/**
|
|
* Map token to type name
|
|
* @param {string} token - The token to map.
|
|
* @returns {string} Returns mapped type name.
|
|
*/
|
|
|
|
function tokenToType(token) {
|
|
return {
|
|
Y: 'year',
|
|
M: 'month',
|
|
D: 'day',
|
|
H: 'hour',
|
|
m: 'minute',
|
|
s: 'second',
|
|
S: 'millisecond'
|
|
}[token.charAt(0)];
|
|
}
|
|
var REGEXP_TOKENS = /(Y|M|D|H|m|s|S)\1*/g;
|
|
/**
|
|
* Parse date format.
|
|
* @param {string} format - The format to parse.
|
|
* @returns {Object} Returns parsed format data.
|
|
*/
|
|
|
|
function parseFormat(format) {
|
|
var tokens = format.match(REGEXP_TOKENS);
|
|
|
|
if (!tokens) {
|
|
throw new Error('Invalid format.');
|
|
}
|
|
|
|
var result = {
|
|
tokens: tokens
|
|
};
|
|
tokens.forEach(function (token) {
|
|
result[tokenToType(token)] = token;
|
|
});
|
|
return result;
|
|
}
|
|
|
|
var events = {
|
|
bind: function bind() {
|
|
var element = this.element,
|
|
options = this.options,
|
|
grid = this.grid;
|
|
|
|
if (isFunction(options.show)) {
|
|
addListener(element, EVENT_SHOW, options.show);
|
|
}
|
|
|
|
if (isFunction(options.shown)) {
|
|
addListener(element, EVENT_SHOWN, options.shown);
|
|
}
|
|
|
|
if (isFunction(options.hide)) {
|
|
addListener(element, EVENT_HIDE, options.hide);
|
|
}
|
|
|
|
if (isFunction(options.hidden)) {
|
|
addListener(element, EVENT_HIDDEN, options.hidden);
|
|
}
|
|
|
|
if (isFunction(options.pick)) {
|
|
addListener(element, EVENT_PICK, options.pick);
|
|
}
|
|
|
|
addListener(element, EVENT_FOCUS, this.onFocus = this.focus.bind(this));
|
|
addListener(element, EVENT_CLICK, this.onFocus);
|
|
addListener(this.picker, EVENT_CLICK, this.onClick = this.click.bind(this));
|
|
addListener(grid, EVENT_WHEEL, this.onWheel = this.wheel.bind(this));
|
|
addListener(grid, EVENT_POINTER_DOWN, this.onPointerDown = this.pointerdown.bind(this));
|
|
addListener(document, EVENT_POINTER_MOVE, this.onPointerMove = this.pointermove.bind(this));
|
|
addListener(document, EVENT_POINTER_UP, this.onPointerUp = this.pointerup.bind(this));
|
|
addListener(document, EVENT_KEY_DOWN, this.onKeyDown = this.keydown.bind(this));
|
|
},
|
|
unbind: function unbind() {
|
|
var element = this.element,
|
|
options = this.options,
|
|
grid = this.grid;
|
|
|
|
if (isFunction(options.show)) {
|
|
removeListener(element, EVENT_SHOW, options.show);
|
|
}
|
|
|
|
if (isFunction(options.shown)) {
|
|
removeListener(element, EVENT_SHOWN, options.shown);
|
|
}
|
|
|
|
if (isFunction(options.hide)) {
|
|
removeListener(element, EVENT_HIDE, options.hide);
|
|
}
|
|
|
|
if (isFunction(options.hidden)) {
|
|
removeListener(element, EVENT_HIDDEN, options.hidden);
|
|
}
|
|
|
|
if (isFunction(options.pick)) {
|
|
removeListener(element, EVENT_PICK, options.pick);
|
|
}
|
|
|
|
removeListener(element, EVENT_FOCUS, this.onFocus);
|
|
removeListener(element, EVENT_CLICK, this.onFocus);
|
|
removeListener(this.picker, EVENT_CLICK, this.onClick);
|
|
removeListener(grid, EVENT_WHEEL, this.onWheel);
|
|
removeListener(grid, EVENT_POINTER_DOWN, this.onPointerDown);
|
|
removeListener(document, EVENT_POINTER_MOVE, this.onPointerMove);
|
|
removeListener(document, EVENT_POINTER_UP, this.onPointerUp);
|
|
removeListener(document, EVENT_KEY_DOWN, this.onKeyDown);
|
|
}
|
|
};
|
|
|
|
var handlers = {
|
|
focus: function focus(event) {
|
|
event.target.blur();
|
|
this.show();
|
|
},
|
|
click: function click(event) {
|
|
var target = event.target;
|
|
var action = getData(target, DATA_ACTION);
|
|
|
|
switch (action) {
|
|
case ACTION_HIDE:
|
|
this.hide();
|
|
break;
|
|
|
|
case ACTION_PICK:
|
|
this.pick();
|
|
break;
|
|
|
|
case ACTION_PREV:
|
|
case ACTION_NEXT:
|
|
this[action](getData(target.parentElement, DATA_TYPE));
|
|
break;
|
|
|
|
default:
|
|
}
|
|
},
|
|
wheel: function wheel(event) {
|
|
var target = event.target;
|
|
|
|
if (target === this.grid) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
|
|
while (target.parentElement && target.parentElement !== this.grid) {
|
|
target = target.parentElement;
|
|
}
|
|
|
|
var type = getData(target, DATA_TYPE);
|
|
|
|
if (event.deltaY < 0) {
|
|
this.prev(type);
|
|
} else {
|
|
this.next(type);
|
|
}
|
|
},
|
|
pointerdown: function pointerdown(event) {
|
|
var target = event.target;
|
|
|
|
if (target === this.grid || getData(target, DATA_ACTION)) {
|
|
return;
|
|
} // This line is required for preventing page scrolling in iOS browsers
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
while (target.parentElement && target.parentElement !== this.grid) {
|
|
target = target.parentElement;
|
|
}
|
|
|
|
var list = target.querySelector(".".concat(NAMESPACE, "-list"));
|
|
var itemHeight = list.firstElementChild.offsetHeight;
|
|
this.cell = {
|
|
elem: target,
|
|
list: list,
|
|
moveY: 0,
|
|
maxMoveY: itemHeight,
|
|
minMoveY: itemHeight / 2,
|
|
startY: event.changedTouches ? event.changedTouches[0].pageY : event.pageY,
|
|
type: getData(target, DATA_TYPE)
|
|
};
|
|
},
|
|
pointermove: function pointermove(event) {
|
|
var cell = this.cell;
|
|
|
|
if (!cell) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
var endY = event.changedTouches ? event.changedTouches[0].pageY : event.pageY;
|
|
var moveY = cell.moveY + (endY - cell.startY);
|
|
cell.startY = endY;
|
|
cell.moveY = moveY;
|
|
|
|
if (Math.abs(moveY) < cell.maxMoveY) {
|
|
cell.list.style.top = "".concat(moveY, "px");
|
|
return;
|
|
}
|
|
|
|
cell.list.style.top = 0;
|
|
cell.moveY = 0;
|
|
|
|
if (moveY >= cell.maxMoveY) {
|
|
this.prev(cell.type);
|
|
} else if (moveY <= -cell.maxMoveY) {
|
|
this.next(cell.type);
|
|
}
|
|
},
|
|
pointerup: function pointerup(event) {
|
|
var cell = this.cell;
|
|
|
|
if (!cell) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
cell.list.style.top = 0;
|
|
|
|
if (cell.moveY >= cell.minMoveY) {
|
|
this.prev(cell.type);
|
|
} else if (cell.moveY <= -cell.minMoveY) {
|
|
this.next(cell.type);
|
|
}
|
|
|
|
this.cell = null;
|
|
},
|
|
keydown: function keydown(event) {
|
|
if (this.shown && (event.key === 'Escape' || event.keyCode === 27)) {
|
|
this.hide();
|
|
}
|
|
}
|
|
};
|
|
|
|
var helpers = {
|
|
render: function render(type) {
|
|
var _this = this;
|
|
|
|
if (!type) {
|
|
this.format.tokens.forEach(function (token) {
|
|
return _this.render(tokenToType(token));
|
|
});
|
|
return;
|
|
}
|
|
|
|
var options = this.options;
|
|
var data = this.data[type];
|
|
var current = this.current(type);
|
|
var max = isFunction(data.max) ? data.max() : data.max;
|
|
var min = isFunction(data.min) ? data.min() : data.min;
|
|
var base = 0;
|
|
|
|
if (isFinite(max)) {
|
|
base = min > 0 ? max : max + 1;
|
|
}
|
|
|
|
data.list.innerHTML = '';
|
|
data.current = current;
|
|
|
|
for (var i = 0; i < options.rows + 2; i += 1) {
|
|
var item = document.createElement('li');
|
|
var position = i - data.index;
|
|
var newValue = current + position * data.increment;
|
|
|
|
if (base) {
|
|
newValue %= base;
|
|
|
|
if (newValue < min) {
|
|
newValue += base;
|
|
}
|
|
}
|
|
|
|
item.textContent = options.translate(type, data.aliases ? data.aliases[newValue] : addLeadingZero(newValue + data.offset, data.digit));
|
|
setData(item, DATA_NAME, type);
|
|
setData(item, DATA_VALUE, newValue);
|
|
addClass(item, "".concat(NAMESPACE, "-item"));
|
|
|
|
if (position === 0) {
|
|
addClass(item, CLASS_PICKED);
|
|
data.item = item;
|
|
}
|
|
|
|
data.list.appendChild(item);
|
|
}
|
|
},
|
|
current: function current(type, value) {
|
|
var date = this.date;
|
|
var format = this.format;
|
|
var token = format[type];
|
|
|
|
switch (token.charAt(0)) {
|
|
case 'Y':
|
|
if (isNumber(value)) {
|
|
date.setFullYear(token.length === 2 ? 2000 + value : value);
|
|
|
|
if (format.month) {
|
|
this.render(tokenToType(format.month));
|
|
}
|
|
|
|
if (format.day) {
|
|
this.render(tokenToType(format.day));
|
|
}
|
|
}
|
|
|
|
return date.getFullYear();
|
|
|
|
case 'M':
|
|
if (isNumber(value)) {
|
|
date.setMonth(value, // The current day should not exceed its maximum day in current month
|
|
Math.min(date.getDate(), getDaysInMonth(date.getFullYear(), value)));
|
|
|
|
if (format.day) {
|
|
this.render(tokenToType(format.day));
|
|
}
|
|
}
|
|
|
|
return date.getMonth();
|
|
|
|
case 'D':
|
|
if (isNumber(value)) {
|
|
date.setDate(value);
|
|
}
|
|
|
|
return date.getDate();
|
|
|
|
case 'H':
|
|
if (isNumber(value)) {
|
|
date.setHours(value);
|
|
}
|
|
|
|
return date.getHours();
|
|
|
|
case 'm':
|
|
if (isNumber(value)) {
|
|
date.setMinutes(value);
|
|
}
|
|
|
|
return date.getMinutes();
|
|
|
|
case 's':
|
|
if (isNumber(value)) {
|
|
date.setSeconds(value);
|
|
}
|
|
|
|
return date.getSeconds();
|
|
|
|
case 'S':
|
|
if (isNumber(value)) {
|
|
date.setMilliseconds(value);
|
|
}
|
|
|
|
return date.getMilliseconds();
|
|
|
|
default:
|
|
}
|
|
|
|
return date;
|
|
},
|
|
getValue: function getValue() {
|
|
var element = this.element;
|
|
return this.isInput ? element.value : element.textContent;
|
|
},
|
|
setValue: function setValue(value) {
|
|
var element = this.element;
|
|
|
|
if (this.isInput) {
|
|
element.value = value;
|
|
} else if (this.options.container) {
|
|
element.textContent = value;
|
|
}
|
|
},
|
|
open: function open() {
|
|
var body = this.body;
|
|
body.style.overflow = 'hidden';
|
|
body.style.paddingRight = "".concat(this.scrollBarWidth + (parseFloat(this.initialBodyPaddingRight) || 0), "px");
|
|
},
|
|
close: function close() {
|
|
var body = this.body;
|
|
body.style.overflow = '';
|
|
body.style.paddingRight = this.initialBodyPaddingRight;
|
|
}
|
|
};
|
|
|
|
var methods = {
|
|
/**
|
|
* Show the picker.
|
|
* @param {boolean} [immediate=false] - Indicate if show the picker immediately or not.
|
|
* @returns {Picker} this
|
|
*/
|
|
show: function show() {
|
|
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
var element = this.element,
|
|
picker = this.picker;
|
|
|
|
if (this.inline || this.shown) {
|
|
return this;
|
|
}
|
|
|
|
if (dispatchEvent(element, EVENT_SHOW) === false) {
|
|
return this;
|
|
}
|
|
|
|
this.shown = true;
|
|
this.open();
|
|
addClass(picker, CLASS_OPEN);
|
|
|
|
var done = function done() {
|
|
dispatchEvent(element, EVENT_SHOWN);
|
|
};
|
|
|
|
if (!immediate) {
|
|
// Reflow to enable transition
|
|
// eslint-disable-next-line
|
|
picker.offsetWidth;
|
|
}
|
|
|
|
addClass(picker, CLASS_OPENED);
|
|
|
|
if (immediate) {
|
|
done();
|
|
} else {
|
|
setTimeout(done, 300);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Hide the picker.
|
|
* @param {boolean} [immediate=false] - Indicate if hide the picker immediately or not.
|
|
* @returns {Picker} this
|
|
*/
|
|
hide: function hide() {
|
|
var _this = this;
|
|
|
|
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
var element = this.element,
|
|
picker = this.picker;
|
|
|
|
if (this.inline || !this.shown) {
|
|
return this;
|
|
}
|
|
|
|
if (dispatchEvent(element, EVENT_HIDE) === false) {
|
|
return this;
|
|
}
|
|
|
|
this.shown = false;
|
|
removeClass(picker, CLASS_OPENED);
|
|
|
|
var done = function done() {
|
|
_this.close();
|
|
|
|
removeClass(picker, CLASS_OPEN);
|
|
dispatchEvent(element, EVENT_HIDDEN);
|
|
};
|
|
|
|
if (immediate) {
|
|
done();
|
|
} else {
|
|
setTimeout(done, 300);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Pick to the previous item.
|
|
* @param {string} type - The column type.
|
|
* @returns {Picker} this
|
|
*/
|
|
prev: function prev(type) {
|
|
var options = this.options;
|
|
var token = this.format[type];
|
|
var data = this.data[type];
|
|
var list = data.list;
|
|
var item = list.lastElementChild;
|
|
var max = isFunction(data.max) ? data.max() : data.max;
|
|
var min = isFunction(data.min) ? data.min() : data.min;
|
|
var prev = data.item.previousElementSibling;
|
|
var value = Number(getData(list.firstElementChild, DATA_VALUE)) - data.increment;
|
|
|
|
if (value < min) {
|
|
value += max - min + 1;
|
|
}
|
|
|
|
item.textContent = options.translate(type, data.aliases ? data.aliases[value] : addLeadingZero(value + data.offset, token.length));
|
|
setData(item, DATA_VALUE, value);
|
|
|
|
if (prev) {
|
|
removeClass(data.item, CLASS_PICKED);
|
|
addClass(prev, CLASS_PICKED);
|
|
data.item = prev;
|
|
}
|
|
|
|
list.insertBefore(item, list.firstElementChild);
|
|
data.current = Number(getData(data.item, DATA_VALUE));
|
|
this.current(type, data.current);
|
|
|
|
if (this.inline && options.container) {
|
|
this.pick();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Pick to the next item.
|
|
* @param {String} type - The column type.
|
|
* @returns {Picker} this
|
|
*/
|
|
next: function next(type) {
|
|
var options = this.options;
|
|
var token = this.format[type];
|
|
var data = this.data[type];
|
|
var list = data.list;
|
|
var item = list.firstElementChild;
|
|
var max = isFunction(data.max) ? data.max() : data.max;
|
|
var min = isFunction(data.min) ? data.min() : data.min;
|
|
var next = data.item.nextElementSibling;
|
|
var value = Number(getData(list.lastElementChild, DATA_VALUE)) + data.increment;
|
|
|
|
if (value > max) {
|
|
value -= max - min + 1;
|
|
}
|
|
|
|
item.textContent = options.translate(type, data.aliases ? data.aliases[value] : addLeadingZero(value + data.offset, token.length));
|
|
setData(item, DATA_VALUE, value);
|
|
list.appendChild(item);
|
|
|
|
if (next) {
|
|
removeClass(data.item, CLASS_PICKED);
|
|
addClass(next, CLASS_PICKED);
|
|
data.item = next;
|
|
}
|
|
|
|
data.current = Number(getData(data.item, DATA_VALUE));
|
|
this.current(type, data.current);
|
|
|
|
if (this.inline && options.container) {
|
|
this.pick();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
// Pick the current date to the target element.
|
|
pick: function pick() {
|
|
var element = this.element;
|
|
|
|
if (dispatchEvent(element, EVENT_PICK) === false) {
|
|
return this;
|
|
}
|
|
|
|
var value = this.formatDate(this.date);
|
|
this.setValue(value);
|
|
|
|
if (this.isInput && dispatchEvent(element, 'change') === false) {
|
|
this.reset();
|
|
}
|
|
|
|
this.hide();
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Get the current date.
|
|
* @param {boolean} [formatted=false] - Indicate if format the date or not.
|
|
* @return {Date|string} The output date.
|
|
*/
|
|
getDate: function getDate() {
|
|
var formatted = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
var date = this.date;
|
|
return formatted ? this.formatDate(date) : new Date(date);
|
|
},
|
|
|
|
/**
|
|
* Override the current date with a new date.
|
|
* @param {Date|string} date - The date to set.
|
|
* @returns {Picker} this
|
|
*/
|
|
setDate: function setDate(date) {
|
|
if (date) {
|
|
this.date = this.parseDate(date);
|
|
this.render();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
// Update the picker with the current element value / text.
|
|
update: function update() {
|
|
this.date = this.parseDate(this.getValue());
|
|
this.render();
|
|
return this;
|
|
},
|
|
// Reset the picker and element value / text.
|
|
reset: function reset() {
|
|
this.setValue(this.initialValue);
|
|
this.date = new Date(this.initialDate);
|
|
this.render();
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Parse a date with the set date format.
|
|
* @param {Date|string} date - The date to parse.
|
|
* @returns {Date} The parsed date object.
|
|
*/
|
|
parseDate: function parseDate(date) {
|
|
var options = this.options,
|
|
format = this.format;
|
|
var digits = [];
|
|
|
|
if (isDate(date)) {
|
|
return new Date(date);
|
|
}
|
|
|
|
if (isString(date)) {
|
|
var groups = _toConsumableArray(options.months).concat(_toConsumableArray(options.monthsShort), ['\\d+']);
|
|
|
|
digits = date.match(new RegExp("(".concat(groups.join('|'), ")"), 'g')); // Parse `11111111` (YYYYMMDD) to ['1111', '11', '11']
|
|
|
|
if (digits && date.length === options.format.length && digits.length !== format.tokens.length) {
|
|
digits = format.tokens.map(function (token) {
|
|
return date.substr(options.format.indexOf(token), token.length);
|
|
});
|
|
}
|
|
|
|
if (!digits || digits.length !== format.tokens.length) {
|
|
return new Date();
|
|
}
|
|
}
|
|
|
|
var parsedDate = new Date();
|
|
digits.forEach(function (digit, i) {
|
|
var token = format.tokens[i];
|
|
var n = Number(digit);
|
|
|
|
switch (token) {
|
|
case 'YYYY':
|
|
case 'YYY':
|
|
case 'Y':
|
|
{
|
|
var index = date.indexOf(digit);
|
|
var isHyphen = date.substr(index - 1, 1) === '-';
|
|
var isBC = index > 1 && isHyphen && /\S/.test(date.substr(index - 2, 1)) || index === 1 && isHyphen;
|
|
parsedDate.setFullYear(isBC ? -n : n);
|
|
break;
|
|
}
|
|
|
|
case 'YY':
|
|
parsedDate.setFullYear(2000 + n);
|
|
break;
|
|
|
|
case 'MMMM':
|
|
parsedDate.setMonth(options.months.indexOf(digit));
|
|
break;
|
|
|
|
case 'MMM':
|
|
parsedDate.setMonth(options.monthsShort.indexOf(digit));
|
|
break;
|
|
|
|
case 'MM':
|
|
case 'M':
|
|
parsedDate.setMonth(n - 1);
|
|
break;
|
|
|
|
case 'DD':
|
|
case 'D':
|
|
parsedDate.setDate(n);
|
|
break;
|
|
|
|
case 'HH':
|
|
case 'H':
|
|
parsedDate.setHours(n);
|
|
break;
|
|
|
|
case 'mm':
|
|
case 'm':
|
|
parsedDate.setMinutes(n);
|
|
break;
|
|
|
|
case 'ss':
|
|
case 's':
|
|
parsedDate.setSeconds(n);
|
|
break;
|
|
|
|
case 'SSS':
|
|
case 'SS':
|
|
case 'S':
|
|
parsedDate.setMilliseconds(n);
|
|
break;
|
|
|
|
default:
|
|
}
|
|
});
|
|
return parsedDate;
|
|
},
|
|
|
|
/**
|
|
* Format a date object to a string with the set date format.
|
|
* @param {Date} date - The date to format.
|
|
* @return {string} THe formatted date.
|
|
*/
|
|
formatDate: function formatDate(date) {
|
|
var options = this.options,
|
|
format = this.format;
|
|
var formatted = '';
|
|
|
|
if (isValidDate(date)) {
|
|
var year = date.getFullYear();
|
|
var month = date.getMonth();
|
|
var day = date.getDate();
|
|
var hours = date.getHours();
|
|
var minutes = date.getMinutes();
|
|
var seconds = date.getSeconds();
|
|
var milliseconds = date.getMilliseconds();
|
|
formatted = options.format;
|
|
format.tokens.forEach(function (token) {
|
|
var replacement = '';
|
|
|
|
switch (token) {
|
|
case 'YYYY':
|
|
case 'YYY':
|
|
case 'Y':
|
|
replacement = addLeadingZero(year, token.length);
|
|
break;
|
|
|
|
case 'YY':
|
|
replacement = addLeadingZero(year % 100, 2);
|
|
break;
|
|
|
|
case 'MMMM':
|
|
replacement = options.months[month];
|
|
break;
|
|
|
|
case 'MMM':
|
|
replacement = options.monthsShort[month];
|
|
break;
|
|
|
|
case 'MM':
|
|
case 'M':
|
|
replacement = addLeadingZero(month + 1, token.length);
|
|
break;
|
|
|
|
case 'DD':
|
|
case 'D':
|
|
replacement = addLeadingZero(day, token.length);
|
|
break;
|
|
|
|
case 'HH':
|
|
case 'H':
|
|
replacement = addLeadingZero(hours, token.length);
|
|
break;
|
|
|
|
case 'mm':
|
|
case 'm':
|
|
replacement = addLeadingZero(minutes, token.length);
|
|
break;
|
|
|
|
case 'ss':
|
|
case 's':
|
|
replacement = addLeadingZero(seconds, token.length);
|
|
break;
|
|
|
|
case 'SSS':
|
|
case 'SS':
|
|
case 'S':
|
|
replacement = addLeadingZero(milliseconds, token.length);
|
|
break;
|
|
|
|
default:
|
|
}
|
|
|
|
formatted = formatted.replace(token, replacement);
|
|
});
|
|
}
|
|
|
|
return formatted;
|
|
},
|
|
// Destroy the picker and remove the instance from the target element.
|
|
destroy: function destroy() {
|
|
var element = this.element,
|
|
picker = this.picker;
|
|
|
|
if (!getData(element, NAMESPACE)) {
|
|
return this;
|
|
}
|
|
|
|
this.hide(true);
|
|
this.unbind();
|
|
removeData(element, NAMESPACE);
|
|
picker.parentNode.removeChild(picker);
|
|
return this;
|
|
}
|
|
};
|
|
|
|
var REGEXP_DELIMITER = /\{\{\s*(\w+)\s*\}\}/g;
|
|
var REGEXP_INPUTS = /input|textarea/i;
|
|
var AnotherPicker = WINDOW.Picker;
|
|
|
|
var Picker =
|
|
/*#__PURE__*/
|
|
function () {
|
|
/**
|
|
* Create a new Picker.
|
|
* @param {Element} element - The target element for picking.
|
|
* @param {Object} [options={}] - The configuration options.
|
|
*/
|
|
function Picker(element) {
|
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
|
|
_classCallCheck(this, Picker);
|
|
|
|
if (!element || element.nodeType !== 1) {
|
|
throw new Error('The first argument is required and must be an element.');
|
|
}
|
|
|
|
this.element = element;
|
|
this.options = deepAssign({}, DEFAULTS, LANGUAGES[options.language], isPlainObject(options) && options);
|
|
this.shown = false;
|
|
this.init();
|
|
}
|
|
|
|
_createClass(Picker, [{
|
|
key: "init",
|
|
value: function init() {
|
|
var _this = this;
|
|
|
|
var element = this.element;
|
|
|
|
if (getData(element, NAMESPACE)) {
|
|
return;
|
|
}
|
|
|
|
setData(element, NAMESPACE, this);
|
|
var options = this.options;
|
|
var isInput = REGEXP_INPUTS.test(element.tagName);
|
|
var inline = options.inline && (options.container || !isInput);
|
|
var template = document.createElement('div');
|
|
template.insertAdjacentHTML('afterbegin', TEMPLATE.replace(REGEXP_DELIMITER, function () {
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
return options.text[args[1]];
|
|
}));
|
|
var picker = template.getElementsByClassName(NAMESPACE)[0];
|
|
var grid = picker.getElementsByClassName("".concat(NAMESPACE, "-grid"))[0];
|
|
var container = options.container;
|
|
|
|
if (isString(container)) {
|
|
container = document.querySelector(container);
|
|
}
|
|
|
|
if (inline) {
|
|
addClass(picker, CLASS_OPEN);
|
|
addClass(picker, CLASS_OPENED);
|
|
|
|
if (!container) {
|
|
container = element;
|
|
}
|
|
} else {
|
|
var ownerDocument = element.ownerDocument;
|
|
var body = ownerDocument.body || ownerDocument.documentElement;
|
|
this.body = body;
|
|
this.scrollBarWidth = WINDOW.innerWidth - ownerDocument.documentElement.clientWidth;
|
|
this.initialBodyPaddingRight = WINDOW.getComputedStyle(body).paddingRight;
|
|
addClass(picker, "".concat(NAMESPACE, "-fixed"));
|
|
|
|
if (!container) {
|
|
container = document.body;
|
|
}
|
|
}
|
|
|
|
this.isInput = isInput;
|
|
this.inline = inline;
|
|
this.container = container;
|
|
this.picker = picker;
|
|
this.grid = grid;
|
|
this.cell = null;
|
|
this.format = parseFormat(options.format);
|
|
var initialValue = this.getValue();
|
|
var date = this.parseDate(options.date || initialValue);
|
|
this.date = date;
|
|
this.initialDate = new Date(date);
|
|
this.initialValue = initialValue;
|
|
this.data = {};
|
|
var rows = Number(options.rows);
|
|
|
|
if (!(rows % 2)) {
|
|
rows += 1;
|
|
}
|
|
|
|
options.rows = rows || 5;
|
|
addClass(grid, "".concat(NAMESPACE, "-").concat(options.rows > 1 ? 'multiple' : 'single'));
|
|
|
|
if (options.controls) {
|
|
addClass(grid, "".concat(NAMESPACE, "-controls"));
|
|
}
|
|
|
|
var headers = options.headers,
|
|
increment = options.increment;
|
|
|
|
if (headers) {
|
|
addClass(grid, "".concat(NAMESPACE, "-headers")); // TODO: Drop the `headers` option's object support in v2.
|
|
|
|
headers = isPlainObject(headers) ? headers : options.text;
|
|
}
|
|
|
|
if (!isPlainObject(increment)) {
|
|
increment = {
|
|
year: increment,
|
|
month: increment,
|
|
day: increment,
|
|
hour: increment,
|
|
minute: increment,
|
|
second: increment,
|
|
millisecond: increment
|
|
};
|
|
}
|
|
|
|
this.format.tokens.forEach(function (token) {
|
|
var type = tokenToType(token);
|
|
var cell = document.createElement('div');
|
|
var cellBody = document.createElement('div');
|
|
var list = document.createElement('ul');
|
|
var data = {
|
|
digit: token.length,
|
|
increment: Math.abs(Number(increment[type])) || 1,
|
|
list: list,
|
|
max: Infinity,
|
|
min: -Infinity,
|
|
index: Math.floor((options.rows + 2) / 2),
|
|
offset: 0
|
|
};
|
|
|
|
switch (token.charAt(0)) {
|
|
case 'Y':
|
|
if (data.digit === 2) {
|
|
data.max = 99;
|
|
data.min = 0;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
data.max = 11;
|
|
data.min = 0;
|
|
data.offset = 1;
|
|
|
|
if (data.digit === 3) {
|
|
data.aliases = options.monthsShort;
|
|
} else if (data.digit === 4) {
|
|
data.aliases = options.months;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
data.max = function () {
|
|
return getDaysInMonth(date.getFullYear(), date.getMonth());
|
|
};
|
|
|
|
data.min = 1;
|
|
break;
|
|
|
|
case 'H':
|
|
data.max = 23;
|
|
data.min = 0;
|
|
break;
|
|
|
|
case 'm':
|
|
data.max = 59;
|
|
data.min = 0;
|
|
break;
|
|
|
|
case 's':
|
|
data.max = 59;
|
|
data.min = 0;
|
|
break;
|
|
|
|
case 'S':
|
|
data.max = 999;
|
|
data.min = 0;
|
|
break;
|
|
|
|
default:
|
|
}
|
|
|
|
setData(cell, DATA_TYPE, type);
|
|
setData(cell, DATA_TOKEN, token);
|
|
|
|
if (headers) {
|
|
var cellHeader = document.createElement('div');
|
|
addClass(cellHeader, "".concat(NAMESPACE, "-cell__header"));
|
|
cellHeader.textContent = headers[type] || type[0].toUpperCase() + type.substr(1);
|
|
cell.appendChild(cellHeader);
|
|
}
|
|
|
|
if (options.controls) {
|
|
var prev = document.createElement('div');
|
|
addClass(prev, "".concat(NAMESPACE, "-cell__control"));
|
|
addClass(prev, "".concat(NAMESPACE, "-cell__control--prev"));
|
|
setData(prev, DATA_ACTION, ACTION_PREV);
|
|
cell.appendChild(prev);
|
|
}
|
|
|
|
addClass(list, "".concat(NAMESPACE, "-list"));
|
|
addClass(cellBody, "".concat(NAMESPACE, "-cell__body"));
|
|
addClass(cell, "".concat(NAMESPACE, "-cell"));
|
|
addClass(cell, "".concat(NAMESPACE, "-").concat(type, "s"));
|
|
cellBody.appendChild(list);
|
|
cell.appendChild(cellBody);
|
|
|
|
if (options.controls) {
|
|
var next = document.createElement('div');
|
|
addClass(next, "".concat(NAMESPACE, "-cell__control"));
|
|
addClass(next, "".concat(NAMESPACE, "-cell__control--next"));
|
|
setData(next, DATA_ACTION, ACTION_NEXT);
|
|
cell.appendChild(next);
|
|
}
|
|
|
|
grid.appendChild(cell);
|
|
_this.data[type] = data;
|
|
|
|
_this.render(type);
|
|
});
|
|
|
|
if (inline) {
|
|
container.innerHTML = '';
|
|
}
|
|
|
|
container.appendChild(picker);
|
|
this.bind();
|
|
}
|
|
/**
|
|
* Get the no conflict picker class.
|
|
* @returns {Picker} The picker class.
|
|
*/
|
|
|
|
}], [{
|
|
key: "noConflict",
|
|
value: function noConflict() {
|
|
WINDOW.Picker = AnotherPicker;
|
|
return Picker;
|
|
}
|
|
/**
|
|
* Change the default options.
|
|
* @param {Object} options - The new default options.
|
|
*/
|
|
|
|
}, {
|
|
key: "setDefaults",
|
|
value: function setDefaults(options) {
|
|
deepAssign(DEFAULTS, LANGUAGES[options.language], isPlainObject(options) && options);
|
|
}
|
|
}]);
|
|
|
|
return Picker;
|
|
}();
|
|
|
|
deepAssign(Picker.prototype, events, handlers, helpers, methods);
|
|
Picker.languages = LANGUAGES;
|
|
|
|
module.exports = Picker;
|