smart-webcomponents
Version:
Web Components & Custom Elements for Professional Web Applications
1,433 lines (1,140 loc) • 347 kB
JavaScript
/* Smart UI v22.0.10 (2025-02-10)
Copyright (c) 2011-2025 jQWidgets.
License: https://htmlelements.com/license/ */ //
(function () {
if (typeof window === undefined) {
return;
}
const Version = '21.0.0';
const templates = [];
let namespace = 'Smart';
if (window[namespace] && window[namespace].Version) {
if (window[namespace].Version === Version) {
return;
}
else if (window[namespace].Version !== Version) {
namespace += Version;
}
else {
let suffix = 2;
while (window[namespace]) {
namespace += suffix.toString();
suffix++;
}
}
}
const isEdge = navigator.userAgent.indexOf('Edge') > -1 && navigator.appVersion.indexOf('Edge') > -1;
if (!document.elementsFromPoint) {
document.elementsFromPoint = document.msElementsFromPoint;
}
function Import(urls, async) {
let loadedScriptsLength = 0;
const loadScript = function (url, baseUrl) {
return new Promise(resolve => {
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
for (let j = 0; j < document.head.children.length; j++) {
const child = document.head.children[j];
if (child.src && child.src.toString().indexOf(baseUrl) >= 0) {
resolve();
return;
}
}
document.head.appendChild(script);
});
}
return new Promise(resolve => {
const urlBase = Utilities.Core.getScriptLocation();
const syncLoadScripts = function (index) {
if (!urls[index]) {
return;
}
const url = urlBase + '/' + urls[index];
loadScript(url, urls[index]).then(function () {
loadedScriptsLength++;
if (loadedScriptsLength === urls.length) {
resolve();
}
syncLoadScripts(index + 1)
});
}
if (async) {
for (let i = 0; i < urls.length; i++) {
const url = urlBase + '/' + urls[i];
loadScript(url, urls[i]).then(function () {
loadedScriptsLength++;
if (loadedScriptsLength === urls.length) {
resolve();
}
});
}
}
else {
syncLoadScripts(0);
}
})
}
/** This is a class with utility methods for determing the type of a value. */
class Types {
/**
* Determines whether a value is Boolean.
* @param {Object}.
* @return {Boolean}.
*/
static isBoolean(value) {
return typeof value === 'boolean';
}
/**
* Determines whether a value is Function.
* @param {Object}.
* @return {Boolean}.
*/
static isFunction(value) {
return !!(value && value.constructor && value.call && value.apply);
}
/**
* Determines whether a value is Array.
* @param {Object}.
* @return {Boolean}.
*/
static isArray(value) {
return Array.isArray(value);
}
/**
* Determines whether a value is Object.
* @param {Object}.
* @return {Boolean}.
*/
static isObject(value) {
const that = this;
return (value && (typeof value === 'object' || that.isFunction(value))) || false;
}
/**
* Determines whether a value is Date.
* @param {Object}.
* @return {Boolean}.
*/
static isDate(value) {
return value instanceof Date;
}
/**
* Determines whether a value is String.
* @param {Object}.
* @return {Boolean}.
*/
static isString(value) {
return typeof value === 'string';
}
/**
* Determines whether a value is Number.
* @param {Object}.
* @return {Boolean}.
*/
static isNumber(value) {
return typeof value === 'number';
}
/**
* Determines the type of an object.
* @param {Object}.
* @return {String} The value's type or undefined, if the type is unknown.
*/
static getType(value) {
const that = this;
const types = ['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'Object'];
const type = types.find(type => {
if (that['is' + type](value)) {
return type;
}
});
return type ? type.toLowerCase() : undefined;
}
}
class Ripple {
static animate(element, left, top, callback) {
const target = element;
if (!target || target instanceof HTMLElement === false) {
return;
}
if (target.getElementsByClassName('smart-ripple').length === 0) {
const span = document.createElement('span');
span.classList.add('smart-ripple');
span.setAttribute('role', 'presentation');
let canAppendRipple = true;
let firstElementChild = null;
if (window[namespace].EnableShadowDOM && target.enableShadowDOM && target.isInShadowDOM !== true) {
for (let i = 0; i < target.shadowRoot.host.shadowRoot.children.length; i++) {
if (target.shadowRoot.host.shadowRoot.children[i].tagName.toLowerCase() === 'link') {
continue;
}
firstElementChild = target.shadowRoot.host.shadowRoot.children[i];
}
if (target.shadowRoot.host.shadowRoot.querySelector('.smart-ripple')) {
canAppendRipple = false;
}
}
else {
firstElementChild = target.firstElementChild;
}
if (canAppendRipple) {
if (firstElementChild && !firstElementChild.noRipple && firstElementChild.offsetHeight > 0) {
firstElementChild.appendChild(span);
}
else {
target.appendChild(span);
}
}
}
let ripple = null;
if (window[namespace].EnableShadowDOM && target.shadowRoot) {
ripple = target.shadowRoot.host.shadowRoot.querySelector('.smart-ripple');
}
else {
ripple = target.getElementsByClassName('smart-ripple')[0];
}
if (!ripple) {
return;
}
ripple.innerHTML = '';
ripple.classList.remove('smart-animate');
ripple.style.height = ripple.style.width = Math.max(target.offsetHeight, target.offsetWidth) + 'px';
const parentStyle = window.getComputedStyle(ripple.parentElement),
borderLeftWidth = parseInt(parentStyle.borderLeftWidth) || 0,
borderTopWidth = parseInt(parentStyle.borderTopWidth) || 0,
rect = target.getBoundingClientRect(),
x = left - (rect.left + window.pageXOffset) - ripple.offsetWidth / 2 - borderLeftWidth,
y = top - (rect.top + window.pageYOffset) - ripple.offsetHeight / 2 - borderTopWidth;
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
ripple.classList.add('smart-animate');
//Remove the ripple element when animation is over
ripple.addEventListener('animationend', function handler() {
if (ripple.parentElement) {
ripple.parentElement.removeChild(ripple);
}
if (callback) {
callback();
}
ripple.removeEventListener('animationend', handler);
ripple.removeEventListener('animationcancel', handler);
});
//Remove the ripple element if the animation is canceled. Just in case
ripple.addEventListener('animationcancel', function handler() {
if (ripple.parentElement) {
ripple.parentElement.removeChild(ripple);
}
if (callback) {
callback();
}
ripple.removeEventListener('animationcancel', handler);
ripple.removeEventListener('animationend', handler);
});
}
}
class Easings {
static easeInQuad(t, b, c, d) {
return c * (t /= d) * t + b;
}
static easeOutQuad(t, b, c, d) {
return -c * (t /= d) * (t - 2) + b;
}
static easeInOutQuad(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t + b;
}
return -c / 2 * ((--t) * (t - 2) - 1) + b;
}
static easeInCubic(t, b, c, d) {
return c * (t /= d) * t * t + b;
}
static easeOutCubic(t, b, c, d) {
return c * ((t = t / d - 1) * t * t + 1) + b;
}
static easeInOutCubic(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t * t + b;
}
return c / 2 * ((t -= 2) * t * t + 2) + b;
}
static easeInQuart(t, b, c, d) {
return c * (t /= d) * t * t * t + b;
}
static easeOutQuart(t, b, c, d) {
return -c * ((t = t / d - 1) * t * t * t - 1) + b;
}
static easeInOutQuart(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t * t * t + b;
}
return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
}
static easeInQuint(t, b, c, d) {
return c * (t /= d) * t * t * t * t + b;
}
static easeOutQuint(t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
}
static easeInOutQuint(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t * t * t * t + b;
}
return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
}
static easeInSine(t, b, c, d) {
return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
}
static easeOutSine(t, b, c, d) {
return c * Math.sin(t / d * (Math.PI / 2)) + b;
}
static easeInOutSine(t, b, c, d) {
return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
}
static easeInExpo(t, b, c, d) {
return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
}
static easeOutExpo(t, b, c, d) {
return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
}
static easeInOutExpo(t, b, c, d) {
if (t === 0) {
return b;
}
if (t === d) {
return b + c;
}
if ((t /= d / 2) < 1) {
return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
}
return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
}
static easeInCirc(t, b, c, d) {
return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
}
static easeOutCirc(t, b, c, d) {
return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
}
static easeInOutCirc(t, b, c, d) {
if ((t /= d / 2) < 1) {
return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
}
return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
}
static easeInElastic(t, b, c, d) {
let s = 1.70158;
let p = 0;
let a = c;
if (t === 0) {
return b;
}
if ((t /= d) === 1) {
return b + c;
}
if (!p) {
p = d * .3;
}
if (a < Math.abs(c)) {
a = c;
s = p / 4;
}
else {
s = p / (2 * Math.PI) * Math.asin(c / a);
}
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
}
static easeOutElastic(t, b, c, d) {
let s = 1.70158;
let p = 0;
let a = c;
if (t === 0) {
return b;
}
if ((t /= d) === 1) {
return b + c;
}
if (!p) {
p = d * .3;
}
if (a < Math.abs(c)) {
a = c;
s = p / 4;
}
else {
s = p / (2 * Math.PI) * Math.asin(c / a);
}
return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
}
static easeInOutElastic(t, b, c, d) {
let s = 1.70158;
let p = 0;
let a = c;
if (t === 0) {
return b;
}
if ((t /= d / 2) === 2) {
return b + c;
}
if (!p) {
p = d * (.3 * 1.5);
}
if (a < Math.abs(c)) {
a = c;
s = p / 4;
}
else {
s = p / (2 * Math.PI) * Math.asin(c / a);
}
if (t < 1) {
return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
}
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
}
static easeInBack(t, b, c, d, s) {
if (s === undefined) {
s = 1.70158;
}
return c * (t /= d) * t * ((s + 1) * t - s) + b;
}
static easeOutBack(t, b, c, d, s) {
if (s === undefined) {
s = 1.70158;
}
return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
}
static easeInOutBack(t, b, c, d, s) {
if (s === undefined) {
s = 1.70158;
}
if ((t /= d / 2) < 1) {
return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
}
return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
}
static easeInBounce(t, b, c, d) {
return c - this.easeOutBounce(d - t, 0, c, d) + b;
}
static easeOutBounce(t, b, c, d) {
if ((t /= d) < (1 / 2.75)) {
return c * (7.5625 * t * t) + b;
}
else if (t < (2 / 2.75)) {
return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
}
else if (t < (2.5 / 2.75)) {
return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
}
else {
return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
}
}
static easeInOutBounce(t, b, c, d) {
if (t < d / 2) {
return this.easeInBounce(t * 2, 0, c, d) * .5 + b;
}
return this.easeOutBounce(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
}
}
/** This is a class with utility methods. */
class Core {
static get isMobile() {
const isMobile = /(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase());
const iOS = () => {
return [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod'
].includes(navigator.platform)
// iPad on iOS 13 detection
|| (navigator.userAgent.includes('Mac') && 'ontouchend' in document)
}
if (!isMobile) {
return iOS();
}
return isMobile;
}
static get Browser() {
let versionSearchString;
const browser = function () {
const data = [
{
string: navigator.userAgent, subString: 'Edge', identity: 'Edge'
},
{
string: navigator.userAgent, subString: 'MSIE', identity: 'IE'
},
{
string: navigator.userAgent, subString: 'Trident', identity: 'IE'
},
{
string: navigator.userAgent, subString: 'Firefox', identity: 'Firefox'
},
{
string: navigator.userAgent, subString: 'Opera', identity: 'Opera'
},
{
string: navigator.userAgent, subString: 'OPR', identity: 'Opera'
},
{
string: navigator.userAgent, subString: 'Chrome', identity: 'Chrome'
},
{ string: navigator.userAgent, subString: 'Safari', identity: 'Safari' }
];
for (let i = 0; i < data.length; i++) {
let dataString = data[i].string;
versionSearchString = data[i].subString;
if (dataString.indexOf(data[i].subString) !== -1) {
return data[i].identity;
}
}
return 'Other';
};
const version = function (dataString) {
let index = dataString.indexOf(versionSearchString);
if (index === -1) {
return;
}
const rv = dataString.indexOf('rv:');
if (versionSearchString === 'Trident' && rv !== -1) {
return parseFloat(dataString.substring(rv + 3));
}
else {
return parseFloat(dataString.substring(index + versionSearchString.length + 1));
}
}
let result = {
};
result[browser()] = true;
result.version = version(navigator.userAgent) || version(navigator.appVersion) || 'Unknown';
return result;
}
static toCamelCase(value) {
return value.replace(/-([a-z])/g, function (g) {
return g[1].toUpperCase();
});
}
static toDash(value) {
return value.split(/(?=[A-Z])/).join('-').toLowerCase();
}
static unescapeHTML(value) {
let doc = new DOMParser().parseFromString(value, 'text/html');
return doc.documentElement.textContent;
}
static escapeHTML(value) {
const entityMap = {
'&': '&', '<': '<', '>': '>', '"': '"', '\'': ''', '/': '/', '`': '`', '=': '='
};
return String(value).replace(/[&<>"'`=\/]/g, s => entityMap[s]);
}
static sanitizeHTML(value) {
if (value && (value.indexOf('onclick') >= 0 || value.indexOf('onload') >= 0 || value.indexOf('onerror') >= 0)) {
return this.escapeHTML(value)
}
const regExp = new RegExp('<\s*(applet|audio|base|bgsound|embed|form|iframe|isindex|keygen|layout|link|meta|object|script|svg|style|template|video)[^>]*>(.*?)<\s*/\s*(applet|audio|base|bgsound|embed|form|iframe|isindex|keygen|layout|link|meta|object|script|svg|style|template|video)>', 'ig');
const result = String(value).replace(regExp, s => this.escapeHTML(s));
return result;
}
static createGUID() {
function part() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return part() + part() + '-' + part() + '-' + part() + '-' + part() + '-' + part() + part() + part();
}
static getScriptLocation() {
if (window[namespace].BaseUrl !== './') {
return window[namespace].BaseUrl;
}
const location = (function () {
if (document.currentScript) {
let link = document.currentScript.src;
let lastIndex = link.lastIndexOf('/');
link = link.substring(0, lastIndex);
return link;
}
const error = new Error();
let startCharacter = '(',
endCharacter = ')';
if (Smart.Utilities.Core.Browser.Safari) {
startCharacter = '@';
endCharacter = '\n';
}
if (error.fileName) {
return error.fileName.replace('/smart.element.js', '');
}
let link = error.stack.split(startCharacter);
link = link[1];
link = link.split(endCharacter)[0];
link = link.split(':')
link.splice(-2, 2)
link = link.join(':')
return link.replace('/smart.element.js', '');
})();
return location;
}
static CSSVariablesSupport() {
return window.CSS && window.CSS.supports && window.CSS.supports('(--fake-var: 0)');
}
static assign(target, source) {
const isObject = item => {
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
}
let output = Object.assign({}, target);
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach(key => {
if (isObject(source[key])) {
if (!(key in target)) {
Object.assign(output, { [key]: source[key] });
}
else {
output[key] = this.assign(target[key], source[key]);
}
}
else {
Object.assign(output, { [key]: source[key] });
}
});
}
return output;
}
static html(node, htmlString) {
const that = this;
let output = '';
let nodes = node.childNodes;
if (htmlString) {
const rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
node.innerHTML = htmlString.replace(rxhtmlTag, '<$1></$2>');
return;
}
for (let i = 0, l = nodes.length, child; (i < l) && (child = nodes[i]); i++) {
const miscElements = ['strong'];
if (child instanceof HTMLElement || (child.tagName && miscElements.indexOf(child.tagName.toLowerCase()) >= 0)) {
const tagName = child.tagName.toLowerCase();
const attrs = child.attributes;
let nodeOutput = '<' + tagName;
for (let j = 0, attr; (attr = attrs[j]); j++) {
nodeOutput += ' ' + attr.name + '="' + attr.value.replace(/[&\u00A0"]/g, Utilities.Core.escapeHTML) + '"';
}
nodeOutput += '>';
const voidElements = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
if (voidElements[tagName]) {
output += nodeOutput;
}
output = output + nodeOutput + that.html(child) + '</' + tagName + '>';
}
else if (child.nodeType === 8) {
continue;
}
else {
output += child.textContent.replace(/[&\u00A0<>]/g, Utilities.Core.escapeHTML);
}
}
return output;
}
}
let styleObservedElements = [];
class StyleObserver {
static watch(element) {
switch (element.nodeName.toLowerCase()) {
case 'smart-grid':
case 'smart-kanban':
case 'smart-table':
case 'smart-pivot-table':
case 'smart-scheduler':
case 'smart-tabs':
case 'smart-card-view':
case 'smart-list-box':
case 'smart-combo-box':
case 'smart-drop-down-list':
case 'smart-calendar':
case 'smart-gauge':
case 'smart-numeric-text-box':
case 'smart-menu':
case 'smart-tree':
styleObservedElements.push(element);
break;
default: {
return;
}
}
StyleObserver.start();
}
static start() {
if (StyleObserver.isStarted) {
return;
}
StyleObserver.isStarted = true;
if (StyleObserver.interval) {
clearInterval(StyleObserver.interval);
}
if (styleObservedElements.length === 0 || document.hidden) {
StyleObserver.isStarted = false;
return;
}
StyleObserver.interval = setInterval(function () {
StyleObserver.observe();
}, 100);
}
static stop() {
StyleObserver.isStarted = false;
if (StyleObserver.interval) {
clearInterval(StyleObserver.interval);
}
}
static observeElement(element) {
const that = element;
if (window.Smart.Mode === 'test' || document.hidden) {
if (StyleObserver.interval) {
clearInterval(StyleObserver.interval);
}
return;
}
let computedStyle = element._computedStyle || that.hasStyleObserver !== 'resize' ? document.defaultView.getComputedStyle(that, null) : {
};
let canRaiseResize = true;
let styleProperties = that.hasStyleObserver !== 'resize' ? ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth', 'borderBottomWidth', 'display', 'visibility', 'font-size', 'font-family', 'font-style', 'font-weight', 'max-height', 'min-height', 'max-width', 'min-width', 'overflow', 'overflow-x', 'overflow-y']
: [];
if (element.styleProperties) {
styleProperties = styleProperties.concat(element.styleProperties);
}
if (element.observableStyleProperties) {
styleProperties = element.observableStyleProperties;
}
if (!that._styleInfo) {
that._styleInfo = [];
for (let i = 0; i < styleProperties.length; i++) {
const styleProperty = styleProperties[i];
const propertyValue = styleProperty.startsWith('--') ? computedStyle.getPropertyValue(styleProperty) : computedStyle[styleProperty];
that._styleInfo[styleProperty] = propertyValue;
}
return;
}
if (!element.isHidden) {
if (computedStyle['display'] !== 'none') {
if (element.offsetWidth === 0 || element.offsetHeight === 0) {
element.isHidden = true;
}
}
}
if (element.isHidden) {
element.visibilityChangedHandler();
if (!element.isHidden) {
canRaiseResize = false;
}
else {
return;
}
}
let changedStyleProperties = [];
for (let i = 0; i < styleProperties.length; i++) {
const styleProperty = styleProperties[i];
const propertyValue = styleProperty.startsWith('--') ? computedStyle.getPropertyValue(styleProperty) : computedStyle[styleProperty];
if (that._styleInfo[styleProperty] !== propertyValue) {
changedStyleProperties[styleProperty] = {
oldValue: that._styleInfo[styleProperty], value: propertyValue
};
changedStyleProperties.length++;
}
that._styleInfo[styleProperty] = propertyValue;
}
if (changedStyleProperties.length > 0) {
that.$.fireEvent('styleChanged', {
styleProperties: changedStyleProperties
},
{
bubbles: false,
cancelable: true
}
);
if (changedStyleProperties['display'] && canRaiseResize) {
that.$.fireEvent('resize', that, {
bubbles: false,
cancelable: true
});
}
}
}
static observe() {
for (let i = 0; i < styleObservedElements.length; i++) {
const that = styleObservedElements[i];
this.observeElement(that);
}
}
static unwatch(element) {
StyleObserver.stop();
const elementIndex = styleObservedElements.indexOf(element);
if (elementIndex !== -1) {
styleObservedElements.splice(elementIndex, 1);
}
StyleObserver.start();
}
}
let dataContextInfo = [];
const data = [];
const inputEventTypes = ['resize', 'down', 'up', 'move', 'tap', 'taphold', 'swipeleft', 'swiperight', 'swipetop', 'swipebottom'];
/** This is a class which extends an element and adds custom input events to it. */
class InputEvents {
constructor(target) {
const that = this;
that.target = target;
that.$target = new Extend(target);
that.$document = target.$document ? target.$document : new Extend(document);
that.id = (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase();
// that.target === document ? '' : that.target.id || that.target.getAttribute('smart-id');
let result = {
handlers: {}, boundEventTypes: [], listen: that.listen.bind(that), unlisten: that.unlisten.bind(that)
};
//The taphold delay. If this delay is passed then taphold event will be fired.
that.tapHoldDelay = 750;
//Defines the minimum swipe distance required by the plugin.
that.swipeMin = 10;
//Defines the maximum swipe distance. After it is passed the propagation of the event will be restored, therefore the scrolling will be available.
that.swipeMax = 5000;
//The swipe delay. After it is passed swipe event won't be fired.
that.swipeDelay = 1000;
//The taphold delay. If this delay is passed then taphold event will be fired.
that.tapHoldDelay = 750;
that.inputEventProperties = ['clientX', 'clientY', 'pageX', 'pageY', 'screenX', 'screenY'];
inputEventTypes.forEach((eventType) => {
result[eventType] = (handler) => {
result.handlers[eventType] = handler;
}
that[eventType] = (event) => {
if (!result.handlers[event.type]) {
if ((event.type === 'mousemove' || event.type === 'pointermove' || event.type === 'touchmove') && result.handlers['move']) {
const moveEvent = that.createEvent(event, 'move');
result.handlers['move'](moveEvent);
}
return true;
}
return result.handlers[event.type](event);
};
});
that.listen();
that.handlers = result.handlers;
return result;
}
listen(eventType) {
const that = this;
if (eventType === 'resize' && that.target !== document && that.target !== window && that.target.hasResizeObserver !== false) {
if (Smart.Utilities.Core.Browser.Firefox) {
if (!that.target.resizeObserver) {
let firstCallPassed = false;
let dirty, newWidth, newHeight;
let lastWidth = that.target.offsetWidth;
let lastHeight = that.target.offsetHeight;
const resizeObserver = new ResizeObserver(() => {
if (!firstCallPassed) {
firstCallPassed = true;
return;
}
const resizeEvent = new CustomEvent('resize', {
bubbles: false,
cancelable: true
});
newWidth = that.target.offsetWidth;
newHeight = that.target.offsetHeight;
dirty = newWidth !== lastWidth || newHeight !== lastHeight;
if (that.target.requiresLayout) {
dirty = true;
}
if (!dirty) {
return;
}
that.resize(resizeEvent);
that.target.requiresLayout = false;
lastWidth = newWidth;
lastHeight = newHeight;
});
resizeObserver.observe(that.target);
that.target.resizeObserver = resizeObserver;
}
}
else if (!that.target.resizeTrigger) {
const container = document.createElement('div');
container.className = 'smart-resize-trigger-container';
container.innerHTML =
'<div class="smart-resize-trigger-container">' +
'<div class="smart-resize-trigger"></div>' +
'</div>' +
'<div class="smart-resize-trigger-container">' +
'<div class="smart-resize-trigger-shrink"></div>' +
'</div>';
container.setAttribute('aria-hidden', true);
if (window[namespace].EnableShadowDOM && that.target.shadowRoot) {
that.target.shadowRoot.appendChild(container);
}
else {
that.target.appendChild(container);
}
that.target.resizeTrigger = container;
const expand = container.childNodes[0];
const expandChild = expand.childNodes[0];
const shrink = container.childNodes[1];
const reset = function () {
expandChild.style.width = '100000px';
expandChild.style.height = '100000px';
expand.scrollLeft = 100000;
expand.scrollTop = 100000;
shrink.scrollLeft = 100000;
shrink.scrollTop = 100000;
};
let dirty, requestAnimationFrameId, newWidth, newHeight;
let lastWidth = that.target.offsetWidth;
let lastHeight = that.target.offsetHeight;
if (lastWidth === 0 || lastHeight === 0) {
const resizeFunc = function () {
reset();
that.target.removeEventListener('resize', resizeFunc);
}
that.target.addEventListener('resize', resizeFunc);
reset();
}
else {
reset();
}
that.target.resizeHandler = function () {
if (!requestAnimationFrameId) {
requestAnimationFrameId = requestAnimationFrame(function () {
requestAnimationFrameId = 0;
newWidth = that.target.offsetWidth;
newHeight = that.target.offsetHeight;
dirty = newWidth !== lastWidth || newHeight !== lastHeight;
if (that.target.requiresLayout) {
dirty = true;
}
if (!dirty) {
return;
}
lastWidth = newWidth;
lastHeight = newHeight;
const resizeEvent = new CustomEvent('resize', {
bubbles: false,
cancelable: true
});
that.resize(resizeEvent);
that.target.requiresLayout = false;
});
}
reset();
};
expand.addEventListener('scroll', that.target.resizeHandler);
shrink.addEventListener('scroll', that.target.resizeHandler);
}
}
if (that.isListening) {
return;
}
that.isListening = true;
that.isPressed = false;
that.isReleased = false;
that.isInBounds = false;
if (window.PointerEvent) {
that.$target.listen('pointerdown.inputEvents' + that.id, that.pointerDown.bind(that));
that.$target.listen('pointerup.inputEvents' + that.id, that.pointerUp.bind(that));
that.$target.listen('pointermove.inputEvents' + that.id, that.pointerMove.bind(that));
that.$target.listen('pointercancel.inputEvents' + that.id, that.pointerCancel.bind(that));
}
else {
const hasTouch = 'ontouchstart' in window;
if (hasTouch) {
that.$target.listen('touchmove.inputEvents' + that.id, that.touchMove.bind(that));
that.$target.listen('touchstart.inputEvents' + that.id, that.touchStart.bind(that));
that.$target.listen('touchend.inputEvents' + that.id, that.touchEnd.bind(that));
that.$target.listen('touchcancel.inputEvents' + that.id, that.touchCancel.bind(that));
}
that.$target.listen('mousedown.inputEvents' + that.id, that.mouseDown.bind(that));
that.$target.listen('mouseup.inputEvents' + that.id, that.mouseUp.bind(that));
that.$target.listen('mousemove.inputEvents' + that.id, that.mouseMove.bind(that));
that.$target.listen('mouseleave.inputEvents' + that.id, that.mouseLeave.bind(that));
}
if (!that.target._handleDocumentUp) {
that.target._handleDocumentUp = that.handleDocumentUp.bind(that);
that.target._handleDocumentUpId = that.id;
that.$document.listen('mouseup.inputEvents' + that.target._handleDocumentUpId, that.target._handleDocumentUp);
}
}
unlisten(eventType) {
const that = this;
that.isListening = false;
if (window.PointerEvent) {
that.$target.unlisten('pointerdown.inputEvents' + that.id);
that.$target.unlisten('pointerup.inputEvents' + that.id);
that.$target.unlisten('pointermove.inputEvents' + that.id);
that.$target.unlisten('pointercancel.inputEvents' + that.id);
}
else {
const hasTouch = 'ontouchstart' in window;
if (hasTouch) {
that.$target.unlisten('touchstart.inputEvents' + that.id);
that.$target.unlisten('touchmove.inputEvents' + that.id);
that.$target.unlisten('touchend.inputEvents' + that.id);
that.$target.unlisten('touchcancel.inputEvents' + that.id);
}
that.$target.unlisten('mousedown.inputEvents' + that.id);
that.$target.unlisten('mouseup.inputEvents' + that.id);
that.$target.unlisten('mousemove.inputEvents' + that.id);
that.$target.unlisten('mouseleave.inputEvents' + that.id);
}
if (that.target._handleDocumentUp) {
that.$document.unlisten('mouseup.inputEvents' + that.target._handleDocumentUpId, that.target._handleDocumentUp);
delete that.target._handleDocumentUp;
delete that.target._handleDocumentUpId;
}
if (eventType === 'resize') {
if (Smart.Utilities.Core.Browser.Firefox) {
if (that.target.resizeObserver) {
that.target.resizeObserver.unobserve(that.target);
delete that.target.resizeObserver;
}
}
else if (that.target.resizeTrigger) {
const container = that.target.resizeTrigger;
const expand = container.childNodes[0];
const shrink = container.childNodes[1];
expand.removeEventListener('scroll', that.target.resizeHandler);
shrink.removeEventListener('scroll', that.target.resizeHandler);
that.target.resizeHandler = null;
container.parentNode.removeChild(container);
delete that.target.resizeTrigger;
}
}
}
handleDocumentUp(event) {
const that = this;
that.isPressed = false;
that.isReleased = false;
that.resetSwipe(event);
}
createEvent(event, eventType) {
const that = this;
const touches = event.touches;
const changedTouches = event.changedTouches;
const touch = (touches && touches.length) ? touches[0] : ((changedTouches && changedTouches.length) ? changedTouches[0] : undefined);
const customEvent = new CustomEvent(eventType, {
bubbles: true,
cancelable: true,
composed: that.$target.element.getRootNode().host !== undefined
});
customEvent.originalEvent = event;
if (touch) {
for (let j = 0; j < that.inputEventProperties.length; j++) {
const key = that.inputEventProperties[j];
customEvent[key] = touch[key];
}
return customEvent;
}
for (let key in event) {
if (!(key in customEvent)) {
customEvent[key] = event[key];
}
}
return customEvent;
}
fireTap(event) {
const that = this;
clearTimeout(this.tapHoldTimeout);
if (!this.tapHoldFired && this.isInBounds) {
const tap = that.createEvent(event, 'tap');
that.tap(tap);
}
}
initTap(event) {
const that = this;
that.isInBounds = true;
that.tapHoldFired = false;
that.tapHoldTimeout = setTimeout(function () {
if (that.isInBounds) {
that.tapHoldFired = true;
const taphold = that.createEvent(event, 'taphold');
that.taphold(taphold);
}
}, that.tapHoldDelay);
}
pointerDown(event) {
const that = this;
return that.handleDown(event);
}
mouseDown(event) {
const that = this;
if (that.isPressed || (that.touchStartTime && new Date() - that.touchStartTime < 500)) {
return;
}
return that.handleDown(event);
}
touchStart(event) {
const that = this;
that.touchStartTime = new Date();
that.isTouchMoved = true;
return that.handleDown(event);
}
mouseUp(event) {
const that = this;
if (that.isReleased || (that.touchEndTime && new Date() - that.touchEndTime < 500)) {
return;
}
return that.handleUp(event);
}
handleDown(event) {
const that = this;
that.isReleased = false;
that.isPressed = true;
const down = that.createEvent(event, 'down');
if (that.handlers['tap'] || that.handlers['taphold']) {
that.initTap(down);
}
if (that.handlers['swipeleft'] || that.handlers['swiperight'] || that.handlers['swipetop'] || that.handlers['swipebottom']) {
that.initSwipe(down);
}
return that.down(down);
}
handleUp(event) {
const that = this;
that.isReleased = true;
that.isPressed = false;
const up = that.createEvent(event, 'up');
const result = that.up(up);
if (that.handlers['tap'] || that.handlers['taphold']) {
that.fireTap(up);
}
that.resetSwipe(up);
return result;
}
handleMove(event) {
const that = this;
let eventResult = that.move(event);
if (that.isPressed) {
that._maxSwipeVerticalDistance = Math.max(that._maxSwipeVerticalDistance, Math.abs(that._startY - event.pageY));
that._maxSwipeHorizontalDistance = Math.max(that._maxSwipeHorizontalDistance, Math.abs(that._startX - event.pageX));
eventResult = that.handleSwipeEvents(event);
}
return eventResult;
}
touchEnd(event) {
const that = this;
that.touchEndTime = new Date();
return that.handleUp(event);
}
pointerUp(event) {
const that = this;
return that.handleUp(event);
}
pointerCancel(event) {
const that = this;
that.pointerUp(event);
}
touchCancel(event) {
const that = this;
that.touchEnd(event);
}
mouseLeave() {
const that = this;
that.isInBounds = false;
}
mouseMove(event) {
const that = this;
if (that.isTouchMoved) {
return;
}