UNPKG

jspanel4

Version:

A JavaScript library to create highly configurable multifunctional floating panels that can also be used as modal, tooltip, hint or contextmenu

1,226 lines (1,203 loc) 267 kB
/** * jsPanel - A JavaScript library to create highly configurable multifunctional floating panels that can also be used as modal, tooltip, hint or contextmenu * @version v4.16.1 * @homepage https://jspanel.de/ * @license MIT * @author Stefan Sträßer - info@jspanel.de * @author of dialog extension: Michael Daumling - michael@terrapinlogo.com * @github https://github.com/Flyer53/jsPanel4.git */ export // eslint-disable-next-line no-redeclare // noinspection JSVoidFunctionReturnValueUsed // eslint-disable-next-line no-redeclare let jsPanel = { version: '4.16.1', date: '2022-11-03 09:18', ajaxAlwaysCallbacks: [], autopositionSpacing: 4, closeOnEscape: (() => { document.addEventListener('keydown', e => { if (e.key === 'Escape' || e.code === 'Escape' || e.key === 'Esc') { jsPanel .getPanels(panel => panel.classList.contains('jsPanel')) // Array is sorted by z-index (the highest first) .some(item => { if (item.options.closeOnEscape) { if (typeof item.options.closeOnEscape === 'function') { return item.options.closeOnEscape.call(item, item); // if return value is falsy next panel in sequence will close, otherwise processing of Array.prototype.some() stops } else { item.close(null, true); return true; } } return false; }); } }, false); })(), defaults: { boxShadow: 3, container: 'window', contentSize: { width: '400px', height: '200px' }, // must be an object dragit: { cursor: 'move', handles: '.jsPanel-headerlogo, .jsPanel-titlebar, .jsPanel-ftr', // do not use .jsPanel-headerbar opacity: 0.8, disableOnMaximized: true, }, header: true, headerTitle: 'jsPanel', headerControls: {size: 'md'}, // must be an object iconfont: undefined, maximizedMargin: 0, minimizeTo: 'default', paneltype: 'standard', position: {my: 'center', at: 'center'}, // default position.of MUST NOT be set with new positioning engine resizeit: { handles: 'n, e, s, w, ne, se, sw, nw', minWidth: 128, minHeight: 38, }, theme: 'default' }, defaultAutocloseConfig: {time: '8s', progressbar: true}, defaultSnapConfig: { sensitivity: 70, trigger: 'panel', active: 'both', }, extensions: {}, globalCallbacks: false, icons: { close: `<svg focusable="false" class="jsPanel-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><path fill="currentColor" d="M13.7,11l6.1-6.1c0.4-0.4,0.4-0.9,0-1.3l-1.4-1.4c-0.4-0.4-0.9-0.4-1.3,0L11,8.3L4.9,2.3C4.6,1.9,4,1.9,3.7,2.3L2.3,3.7 C1.9,4,1.9,4.6,2.3,4.9L8.3,11l-6.1,6.1c-0.4,0.4-0.4,0.9,0,1.3l1.4,1.4c0.4,0.4,0.9,0.4,1.3,0l6.1-6.1l6.1,6.1 c0.4,0.4,0.9,0.4,1.3,0l1.4-1.4c0.4-0.4,0.4-0.9,0-1.3L13.7,11z"/></svg>`, maximize: `<svg focusable="false" class="jsPanel-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><path fill="currentColor" d="M18.3,2H3.7C2.8,2,2,2.9,2,3.9v14.1C2,19.1,2.8,20,3.7,20h14.6c0.9,0,1.7-0.9,1.7-1.9V3.9C20,2.9,19.2,2,18.3,2z M18.3,17.8 c0,0.1-0.1,0.2-0.2,0.2H3.9c-0.1,0-0.2-0.1-0.2-0.2V8.4h14.6V17.8z"/></svg>`, normalize: `<svg focusable="false" class="jsPanel-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><path fill="currentColor" d="M18.3,2H7.1C6.1,2,5.4,2.8,5.4,3.7v1.7H3.7C2.8,5.4,2,6.1,2,7.1v11.3C2,19.2,2.8,20,3.7,20h11.3c0.9,0,1.7-0.8,1.7-1.7v-1.7 h1.7c0.9,0,1.7-0.8,1.7-1.7V3.7C20,2.8,19.2,2,18.3,2z M14.9,18.3H3.7V11h11.3V18.3z M18.3,14.9h-1.7V7.1c0-0.9-0.8-1.7-1.7-1.7H7.1 V3.7h11.3V14.9z"/></svg>`, minimize: `<svg focusable="false" class="jsPanel-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><path fill="currentColor" d="M18.9,19.8H3.1c-0.6,0-1.1-0.5-1.1-1.1s0.5-1.1,1.1-1.1h15.8c0.6,0,1.1,0.5,1.1,1.1S19.5,19.8,18.9,19.8z"/></svg>`, smallify: `<svg focusable="false" class="jsPanel-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><path fill="currentColor" d="M2.1,15.2L2.9,16c0.2,0.2,0.5,0.2,0.7,0L11,8.7l7.4,7.3c0.2,0.2,0.5,0.2,0.7,0l0.8-0.8c0.2-0.2,0.2-0.5,0-0.7L11.3,6 c-0.2-0.2-0.5-0.2-0.7,0l-8.5,8.5C2,14.7,2,15,2.1,15.2z"/></svg>`, }, idCounter: 0, isIE: (() => {return document.documentMode || false;})(), pointerdown: 'onpointerdown' in window ? ['pointerdown'] : 'ontouchend' in window ? ['touchstart', 'mousedown'] : ['mousedown'], pointermove: 'onpointermove' in window ? ['pointermove'] : 'ontouchend' in window ? ['touchmove', 'mousemove'] : ['mousemove'], pointerup: 'onpointerup' in window ? ['pointerup'] : 'ontouchend' in window ? ['touchend', 'mouseup'] : ['mouseup'], polyfills: (() => { // Polyfills for IE11 only // Object.assign polyfill - https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/assign if (!Object.assign) { Object.defineProperty(Object, 'assign', { enumerable: false, configurable: true, writable: true, value: function (target) { if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object'); } let to = Object(target); for (let i = 1; i < arguments.length; i++) { let nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) { continue; } nextSource = Object(nextSource); let keysArray = Object.keys(Object(nextSource)); for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { let nextKey = keysArray[nextIndex]; let desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey]; } } } return to; }, }); } // Object.entries() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries if (!Object.entries) { Object.entries = function( obj ){ // noinspection ES6ConvertVarToLetConst var ownProps = Object.keys( obj ), i = ownProps.length, resArray = new Array(i); // preallocate the Array while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]]; return resArray; }; } // NodeList.prototype.forEach() polyfill - https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach if (window.NodeList && !NodeList.prototype.forEach) { NodeList.prototype.forEach = function (callback, thisArg) { thisArg = thisArg || window; for (let i = 0; i < this.length; i++) { callback.call(thisArg, this[i], i, this); } }; } // .append() polyfill - https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append (function (arr) { arr.forEach(function (item) { item.append = item.append || function () { let argArr = Array.prototype.slice.call(arguments), docFrag = document.createDocumentFragment(); argArr.forEach(function (argItem) { let isNode = argItem instanceof Node; docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); }); this.appendChild(docFrag); }; }); })([Element.prototype, Document.prototype, DocumentFragment.prototype]); // Element.closest() polyfill - https://developer.mozilla.org/en-US/docs/Web/API/Element/closest if (window.Element && !Element.prototype.closest) { // noinspection JSValidateTypes Element.prototype.closest = function (s) { // noinspection JSUnresolvedVariable let matches = (this.document || this.ownerDocument).querySelectorAll(s), i, el = this; do { i = matches.length; // eslint-disable-next-line no-empty while (--i >= 0 && matches.item(i) !== el) {} } while (i < 0 && (el = el.parentElement)); return el; }; } // CustomEvent - https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent (function () { if (typeof window.CustomEvent === 'function') return false; function CustomEvent(event, params) { params = params || { bubbles: false, cancelable: false, detail: undefined, }; let evt = document.createEvent('CustomEvent'); // noinspection JSDeprecatedSymbols evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); return evt; } // noinspection JSValidateTypes CustomEvent.prototype = window.Event.prototype; // noinspection JSValidateTypes window.CustomEvent = CustomEvent; })(); // String.prototype.endsWith() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith if (!String.prototype.endsWith) { String.prototype.endsWith = function(search, this_len) { if (this_len === undefined || this_len > this.length) { this_len = this.length; } return this.substring(this_len - search.length, this_len) === search; }; } // String.prototype.startsWith() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith if (!String.prototype.startsWith) { Object.defineProperty(String.prototype, 'startsWith', { value: function(search, rawPos) { // noinspection ES6ConvertVarToLetConst var pos = rawPos > 0 ? rawPos|0 : 0; return this.substring(pos, pos + search.length) === search; } }); } // String.prototype.includes() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes if (!String.prototype.includes) { String.prototype.includes = function(search, start) { 'use strict'; if (search instanceof RegExp) { throw TypeError('first argument must not be a RegExp'); } if (start === undefined) { start = 0; } return this.indexOf(search, start) !== -1; }; } // String.prototype repeat() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat if (!String.prototype.repeat) { String.prototype.repeat = function(count) { 'use strict'; if (this == null) throw new TypeError('can\'t convert ' + this + ' to object'); // noinspection ES6ConvertVarToLetConst var str = '' + this; count = +count; if (count != count) count = 0; if (count < 0) throw new RangeError('repeat count must be non-negative'); if (count == Infinity) throw new RangeError('repeat count must be less than infinity'); count = Math.floor(count); if (str.length == 0 || count == 0) return ''; if (str.length * count >= 1 << 28) throw new RangeError('repeat count must not overflow maximum string size'); // noinspection ES6ConvertVarToLetConst var maxCount = str.length * count; count = Math.floor(Math.log(count) / Math.log(2)); while (count) { str += str; count--; } str += str.substring(0, maxCount - str.length); return str; }; } // Number.isInteger() - Number.isInteger = Number.isInteger || function (value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; }; // Array.prototype.includes() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes if (!Array.prototype.includes) { Object.defineProperty(Array.prototype, 'includes', { value: function (searchElement, fromIndex) { if (this == null) { throw new TypeError('"this" is null or not defined'); } // 1. Let O be ? ToObject(this value). let o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). let len = o.length >>> 0; // 3. If len is 0, return false. if (len === 0) { return false; } // 4. Let n be ? ToInteger(fromIndex). // (If fromIndex is undefined, this step produces the value 0.) let n = fromIndex | 0; // 5. If n ≥ 0, then // a. Let k be n. // 6. Else n < 0, // a. Let k be len + n. // b. If k < 0, let k be 0. let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); function sameValueZero(x, y) { return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); } // 7. Repeat, while k < len while (k < len) { // a. Let elementK be the result of ? Get(O, ! ToString(k)). // b. If SameValueZero(searchElement, elementK) is true, return true. if (sameValueZero(o[k], searchElement)) { return true; } // c. Increase k by 1. k++; } // 8. Return false return false; }, }); } })(), ziBase: 100, colorFilledLight: 0.81, colorFilledDark: 0.08, colorFilled: 0, colorBrightnessThreshold: 0.55, colorNames: { default: 'b0bec5', // Material Design bluegray200 secondary: 'b0bec5', primary: '01579b', // Material Design lightblue900 info: '039be5', // Material Design lightblue600 success: '2e7d32', // Material Design green800 warning: 'f57f17', // Material Design yellow900 danger: 'dd2c00', // Material Design deeporangeA700 light: 'e0e0e0', // Material Design gray300 dark: '263238', // Material Design bluegray900 // https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords aliceblue: 'f0f8ff', antiquewhite: 'faebd7', aqua: '00ffff', aquamarine: '7fffd4', azure: 'f0ffff', beige: 'f5f5dc', bisque: 'ffe4c4', black: '000000', blanchedalmond: 'ffebcd', blue: '0000ff', blueviolet: '8a2be2', brown: 'a52a2a', burlywood: 'deb887', cadetblue: '5f9ea0', chartreuse: '7fff00', chocolate: 'd2691e', coral: 'ff7f50', cornflowerblue: '6495ed', cornsilk: 'fff8dc', crimson: 'dc143c', cyan: '00ffff', darkblue: '00008b', darkcyan: '008b8b', darkgoldenrod: 'b8860b', darkgray: 'a9a9a9', darkgrey: 'a9a9a9', darkgreen: '006400', darkkhaki: 'bdb76b', darkmagenta: '8b008b', darkolivegreen: '556b2f', darkorange: 'ff8c00', darkorchid: '9932cc', darkred: '8b0000', darksalmon: 'e9967a', darkseagreen: '8fbc8f', darkslateblue: '483d8b', darkslategray: '2f4f4f', darkslategrey: '2f4f4f', darkturquoise: '00ced1', darkviolet: '9400d3', deeppink: 'ff1493', deepskyblue: '00bfff', dimgray: '696969', dimgrey: '696969', dodgerblue: '1e90ff', firebrick: 'b22222', floralwhite: 'fffaf0', forestgreen: '228b22', fuchsia: 'ff00ff', gainsboro: 'dcdcdc', ghostwhite: 'f8f8ff', gold: 'ffd700', goldenrod: 'daa520', gray: '808080', grey: '808080', green: '008000', greenyellow: 'adff2f', honeydew: 'f0fff0', hotpink: 'ff69b4', indianred: 'cd5c5c', indigo: '4b0082', ivory: 'fffff0', khaki: 'f0e68c', lavender: 'e6e6fa', lavenderblush: 'fff0f5', lawngreen: '7cfc00', lemonchiffon: 'fffacd', lightblue: 'add8e6', lightcoral: 'f08080', lightcyan: 'e0ffff', lightgoldenrodyellow: 'fafad2', lightgray: 'd3d3d3', lightgrey: 'd3d3d3', lightgreen: '90ee90', lightpink: 'ffb6c1', lightsalmon: 'ffa07a', lightseagreen: '20b2aa', lightskyblue: '87cefa', lightslategray: '778899', lightslategrey: '778899', lightsteelblue: 'b0c4de', lightyellow: 'ffffe0', lime: '00ff00', limegreen: '32cd32', linen: 'faf0e6', magenta: 'ff00ff', maroon: '800000', mediumaquamarine: '66cdaa', mediumblue: '0000cd', mediumorchid: 'ba55d3', mediumpurple: '9370d8', mediumseagreen: '3cb371', mediumslateblue: '7b68ee', mediumspringgreen: '00fa9a', mediumturquoise: '48d1cc', mediumvioletred: 'c71585', midnightblue: '191970', mintcream: 'f5fffa', mistyrose: 'ffe4e1', moccasin: 'ffe4b5', navajowhite: 'ffdead', navy: '000080', oldlace: 'fdf5e6', olive: '808000', olivedrab: '6b8e23', orange: 'ffa500', orangered: 'ff4500', orchid: 'da70d6', palegoldenrod: 'eee8aa', palegreen: '98fb98', paleturquoise: 'afeeee', palevioletred: 'd87093', papayawhip: 'ffefd5', peachpuff: 'ffdab9', peru: 'cd853f', pink: 'ffc0cb', plum: 'dda0dd', powderblue: 'b0e0e6', purple: '800080', rebeccapurple: '663399', red: 'ff0000', rosybrown: 'bc8f8f', royalblue: '4169e1', saddlebrown: '8b4513', salmon: 'fa8072', sandybrown: 'f4a460', seagreen: '2e8b57', seashell: 'fff5ee', sienna: 'a0522d', silver: 'c0c0c0', skyblue: '87ceeb', slateblue: '6a5acd', slategray: '708090', slategrey: '708090', snow: 'fffafa', springgreen: '00ff7f', steelblue: '4682b4', tan: 'd2b48c', teal: '008080', thistle: 'd8bfd8', tomato: 'ff6347', turquoise: '40e0d0', violet: 'ee82ee', wheat: 'f5deb3', white: 'ffffff', whitesmoke: 'f5f5f5', yellow: 'ffff00', yellowgreen: '9acd32', /* Material Design Colors https://material.io/design/color/the-color-system.html#tools-for-picking-colors */ grey50: 'fafafa', grey100: 'f5f5f5', grey200: 'eeeeee', grey300: 'e0e0e0', grey400: 'bdbdbd', grey500: '9e9e9e', grey600: '757575', grey700: '616161', grey800: '424242', grey900: '212121', gray50: 'fafafa', gray100: 'f5f5f5', gray200: 'eeeeee', gray300: 'e0e0e0', gray400: 'bdbdbd', gray500: '9e9e9e', gray600: '757575', gray700: '616161', gray800: '424242', gray900: '212121', bluegrey50: 'eceff1', bluegrey100: 'CFD8DC', bluegrey200: 'B0BEC5', bluegrey300: '90A4AE', bluegrey400: '78909C', bluegrey500: '607D8B', bluegrey600: '546E7A', bluegrey700: '455A64', bluegrey800: '37474F', bluegrey900: '263238', bluegray50: 'eceff1', bluegray100: 'CFD8DC', bluegray200: 'B0BEC5', bluegray300: '90A4AE', bluegray400: '78909C', bluegray500: '607D8B', bluegray600: '546E7A', bluegray700: '455A64', bluegray800: '37474F', bluegray900: '263238', red50: 'FFEBEE', red100: 'FFCDD2', red200: 'EF9A9A', red300: 'E57373', red400: 'EF5350', red500: 'F44336', red600: 'E53935', red700: 'D32F2F', red800: 'C62828', red900: 'B71C1C', reda100: 'FF8A80', reda200: 'FF5252', reda400: 'FF1744', reda700: 'D50000', pink50: 'FCE4EC', pink100: 'F8BBD0', pink200: 'F48FB1', pink300: 'F06292', pink400: 'EC407A', pink500: 'E91E63', pink600: 'D81B60', pink700: 'C2185B', pink800: 'AD1457', pink900: '880E4F', pinka100: 'FF80AB', pinka200: 'FF4081', pinka400: 'F50057', pinka700: 'C51162', purple50: 'F3E5F5', purple100: 'E1BEE7', purple200: 'CE93D8', purple300: 'BA68C8', purple400: 'AB47BC', purple500: '9C27B0', purple600: '8E24AA', purple700: '7B1FA2', purple800: '6A1B9A', purple900: '4A148C', purplea100: 'EA80FC', purplea200: 'E040FB', purplea400: 'D500F9', purplea700: 'AA00FF', deeppurple50: 'EDE7F6', deeppurple100: 'D1C4E9', deeppurple200: 'B39DDB', deeppurple300: '9575CD', deeppurple400: '7E57C2', deeppurple500: '673AB7', deeppurple600: '5E35B1', deeppurple700: '512DA8', deeppurple800: '4527A0', deeppurple900: '311B92', deeppurplea100: 'B388FF', deeppurplea200: '7C4DFF', deeppurplea400: '651FFF', deeppurplea700: '6200EA', indigo50: 'E8EAF6', indigo100: 'C5CAE9', indigo200: '9FA8DA', indigo300: '7986CB', indigo400: '5C6BC0', indigo500: '3F51B5', indigo600: '3949AB', indigo700: '303F9F', indigo800: '283593', indigo900: '1A237E', indigoa100: '8C9EFF', indigoa200: '536DFE', indigoa400: '3D5AFE', indigoa700: '304FFE', blue50: 'E3F2FD', blue100: 'BBDEFB', blue200: '90CAF9', blue300: '64B5F6', blue400: '42A5F5', blue500: '2196F3', blue600: '1E88E5', blue700: '1976D2', blue800: '1565C0', blue900: '0D47A1', bluea100: '82B1FF', bluea200: '448AFF', bluea400: '2979FF', bluea700: '2962FF', lightblue50: 'E1F5FE', lightblue100: 'B3E5FC', lightblue200: '81D4FA', lightblue300: '4FC3F7', lightblue400: '29B6F6', lightblue500: '03A9F4', lightblue600: '039BE5', lightblue700: '0288D1', lightblue800: '0277BD', lightblue900: '01579B', lightbluea100: '80D8FF', lightbluea200: '40C4FF', lightbluea400: '00B0FF', lightbluea700: '0091EA', cyan50: 'E0F7FA', cyan100: 'B2EBF2', cyan200: '80DEEA', cyan300: '4DD0E1', cyan400: '26C6DA', cyan500: '00BCD4', cyan600: '00ACC1', cyan700: '0097A7', cyan800: '00838F', cyan900: '006064', cyana100: '84FFFF', cyana200: '18FFFF', cyana400: '00E5FF', cyana700: '00B8D4', teal50: 'E0F2F1', teal100: 'B2DFDB', teal200: '80CBC4', teal300: '4DB6AC', teal400: '26A69A', teal500: '009688', teal600: '00897B', teal700: '00796B', teal800: '00695C', teal900: '004D40', teala100: 'A7FFEB', teala200: '64FFDA', teala400: '1DE9B6', teala700: '00BFA5', green50: 'E8F5E9', green100: 'C8E6C9', green200: 'A5D6A7', green300: '81C784', green400: '66BB6A', green500: '4CAF50', green600: '43A047', green700: '388E3C', green800: '2E7D32', green900: '1B5E20', greena100: 'B9F6CA', greena200: '69F0AE', greena400: '00E676', greena700: '00C853', lightgreen50: 'F1F8E9', lightgreen100: 'DCEDC8', lightgreen200: 'C5E1A5', lightgreen300: 'AED581', lightgreen400: '9CCC65', lightgreen500: '8BC34A', lightgreen600: '7CB342', lightgreen700: '689F38', lightgreen800: '558B2F', lightgreen900: '33691E', lightgreena100: 'CCFF90', lightgreena200: 'B2FF59', lightgreena400: '76FF03', lightgreena700: '64DD17', lime50: 'F9FBE7', lime100: 'F0F4C3', lime200: 'E6EE9C', lime300: 'DCE775', lime400: 'D4E157', lime500: 'CDDC39', lime600: 'C0CA33', lime700: 'AFB42B', lime800: '9E9D24', lime900: '827717', limea100: 'F4FF81', limea200: 'EEFF41', limea400: 'C6FF00', limea700: 'AEEA00', yellow50: 'FFFDE7', yellow100: 'FFF9C4', yellow200: 'FFF59D', yellow300: 'FFF176', yellow400: 'FFEE58', yellow500: 'FFEB3B', yellow600: 'FDD835', yellow700: 'FBC02D', yellow800: 'F9A825', yellow900: 'F57F17', yellowa100: 'FFFF8D', yellowa200: 'FFFF00', yellowa400: 'FFEA00', yellowa700: 'FFD600', amber50: 'FFF8E1', amber100: 'FFECB3', amber200: 'FFE082', amber300: 'FFD54F', amber400: 'FFCA28', amber500: 'FFC107', amber600: 'FFB300', amber700: 'FFA000', amber800: 'FF8F00', amber900: 'FF6F00', ambera100: 'FFE57F', ambera200: 'FFD740', ambera400: 'FFC400', ambera700: 'FFAB00', orange50: 'FFF3E0', orange100: 'FFE0B2', orange200: 'FFCC80', orange300: 'FFB74D', orange400: 'FFA726', orange500: 'FF9800', orange600: 'FB8C00', orange700: 'F57C00', orange800: 'EF6C00', orange900: 'E65100', orangea100: 'FFD180', orangea200: 'FFAB40', orangea400: 'FF9100', orangea700: 'FF6D00', deeporange50: 'FBE9E7', deeporange100: 'FFCCBC', deeporange200: 'FFAB91', deeporange300: 'FF8A65', deeporange400: 'FF7043', deeporange500: 'FF5722', deeporange600: 'F4511E', deeporange700: 'E64A19', deeporange800: 'D84315', deeporange900: 'BF360C', deeporangea100: 'FF9E80', deeporangea200: 'FF6E40', deeporangea400: 'FF3D00', deeporangea700: 'DD2C00', brown50: 'EFEBE9', brown100: 'D7CCC8', brown200: 'BCAAA4', brown300: 'A1887F', brown400: '8D6E63', brown500: '795548', brown600: '6D4C41', brown700: '5D4037', brown800: '4E342E', brown900: '3E2723', /* Material Design for Bootstrap v4 themes https://mdbootstrap.com/docs/b4/jquery/css/colors/#mdb-colors */ 'mdb-default': '2BBBAD', 'mdb-default-dark': '00695c', 'mdb-primary': '4285F4', 'mdb-primary-dark': '0d47a1', 'mdb-secondary': 'aa66cc', 'mdb-secondary-dark': '9933CC', 'mdb-danger': 'ff4444', 'mdb-danger-dark': 'CC0000', 'mdb-warning': 'ffbb33', 'mdb-warning-dark': 'FF8800', 'mdb-success': '00C851', 'mdb-success-dark': '007E33', 'mdb-info': '33b5e5', 'mdb-info-dark': '0099CC', 'mdb-elegant': '2E2E2E', 'mdb-elegant-dark': '212121', 'mdb-stylish': '4B515D', 'mdb-stylish-dark': '3E4551', 'mdb-unique': '3F729B', 'mdb-unique-dark': '1C2331', 'mdb-special': '37474F', 'mdb-special-dark': '263238' }, errorReporting: 1, modifier: false, helper: (() => { document.addEventListener('keydown', e => jsPanel.modifier = e); document.addEventListener('keyup', () => jsPanel.modifier = false); })(), usePointerEvents(use = true) { if (!use) { this.pointerdown = 'ontouchend' in window ? ['touchstart', 'mousedown'] : ['mousedown']; this.pointermove = 'ontouchend' in window ? ['touchmove', 'mousemove'] : ['mousemove']; this.pointerup = 'ontouchend' in window ? ['touchend', 'mouseup'] : ['mouseup']; } else { this.pointerdown = 'onpointerdown' in window ? ['pointerdown'] : 'ontouchend' in window ? ['touchstart', 'mousedown'] : ['mousedown']; this.pointermove = 'onpointermove' in window ? ['pointermove'] : 'ontouchend' in window ? ['touchmove', 'mousemove'] : ['mousemove']; this.pointerup = 'onpointerup' in window ? ['pointerup'] : 'ontouchend' in window ? ['touchend', 'mouseup'] : ['mouseup']; } }, // normalize some values passed via panel's options object pOcontainer(container) { if (container === 'window') { return document.body; } else if (typeof container === 'string') { let list = document.querySelectorAll(container); // a returned list is a NodeList return list.length && list.length > 0 ? list : false; } else if (container.nodeType === 1) { return container; } else if (container.length) { return container[0]; } return false; }, pOcontainment(arg) { let value = arg; if (typeof arg === 'function') { value = arg(); } if (typeof value === 'number') { // value: 20 => value: [20, 20, 20, 20] return [value, value, value, value]; } else if (Array.isArray(value)) { if (value.length === 1) { // value: [20] => value: [20, 20, 20, 20] return [value[0], value[0], value[0], value[0]]; } else if (value.length === 2) { // value: [20, 40] => value: [20, 40, 20, 40] return value.concat(value); } else if (value.length === 3) { value[3] = value[1]; } } return value; // assumed to be an array with 4 values }, pOsize(panel, size) { let values = size || this.defaults.contentSize; const parent = panel.parentElement; if (typeof values === 'string') { const nums = values.trim().split(' '); values = {}; values.width = nums[0]; nums.length === 2 ? (values.height = nums[1]) : (values.height = nums[0]); } else { if (values.width && !values.height) { // noinspection JSSuspiciousNameCombination values.height = values.width; } else if (values.height && !values.width) { // noinspection JSSuspiciousNameCombination values.width = values.height; } } if (String(values.width).match(/^[\d.]+$/gi)) { // if number only values.width += 'px'; } else if (typeof values.width === 'string' && values.width.endsWith('%')) { if (parent === document.body) { values.width = window.innerWidth * (parseFloat(values.width) / 100) + 'px'; } else { const prtStyles = window.getComputedStyle(parent), border = parseFloat(prtStyles.borderLeftWidth) + parseFloat(prtStyles.borderRightWidth); values.width = (parseFloat(prtStyles.width) - border) * (parseFloat(values.width) / 100) + 'px'; } } else if (typeof values.width === 'function') { values.width = values.width.call(panel, panel); if (typeof values.width === 'number') { values.width += 'px'; } else if (typeof values.width === 'string' && values.width.match(/^[\d.]+$/gi)) { values.width += 'px'; } } if (String(values.height).match(/^[\d.]+$/gi)) { // if number only values.height += 'px'; } else if (typeof values.height === 'string' && values.height.endsWith('%')) { if (parent === document.body) { values.height = window.innerHeight * (parseFloat(values.height) / 100) + 'px'; } else { const prtStyles = window.getComputedStyle(parent), border = parseFloat(prtStyles.borderTopWidth) + parseFloat(prtStyles.borderBottomWidth); values.height = (parseFloat(prtStyles.height) - border) * (parseFloat(values.height) / 100) + 'px'; } } else if (typeof values.height === 'function') { values.height = values.height.call(panel, panel); if (typeof values.height === 'number') { values.height += 'px'; } else if (typeof values.height === 'string' && values.height.match(/^[\d.]+$/gi)) { values.height += 'px'; } } return values; // return value must be an object {width: xxx, height: xxx} }, pOborder(str) { let result = []; // remove all unnecessary whitepsace let border = str.trim() .replace(/\s*\(\s*/g, '(') // remove whitespace around opening brackets .replace(/\s*\)/g, ')') // remove whitespace around closing brackets .replace(/\s+/g, ' ') // replace all other whitespace(s) with a single whitespace .split(' '); // replace css custom props/variables with values border.forEach((val, index) => { if(val.startsWith('--') || val.startsWith('var')) { border[index] = jsPanel.getCssVariableValue(val); } }); // border is now an array like ['5px', 'solid', 'red'] // check values for type (border width, style or color) and add to result array border.forEach(val => { if (jsPanel.colorNames[val]) { result[2] = '#' + jsPanel.colorNames[val]; } else if (val.match(/(none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset)/)) { result[1] = val; } else if (val.match(/(thin|medium|thick)|(\d*\.?\d*(cap|ch|em|ex|ic|lh|rem|rlh|vh|vw|vmax|vmin|vb|vi|px|cm|mm|Q|in|pc|pt))/)) { result[0] = val; } else { result[2] = val; } }); // set default values if needed if (!result[0]) {result[0] = 'medium';} if (!result[1]) {result[1] = 'solid';} if (!result[2]) {result[2] = '';} return result; }, pOheaderControls(oHdrCtrls) { if (typeof oHdrCtrls === 'string') { let setting = {}, str = oHdrCtrls.toLowerCase(), sizeMatch = str.match(/xl|lg|md|sm|xs/), ctrlMatch = str.match(/closeonly|none/); if (sizeMatch) { setting.size = sizeMatch[0]; } if (ctrlMatch) { setting = Object.assign({}, setting, { maximize: 'remove', normalize: 'remove', minimize: 'remove', smallify: 'remove', }); if (ctrlMatch[0] === 'none') { setting.close = 'remove'; } } return Object.assign({}, this.defaults.headerControls, setting); } else { return Object.assign({}, this.defaults.headerControls, oHdrCtrls); } }, pOtheme(optionTheme) { optionTheme = optionTheme.trim(); let color, filling = ''; if (optionTheme.match(/^(rgb|hsl|var)/)) { // for themes starting with rgb , hsl or var let devide = optionTheme.indexOf(')'); color = optionTheme.slice(0, devide + 1).replace(/\s+/g, ''); if (color.startsWith('var')) { color = jsPanel.getCssVariableValue(color); } filling = optionTheme.slice(devide + 1, optionTheme.length).trim(); } else if (optionTheme.match(/^(#|\w|--)/)) { // for themes starting with #, [A-Za-z0-9_] or -- let devide = optionTheme.indexOf(' '); if (devide > 0) { color = optionTheme.slice(0,devide + 1).replace(/\s+/g, ''); filling = optionTheme.slice(devide + 1, optionTheme.length).trim(); } else { color = optionTheme; } if (color.startsWith('--')) { color = jsPanel.getCssVariableValue(color); } } if (color.match(/^([\da-f]{3}|[\da-f]{6})$/gi)) { color = '#' + color; } if (filling.startsWith('fillcolor')) { let devide = filling.indexOf(' '); filling = filling.slice(devide + 1, filling.length).trim().replace(/\s+/g, ''); if (filling.match(/^([\da-f]{3}|[\da-f]{6})$/gi)) { filling = '#' + filling; } else if (jsPanel.colorNames[filling]) { filling = '#' + jsPanel.colorNames[filling]; } else if (filling.match(/^(--|var)/)) { filling = jsPanel.getCssVariableValue(filling); } else { filling = '#fff'; } } return {color: color, colors: false, filling: filling}; }, // color methods --------------- color(val) { let color = val.toLowerCase(), r, g, b, h, s, l, match, channels, hsl, result = {}; const hexPattern = /^#?([\da-f]{3}|[\da-f]{6})$/gi, // matches "#123" or "#f05a78" with or without "#" RGBAPattern = /^rgba?\((\d{1,3}),(\d{1,3}),(\d{1,3}),?(0|1|0\.\d{1,2}|\.\d{1,2})?\)$/gi, // matches rgb/rgba color values, whitespace allowed HSLAPattern = /^hsla?\((\d{1,3}),(\d{1,3}%),(\d{1,3}%),?(0|1|0\.\d{1,2}|\.\d{1,2})?\)$/gi, namedColors = this.colorNames; // change named color to corresponding hex value if (namedColors[color]) { color = namedColors[color]; } // check val for hex color if (color.match(hexPattern) !== null) { // '#' remove color = color.replace('#', ''); // color has either 3 or 6 characters if (color.length % 2 === 1) { // color has 3 char -> convert to 6 char r = color.slice(0,1).repeat(2); g = color.slice(1,2).repeat(2); b = color.slice(2,3).repeat(2); result.rgb = { r: parseInt(r, 16), g: parseInt(g, 16), b: parseInt(b, 16), }; result.hex = `#${r}${g}${b}`; } else { // color has 6 char result.rgb = { r: parseInt(color.slice(0, 2), 16), g: parseInt(color.slice(2, 4), 16), b: parseInt(color.slice(4, 6), 16) }; result.hex = `#${color}`; } hsl = this.rgbToHsl(result.rgb.r, result.rgb.g, result.rgb.b); result.hsl = hsl; result.rgb.css = `rgb(${result.rgb.r},${result.rgb.g},${result.rgb.b})`; } // check val for rgb/rgba color else if (color.match(RGBAPattern)) { match = RGBAPattern.exec(color); result.rgb = { css: color, r: match[1], g: match[2], b: match[3] }; result.hex = this.rgbToHex(match[1], match[2], match[3]); hsl = this.rgbToHsl(match[1], match[2], match[3]); result.hsl = hsl; } // check val for hsl/hsla color else if (color.match(HSLAPattern)) { match = HSLAPattern.exec(color); h = match[1] / 360; s = match[2].slice(0, match[2].length - 1) / 100; l = match[3].slice(0, match[3].length - 1) / 100; channels = this.hslToRgb(h, s, l); result.rgb = { css: `rgb(${channels[0]},${channels[1]},${channels[2]})`, r: channels[0], g: channels[1], b: channels[2], }; result.hex = this.rgbToHex(result.rgb.r, result.rgb.g, result.rgb.b); result.hsl = { css: `hsl(${match[1]},${match[2]},${match[3]})`, h: match[1], s: match[2], l: match[3], }; } // or return #f5f5f5 else { result.hex = '#f5f5f5'; result.rgb = { css: 'rgb(245,245,245)', r: 245, g: 245, b: 245 }; result.hsl = { css: 'hsl(0,0%,96%)', h: 0, s: '0%', l: '96%' }; } return result; }, calcColors(primaryColor) { const threshold = this.colorBrightnessThreshold, primeColor = this.color(primaryColor), filledlightColor = this.lighten(primaryColor, this.colorFilledLight), filledColor = this.darken(primaryColor, this.colorFilled), fontColorForPrimary = this.perceivedBrightness(primaryColor) <= threshold ? '#ffffff' : '#000000', fontColorFilledlight = this.perceivedBrightness(filledlightColor) <= threshold ? '#ffffff' : '#000000', fontColorFilled = this.perceivedBrightness(filledColor) <= threshold ? '#ffffff' : '#000000', filleddarkColor = this.lighten(primaryColor, this.colorFilledDark), fontColorFilleddark = this.perceivedBrightness(filleddarkColor) <= threshold ? '#ffffff' : '#000000'; return [ primeColor.hsl.css, filledlightColor, filledColor, fontColorForPrimary, fontColorFilledlight, fontColorFilled, filleddarkColor, fontColorFilleddark, ]; }, darken(val, amount) { // amount is value between 0 and 1 const hsl = this.color(val).hsl, l = parseFloat(hsl.l), lnew = Math.round(l - l * amount) + '%'; return `hsl(${hsl.h},${hsl.s},${lnew})`; }, lighten(val, amount) { // amount is value between 0 and 1 const hsl = this.color(val).hsl, l = parseFloat(hsl.l), lnew = Math.round(l + (100 - l) * amount) + '%'; return `hsl(${hsl.h},${hsl.s},${lnew})`; }, hslToRgb(h, s, l) { // h, s and l must be values between 0 and 1 let r, g, b; if (s === 0) { r = g = b = l; // achromatic } else { let hue2rgb = (p, q, t) => { if (t < 0) { t += 1; } if (t > 1) { t -= 1; } if (t < 1 / 6) { return p + (q - p) * 6 * t; } if (t < 1 / 2) { return q; } if (t < 2 / 3) { return p + (q - p) * (2 / 3 - t) * 6; } return p; }; let q = l < 0.5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; }, rgbToHsl(r, g, b) { r /= 255; g /= 255; b /= 255; let max = Math.max(r, g, b), min = Math.min(r, g, b), h, s, l = (max + min) / 2; if (max === min) { h = s = 0; // achromatic } else { let d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } //return [ h, s, l ]; h = Math.round(h * 360); s = Math.round(s * 100) + '%'; l = Math.round(l * 100) + '%'; return { css: 'hsl(' + h + ',' + s + ',' + l + ')', h: h, s: s, l: l }; }, rgbToHex(r, g, b) { let red = Number(r).toString(16), green = Number(g).toString(16), blue = Number(b).toString(16); if (red.length === 1) { red = `0${red}`; } if (green.length === 1) { green = `0${green}`; } if (blue.length === 1) { blue = `0${blue}`; } return `#${red}${green}${blue}`; }, perceivedBrightness(val) { const rgb = this.color(val).rgb; // return value is in the range 0 - 1 and input rgb values must also be in the range 0 - 1 // https://www.w3.org/TR/WCAG20-TECHS/G18.html return (rgb.r / 255) * 0.2126 + (rgb.g / 255) * 0.7152 + (rgb.b / 255) * 0.0722; }, // positioning methods --------------- pOposition(positionshorthand) { let result = {}; // remove leading and trailing whitespace and split position shorthand string into array let pos = positionshorthand.trim().split(/\s+/); // find autoposition value and assign to result, must be the first item to find and remove let auto = pos.filter(item => item.match(/^(down|right|up|left)$/i)); if (auto.length) { result.autoposition = auto[0]; pos.splice(pos.indexOf(auto[0]), 1); } // find my and at values and assign to result let my_at = pos.filter(item => item.match(/^(left-|right-)(top|center|bottom)$|(^center-)(top|bottom)$|(^center$)/i)); if (my_at.length) { result.my = my_at[0]; result.at = my_at[1] || my_at[0]; pos.splice(pos.indexOf(my_at[0]), 1); if (my_at[1]) { pos.splice(pos.indexOf(my_at[1]), 1); } } else { result.my = 'center'; result.at = 'center'; } // find offset and assign to result let offsets = pos.filter(item => item.match(/^[+-]?\d*\.?\d+[a-z%]*$/i)); if (offsets.length) { result.offsetX = offsets[0].match(/^[+-]?\d*\.?\d+$/i) ? `${offsets[0]}px` : offsets[0]; if (offsets[1]) { result.offsetY = offsets[1].match(/^[+-]?\d*\.?\d+$/i) ? `${offsets[1]}px` : offsets[1]; } else { // noinspection JSSuspiciousNameCombination result.offsetY = result.offsetX; } pos.splice(pos.indexOf(offsets[0]), 1); if (offsets[1]) { pos.splice(pos.