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
JavaScript
/**
* 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.