mirror of
https://github.com/zero-peak/ZeroOmega.git
synced 2025-01-23 07:18:13 -05:00
1467 lines
37 KiB
JavaScript
1467 lines
37 KiB
JavaScript
|
/*
|
||
|
* 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]', // Must match iframe msg ID
|
||
|
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 <IFRAME> tag, found <' + element.tagName + '>'
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (element) {
|
||
|
chkType()
|
||
|
setupIFrame(element, options)
|
||
|
iFrames.push(element)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function warnDeprecatedOptions(options) {
|
||
|
if (options && options.enablePublicMethods) {
|
||
|
warn(
|
||
|
'enablePublicMethods option has been removed, public methods are now always available in the iFrame'
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var iFrames
|
||
|
|
||
|
setupRequestAnimationFrame()
|
||
|
setupEventListeners()
|
||
|
|
||
|
return function iFrameResizeF(options, target) {
|
||
|
iFrames = [] // Only return iFrames past in on this call
|
||
|
|
||
|
warnDeprecatedOptions(options)
|
||
|
|
||
|
switch (typeof target) {
|
||
|
case 'undefined':
|
||
|
case 'string': {
|
||
|
Array.prototype.forEach.call(
|
||
|
document.querySelectorAll(target || 'iframe'),
|
||
|
init.bind(undefined, options)
|
||
|
)
|
||
|
break
|
||
|
}
|
||
|
|
||
|
case 'object': {
|
||
|
init(options, target)
|
||
|
break
|
||
|
}
|
||
|
|
||
|
default: {
|
||
|
throw new TypeError('Unexpected data type (' + typeof target + ')')
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return iFrames
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function createJQueryPublicMethod($) {
|
||
|
if (!$.fn) {
|
||
|
info('', 'Unable to bind to jQuery, it is not fully loaded.')
|
||
|
} else if (!$.fn.iFrameResize) {
|
||
|
$.fn.iFrameResize = function $iFrameResizeF(options) {
|
||
|
function init(index, element) {
|
||
|
setupIFrame(element, options)
|
||
|
}
|
||
|
|
||
|
return this.filter('iframe').each(init).end()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (window.jQuery !== undefined) {
|
||
|
createJQueryPublicMethod(window.jQuery)
|
||
|
}
|
||
|
|
||
|
if (typeof define === 'function' && define.amd) {
|
||
|
define([], factory)
|
||
|
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
||
|
// Node for browserfy
|
||
|
module.exports = factory()
|
||
|
}
|
||
|
window.iFrameResize = window.iFrameResize || factory()
|
||
|
})()
|