import assign from 'assign-deep' const inBrowser = typeof window !== 'undefined' export const hasIntersectionObserver = inBrowser && 'IntersectionObserver' in window export const modeType = { event: 'event', observer: 'observer' } // CustomEvent polyfill const CustomEvent = (function () { if (!inBrowser) return if (typeof window.CustomEvent === 'function') return window.CustomEvent function CustomEvent (event, params) { params = params || { bubbles: false, cancelable: false, detail: undefined } var evt = document.createEvent('CustomEvent') evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail) return evt } CustomEvent.prototype = window.Event.prototype return CustomEvent })() function remove (arr, item) { if (!arr.length) return const index = arr.indexOf(item) if (index > -1) return arr.splice(index, 1) } function some (arr, fn) { let has = false for (let i = 0, len = arr.length; i < len; i++) { if (fn(arr[i])) { has = true break } } return has } function getBestSelectionFromSrcset (el, scale) { if (el.tagName !== 'IMG' || !el.getAttribute('data-srcset')) return let options = el.getAttribute('data-srcset') const result = [] const container = el.parentNode const containerWidth = container.offsetWidth * scale let spaceIndex let tmpSrc let tmpWidth options = options.trim().split(',') options.map(item => { item = item.trim() spaceIndex = item.lastIndexOf(' ') if (spaceIndex === -1) { tmpSrc = item tmpWidth = 999998 } else { tmpSrc = item.substr(0, spaceIndex) tmpWidth = parseInt(item.substr(spaceIndex + 1, item.length - spaceIndex - 2), 10) } result.push([tmpWidth, tmpSrc]) }) result.sort(function (a, b) { if (a[0] < b[0]) { return -1 } if (a[0] > b[0]) { return 1 } if (a[0] === b[0]) { if (b[1].indexOf('.webp', b[1].length - 5) !== -1) { return 1 } if (a[1].indexOf('.webp', a[1].length - 5) !== -1) { return -1 } } return 0 }) let bestSelectedSrc = '' let tmpOption const resultCount = result.length for (let i = 0; i < resultCount; i++) { tmpOption = result[i] if (tmpOption[0] >= containerWidth) { bestSelectedSrc = tmpOption[1] break } } return bestSelectedSrc } function find (arr, fn) { let item for (let i = 0, len = arr.length; i < len; i++) { if (fn(arr[i])) { item = arr[i] break } } return item } const getDPR = (scale = 1) => inBrowser ? (window.devicePixelRatio || scale) : scale function supportWebp () { if (!inBrowser) return false let support = true const d = document try { let el = d.createElement('object') el.type = 'image/webp' el.style.visibility = 'hidden' el.innerHTML = '!' d.body.appendChild(el) support = !el.offsetWidth d.body.removeChild(el) } catch (err) { support = false } return support } function throttle (action, delay) { let timeout = null let lastRun = 0 return function () { if (timeout) { return } let elapsed = Date.now() - lastRun let context = this let args = arguments let runCallback = function () { lastRun = Date.now() timeout = false action.apply(context, args) } if (elapsed >= delay) { runCallback() } else { timeout = setTimeout(runCallback, delay) } } } function testSupportsPassive () { if (!inBrowser) return let support = false try { let opts = Object.defineProperty({}, 'passive', { get: function () { support = true } }) window.addEventListener('test', null, opts) } catch (e) {} return support } const supportsPassive = testSupportsPassive() const _ = { on (el, type, func, capture = false) { if (supportsPassive) { el.addEventListener(type, func, { capture: capture, passive: true }) } else { el.addEventListener(type, func, capture) } }, off (el, type, func, capture = false) { el.removeEventListener(type, func, capture) } } const loadImageAsync = (item, resolve, reject) => { let image = new Image() image.src = item.src image.onload = function () { resolve({ naturalHeight: image.naturalHeight, naturalWidth: image.naturalWidth, src: image.src }) } image.onerror = function (e) { reject(e) } } const style = (el, prop) => { return typeof getComputedStyle !== 'undefined' ? getComputedStyle(el, null).getPropertyValue(prop) : el.style[prop] } const overflow = (el) => { return style(el, 'overflow') + style(el, 'overflow-y') + style(el, 'overflow-x') } const scrollParent = (el) => { if (!inBrowser) return if (!(el instanceof HTMLElement)) { return window } let parent = el while (parent) { if (parent === document.body || parent === document.documentElement) { break } if (!parent.parentNode) { break } if (/(scroll|auto)/.test(overflow(parent))) { return parent } parent = parent.parentNode } return window } function isObject (obj) { return obj !== null && typeof obj === 'object' } function ObjectKeys (obj) { if (!(obj instanceof Object)) return [] if (Object.keys) { return Object.keys(obj) } else { let keys = [] for (let key in obj) { if (obj.hasOwnProperty(key)) { keys.push(key) } } return keys } } function ArrayFrom (arrLike) { let len = arrLike.length const list = [] for (let i = 0; i < len; i++) { list.push(arrLike[i]) } return list } function noop () {} export { inBrowser, CustomEvent, remove, some, find, assign, noop, ArrayFrom, _, isObject, throttle, supportWebp, getDPR, scrollParent, loadImageAsync, getBestSelectionFromSrcset, ObjectKeys }