Download node_modules/iframe-resizer/js/iframeResizer.contentWindow.js from Leon4gr45/matomo: direct link, hf CLI and curl.
- Browser
- Download file 35.1 kB
-
https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/node_modules/iframe-resizer/js/iframeResizer.contentWindow.js
- Command line
-
hf download hf://spaces/Leon4gr45/matomo/node_modules/iframe-resizer/js/iframeResizer.contentWindow.js
-
curl -L -o iframeResizer.contentWindow.js https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/node_modules/iframe-resizer/js/iframeResizer.contentWindow.js
35.1 kB
| /* | |
| * File: iframeResizer.contentWindow.js | |
| * Desc: Include this file in any page being loaded into an iframe | |
| * to force the iframe to resize to the content size. | |
| * Requires: iframeResizer.js on host page. | |
| * Doc: https://github.com/davidjbradshaw/iframe-resizer | |
| * Author: David J. Bradshaw - dave@bradshaw.net | |
| * | |
| */ | |
| // eslint-disable-next-line sonarjs/cognitive-complexity, no-shadow-restricted-names | |
| ;(function (undefined) { | |
| if (typeof window === 'undefined') return // don't run for server side render | |
| var autoResize = true, | |
| base = 10, | |
| bodyBackground = '', | |
| bodyMargin = 0, | |
| bodyMarginStr = '', | |
| bodyObserver = null, | |
| bodyPadding = '', | |
| calculateWidth = false, | |
| doubleEventList = { resize: 1, click: 1 }, | |
| eventCancelTimer = 128, | |
| firstRun = true, | |
| height = 1, | |
| heightCalcModeDefault = 'bodyOffset', | |
| heightCalcMode = heightCalcModeDefault, | |
| initLock = true, | |
| initMsg = '', | |
| inPageLinks = {}, | |
| interval = 32, | |
| intervalTimer = null, | |
| logging = false, | |
| mouseEvents = false, | |
| msgID = '[iFrameSizer]', // Must match host page msg ID | |
| msgIdLen = msgID.length, | |
| myID = '', | |
| resetRequiredMethods = { | |
| max: 1, | |
| min: 1, | |
| bodyScroll: 1, | |
| documentElementScroll: 1 | |
| }, | |
| resizeFrom = 'child', | |
| sendPermit = true, | |
| target = window.parent, | |
| targetOriginDefault = '*', | |
| tolerance = 0, | |
| triggerLocked = false, | |
| triggerLockedTimer = null, | |
| throttledTimer = 16, | |
| width = 1, | |
| widthCalcModeDefault = 'scroll', | |
| widthCalcMode = widthCalcModeDefault, | |
| win = window, | |
| onMessage = function () { | |
| warn('onMessage function not defined') | |
| }, | |
| onReady = function () {}, | |
| onPageInfo = function () {}, | |
| customCalcMethods = { | |
| height: function () { | |
| warn('Custom height calculation function not defined') | |
| return document.documentElement.offsetHeight | |
| }, | |
| width: function () { | |
| warn('Custom width calculation function not defined') | |
| return document.body.scrollWidth | |
| } | |
| }, | |
| eventHandlersByName = {}, | |
| passiveSupported = false | |
| function noop() {} | |
| try { | |
| var options = Object.create( | |
| {}, | |
| { | |
| passive: { | |
| // eslint-disable-next-line getter-return | |
| get: function () { | |
| passiveSupported = true | |
| } | |
| } | |
| } | |
| ) | |
| window.addEventListener('test', noop, options) | |
| window.removeEventListener('test', noop, options) | |
| } catch (error) { | |
| /* */ | |
| } | |
| function addEventListener(el, evt, func, options) { | |
| el.addEventListener(evt, func, passiveSupported ? options || {} : false) | |
| } | |
| function removeEventListener(el, evt, func) { | |
| el.removeEventListener(evt, func, false) | |
| } | |
| function capitalizeFirstLetter(string) { | |
| return string.charAt(0).toUpperCase() + string.slice(1) | |
| } | |
| // Based on underscore.js | |
| function throttle(func) { | |
| var context, | |
| args, | |
| result, | |
| timeout = null, | |
| previous = 0, | |
| later = function () { | |
| previous = Date.now() | |
| timeout = null | |
| result = func.apply(context, args) | |
| if (!timeout) { | |
| // eslint-disable-next-line no-multi-assign | |
| context = args = null | |
| } | |
| } | |
| return function () { | |
| var now = Date.now() | |
| if (!previous) { | |
| previous = now | |
| } | |
| var remaining = throttledTimer - (now - previous) | |
| context = this | |
| args = arguments | |
| if (remaining <= 0 || remaining > throttledTimer) { | |
| if (timeout) { | |
| clearTimeout(timeout) | |
| timeout = null | |
| } | |
| previous = now | |
| result = func.apply(context, args) | |
| if (!timeout) { | |
| // eslint-disable-next-line no-multi-assign | |
| context = args = null | |
| } | |
| } else if (!timeout) { | |
| timeout = setTimeout(later, remaining) | |
| } | |
| return result | |
| } | |
| } | |
| function formatLogMsg(msg) { | |
| return msgID + '[' + myID + '] ' + msg | |
| } | |
| function log(msg) { | |
| if (logging && 'object' === typeof window.console) { | |
| // eslint-disable-next-line no-console | |
| console.log(formatLogMsg(msg)) | |
| } | |
| } | |
| function warn(msg) { | |
| if ('object' === typeof window.console) { | |
| // eslint-disable-next-line no-console | |
| console.warn(formatLogMsg(msg)) | |
| } | |
| } | |
| function init() { | |
| readDataFromParent() | |
| log('Initialising iFrame (' + window.location.href + ')') | |
| readDataFromPage() | |
| setMargin() | |
| setBodyStyle('background', bodyBackground) | |
| setBodyStyle('padding', bodyPadding) | |
| injectClearFixIntoBodyElement() | |
| checkHeightMode() | |
| checkWidthMode() | |
| stopInfiniteResizingOfIFrame() | |
| setupPublicMethods() | |
| setupMouseEvents() | |
| startEventListeners() | |
| inPageLinks = setupInPageLinks() | |
| sendSize('init', 'Init message from host page') | |
| onReady() | |
| } | |
| function readDataFromParent() { | |
| function strBool(str) { | |
| return 'true' === str | |
| } | |
| var data = initMsg.slice(msgIdLen).split(':') | |
| myID = data[0] | |
| bodyMargin = undefined === data[1] ? bodyMargin : Number(data[1]) // For V1 compatibility | |
| calculateWidth = undefined === data[2] ? calculateWidth : strBool(data[2]) | |
| logging = undefined === data[3] ? logging : strBool(data[3]) | |
| interval = undefined === data[4] ? interval : Number(data[4]) | |
| autoResize = undefined === data[6] ? autoResize : strBool(data[6]) | |
| bodyMarginStr = data[7] | |
| heightCalcMode = undefined === data[8] ? heightCalcMode : data[8] | |
| bodyBackground = data[9] | |
| bodyPadding = data[10] | |
| tolerance = undefined === data[11] ? tolerance : Number(data[11]) | |
| inPageLinks.enable = undefined === data[12] ? false : strBool(data[12]) | |
| resizeFrom = undefined === data[13] ? resizeFrom : data[13] | |
| widthCalcMode = undefined === data[14] ? widthCalcMode : data[14] | |
| mouseEvents = undefined === data[15] ? mouseEvents : strBool(data[15]) | |
| } | |
| function depricate(key) { | |
| var splitName = key.split('Callback') | |
| if (splitName.length === 2) { | |
| var name = | |
| 'on' + splitName[0].charAt(0).toUpperCase() + splitName[0].slice(1) | |
| this[name] = this[key] | |
| delete this[key] | |
| warn( | |
| "Deprecated: '" + | |
| key + | |
| "' has been renamed '" + | |
| name + | |
| "'. The old method will be removed in the next major version." | |
| ) | |
| } | |
| } | |
| function readDataFromPage() { | |
| function readData() { | |
| var data = window.iFrameResizer | |
| log('Reading data from page: ' + JSON.stringify(data)) | |
| Object.keys(data).forEach(depricate, data) | |
| onMessage = 'onMessage' in data ? data.onMessage : onMessage | |
| onReady = 'onReady' in data ? data.onReady : onReady | |
| targetOriginDefault = | |
| 'targetOrigin' in data ? data.targetOrigin : targetOriginDefault | |
| heightCalcMode = | |
| 'heightCalculationMethod' in data | |
| ? data.heightCalculationMethod | |
| : heightCalcMode | |
| widthCalcMode = | |
| 'widthCalculationMethod' in data | |
| ? data.widthCalculationMethod | |
| : widthCalcMode | |
| } | |
| function setupCustomCalcMethods(calcMode, calcFunc) { | |
| if ('function' === typeof calcMode) { | |
| log('Setup custom ' + calcFunc + 'CalcMethod') | |
| customCalcMethods[calcFunc] = calcMode | |
| calcMode = 'custom' | |
| } | |
| return calcMode | |
| } | |
| if ( | |
| 'iFrameResizer' in window && | |
| Object === window.iFrameResizer.constructor | |
| ) { | |
| readData() | |
| heightCalcMode = setupCustomCalcMethods(heightCalcMode, 'height') | |
| widthCalcMode = setupCustomCalcMethods(widthCalcMode, 'width') | |
| } | |
| log('TargetOrigin for parent set to: ' + targetOriginDefault) | |
| } | |
| function chkCSS(attr, value) { | |
| if (-1 !== value.indexOf('-')) { | |
| warn('Negative CSS value ignored for ' + attr) | |
| value = '' | |
| } | |
| return value | |
| } | |
| function setBodyStyle(attr, value) { | |
| if (undefined !== value && '' !== value && 'null' !== value) { | |
| document.body.style[attr] = value | |
| log('Body ' + attr + ' set to "' + value + '"') | |
| } | |
| } | |
| function setMargin() { | |
| // If called via V1 script, convert bodyMargin from int to str | |
| if (undefined === bodyMarginStr) { | |
| bodyMarginStr = bodyMargin + 'px' | |
| } | |
| setBodyStyle('margin', chkCSS('margin', bodyMarginStr)) | |
| } | |
| function stopInfiniteResizingOfIFrame() { | |
| document.documentElement.style.height = '' | |
| document.body.style.height = '' | |
| log('HTML & body height set to "auto"') | |
| } | |
| function manageTriggerEvent(options) { | |
| var listener = { | |
| add: function (eventName) { | |
| function handleEvent() { | |
| sendSize(options.eventName, options.eventType) | |
| } | |
| eventHandlersByName[eventName] = handleEvent | |
| addEventListener(window, eventName, handleEvent, { passive: true }) | |
| }, | |
| remove: function (eventName) { | |
| var handleEvent = eventHandlersByName[eventName] | |
| delete eventHandlersByName[eventName] | |
| removeEventListener(window, eventName, handleEvent) | |
| } | |
| } | |
| if (options.eventNames && Array.prototype.map) { | |
| options.eventName = options.eventNames[0] | |
| options.eventNames.map(listener[options.method]) | |
| } else { | |
| listener[options.method](options.eventName) | |
| } | |
| log( | |
| capitalizeFirstLetter(options.method) + | |
| ' event listener: ' + | |
| options.eventType | |
| ) | |
| } | |
| function manageEventListeners(method) { | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Animation Start', | |
| eventNames: ['animationstart', 'webkitAnimationStart'] | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Animation Iteration', | |
| eventNames: ['animationiteration', 'webkitAnimationIteration'] | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Animation End', | |
| eventNames: ['animationend', 'webkitAnimationEnd'] | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Input', | |
| eventName: 'input' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Mouse Up', | |
| eventName: 'mouseup' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Mouse Down', | |
| eventName: 'mousedown' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Orientation Change', | |
| eventName: 'orientationchange' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Print', | |
| eventNames: ['afterprint', 'beforeprint'] | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Ready State Change', | |
| eventName: 'readystatechange' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Touch Start', | |
| eventName: 'touchstart' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Touch End', | |
| eventName: 'touchend' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Touch Cancel', | |
| eventName: 'touchcancel' | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Transition Start', | |
| eventNames: [ | |
| 'transitionstart', | |
| 'webkitTransitionStart', | |
| 'MSTransitionStart', | |
| 'oTransitionStart', | |
| 'otransitionstart' | |
| ] | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Transition Iteration', | |
| eventNames: [ | |
| 'transitioniteration', | |
| 'webkitTransitionIteration', | |
| 'MSTransitionIteration', | |
| 'oTransitionIteration', | |
| 'otransitioniteration' | |
| ] | |
| }) | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'Transition End', | |
| eventNames: [ | |
| 'transitionend', | |
| 'webkitTransitionEnd', | |
| 'MSTransitionEnd', | |
| 'oTransitionEnd', | |
| 'otransitionend' | |
| ] | |
| }) | |
| if ('child' === resizeFrom) { | |
| manageTriggerEvent({ | |
| method: method, | |
| eventType: 'IFrame Resized', | |
| eventName: 'resize' | |
| }) | |
| } | |
| } | |
| function checkCalcMode(calcMode, calcModeDefault, modes, type) { | |
| if (calcModeDefault !== calcMode) { | |
| if (!(calcMode in modes)) { | |
| warn( | |
| calcMode + ' is not a valid option for ' + type + 'CalculationMethod.' | |
| ) | |
| calcMode = calcModeDefault | |
| } | |
| log(type + ' calculation method set to "' + calcMode + '"') | |
| } | |
| return calcMode | |
| } | |
| function checkHeightMode() { | |
| heightCalcMode = checkCalcMode( | |
| heightCalcMode, | |
| heightCalcModeDefault, | |
| getHeight, | |
| 'height' | |
| ) | |
| } | |
| function checkWidthMode() { | |
| widthCalcMode = checkCalcMode( | |
| widthCalcMode, | |
| widthCalcModeDefault, | |
| getWidth, | |
| 'width' | |
| ) | |
| } | |
| function startEventListeners() { | |
| if (true === autoResize) { | |
| manageEventListeners('add') | |
| setupMutationObserver() | |
| } else { | |
| log('Auto Resize disabled') | |
| } | |
| } | |
| // function stopMsgsToParent() { | |
| // log('Disable outgoing messages') | |
| // sendPermit = false | |
| // } | |
| // function removeMsgListener() { | |
| // log('Remove event listener: Message') | |
| // removeEventListener(window, 'message', receiver) | |
| // } | |
| function disconnectMutationObserver() { | |
| if (null !== bodyObserver) { | |
| /* istanbul ignore next */ // Not testable in PhantonJS | |
| bodyObserver.disconnect() | |
| } | |
| } | |
| function stopEventListeners() { | |
| manageEventListeners('remove') | |
| disconnectMutationObserver() | |
| clearInterval(intervalTimer) | |
| } | |
| // function teardown() { | |
| // stopMsgsToParent() | |
| // removeMsgListener() | |
| // if (true === autoResize) stopEventListeners() | |
| // } | |
| function injectClearFixIntoBodyElement() { | |
| var clearFix = document.createElement('div') | |
| clearFix.style.clear = 'both' | |
| // Guard against the following having been globally redefined in CSS. | |
| clearFix.style.display = 'block' | |
| clearFix.style.height = '0' | |
| document.body.appendChild(clearFix) | |
| } | |
| function setupInPageLinks() { | |
| function getPagePosition() { | |
| return { | |
| x: | |
| window.pageXOffset === undefined | |
| ? document.documentElement.scrollLeft | |
| : window.pageXOffset, | |
| y: | |
| window.pageYOffset === undefined | |
| ? document.documentElement.scrollTop | |
| : window.pageYOffset | |
| } | |
| } | |
| function getElementPosition(el) { | |
| var elPosition = el.getBoundingClientRect(), | |
| pagePosition = getPagePosition() | |
| return { | |
| x: parseInt(elPosition.left, 10) + parseInt(pagePosition.x, 10), | |
| y: parseInt(elPosition.top, 10) + parseInt(pagePosition.y, 10) | |
| } | |
| } | |
| function findTarget(location) { | |
| function jumpToTarget(target) { | |
| var jumpPosition = getElementPosition(target) | |
| log( | |
| 'Moving to in page link (#' + | |
| hash + | |
| ') at x: ' + | |
| jumpPosition.x + | |
| ' y: ' + | |
| jumpPosition.y | |
| ) | |
| sendMsg(jumpPosition.y, jumpPosition.x, 'scrollToOffset') // X&Y reversed at sendMsg uses height/width | |
| } | |
| var hash = location.split('#')[1] || location, // Remove # if present | |
| hashData = decodeURIComponent(hash), | |
| target = | |
| document.getElementById(hashData) || | |
| document.getElementsByName(hashData)[0] | |
| if (undefined === target) { | |
| log( | |
| 'In page link (#' + | |
| hash + | |
| ') not found in iFrame, so sending to parent' | |
| ) | |
| sendMsg(0, 0, 'inPageLink', '#' + hash) | |
| } else { | |
| jumpToTarget(target) | |
| } | |
| } | |
| function checkLocationHash() { | |
| var hash = window.location.hash | |
| var href = window.location.href | |
| if ('' !== hash && '#' !== hash) { | |
| findTarget(href) | |
| } | |
| } | |
| function bindAnchors() { | |
| function setupLink(el) { | |
| function linkClicked(e) { | |
| e.preventDefault() | |
| /* jshint validthis:true */ | |
| findTarget(this.getAttribute('href')) | |
| } | |
| if ('#' !== el.getAttribute('href')) { | |
| addEventListener(el, 'click', linkClicked) | |
| } | |
| } | |
| Array.prototype.forEach.call( | |
| document.querySelectorAll('a[href^="#"]'), | |
| setupLink | |
| ) | |
| } | |
| function bindLocationHash() { | |
| addEventListener(window, 'hashchange', checkLocationHash) | |
| } | |
| function initCheck() { | |
| // Check if page loaded with location hash after init resize | |
| setTimeout(checkLocationHash, eventCancelTimer) | |
| } | |
| function enableInPageLinks() { | |
| /* istanbul ignore else */ // Not testable in phantonJS | |
| if (Array.prototype.forEach && document.querySelectorAll) { | |
| log('Setting up location.hash handlers') | |
| bindAnchors() | |
| bindLocationHash() | |
| initCheck() | |
| } else { | |
| warn( | |
| 'In page linking not fully supported in this browser! (See README.md for IE8 workaround)' | |
| ) | |
| } | |
| } | |
| if (inPageLinks.enable) { | |
| enableInPageLinks() | |
| } else { | |
| log('In page linking not enabled') | |
| } | |
| return { | |
| findTarget: findTarget | |
| } | |
| } | |
| function setupMouseEvents() { | |
| if (mouseEvents !== true) return | |
| function sendMouse(e) { | |
| sendMsg(0, 0, e.type, e.screenY + ':' + e.screenX) | |
| } | |
| function addMouseListener(evt, name) { | |
| log('Add event listener: ' + name) | |
| addEventListener(window.document, evt, sendMouse) | |
| } | |
| addMouseListener('mouseenter', 'Mouse Enter') | |
| addMouseListener('mouseleave', 'Mouse Leave') | |
| } | |
| function setupPublicMethods() { | |
| log('Enable public methods') | |
| win.parentIFrame = { | |
| autoResize: function autoResizeF(resize) { | |
| if (true === resize && false === autoResize) { | |
| autoResize = true | |
| startEventListeners() | |
| } else if (false === resize && true === autoResize) { | |
| autoResize = false | |
| stopEventListeners() | |
| } | |
| sendMsg(0, 0, 'autoResize', JSON.stringify(autoResize)) | |
| return autoResize | |
| }, | |
| close: function closeF() { | |
| sendMsg(0, 0, 'close') | |
| // teardown() | |
| }, | |
| getId: function getIdF() { | |
| return myID | |
| }, | |
| getPageInfo: function getPageInfoF(callback) { | |
| if ('function' === typeof callback) { | |
| onPageInfo = callback | |
| sendMsg(0, 0, 'pageInfo') | |
| } else { | |
| onPageInfo = function () {} | |
| sendMsg(0, 0, 'pageInfoStop') | |
| } | |
| }, | |
| moveToAnchor: function moveToAnchorF(hash) { | |
| inPageLinks.findTarget(hash) | |
| }, | |
| reset: function resetF() { | |
| resetIFrame('parentIFrame.reset') | |
| }, | |
| scrollTo: function scrollToF(x, y) { | |
| sendMsg(y, x, 'scrollTo') // X&Y reversed at sendMsg uses height/width | |
| }, | |
| scrollToOffset: function scrollToF(x, y) { | |
| sendMsg(y, x, 'scrollToOffset') // X&Y reversed at sendMsg uses height/width | |
| }, | |
| sendMessage: function sendMessageF(msg, targetOrigin) { | |
| sendMsg(0, 0, 'message', JSON.stringify(msg), targetOrigin) | |
| }, | |
| setHeightCalculationMethod: function setHeightCalculationMethodF( | |
| heightCalculationMethod | |
| ) { | |
| heightCalcMode = heightCalculationMethod | |
| checkHeightMode() | |
| }, | |
| setWidthCalculationMethod: function setWidthCalculationMethodF( | |
| widthCalculationMethod | |
| ) { | |
| widthCalcMode = widthCalculationMethod | |
| checkWidthMode() | |
| }, | |
| setTargetOrigin: function setTargetOriginF(targetOrigin) { | |
| log('Set targetOrigin: ' + targetOrigin) | |
| targetOriginDefault = targetOrigin | |
| }, | |
| size: function sizeF(customHeight, customWidth) { | |
| var valString = | |
| '' + (customHeight || '') + (customWidth ? ',' + customWidth : '') | |
| sendSize( | |
| 'size', | |
| 'parentIFrame.size(' + valString + ')', | |
| customHeight, | |
| customWidth | |
| ) | |
| } | |
| } | |
| } | |
| function initInterval() { | |
| if (0 !== interval) { | |
| log('setInterval: ' + interval + 'ms') | |
| intervalTimer = setInterval(function () { | |
| sendSize('interval', 'setInterval: ' + interval) | |
| }, Math.abs(interval)) | |
| } | |
| } | |
| // Not testable in PhantomJS | |
| /* istanbul ignore next */ | |
| function setupBodyMutationObserver() { | |
| function addImageLoadListners(mutation) { | |
| function addImageLoadListener(element) { | |
| if (false === element.complete) { | |
| log('Attach listeners to ' + element.src) | |
| element.addEventListener('load', imageLoaded, false) | |
| element.addEventListener('error', imageError, false) | |
| elements.push(element) | |
| } | |
| } | |
| if (mutation.type === 'attributes' && mutation.attributeName === 'src') { | |
| addImageLoadListener(mutation.target) | |
| } else if (mutation.type === 'childList') { | |
| Array.prototype.forEach.call( | |
| mutation.target.querySelectorAll('img'), | |
| addImageLoadListener | |
| ) | |
| } | |
| } | |
| function removeFromArray(element) { | |
| elements.splice(elements.indexOf(element), 1) | |
| } | |
| function removeImageLoadListener(element) { | |
| log('Remove listeners from ' + element.src) | |
| element.removeEventListener('load', imageLoaded, false) | |
| element.removeEventListener('error', imageError, false) | |
| removeFromArray(element) | |
| } | |
| function imageEventTriggered(event, type, typeDesc) { | |
| removeImageLoadListener(event.target) | |
| sendSize(type, typeDesc + ': ' + event.target.src) | |
| } | |
| function imageLoaded(event) { | |
| imageEventTriggered(event, 'imageLoad', 'Image loaded') | |
| } | |
| function imageError(event) { | |
| imageEventTriggered(event, 'imageLoadFailed', 'Image load failed') | |
| } | |
| function mutationObserved(mutations) { | |
| sendSize( | |
| 'mutationObserver', | |
| 'mutationObserver: ' + mutations[0].target + ' ' + mutations[0].type | |
| ) | |
| // Deal with WebKit / Blink asyncing image loading when tags are injected into the page | |
| mutations.forEach(addImageLoadListners) | |
| } | |
| function createMutationObserver() { | |
| var target = document.querySelector('body'), | |
| config = { | |
| attributes: true, | |
| attributeOldValue: false, | |
| characterData: true, | |
| characterDataOldValue: false, | |
| childList: true, | |
| subtree: true | |
| } | |
| observer = new MutationObserver(mutationObserved) | |
| log('Create body MutationObserver') | |
| observer.observe(target, config) | |
| return observer | |
| } | |
| var elements = [], | |
| MutationObserver = | |
| window.MutationObserver || window.WebKitMutationObserver, | |
| observer = createMutationObserver() | |
| return { | |
| disconnect: function () { | |
| if ('disconnect' in observer) { | |
| log('Disconnect body MutationObserver') | |
| observer.disconnect() | |
| elements.forEach(removeImageLoadListener) | |
| } | |
| } | |
| } | |
| } | |
| function setupMutationObserver() { | |
| var forceIntervalTimer = 0 > interval | |
| // Not testable in PhantomJS | |
| /* istanbul ignore if */ if ( | |
| window.MutationObserver || | |
| window.WebKitMutationObserver | |
| ) { | |
| if (forceIntervalTimer) { | |
| initInterval() | |
| } else { | |
| bodyObserver = setupBodyMutationObserver() | |
| } | |
| } else { | |
| log('MutationObserver not supported in this browser!') | |
| initInterval() | |
| } | |
| } | |
| // document.documentElement.offsetHeight is not reliable, so | |
| // we have to jump through hoops to get a better value. | |
| function getComputedStyle(prop, el) { | |
| var retVal = 0 | |
| el = el || document.body // Not testable in phantonJS | |
| retVal = document.defaultView.getComputedStyle(el, null) | |
| retVal = null === retVal ? 0 : retVal[prop] | |
| return parseInt(retVal, base) | |
| } | |
| function chkEventThottle(timer) { | |
| if (timer > throttledTimer / 2) { | |
| throttledTimer = 2 * timer | |
| log('Event throttle increased to ' + throttledTimer + 'ms') | |
| } | |
| } | |
| // Idea from https://github.com/guardian/iframe-messenger | |
| function getMaxElement(side, elements) { | |
| var elementsLength = elements.length, | |
| elVal = 0, | |
| maxVal = 0, | |
| Side = capitalizeFirstLetter(side), | |
| timer = Date.now() | |
| for (var i = 0; i < elementsLength; i++) { | |
| elVal = | |
| elements[i].getBoundingClientRect()[side] + | |
| getComputedStyle('margin' + Side, elements[i]) | |
| if (elVal > maxVal) { | |
| maxVal = elVal | |
| } | |
| } | |
| timer = Date.now() - timer | |
| log('Parsed ' + elementsLength + ' HTML elements') | |
| log('Element position calculated in ' + timer + 'ms') | |
| chkEventThottle(timer) | |
| return maxVal | |
| } | |
| function getAllMeasurements(dimensions) { | |
| return [ | |
| dimensions.bodyOffset(), | |
| dimensions.bodyScroll(), | |
| dimensions.documentElementOffset(), | |
| dimensions.documentElementScroll() | |
| ] | |
| } | |
| function getTaggedElements(side, tag) { | |
| function noTaggedElementsFound() { | |
| warn('No tagged elements (' + tag + ') found on page') | |
| return document.querySelectorAll('body *') | |
| } | |
| var elements = document.querySelectorAll('[' + tag + ']') | |
| if (elements.length === 0) noTaggedElementsFound() | |
| return getMaxElement(side, elements) | |
| } | |
| function getAllElements() { | |
| return document.querySelectorAll('body *') | |
| } | |
| var getHeight = { | |
| bodyOffset: function getBodyOffsetHeight() { | |
| return ( | |
| document.body.offsetHeight + | |
| getComputedStyle('marginTop') + | |
| getComputedStyle('marginBottom') | |
| ) | |
| }, | |
| offset: function () { | |
| return getHeight.bodyOffset() // Backwards compatibility | |
| }, | |
| bodyScroll: function getBodyScrollHeight() { | |
| return document.body.scrollHeight | |
| }, | |
| custom: function getCustomWidth() { | |
| return customCalcMethods.height() | |
| }, | |
| documentElementOffset: function getDEOffsetHeight() { | |
| return document.documentElement.offsetHeight | |
| }, | |
| documentElementScroll: function getDEScrollHeight() { | |
| return document.documentElement.scrollHeight | |
| }, | |
| max: function getMaxHeight() { | |
| return Math.max.apply(null, getAllMeasurements(getHeight)) | |
| }, | |
| min: function getMinHeight() { | |
| return Math.min.apply(null, getAllMeasurements(getHeight)) | |
| }, | |
| grow: function growHeight() { | |
| return getHeight.max() // Run max without the forced downsizing | |
| }, | |
| lowestElement: function getBestHeight() { | |
| return Math.max( | |
| getHeight.bodyOffset() || getHeight.documentElementOffset(), | |
| getMaxElement('bottom', getAllElements()) | |
| ) | |
| }, | |
| taggedElement: function getTaggedElementsHeight() { | |
| return getTaggedElements('bottom', 'data-iframe-height') | |
| } | |
| }, | |
| getWidth = { | |
| bodyScroll: function getBodyScrollWidth() { | |
| return document.body.scrollWidth | |
| }, | |
| bodyOffset: function getBodyOffsetWidth() { | |
| return document.body.offsetWidth | |
| }, | |
| custom: function getCustomWidth() { | |
| return customCalcMethods.width() | |
| }, | |
| documentElementScroll: function getDEScrollWidth() { | |
| return document.documentElement.scrollWidth | |
| }, | |
| documentElementOffset: function getDEOffsetWidth() { | |
| return document.documentElement.offsetWidth | |
| }, | |
| scroll: function getMaxWidth() { | |
| return Math.max(getWidth.bodyScroll(), getWidth.documentElementScroll()) | |
| }, | |
| max: function getMaxWidth() { | |
| return Math.max.apply(null, getAllMeasurements(getWidth)) | |
| }, | |
| min: function getMinWidth() { | |
| return Math.min.apply(null, getAllMeasurements(getWidth)) | |
| }, | |
| rightMostElement: function rightMostElement() { | |
| return getMaxElement('right', getAllElements()) | |
| }, | |
| taggedElement: function getTaggedElementsWidth() { | |
| return getTaggedElements('right', 'data-iframe-width') | |
| } | |
| } | |
| function sizeIFrame( | |
| triggerEvent, | |
| triggerEventDesc, | |
| customHeight, | |
| customWidth | |
| ) { | |
| function resizeIFrame() { | |
| height = currentHeight | |
| width = currentWidth | |
| sendMsg(height, width, triggerEvent) | |
| } | |
| function isSizeChangeDetected() { | |
| function checkTolarance(a, b) { | |
| var retVal = Math.abs(a - b) <= tolerance | |
| return !retVal | |
| } | |
| currentHeight = | |
| undefined === customHeight ? getHeight[heightCalcMode]() : customHeight | |
| currentWidth = | |
| undefined === customWidth ? getWidth[widthCalcMode]() : customWidth | |
| return ( | |
| checkTolarance(height, currentHeight) || | |
| (calculateWidth && checkTolarance(width, currentWidth)) | |
| ) | |
| } | |
| function isForceResizableEvent() { | |
| return !(triggerEvent in { init: 1, interval: 1, size: 1 }) | |
| } | |
| function isForceResizableCalcMode() { | |
| return ( | |
| heightCalcMode in resetRequiredMethods || | |
| (calculateWidth && widthCalcMode in resetRequiredMethods) | |
| ) | |
| } | |
| function logIgnored() { | |
| log('No change in size detected') | |
| } | |
| function checkDownSizing() { | |
| if (isForceResizableEvent() && isForceResizableCalcMode()) { | |
| resetIFrame(triggerEventDesc) | |
| } else if (!(triggerEvent in { interval: 1 })) { | |
| logIgnored() | |
| } | |
| } | |
| var currentHeight, currentWidth | |
| if (isSizeChangeDetected() || 'init' === triggerEvent) { | |
| lockTrigger() | |
| resizeIFrame() | |
| } else { | |
| checkDownSizing() | |
| } | |
| } | |
| var sizeIFrameThrottled = throttle(sizeIFrame) | |
| function sendSize(triggerEvent, triggerEventDesc, customHeight, customWidth) { | |
| function recordTrigger() { | |
| if (!(triggerEvent in { reset: 1, resetPage: 1, init: 1 })) { | |
| log('Trigger event: ' + triggerEventDesc) | |
| } | |
| } | |
| function isDoubleFiredEvent() { | |
| return triggerLocked && triggerEvent in doubleEventList | |
| } | |
| if (isDoubleFiredEvent()) { | |
| log('Trigger event cancelled: ' + triggerEvent) | |
| } else { | |
| recordTrigger() | |
| if (triggerEvent === 'init') { | |
| sizeIFrame(triggerEvent, triggerEventDesc, customHeight, customWidth) | |
| } else { | |
| sizeIFrameThrottled( | |
| triggerEvent, | |
| triggerEventDesc, | |
| customHeight, | |
| customWidth | |
| ) | |
| } | |
| } | |
| } | |
| function lockTrigger() { | |
| if (!triggerLocked) { | |
| triggerLocked = true | |
| log('Trigger event lock on') | |
| } | |
| clearTimeout(triggerLockedTimer) | |
| triggerLockedTimer = setTimeout(function () { | |
| triggerLocked = false | |
| log('Trigger event lock off') | |
| log('--') | |
| }, eventCancelTimer) | |
| } | |
| function triggerReset(triggerEvent) { | |
| height = getHeight[heightCalcMode]() | |
| width = getWidth[widthCalcMode]() | |
| sendMsg(height, width, triggerEvent) | |
| } | |
| function resetIFrame(triggerEventDesc) { | |
| var hcm = heightCalcMode | |
| heightCalcMode = heightCalcModeDefault | |
| log('Reset trigger event: ' + triggerEventDesc) | |
| lockTrigger() | |
| triggerReset('reset') | |
| heightCalcMode = hcm | |
| } | |
| function sendMsg(height, width, triggerEvent, msg, targetOrigin) { | |
| function setTargetOrigin() { | |
| if (undefined === targetOrigin) { | |
| targetOrigin = targetOriginDefault | |
| } else { | |
| log('Message targetOrigin: ' + targetOrigin) | |
| } | |
| } | |
| function sendToParent() { | |
| var size = height + ':' + width, | |
| message = | |
| myID + | |
| ':' + | |
| size + | |
| ':' + | |
| triggerEvent + | |
| (undefined === msg ? '' : ':' + msg) | |
| log('Sending message to host page (' + message + ')') | |
| target.postMessage(msgID + message, targetOrigin) | |
| } | |
| if (true === sendPermit) { | |
| setTargetOrigin() | |
| sendToParent() | |
| } | |
| } | |
| function receiver(event) { | |
| var processRequestFromParent = { | |
| init: function initFromParent() { | |
| initMsg = event.data | |
| target = event.source | |
| init() | |
| firstRun = false | |
| setTimeout(function () { | |
| initLock = false | |
| }, eventCancelTimer) | |
| }, | |
| reset: function resetFromParent() { | |
| if (initLock) { | |
| log('Page reset ignored by init') | |
| } else { | |
| log('Page size reset by host page') | |
| triggerReset('resetPage') | |
| } | |
| }, | |
| resize: function resizeFromParent() { | |
| sendSize('resizeParent', 'Parent window requested size check') | |
| }, | |
| moveToAnchor: function moveToAnchorF() { | |
| inPageLinks.findTarget(getData()) | |
| }, | |
| inPageLink: function inPageLinkF() { | |
| this.moveToAnchor() | |
| }, // Backward compatibility | |
| pageInfo: function pageInfoFromParent() { | |
| var msgBody = getData() | |
| log('PageInfoFromParent called from parent: ' + msgBody) | |
| onPageInfo(JSON.parse(msgBody)) | |
| log(' --') | |
| }, | |
| message: function messageFromParent() { | |
| var msgBody = getData() | |
| log('onMessage called from parent: ' + msgBody) | |
| // eslint-disable-next-line sonarjs/no-extra-arguments | |
| onMessage(JSON.parse(msgBody)) | |
| log(' --') | |
| } | |
| } | |
| function isMessageForUs() { | |
| return msgID === ('' + event.data).slice(0, msgIdLen) // ''+ Protects against non-string messages | |
| } | |
| function getMessageType() { | |
| return event.data.split(']')[1].split(':')[0] | |
| } | |
| function getData() { | |
| return event.data.slice(event.data.indexOf(':') + 1) | |
| } | |
| function isMiddleTier() { | |
| return ( | |
| (!(typeof module !== 'undefined' && module.exports) && | |
| 'iFrameResize' in window) || | |
| (window.jQuery !== undefined && | |
| 'iFrameResize' in window.jQuery.prototype) | |
| ) | |
| } | |
| function isInitMsg() { | |
| // Test if this message is from a child below us. This is an ugly test, however, updating | |
| // the message format would break backwards compatibility. | |
| return event.data.split(':')[2] in { true: 1, false: 1 } | |
| } | |
| function callFromParent() { | |
| var messageType = getMessageType() | |
| if (messageType in processRequestFromParent) { | |
| processRequestFromParent[messageType]() | |
| } else if (!isMiddleTier() && !isInitMsg()) { | |
| warn('Unexpected message (' + event.data + ')') | |
| } | |
| } | |
| function processMessage() { | |
| if (false === firstRun) { | |
| callFromParent() | |
| } else if (isInitMsg()) { | |
| processRequestFromParent.init() | |
| } else { | |
| log( | |
| 'Ignored message of type "' + | |
| getMessageType() + | |
| '". Received before initialization.' | |
| ) | |
| } | |
| } | |
| if (isMessageForUs()) { | |
| processMessage() | |
| } | |
| } | |
| // Normally the parent kicks things off when it detects the iFrame has loaded. | |
| // If this script is async-loaded, then tell parent page to retry init. | |
| function chkLateLoaded() { | |
| if ('loading' !== document.readyState) { | |
| window.parent.postMessage('[iFrameResizerChild]Ready', '*') | |
| } | |
| } | |
| // Setup if not already running | |
| if (!('iframeResizer' in window)) { | |
| window.iframeChildListener = function (data) { | |
| receiver({ data, sameDomian: true }) | |
| } | |
| addEventListener(window, 'message', receiver) | |
| addEventListener(window, 'readystatechange', chkLateLoaded) | |
| chkLateLoaded() | |
| } | |
| })() | |