(() => { var $5180433265c858be$exports = {}; /* * File: iframeResizer.js * Desc: Force iframes to size to content. * Requires: iframeResizer.contentWindow.js to be loaded into the target frame. * Doc: https://github.com/davidjbradshaw/iframe-resizer * Author: David J. Bradshaw - dave@bradshaw.net * Contributor: Jure Mav - jure.mav@gmail.com * Contributor: Reed Dadoune - reed@dadoune.com */ // 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 count = 0, logEnabled = false, hiddenCheckEnabled = false, msgHeader = "message", msgHeaderLen = msgHeader.length, msgId = "[iFrameSizer]", msgIdLen = msgId.length, pagePosition = null, requestAnimationFrame = window.requestAnimationFrame, resetRequiredMethods = Object.freeze({ max: 1, scroll: 1, bodyScroll: 1, documentElementScroll: 1 }), settings = {}, timer = null, defaults = Object.freeze({ autoResize: true, bodyBackground: null, bodyMargin: null, bodyMarginV1: 8, bodyPadding: null, checkOrigin: true, inPageLinks: false, enablePublicMethods: true, heightCalculationMethod: "bodyOffset", id: "iFrameResizer", interval: 32, log: false, maxHeight: Infinity, maxWidth: Infinity, minHeight: 0, minWidth: 0, mouseEvents: true, resizeFrom: "parent", scrolling: false, sizeHeight: true, sizeWidth: false, warningTimeout: 5000, tolerance: 0, widthCalculationMethod: "scroll", onClose: function() { return true; }, onClosed: function() {}, onInit: function() {}, onMessage: function() { warn("onMessage function not defined"); }, onMouseEnter: function() {}, onMouseLeave: function() {}, onResized: function() {}, onScroll: function() { return true; } }); function getMutationObserver() { return window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; } function addEventListener(el, evt, func) { el.addEventListener(evt, func, false); } function removeEventListener(el, evt, func) { el.removeEventListener(evt, func, false); } function setupRequestAnimationFrame() { var vendors = [ "moz", "webkit", "o", "ms" ]; var x; // Remove vendor prefixing if prefixed and break early if not for(x = 0; x < vendors.length && !requestAnimationFrame; x += 1)requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"]; if (requestAnimationFrame) // Firefox extension content-scripts have a globalThis object that is not the same as window. // Binding `requestAnimationFrame` to window allows the function to work and prevents errors // being thrown when run in that context, and should be a no-op in every other context. requestAnimationFrame = requestAnimationFrame.bind(window); else log("setup", "RequestAnimationFrame not supported"); } function getMyID(iframeId) { var retStr = "Host page: " + iframeId; if (window.top !== window.self) retStr = window.parentIFrame && window.parentIFrame.getId ? window.parentIFrame.getId() + ": " + iframeId : "Nested host page: " + iframeId; return retStr; } function formatLogHeader(iframeId) { return msgId + "[" + getMyID(iframeId) + "]"; } function isLogEnabled(iframeId) { return settings[iframeId] ? settings[iframeId].log : logEnabled; } function log(iframeId, msg) { output("log", iframeId, msg, isLogEnabled(iframeId)); } function info(iframeId, msg) { output("info", iframeId, msg, isLogEnabled(iframeId)); } function warn(iframeId, msg) { output("warn", iframeId, msg, true); } function output(type, iframeId, msg, enabled) { if (true === enabled && "object" === typeof window.console) // eslint-disable-next-line no-console console[type](formatLogHeader(iframeId), msg); } function iFrameListener(event) { function resizeIFrame() { function resize() { setSize(messageData); setPagePosition(iframeId); on("onResized", messageData); } ensureInRange("Height"); ensureInRange("Width"); syncResize(resize, messageData, "init"); } function processMsg() { var data = msg.slice(msgIdLen).split(":"); var height = data[1] ? parseInt(data[1], 10) : 0; var iframe = settings[data[0]] && settings[data[0]].iframe; var compStyle = getComputedStyle(iframe); return { iframe: iframe, id: data[0], height: height + getPaddingEnds(compStyle) + getBorderEnds(compStyle), width: data[2], type: data[3] }; } function getPaddingEnds(compStyle) { if (compStyle.boxSizing !== "border-box") return 0; var top = compStyle.paddingTop ? parseInt(compStyle.paddingTop, 10) : 0; var bot = compStyle.paddingBottom ? parseInt(compStyle.paddingBottom, 10) : 0; return top + bot; } function getBorderEnds(compStyle) { if (compStyle.boxSizing !== "border-box") return 0; var top = compStyle.borderTopWidth ? parseInt(compStyle.borderTopWidth, 10) : 0; var bot = compStyle.borderBottomWidth ? parseInt(compStyle.borderBottomWidth, 10) : 0; return top + bot; } function ensureInRange(Dimension) { var max = Number(settings[iframeId]["max" + Dimension]), min = Number(settings[iframeId]["min" + Dimension]), dimension = Dimension.toLowerCase(), size = Number(messageData[dimension]); log(iframeId, "Checking " + dimension + " is in range " + min + "-" + max); if (size < min) { size = min; log(iframeId, "Set " + dimension + " to min value"); } if (size > max) { size = max; log(iframeId, "Set " + dimension + " to max value"); } messageData[dimension] = "" + size; } function isMessageFromIFrame() { function checkAllowedOrigin() { function checkList() { var i = 0, retCode = false; log(iframeId, "Checking connection is from allowed list of origins: " + checkOrigin); for(; i < checkOrigin.length; i++)if (checkOrigin[i] === origin) { retCode = true; break; } return retCode; } function checkSingle() { var remoteHost = settings[iframeId] && settings[iframeId].remoteHost; log(iframeId, "Checking connection is from: " + remoteHost); return origin === remoteHost; } return checkOrigin.constructor === Array ? checkList() : checkSingle(); } var origin = event.origin, checkOrigin = settings[iframeId] && settings[iframeId].checkOrigin; if (checkOrigin && "" + origin !== "null" && !checkAllowedOrigin()) throw new Error("Unexpected message received from: " + origin + " for " + messageData.iframe.id + ". Message was: " + event.data + ". This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains."); return true; } function isMessageForUs() { return msgId === ("" + msg).slice(0, msgIdLen) && msg.slice(msgIdLen).split(":")[0] in settings // ''+Protects against non-string msg ; } function isMessageFromMetaParent() { // Test if this message is from a parent above us. This is an ugly test, however, updating // the message format would break backwards compatibility. var retCode = messageData.type in { true: 1, false: 1, undefined: 1 }; if (retCode) log(iframeId, "Ignoring init message from meta parent page"); return retCode; } function getMsgBody(offset) { return msg.slice(msg.indexOf(":") + msgHeaderLen + offset); } function forwardMsgFromIFrame(msgBody) { log(iframeId, "onMessage passed: {iframe: " + messageData.iframe.id + ", message: " + msgBody + "}"); on("onMessage", { iframe: messageData.iframe, message: JSON.parse(msgBody) }); log(iframeId, "--"); } function getPageInfo() { var bodyPosition = document.body.getBoundingClientRect(), iFramePosition = messageData.iframe.getBoundingClientRect(); return JSON.stringify({ iframeHeight: iFramePosition.height, iframeWidth: iFramePosition.width, clientHeight: Math.max(document.documentElement.clientHeight, window.innerHeight || 0), clientWidth: Math.max(document.documentElement.clientWidth, window.innerWidth || 0), offsetTop: parseInt(iFramePosition.top - bodyPosition.top, 10), offsetLeft: parseInt(iFramePosition.left - bodyPosition.left, 10), scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset, documentHeight: document.documentElement.clientHeight, documentWidth: document.documentElement.clientWidth, windowHeight: window.innerHeight, windowWidth: window.innerWidth }); } function sendPageInfoToIframe(iframe, iframeId) { function debouncedTrigger() { trigger("Send Page Info", "pageInfo:" + getPageInfo(), iframe, iframeId); } debounceFrameEvents(debouncedTrigger, 32, iframeId); } function startPageInfoMonitor() { function setListener(type, func) { function sendPageInfo() { if (settings[id]) sendPageInfoToIframe(settings[id].iframe, id); else stop(); } [ "scroll", "resize" ].forEach(function(evt) { log(id, type + evt + " listener for sendPageInfo"); func(window, evt, sendPageInfo); }); } function stop() { setListener("Remove ", removeEventListener); } function start() { setListener("Add ", addEventListener); } var id = iframeId // Create locally scoped copy of iFrame ID ; start(); if (settings[id]) settings[id].stopPageInfo = stop; } function stopPageInfoMonitor() { if (settings[iframeId] && settings[iframeId].stopPageInfo) { settings[iframeId].stopPageInfo(); delete settings[iframeId].stopPageInfo; } } function checkIFrameExists() { var retBool = true; if (null === messageData.iframe) { warn(iframeId, "IFrame (" + messageData.id + ") not found"); retBool = false; } return retBool; } function getElementPosition(target) { var iFramePosition = target.getBoundingClientRect(); getPagePosition(iframeId); return { x: Math.floor(Number(iFramePosition.left) + Number(pagePosition.x)), y: Math.floor(Number(iFramePosition.top) + Number(pagePosition.y)) }; } function scrollRequestFromChild(addOffset) { /* istanbul ignore next */ // Not testable in Karma function reposition() { pagePosition = newPosition; scrollTo(); log(iframeId, "--"); } function calcOffset() { return { x: Number(messageData.width) + offset.x, y: Number(messageData.height) + offset.y }; } function scrollParent() { if (window.parentIFrame) window.parentIFrame["scrollTo" + (addOffset ? "Offset" : "")](newPosition.x, newPosition.y); else warn(iframeId, "Unable to scroll to requested position, window.parentIFrame not found"); } var offset = addOffset ? getElementPosition(messageData.iframe) : { x: 0, y: 0 }, newPosition = calcOffset(); log(iframeId, "Reposition requested from iFrame (offset x:" + offset.x + " y:" + offset.y + ")"); if (window.top === window.self) reposition(); else scrollParent(); } function scrollTo() { if (false === on("onScroll", pagePosition)) unsetPagePosition(); else setPagePosition(iframeId); } function findTarget(location) { function jumpToTarget() { var jumpPosition = getElementPosition(target); log(iframeId, "Moving to in page link (#" + hash + ") at x: " + jumpPosition.x + " y: " + jumpPosition.y); pagePosition = { x: jumpPosition.x, y: jumpPosition.y }; scrollTo(); log(iframeId, "--"); } function jumpToParent() { if (window.parentIFrame) window.parentIFrame.moveToAnchor(hash); else log(iframeId, "In page link #" + hash + " not found and window.parentIFrame not found"); } var hash = location.split("#")[1] || "", hashData = decodeURIComponent(hash), target = document.getElementById(hashData) || document.getElementsByName(hashData)[0]; if (target) jumpToTarget(); else if (window.top === window.self) log(iframeId, "In page link #" + hash + " not found"); else jumpToParent(); } function onMouse(event) { var mousePos = {}; if (Number(messageData.width) === 0 && Number(messageData.height) === 0) { var data = getMsgBody(9).split(":"); mousePos = { x: data[1], y: data[0] }; } else mousePos = { x: messageData.width, y: messageData.height }; on(event, { iframe: messageData.iframe, screenX: Number(mousePos.x), screenY: Number(mousePos.y), type: messageData.type }); } function on(funcName, val) { return chkEvent(iframeId, funcName, val); } function actionMsg() { if (settings[iframeId] && settings[iframeId].firstRun) firstRun(); switch(messageData.type){ case "close": closeIFrame(messageData.iframe); break; case "message": forwardMsgFromIFrame(getMsgBody(6)); break; case "mouseenter": onMouse("onMouseEnter"); break; case "mouseleave": onMouse("onMouseLeave"); break; case "autoResize": settings[iframeId].autoResize = JSON.parse(getMsgBody(9)); break; case "scrollTo": scrollRequestFromChild(false); break; case "scrollToOffset": scrollRequestFromChild(true); break; case "pageInfo": sendPageInfoToIframe(settings[iframeId] && settings[iframeId].iframe, iframeId); startPageInfoMonitor(); break; case "pageInfoStop": stopPageInfoMonitor(); break; case "inPageLink": findTarget(getMsgBody(9)); break; case "reset": resetIFrame(messageData); break; case "init": resizeIFrame(); on("onInit", messageData.iframe); break; default: if (Number(messageData.width) === 0 && Number(messageData.height) === 0) warn("Unsupported message received (" + messageData.type + "), this is likely due to the iframe containing a later " + "version of iframe-resizer than the parent page"); else resizeIFrame(); } } function hasSettings(iframeId) { var retBool = true; if (!settings[iframeId]) { retBool = false; warn(messageData.type + " No settings for " + iframeId + ". Message was: " + msg); } return retBool; } function iFrameReadyMsgReceived() { // eslint-disable-next-line no-restricted-syntax, guard-for-in for(var iframeId in settings)trigger("iFrame requested init", createOutgoingMsg(iframeId), settings[iframeId].iframe, iframeId); } function firstRun() { if (settings[iframeId]) settings[iframeId].firstRun = false; } var msg = event.data, messageData = {}, iframeId = null; if ("[iFrameResizerChild]Ready" === msg) iFrameReadyMsgReceived(); else if (isMessageForUs()) { messageData = processMsg(); iframeId = messageData.id; if (settings[iframeId]) settings[iframeId].loaded = true; if (!isMessageFromMetaParent() && hasSettings(iframeId)) { log(iframeId, "Received: " + msg); if (checkIFrameExists() && isMessageFromIFrame()) actionMsg(); } } else info(iframeId, "Ignored: " + msg); } function chkEvent(iframeId, funcName, val) { var func = null, retVal = null; if (settings[iframeId]) { func = settings[iframeId][funcName]; if ("function" === typeof func) retVal = func(val); else throw new TypeError(funcName + " on iFrame[" + iframeId + "] is not a function"); } return retVal; } function removeIframeListeners(iframe) { var iframeId = iframe.id; delete settings[iframeId]; } function closeIFrame(iframe) { var iframeId = iframe.id; if (chkEvent(iframeId, "onClose", iframeId) === false) { log(iframeId, "Close iframe cancelled by onClose event"); return; } log(iframeId, "Removing iFrame: " + iframeId); try { // Catch race condition error with React if (iframe.parentNode) iframe.parentNode.removeChild(iframe); } catch (error) { warn(error); } chkEvent(iframeId, "onClosed", iframeId); log(iframeId, "--"); removeIframeListeners(iframe); } function getPagePosition(iframeId) { if (null === pagePosition) { pagePosition = { x: window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, y: window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset }; log(iframeId, "Get page position: " + pagePosition.x + "," + pagePosition.y); } } function setPagePosition(iframeId) { if (null !== pagePosition) { window.scrollTo(pagePosition.x, pagePosition.y); log(iframeId, "Set page position: " + pagePosition.x + "," + pagePosition.y); unsetPagePosition(); } } function unsetPagePosition() { pagePosition = null; } function resetIFrame(messageData) { function reset() { setSize(messageData); trigger("reset", "reset", messageData.iframe, messageData.id); } log(messageData.id, "Size reset requested by " + ("init" === messageData.type ? "host page" : "iFrame")); getPagePosition(messageData.id); syncResize(reset, messageData, "reset"); } function setSize(messageData) { function setDimension(dimension) { if (!messageData.id) { log("undefined", "messageData id not set"); return; } messageData.iframe.style[dimension] = messageData[dimension] + "px"; log(messageData.id, "IFrame (" + iframeId + ") " + dimension + " set to " + messageData[dimension] + "px"); } function chkZero(dimension) { // FireFox sets dimension of hidden iFrames to zero. // So if we detect that set up an event to check for // when iFrame becomes visible. /* istanbul ignore next */ // Not testable in PhantomJS if (!hiddenCheckEnabled && "0" === messageData[dimension]) { hiddenCheckEnabled = true; log(iframeId, "Hidden iFrame detected, creating visibility listener"); fixHiddenIFrames(); } } function processDimension(dimension) { setDimension(dimension); chkZero(dimension); } var iframeId = messageData.iframe.id; if (settings[iframeId]) { if (settings[iframeId].sizeHeight) processDimension("height"); if (settings[iframeId].sizeWidth) processDimension("width"); } } function syncResize(func, messageData, doNotSync) { /* istanbul ignore if */ // Not testable in PhantomJS if (doNotSync !== messageData.type && requestAnimationFrame && // including check for jasmine because had trouble getting spy to work in unit test using requestAnimationFrame !window.jasmine) { log(messageData.id, "Requesting animation frame"); requestAnimationFrame(func); } else func(); } function trigger(calleeMsg, msg, iframe, id, noResponseWarning) { function postMessageToIFrame() { var target = settings[id] && settings[id].targetOrigin; log(id, "[" + calleeMsg + "] Sending msg to iframe[" + id + "] (" + msg + ") targetOrigin: " + target); iframe.contentWindow.postMessage(msgId + msg, target); } function iFrameNotFound() { warn(id, "[" + calleeMsg + "] IFrame(" + id + ") not found"); } function chkAndSend() { if (iframe && "contentWindow" in iframe && null !== iframe.contentWindow) // Null test for PhantomJS postMessageToIFrame(); else iFrameNotFound(); } function warnOnNoResponse() { function warning() { if (settings[id] && !settings[id].loaded && !errorShown) { errorShown = true; warn(id, "IFrame has not responded within " + settings[id].warningTimeout / 1000 + " seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ignored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning."); } } if (!!noResponseWarning && settings[id] && !!settings[id].warningTimeout) settings[id].msgTimeout = setTimeout(warning, settings[id].warningTimeout); } var errorShown = false; id = id || iframe.id; if (settings[id]) { chkAndSend(); warnOnNoResponse(); } } function createOutgoingMsg(iframeId) { return iframeId + ":" + settings[iframeId].bodyMarginV1 + ":" + settings[iframeId].sizeWidth + ":" + settings[iframeId].log + ":" + settings[iframeId].interval + ":" + settings[iframeId].enablePublicMethods + ":" + settings[iframeId].autoResize + ":" + settings[iframeId].bodyMargin + ":" + settings[iframeId].heightCalculationMethod + ":" + settings[iframeId].bodyBackground + ":" + settings[iframeId].bodyPadding + ":" + settings[iframeId].tolerance + ":" + settings[iframeId].inPageLinks + ":" + settings[iframeId].resizeFrom + ":" + settings[iframeId].widthCalculationMethod + ":" + settings[iframeId].mouseEvents; } function isNumber(value) { return typeof value === "number"; } function setupIFrame(iframe, options) { function setLimits() { function addStyle(style) { var styleValue = settings[iframeId][style]; if (Infinity !== styleValue && 0 !== styleValue) { iframe.style[style] = isNumber(styleValue) ? styleValue + "px" : styleValue; log(iframeId, "Set " + style + " = " + iframe.style[style]); } } function chkMinMax(dimension) { if (settings[iframeId]["min" + dimension] > settings[iframeId]["max" + dimension]) throw new Error("Value for min" + dimension + " can not be greater than max" + dimension); } chkMinMax("Height"); chkMinMax("Width"); addStyle("maxHeight"); addStyle("minHeight"); addStyle("maxWidth"); addStyle("minWidth"); } function newId() { var id = options && options.id || defaults.id + count++; if (null !== document.getElementById(id)) id += count++; return id; } function ensureHasId(iframeId) { if (typeof iframeId !== "string") throw new TypeError("Invaild id for iFrame. Expected String"); if ("" === iframeId) { // eslint-disable-next-line no-multi-assign iframe.id = iframeId = newId(); logEnabled = (options || {}).log; log(iframeId, "Added missing iframe ID: " + iframeId + " (" + iframe.src + ")"); } return iframeId; } function setScrolling() { log(iframeId, "IFrame scrolling " + (settings[iframeId] && settings[iframeId].scrolling ? "enabled" : "disabled") + " for " + iframeId); iframe.style.overflow = false === (settings[iframeId] && settings[iframeId].scrolling) ? "hidden" : "auto"; switch(settings[iframeId] && settings[iframeId].scrolling){ case "omit": break; case true: iframe.scrolling = "yes"; break; case false: iframe.scrolling = "no"; break; default: iframe.scrolling = settings[iframeId] ? settings[iframeId].scrolling : "no"; } } // The V1 iFrame script expects an int, where as in V2 expects a CSS // string value such as '1px 3em', so if we have an int for V2, set V1=V2 // and then convert V2 to a string PX value. function setupBodyMarginValues() { if ("number" === typeof (settings[iframeId] && settings[iframeId].bodyMargin) || "0" === (settings[iframeId] && settings[iframeId].bodyMargin)) { settings[iframeId].bodyMarginV1 = settings[iframeId].bodyMargin; settings[iframeId].bodyMargin = "" + settings[iframeId].bodyMargin + "px"; } } function checkReset() { // Reduce scope of firstRun to function, because IE8's JS execution // context stack is borked and this value gets externally // changed midway through running this function!!! var firstRun = settings[iframeId] && settings[iframeId].firstRun, resetRequertMethod = settings[iframeId] && settings[iframeId].heightCalculationMethod in resetRequiredMethods; if (!firstRun && resetRequertMethod) resetIFrame({ iframe: iframe, height: 0, width: 0, type: "init" }); } function setupIFrameObject() { if (settings[iframeId]) settings[iframeId].iframe.iFrameResizer = { close: closeIFrame.bind(null, settings[iframeId].iframe), removeListeners: removeIframeListeners.bind(null, settings[iframeId].iframe), resize: trigger.bind(null, "Window resize", "resize", settings[iframeId].iframe), moveToAnchor: function(anchor) { trigger("Move to anchor", "moveToAnchor:" + anchor, settings[iframeId].iframe, iframeId); }, sendMessage: function(message) { message = JSON.stringify(message); trigger("Send Message", "message:" + message, settings[iframeId].iframe, iframeId); } }; } // We have to call trigger twice, as we can not be sure if all // iframes have completed loading when this code runs. The // event listener also catches the page changing in the iFrame. function init(msg) { function iFrameLoaded() { trigger("iFrame.onload", msg, iframe, undefined, true); checkReset(); } function createDestroyObserver(MutationObserver) { if (!iframe.parentNode) return; var destroyObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { var removedNodes = Array.prototype.slice.call(mutation.removedNodes) // Transform NodeList into an Array ; removedNodes.forEach(function(removedNode) { if (removedNode === iframe) closeIFrame(iframe); }); }); }); destroyObserver.observe(iframe.parentNode, { childList: true }); } var MutationObserver = getMutationObserver(); if (MutationObserver) createDestroyObserver(MutationObserver); addEventListener(iframe, "load", iFrameLoaded); trigger("init", msg, iframe, undefined, true); } function checkOptions(options) { if ("object" !== typeof options) throw new TypeError("Options is not an object"); } function copyOptions(options) { // eslint-disable-next-line no-restricted-syntax for(var option in defaults)if (Object.prototype.hasOwnProperty.call(defaults, option)) settings[iframeId][option] = Object.prototype.hasOwnProperty.call(options, option) ? options[option] : defaults[option]; } function getTargetOrigin(remoteHost) { return "" === remoteHost || null !== remoteHost.match(/^(about:blank|javascript:|file:\/\/)/) ? "*" : remoteHost; } 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(iframeId, "Deprecated: '" + key + "' has been renamed '" + name + "'. The old method will be removed in the next major version."); } } function processOptions(options) { options = options || {}; settings[iframeId] = Object.create(null) // Protect against prototype attacks ; settings[iframeId].iframe = iframe; settings[iframeId].firstRun = true; settings[iframeId].remoteHost = iframe.src && iframe.src.split("/").slice(0, 3).join("/"); checkOptions(options); Object.keys(options).forEach(depricate, options); copyOptions(options); if (settings[iframeId]) settings[iframeId].targetOrigin = true === settings[iframeId].checkOrigin ? getTargetOrigin(settings[iframeId].remoteHost) : "*"; } function beenHere() { return iframeId in settings && "iFrameResizer" in iframe; } var iframeId = ensureHasId(iframe.id); if (beenHere()) warn(iframeId, "Ignored iFrame, already setup."); else { processOptions(options); setScrolling(); setLimits(); setupBodyMarginValues(); init(createOutgoingMsg(iframeId)); setupIFrameObject(); } } function debouce(fn, time) { if (null === timer) timer = setTimeout(function() { timer = null; fn(); }, time); } var frameTimer = {}; function debounceFrameEvents(fn, time, frameId) { if (!frameTimer[frameId]) frameTimer[frameId] = setTimeout(function() { frameTimer[frameId] = null; fn(); }, time); } // Not testable in PhantomJS /* istanbul ignore next */ function fixHiddenIFrames() { function checkIFrames() { function checkIFrame(settingId) { function chkDimension(dimension) { return "0px" === (settings[settingId] && settings[settingId].iframe.style[dimension]); } function isVisible(el) { return null !== el.offsetParent; } if (settings[settingId] && isVisible(settings[settingId].iframe) && (chkDimension("height") || chkDimension("width"))) trigger("Visibility change", "resize", settings[settingId].iframe, settingId); } Object.keys(settings).forEach(function(key) { checkIFrame(key); }); } function mutationObserved(mutations) { log("window", "Mutation observed: " + mutations[0].target + " " + mutations[0].type); debouce(checkIFrames, 16); } function createMutationObserver() { var target = document.querySelector("body"), config = { attributes: true, attributeOldValue: false, characterData: true, characterDataOldValue: false, childList: true, subtree: true }, observer = new MutationObserver(mutationObserved); observer.observe(target, config); } var MutationObserver = getMutationObserver(); if (MutationObserver) createMutationObserver(); } function resizeIFrames(event) { function resize() { sendTriggerMsg("Window " + event, "resize"); } log("window", "Trigger event: " + event); debouce(resize, 16); } // Not testable in PhantomJS /* istanbul ignore next */ function tabVisible() { function resize() { sendTriggerMsg("Tab Visible", "resize"); } if ("hidden" !== document.visibilityState) { log("document", "Trigger event: Visibility change"); debouce(resize, 16); } } function sendTriggerMsg(eventName, event) { function isIFrameResizeEnabled(iframeId) { return settings[iframeId] && "parent" === settings[iframeId].resizeFrom && settings[iframeId].autoResize && !settings[iframeId].firstRun; } Object.keys(settings).forEach(function(iframeId) { if (isIFrameResizeEnabled(iframeId)) trigger(eventName, event, settings[iframeId].iframe, iframeId); }); } function setupEventListeners() { addEventListener(window, "message", iFrameListener); addEventListener(window, "resize", function() { resizeIFrames("resize"); }); addEventListener(document, "visibilitychange", tabVisible); addEventListener(document, "-webkit-visibilitychange", tabVisible); } function factory() { function init(options, element) { function chkType() { if (!element.tagName) throw new TypeError("Object is not a valid DOM element"); else if ("IFRAME" !== element.tagName.toUpperCase()) throw new TypeError("Expected