|
| 1 | +function HandleHTMLDimensionsFeature(context) { |
| 2 | + var postMessage = context.postMessage; |
| 3 | + var options = context.options || {}; |
| 4 | + var forceImplementation = options.forceImplementation || false; |
| 5 | + var pollingInterval = |
| 6 | + typeof options.pollingInterval === 'number' ? options.pollingInterval : 200; |
| 7 | + var deltaMin = options.deltaMin || 0; |
| 8 | + var oldDimensions = { |
| 9 | + layoutViewport: { width: 0, height: 0 }, |
| 10 | + content: { width: 0, height: 0 } |
| 11 | + }; |
| 12 | + var MutationObserver = |
| 13 | + window['MutationObserver'] || window['WebKitMutationObserver']; |
| 14 | + function extractNumericValue(pixelString) { |
| 15 | + return pixelString ? parseFloat(pixelString.match(/[\d.]+/)) : 0; |
| 16 | + } |
| 17 | + function dimensionsAreEqual(d1, d2) { |
| 18 | + return ( |
| 19 | + Math.abs(d1.layoutViewport.width - d2.layoutViewport.width) < deltaMin && |
| 20 | + Math.abs(d1.layoutViewport.height - d2.layoutViewport.height) < |
| 21 | + deltaMin && |
| 22 | + Math.abs(d1.content.width - d2.content.width) < deltaMin && |
| 23 | + Math.abs(d1.content.height - d2.content.height) < deltaMin && |
| 24 | + d1.implementation === d2.implementation |
| 25 | + ); |
| 26 | + } |
| 27 | + function createPostDimensions(implementation) { |
| 28 | + return context.makeCallbackSafe(function postSize() { |
| 29 | + var bodyStyle = getComputedStyle(document.body); |
| 30 | + var bodySize = document.body.getBoundingClientRect(); |
| 31 | + var marginRight = extractNumericValue(bodyStyle.marginRight); |
| 32 | + var marginBottom = extractNumericValue(bodyStyle.marginBottom); |
| 33 | + var layoutViewport = { |
| 34 | + width: document.documentElement.clientWidth, |
| 35 | + height: document.documentElement.clientHeight |
| 36 | + }; |
| 37 | + var dimensions = { |
| 38 | + implementation: implementation, |
| 39 | + layoutViewport: layoutViewport, |
| 40 | + content: { |
| 41 | + width: bodySize.right + marginRight, |
| 42 | + height: bodySize.bottom + marginBottom |
| 43 | + } |
| 44 | + }; |
| 45 | + if (!dimensionsAreEqual(oldDimensions, dimensions)) { |
| 46 | + postMessage(dimensions); |
| 47 | + oldDimensions = dimensions; |
| 48 | + } |
| 49 | + }); |
| 50 | + } |
| 51 | + if ( |
| 52 | + window.ResizeObserver && |
| 53 | + (forceImplementation === false || forceImplementation === 'resize') |
| 54 | + ) { |
| 55 | + // resize mode |
| 56 | + var resizePostDimensions = createPostDimensions('resize'); |
| 57 | + var resizeObserver = new window.ResizeObserver(resizePostDimensions); |
| 58 | + resizeObserver.observe(document.body); |
| 59 | + resizePostDimensions(); |
| 60 | + } else if ( |
| 61 | + MutationObserver && |
| 62 | + (forceImplementation === false || forceImplementation === 'mutation') |
| 63 | + ) { |
| 64 | + // mutation mode |
| 65 | + var observerPostDimensions = createPostDimensions('mutation'); |
| 66 | + window.addEventListener('resize', observerPostDimensions); |
| 67 | + var observer = new MutationObserver(observerPostDimensions); |
| 68 | + observer.observe(document, { |
| 69 | + subtree: true, |
| 70 | + attributes: true |
| 71 | + }); |
| 72 | + observerPostDimensions(); |
| 73 | + } else { |
| 74 | + // polling mode |
| 75 | + var pollingPostDimensions = createPostDimensions('polling'); |
| 76 | + window.addEventListener('resize', pollingPostDimensions); |
| 77 | + setInterval(pollingPostDimensions, pollingInterval); |
| 78 | + pollingPostDimensions(); |
| 79 | + context.warn( |
| 80 | + "This browser doesn't support either MutationObserver or ResizeObserver." + |
| 81 | + 'The dimensions will still be read every' + |
| 82 | + pollingInterval + |
| 83 | + 'ms and committed when a change is observed.' |
| 84 | + ); |
| 85 | + } |
| 86 | +} |
0 commit comments