UNPKG

yahoo-x-bv-player

Version:

yahoo-x-bv-player is a video player web component which based on BlendVision Web SDK. It has not only LIVE but also REPLAY features for Yahoo Auction. Sellers could display their products through this player and interact with buyers. We believe this could

1,095 lines (989 loc) 30.2 kB
export const _wcl = {}; Object.defineProperties(_wcl, { getUUID: { configurable: true, enumerable: true, value: function() { return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); } }, getWCConfig: { configurable: true, enumerable: true, value: async function(host) { // gather web component's config from [remoteconfig] or inner script[type=application/json] let error, config; const remoteconfig = host.getAttribute('remoteconfig'); const script = host.querySelector(':scope > script[type="application/json"]'); if (remoteconfig) { // fetch remote config once [remoteconfig] exist try { const configUrl = new URL(remoteconfig); config = await fetch(configUrl.toString(), { headers: { 'content-type': 'application/json' }, method: 'GET', mode: 'cors' }) .then( (response) => { if (!response.ok) { throw new Error('Network response was not OK'); } return response.json(); } ) .catch( (err) => { error = err.message; return {}; } ); } catch(err) { error = err.message; } } else if (script) { // apply inner script's config try { config = JSON.parse(script.textContent.replace(/\n/g, '').trim()); } catch(err) { error = err.message; } } return { config, error }; } }, whenDefined: { configurable: true, enumerable: true, value: function() { /** * Check lib ready * @example whenDefined('document.body', 'YT.Player').then(...) */ const units = Array.from(arguments); if (units.indexOf('document.body') === -1) { units.push('document.body'); } const promises = units.map( (unit) => { return new Promise((resolve, reject) => { let c, iid; const max = 10000; c = 0; iid = setInterval(() => { let _root, parts; c += 5; if (c > max) { clearInterval(iid); return reject(new Error(`"${unit}" unit missing.`)); } _root = window; parts = unit.split('.'); while (parts.length) { const prop = parts.shift(); if (typeof _root[prop] === 'undefined') { _root = null; break; } else { _root = _root[prop]; } } if (_root !== null && document.readyState && document.readyState !== 'loading') { clearInterval(iid); return resolve(); } }, 5); }); } ); return Promise.all(promises); } }, loadScript: { configurable: true, enumerable: true, value: function() { /** * Load script(s) to the document * @example loadScript('script-path') loadScript('script-path1', 'script-path2') */ const currentScripts = Array.from(document.getElementsByTagName('script')).map( (script) => script.src ); Array.from(arguments).forEach( (path) => { if (currentScripts.includes(path)) { return; } const script = document.createElement('script'); document.head.appendChild(script); script.async = true; script.src = path; } ); } }, camelCase: { configurable: true, enumerable: true, value: function(str) { return str.replace(/-([a-z])/ig, function(all, letter) { return letter.toUpperCase(); } ); } }, capitalize: { configurable: true, enumerable: true, value: function(str) { return str.replace(/^[a-z]{1}/, function($1) { return $1.toUpperCase(); } ); } }, checkVisibility: { configurable: true, enumerable: true, value: function(element) { let result = true; if (element.checkVisibility) { result = element.checkVisibility({ contentVisibilityAuto:true, opacityProperty:true, visibilityProperty:true }); } else if (element.computedStyleMap) { const allComputedStyles = element.computedStyleMap(); const { value: display } = allComputedStyles.get('display'); const { value: opacity } = allComputedStyles.get('opacity'); const { value: visibility } = allComputedStyles.get('visibility'); const { value: contentVisibility } = allComputedStyles.get('content-visibility'); result = opacity === 0 || ['none', 'contents'].includes(display) || visibility === 'hidden' || contentVisibility === 'auto' ? false : true; } else if (window.getComputedStyle) { const allComputedStyles = window.getComputedStyle(element); const display = allComputedStyles.getPropertyValue('display'); const opacity = allComputedStyles.getPropertyValue('opacity'); const visibility = allComputedStyles.getPropertyValue('visibility'); const contentVisibility = allComputedStyles.getPropertyValue('content-visibility'); result = +opacity === 0 || ['none', 'contents'].includes(display) || visibility === 'hidden' || contentVisibility === 'auto' ? false : true; } return result; } }, rgbToHex: { configurable: true, enumerable: true, value: function(r, g, b) { /* * https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb * ex: * rgbToHex(255, 0, 0) */ return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); } }, hexToRgb: { configurable: true, enumerable: true, value: function(hex) { /* * https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb * ex: * hexToRgb("#0033ff").g * hexToRgb("#03f").g */ const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; hex = hex.replace(shorthandRegex, function(m, r, g, b) { return r + r + g + g + b + b; }); const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } }, getLuminosity: { configurable: true, enumerable: true, value: function(hex) { /* * https://codepen.io/borlyjenkins/pen/dyPXjPr * https://github.com/Qix-/color * ex: * getLuminosity("#0033ff") * luminosity < 0.57 ? white-text : black-text */ const { r, g, b } = this.hexToRgb(hex); return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255; } }, classToTagName: { configurable: true, enumerable: true, value: function(str) { return str.replace(/([A-Z])/g, function(all, letter) { return '-' + letter.toLowerCase(); } ).replace(/^-(.*)/, '$1'); } }, isObject: { configurable: true, enumerable: true, value: (value) => value && typeof value === 'object' && value.constructor === Object }, isNumeric: { configurable: true, enumerable: true, value: (value) => !isNaN(value - parseFloat(value)) }, isAPISupport: { configurable: true, enumerable: true, value: function(apiName, element) { let node, flag; navigator.supports = navigator.supports || {}; navigator.supports.api = navigator.supports.api || {}; if (typeof navigator.supports.api[apiName] !== 'undefined') { flag = navigator.supports.api[apiName]; } else { if (element) { node = (element.tagName) ? element.cloneNode(true) : element; } else { node = window; } flag = ['', 'webkit', 'moz', 'o', 'ms'].find( (key) => { let s; s = key + (key ? this.capitalize(apiName) : apiName); return node[s]; } ); flag = (flag !== undefined) ? true : false; //localStorage if (['localStorage', 'sessionStorage'].includes(apiName) && flag) { try { localStorage.setItem('isapisupport', 'dummy'); localStorage.removeItem('isapisupport'); } catch(err) { flag = false; } }//end if navigator.supports.api[apiName] = flag; node = null; } return flag; } }, isEventSupport: { configurable: true, enumerable: true, value: function(eventName, element) { /** * reference: * http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ * @example * isEventSupport('touchstart'); */ let node, flag; navigator.supports = navigator.supports || {}; navigator.supports.event = navigator.supports.event || {}; if (typeof navigator.supports.event[eventName] !== 'undefined') { flag = navigator.supports.event[eventName]; } else { if (element) { node = (element.tagName) ? element.cloneNode(true) : element; } else { node = document.createElement('div'); } flag = `on${eventName}` in node; if (!flag && node.setAttribute) { node.setAttribute(eventName, 'return;'); flag = typeof node[eventName] == 'function'; } navigator.supports.event[eventName] = flag; node = null; } return flag; } }, isCSSPropertySupport: { configurable: true, enumerable: true, value: function(property) { /** * @example * isCSSPropertySupport('overscroll-behavior'); * * otherwise, maybe we can try CSS.supports * https://developer.mozilla.org/en-US/docs/Web/API/CSS/supports */ let node, flag; navigator.supports = navigator.supports || {}; navigator.supports.css = navigator.supports.css || {}; property = (/^-ms/.test(property)) ? ('ms' + this.camelCase(property.replace(/-ms/,''))) : this.camelCase(property); if (typeof navigator.supports.css[property] !== 'undefined') { flag = navigator.supports.css[property]; } else { node = document.createElement('div'); flag = property in node.style; navigator.supports.css[property] = flag; node = null; } return flag; } }, isStaticImportSupport:{ configurable: true, enumerable: true, value: () => { /* * https://gist.github.com/ebidel/3201b36f59f26525eb606663f7b487d0 */ navigator.supports = navigator.supports || {}; if (typeof navigator.supports.staticImport === 'undefined') { const script = document.createElement('script'); navigator.supports.staticImport = 'noModule' in script; } return navigator.supports.staticImport; } }, isDynamicImportSupport:{ configurable: true, enumerable: true, value: () => { /* * https://gist.github.com/ebidel/3201b36f59f26525eb606663f7b487d0 */ navigator.supports = navigator.supports || {}; if (typeof navigator.supports.dynamicImport === 'undefined') { try { new Function('import("")'); navigator.supports.dynamicImport = true; } catch (err) { navigator.supports.dynamicImport = false; } } return navigator.supports.dynamicImport; } }, isPrefersColorSchemeSet: { configurable: true, enumerable: true, get: () => { return Array.from(document.styleSheets).some( (styleSheet) => { try { return Array.from(styleSheet.rules).some( (rule) => { return rule.media && /prefers-color-scheme:.*dark/i.test(rule.conditionText); } ); } catch(err) { return false; } } ); } }, isIOS: { configurable: true, enumerable: true, get: () => !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform) }, isMobile: { configurable: true, enumerable: true, value: () => navigator.userAgent.match(/(iPhone|iPod|iPad|Android|webOS|BlackBerry|IEMobile|Opera Mini)/i) || false }, grabEventLock: { configurable: true, enumerable: true, value: function() { return navigator.eventLock || (function() { this.addStylesheetRules('.scroll-lock', { 'overflow': 'hidden', 'pointer-events': 'none' }); navigator.eventLock = (evt) => { evt.preventDefault(); evt.stopImmediatePropagation(); }; return navigator.eventLock; }).bind(this)(); } }, scrollLock: { configurable: true, enumerable: true, value: function(isLock = true, eventLock = this.grabEventLock()) { isLock = Boolean(isLock); if (isLock) { document.body.classList.add('scroll-lock'); window.addEventListener('touchmove', eventLock, { passive: false }); } else { document.body.classList.remove('scroll-lock'); window.removeEventListener('touchmove', eventLock); } } }, scrollX: { configurable: true, enumerable: true, get: () => { return _wcl.getScroll().x; }, set: (x) => { if (document.documentElement && document.documentElement.scrollLeft) { document.documentElement.scrollLeft = x; } else { document.body.scrollLeft = x; } } }, scrollY: { configurable: true, enumerable: true, get: () => { return _wcl.getScroll().y; }, set: (y) => { if (document.documentElement && document.documentElement.scrollTop) { document.documentElement.scrollTop = y; } else { document.body.scrollTop = y; } } }, rollTo: { configurable: true, enumerable: true, value: function(y, offset = 0) { /* * y could be y-coord or DOM element */ const { height } = this.getPageSize(); const { height:winHeight } = this.getViewportSize(); if (typeof y.nodeType !== 'undefined' && y.nodeType === 1 && typeof y.getBoundingClientRect === 'function') { y = this.getPosition(y).y; } y += offset; return new Promise((resolve) => { let iid; const scroll = () => { let shift = Math.ceil((y - this.scrollY) * 0.15); cancelAnimationFrame(iid); scrollBy(0, shift); if (this.scrollY < 0 || this.scrollY + winHeight >= height || shift === 0 || Math.abs(this.scrollY - y) <= Math.abs(shift)) { this.scrollY = y; resolve(); return; } else { iid = requestAnimationFrame(scroll); } }; iid = requestAnimationFrame(scroll); }); } }, maxZIndex: { configurable: true, enumerable: true, get: () => { return Array.from(document.querySelectorAll('body *')) .map((a) => parseFloat(window.getComputedStyle(a).zIndex)) .filter((a) => !isNaN(a)) .sort((a,b) => a - b) .pop(); } }, pointer: { configurable: true, enumerable: true, value: function(e) { let x, y, clientX, clientY, docElement, body; docElement = document.documentElement; if (e?.touches && e?.touches?.length > 0) { clientX = e?.touches?.[0]?.clientX; clientY = e?.touches?.[0]?.clientY; } else { clientX = e.clientX; clientY = e.clientY; } //x body = document.body || { scrollLeft: 0 }; x = e?.pageX || (clientX + (docElement.scrollLeft || body.scrollLeft) - (docElement.clientLeft || 0)); //y body = document.body || { scrollTop: 0 }; y = e?.pageY || (clientY + (docElement.scrollTop || body.scrollTop) - (docElement.clientTop || 0)); return { x, y }; } }, pursuer: { configurable: true, enumerable: true, value: function() { let down, move, up; if (this.isEventSupport('touchstart')) { down = 'touchstart'; move = 'touchmove'; up = 'touchend'; } else if (typeof navigator.msPointerEnabled != 'undefined' && navigator.msPointerEnabled) { down = 'MSPointerDown'; move = 'MSPointerMove'; up = 'MSPointerUp'; } else { down = 'mousedown'; move = 'mousemove'; up = 'mouseup'; } return {down, move, up}; } }, purgeObject: { configurable: true, enumerable: true, value: function(targetObject) { if (this.isObject(targetObject)) { Object.keys(targetObject).forEach( (key) => { let { [key]:prop } = targetObject; if (Array.isArray(prop)) { while (prop.length) { prop.pop(); }// end while }// end if targetObject[key] = null; } ); }// end if } }, isPiPSupport: { configurable: true, enumerable: true, value: function() { navigator.supports = navigator.supports || {}; if (typeof navigator.supports.PiP === 'undefined') { const node = document.createElement('video'); navigator.supports.PiP = this.isAPISupport('requestPictureInPicture', node) || (node.webkitSupportsPresentationMode && typeof node.webkitSetPresentationMode === 'function'); } return navigator.supports.PiP; } }, isFullscreenSupport: { configurable: true, enumerable: true, value: function() { navigator.supports = navigator.supports || {}; if (!navigator.supports.fullscreen) { const node = document.createElement('div'); let request = false; let exit = false; let element = ''; let event = ''; if (node.requestFullscreen) { request = 'requestFullscreen'; exit = 'exitFullscreen'; element = 'fullscreenElement'; event = 'fullscreenchange'; // } else if (node.msRequestFullscreen) { // request = 'msRequestFullscreen'; // exit = 'msExitFullscreen'; } else if (node.webkitRequestFullscreen) { request = 'webkitRequestFullscreen'; exit = 'webkitExitFullscreen'; element = 'webkitFullscreenElement'; event = 'webkitfullscreenchange'; } navigator.supports.fullscreen = { request, exit, element, event }; } return navigator.supports.fullscreen; } }, supports: { configurable: true, enumerable: true, value: function() { // let flag; navigator.supports = navigator.supports || {}; if (!navigator.supports.wp) { // flag = true; // try { // class DummyClass {} // } catch (err) { // flag = false; // } navigator.supports.wp = { // classes: flag, customElements: 'customElements' in window, import: 'import' in document.createElement('link'), shadowDOM: !!HTMLElement.prototype.attachShadow, template: 'content' in document.createElement('template') }; } return navigator.supports.wp; } }, getScroll: { configurable: true, enumerable: true, value: () => { let x, y; x = (self.pageXOffset) ? self.pageXOffset : (document.documentElement && document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft; y = (self.pageYOffset) ? self.pageYOffset : (document.documentElement && document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop; return { x, y }; } }, getPosition: { configurable: true, enumerable: true, value: (element) => { let x, y; x = 0; y = 0; while (element != null) { x += element.offsetLeft; y += element.offsetTop; element = element.offsetParent; } return { x, y }; } }, getPageSize: { configurable: true, enumerable: true, value: function() { let xScroll, yScroll, width, height; const { width:winWidth, height:winHeight } = this.getViewportSize(); if (window.innerHeight && window.scrollMaxY) { xScroll = document.body.scrollWidth; yScroll = window.innerHeight + window.scrollMaxY; } else if (document.body.scrollHeight > document.body.offsetHeight) { xScroll = document.body.scrollWidth; yScroll = document.body.scrollHeight; } else { xScroll = document.body.offsetWidth; yScroll = document.body.offsetHeight; } width = (xScroll < winWidth) ? winWidth : xScroll; height = (yScroll < winHeight) ? winHeight : yScroll; return { width, height }; } }, getViewportSize: { configurable: true, enumerable: true, value: () => { let width, height; if (self.innerHeight) { width = self.innerWidth; height = self.innerHeight; } else if (document.documentElement && document.documentElement.clientHeight) { width = document.documentElement.clientWidth; height = document.documentElement.clientHeight; } else if (document.body) { width = document.body.clientWidth; height = document.body.clientHeight; } return { width, height }; } }, getSize: { configurable: true, enumerable: true, value: (element) => { let width, height; width = element.offsetWidth; height = element.offsetHeight; return { width, height }; } }, getRand: { configurable: true, enumerable: true, value: (a, b) => { let min, max; if (a > b) { min = a; max = b; } else { min = b; max = a; } return Math.floor(Math.random() * (max - min + 1) + min); } }, getRandomIntInclusive: { configurable: true, enumerable: true, value: (min, max) => { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; } }, grabStyleSheet: { configurable: true, enumerable: true, value: function() { return navigator.customStyleSheet || (function() { navigator.customStyleSheet = document.createElement('style'); document.head.appendChild(navigator.customStyleSheet); return navigator.customStyleSheet; })(); } }, removeAllChildNodes: { configurable: true, enumerable: true, value: function(parent) { while (parent.firstChild) { parent.removeChild(parent.firstChild); } } }, isScrollbarShow: { configurable: true, enumerable: true, value: function() { /* https://davidwalsh.name/detect-scrollbar-width */ const scrollDiv = document.createElement('div'); scrollDiv.style.cssText = 'inline-size:100px;block-size:100px;overflow:scroll;position:absolute;top:-9999px;'; document.body.appendChild(scrollDiv); const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; scrollDiv.remove(); return scrollbarWidth > 0; } }, isObjectsEqual: { configurable: true, enumerable: true, value: function(obj1, obj2) { const obj1Keys = Object.keys(obj1).sort(); const obj2Keys = Object.keys(obj2).sort(); let objEqual = false; if (obj1Keys.length !== obj2Keys.length) { objEqual = false; } else { objEqual = obj1Keys.every((key, index) => { const objValue1 = obj1[key]; const objValue2 = obj2[obj2Keys[index]]; return objValue1 === objValue2; }); } return objEqual; } }, isValidURL: { configurable: true, enumerable: true, value: function(url) { try { return Boolean(new URL(url)); } catch(e){ return false; } } }, loadImage: { configurable: true, enumerable: true, value: function(url, crossOrigin) { return new Promise( (resolve, reject) => { const img = new Image(); img.onload = () => { resolve(img); }; img.onerror = (e) => { reject(e); }; if (typeof crossOrigin !== 'undefined') { img.crossOrigin = crossOrigin; } img.src = url; } ); } }, prepareFetch: { configurable: true, enumerable: true, value: function(timeout = 5000) { const fetchController = new AbortController(); const signal = fetchController.signal; // timeout setTimeout(() => fetchController.abort(), timeout); return signal; } }, cloneStyleSheetsToDocument: { configurable: true, enumerable: true, value: function(targetDocument) { [...document.styleSheets].forEach((styleSheet) => { try { const cssRules = [...styleSheet.cssRules].map((rule) => rule.cssText).join(''); const style = document.createElement('style'); style.textContent = cssRules; targetDocument.head.appendChild(style); } catch (e) { const link = document.createElement('link'); link.rel = 'stylesheet'; link.type = styleSheet.type; link.media = styleSheet.media; link.href = styleSheet.href; targetDocument.head.appendChild(link); } }); } }, addStylesheetRules: { configurable: true, enumerable: true, value: function(selector = '', props = {}, styleSheet = this.grabStyleSheet()) { /** * Add a stylesheet rule to the document * @example addStylesheetRules( 'body', { background: '#f00', color: '#0f0' } [, styleSheet] ) addStylesheetRules( '@keyframes fancy-anchor-ripple', { '0%': '{transform:scale(1);opacity:1;}', '100%': '{transform:scale(100);opacity:0;}' } [, styleSheet] ) */ if (!selector || !Object.keys(props).length || !styleSheet.sheet) return; let propStr, findIndex, sign; sign = (/keyframes/i.test(selector)) ? '' : ';'; styleSheet = styleSheet.sheet; propStr = Object.keys(props).reduce( (acc, cur) => { let sign; sign = /^\{.*\}$/.test(props[cur]) ? '' : ':'; return acc.concat([`${cur}${sign}${props[cur]}`]); } , []).join(sign); findIndex = Array.from(styleSheet.cssRules).findIndex((rule) => rule.selectorText == selector); if (findIndex !== -1) { try { styleSheet.cssRules[findIndex].style.cssText = propStr; } catch(err) { /*error*/ } } else { try { styleSheet.insertRule(`${selector}{${propStr}}`, styleSheet.cssRules.length); } catch(err) { /*error*/ } } } } // addStylesheetRules: { // configurable: true, // enumerable: true, // value: function(selector = '', props = {}, ...others) { // /** // * Add a stylesheet rule to the document // * @example // addStylesheetRules( // 'body', // { // background: '#f00', // color: '#0f0' // } // [, styleSheet] // ) // addStylesheetRules( // '@keyframes fancy-anchor-ripple', // { // '0%': '{transform:scale(1);opacity:1;}', // '100%': '{transform:scale(100);opacity:0;}' // } // [, styleSheet] // ) // addStylesheetRules( // 'body', // { // background: '#f00', // color: '#0f0' // } // 'components.heros' // [, styleSheet] // ) // */ // const [ // layerName = undefined, // styleSheet = this.grabStyleSheet() // ] = others; // const sheet = styleSheet.sheet; // const propStr = Object.keys(props).reduce( // (acc, cur) => { // let sign; // sign = /^\{.*\}$/.test(props[cur]) ? '' : ':'; // return acc.concat([`${cur}${sign}${props[cur]}`]); // } // , []).join((/keyframes/i.test(selector)) ? '' : ';'); // if (layerName) { // // add rules to layer // const layer = Array.from(sheet.cssRules).find((rule) => rule?.name === layerName); // if (layer !== undefined) { // try { // const idx = Array.from(layer.cssRules).findIndex((rule) => rule.selectorText === selector); // layer.cssRules[idx].style.cssText = propStr; // } catch(err) { /*error*/ } // } else { // try { // sheet.insertRule(`@layer ${layerName}{${selector}{${propStr}}}`, sheet.cssRules.length); // } catch(err) { /*error*/ } // } // } else { // const idx = Array.from(sheet.cssRules).findIndex((rule) => rule.selectorText === selector); // if (idx !== -1) { // try { // sheet.cssRules[idx].style.cssText = propStr; // } catch(err) { /*error*/ } // } else { // try { // sheet.insertRule(`${selector}{${propStr}}`, sheet.cssRules.length); // } catch(err) { /*error*/ } // } // } // } // } });