Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { IterableWeakMap, IterableWeakSet } from './iterable-weak-struct.js'
const portraitMobileMatchMedia = window.matchMedia('(max-width: 576px) and (orientation: portrait)')
const landscapeMobileMatchMedia = window.matchMedia('(max-width: 768px) and (orientation: landscape)')
export const hasTouchScreen = () => 'ontouchstart' in window || navigator.maxTouchPoints > 0
export const isPortraitMobile = () => portraitMobileMatchMedia.matches && hasTouchScreen()
export const isLandscapeMobile = () => landscapeMobileMatchMedia.matches && hasTouchScreen()
export const isMobile = () => isPortraitMobile() || isLandscapeMobile()
/**
* Map of created observers with its data
* @type {IterableWeakMap<MobileDetectionObserverCallback, MobileDetectionObserverData>}
*/
const observerData = new IterableWeakMap()
/**
*
*/
function updateData () {
const isNowMobile = isMobile()
for (const [callback, data] of observerData.entries()) {
const { currentIsMobile, observingNodes } = data
if (currentIsMobile === isNowMobile) { continue }
data.currentIsMobile = isNowMobile
const events = Iterator.from(observingNodes).map(element => ({
target: element,
isMobile: isNowMobile,
})).toArray()
callback(events)
}
}
let observeMatchMedia = () => {
portraitMobileMatchMedia.addEventListener('change', updateData)
landscapeMobileMatchMedia.addEventListener('change', updateData)
observeMatchMedia = () => {}
}
/**
* @param {MobileDetectionObserverCallback} callback - mutation callback
* @returns {MobileDetectionObserver} - observer
*/
export function MobileDetectionObserver (callback) {
const data = observerData.getOrInsertComputed(callback, () => ({
observingNodes: new IterableWeakSet(),
currentIsMobile: undefined,
}))
return Object.freeze({
observe (node) {
observeMatchMedia()
data.currentIsMobile ??= isMobile()
const { currentIsMobile, observingNodes } = data
if (observingNodes.has(node)) { return }
observingNodes.add(node)
callback([{
target: node,
isMobile: currentIsMobile,
}])
},
})
}
/**
* @typedef {object} MobileDetectionObserver
* @property {(node: Node) => void} observe - observer callback
*/
/**
* @typedef {object} MobileDetectionObserverData
* @property {boolean} [currentIsMobile] - flag saved on observer to determine if the mode changed
* @property {IterableWeakSet<Node>} observingNodes - observer callback
*/
/**
* @callback MobileDetectionObserverCallback
* @param {MobileStateMutationRecord[]} mutations - mutations happened for each observing element
*/
/**
* @typedef {object} MobileStateMutationRecord
* @property {Node} target - observing element
* @property {boolean} isMobile - flag to determine if it's on mobile mode
*/
|