UNPKG

smart-webcomponents

Version:

Web Components & Custom Elements for Professional Web Applications

1,433 lines (1,140 loc) 347 kB
/* 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 = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', '\'': '&#39;', '/': '&#x2F;', '`': '&#x60;', '=': '&#x3D;' }; 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; }