2022-01-13 13:00:31 +00:00
/ *
* 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
* /
; ( function ( undefined ) {
'use strict' ;
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 = { max : 1 , scroll : 1 , bodyScroll : 1 , documentElementScroll : 1 } ,
settings = { } ,
timer = null ,
logId = 'Host Page' ,
defaults = {
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 ,
resizeFrom : 'parent' ,
scrolling : false ,
sizeHeight : true ,
sizeWidth : false ,
warningTimeout : 5000 ,
tolerance : 0 ,
widthCalculationMethod : 'scroll' ,
closedCallback : function ( ) { } ,
initCallback : function ( ) { } ,
messageCallback : function ( ) { warn ( 'MessageCallback function not defined' ) ; } ,
resizedCallback : function ( ) { } ,
scrollCallback : function ( ) { return true ; }
} ;
function addEventListener ( obj , evt , func ) {
/* istanbul ignore else */ // Not testable in PhantonJS
if ( 'addEventListener' in window ) {
obj . addEventListener ( evt , func , false ) ;
} else if ( 'attachEvent' in window ) { //IE
obj . attachEvent ( 'on' + evt , func ) ;
}
}
function removeEventListener ( el , evt , func ) {
/* istanbul ignore else */ // Not testable in phantonJS
if ( 'removeEventListener' in window ) {
el . removeEventListener ( evt , func , false ) ;
} else if ( 'detachEvent' in window ) { //IE
el . detachEvent ( 'on' + evt , func ) ;
}
}
function setupRequestAnimationFrame ( ) {
var
vendors = [ 'moz' , 'webkit' , 'o' , 'ms' ] ,
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 ) ) {
log ( 'setup' , 'RequestAnimationFrame not supported' ) ;
}
}
function getMyID ( iframeId ) {
var retStr = 'Host page: ' + iframeId ;
if ( window . top !== window . self ) {
if ( window . parentIFrame && window . parentIFrame . getId ) {
retStr = window . parentIFrame . getId ( ) + ': ' + iframeId ;
} else {
retStr = '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 ) {
console [ type ] ( formatLogHeader ( iframeId ) , msg ) ;
}
}
function iFrameListener ( event ) {
function resizeIFrame ( ) {
function resize ( ) {
setSize ( messageData ) ;
setPagePosition ( iframeId ) ;
callback ( 'resizedCallback' , messageData ) ;
}
ensureInRange ( 'Height' ) ;
ensureInRange ( 'Width' ) ;
syncResize ( resize , messageData , 'init' ) ;
}
function processMsg ( ) {
2022-06-08 10:36:39 +00:00
var data = msg . slice ( msgIdLen ) . split ( ':' ) ;
2022-01-13 13:00:31 +00:00
return {
iframe : settings [ data [ 0 ] ] && settings [ data [ 0 ] ] . iframe ,
id : data [ 0 ] ,
height : data [ 1 ] ,
width : data [ 2 ] ,
type : data [ 3 ]
} ;
}
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 ( ) {
2022-06-08 10:36:39 +00:00
return msgId === ( ( '' + msg ) . slice ( 0 , msgIdLen ) ) && ( msg . slice ( msgIdLen ) . split ( ':' ) [ 0 ] in settings ) ; //''+Protects against non-string msg
2022-01-13 13:00:31 +00:00
}
function isMessageFromMetaParent ( ) {
//Test if this message is from a parent above us. This is an ugly test, however, updating
2022-06-08 10:36:39 +00:00
//the message format would break backwards compatibility.
2022-01-13 13:00:31 +00:00
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 ) {
2022-06-08 10:36:39 +00:00
return msg . slice ( msg . indexOf ( ':' ) + msgHeaderLen + offset ) ;
2022-01-13 13:00:31 +00:00
}
function forwardMsgFromIFrame ( msgBody ) {
log ( iframeId , 'MessageCallback passed: {iframe: ' + messageData . iframe . id + ', message: ' + msgBody + '}' ) ;
callback ( 'messageCallback' , {
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
} ) ;
}
function sendPageInfoToIframe ( iframe , iframeId ) {
function debouncedTrigger ( ) {
trigger (
'Send Page Info' ,
'pageInfo:' + getPageInfo ( ) ,
iframe ,
iframeId
) ;
}
debouce ( debouncedTrigger , 32 ) ;
}
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 ) {
scrollParent ( ) ;
} else {
reposition ( ) ;
}
}
function scrollTo ( ) {
if ( false !== callback ( 'scrollCallback' , pagePosition ) ) {
setPagePosition ( iframeId ) ;
} else {
unsetPagePosition ( ) ;
}
}
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 ) {
jumpToParent ( ) ;
} else {
log ( iframeId , 'In page link #' + hash + ' not found' ) ;
}
}
function callback ( funcName , val ) {
return chkCallback ( iframeId , funcName , val ) ;
}
function actionMsg ( ) {
if ( settings [ iframeId ] && settings [ iframeId ] . firstRun ) firstRun ( ) ;
switch ( messageData . type ) {
case 'close' :
if ( settings [ iframeId ] . closeRequestCallback ) chkCallback ( iframeId , 'closeRequestCallback' , settings [ iframeId ] . iframe ) ;
else closeIFrame ( messageData . iframe ) ;
break ;
case 'message' :
forwardMsgFromIFrame ( getMsgBody ( 6 ) ) ;
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 ( ) ;
callback ( 'initCallback' , messageData . iframe ) ;
break ;
default :
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 ( ) {
for ( var iframeId in settings ) {
trigger ( 'iFrame requested init' , createOutgoingMsg ( iframeId ) , document . getElementById ( iframeId ) , iframeId ) ;
}
}
function firstRun ( ) {
if ( settings [ iframeId ] ) {
settings [ iframeId ] . firstRun = false ;
}
}
function clearWarningTimeout ( ) {
if ( settings [ iframeId ] ) {
clearTimeout ( settings [ iframeId ] . msgTimeout ) ;
settings [ iframeId ] . warningTimeout = 0 ;
}
}
var
msg = event . data ,
messageData = { } ,
iframeId = null ;
if ( '[iFrameResizerChild]Ready' === msg ) {
iFrameReadyMsgReceived ( ) ;
} else if ( isMessageForUs ( ) ) {
messageData = processMsg ( ) ;
iframeId = logId = 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 chkCallback ( 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 closeIFrame ( iframe ) {
var iframeId = iframe . id ;
log ( iframeId , 'Removing iFrame: ' + iframeId ) ;
if ( iframe . parentNode ) { iframe . parentNode . removeChild ( iframe ) ; }
chkCallback ( iframeId , 'closedCallback' , iframeId ) ;
log ( iframeId , '--' ) ;
delete settings [ iframeId ] ;
}
function getPagePosition ( iframeId ) {
if ( null === pagePosition ) {
pagePosition = {
x : ( window . pageXOffset !== undefined ) ? window . pageXOffset : document . documentElement . scrollLeft ,
y : ( window . pageYOffset !== undefined ) ? window . pageYOffset : document . documentElement . scrollTop
} ;
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 ) {
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 ) {
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 ;
2022-06-08 10:36:39 +00:00
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.' ) ;
2022-01-13 13:00:31 +00:00
}
}
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 ;
}
function setupIFrame ( iframe , options ) {
function setLimits ( ) {
function addStyle ( style ) {
if ( ( Infinity !== settings [ iframeId ] [ style ] ) && ( 0 !== settings [ iframeId ] [ style ] ) ) {
iframe . style [ style ] = settings [ iframeId ] [ style ] + 'px' ;
log ( iframeId , 'Set ' + style + ' = ' + settings [ iframeId ] [ style ] + 'px' ) ;
}
}
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 = id + count ++ ;
}
return id ;
}
function ensureHasId ( iframeId ) {
logId = iframeId ;
if ( '' === iframeId ) {
iframe . id = iframeId = newId ( ) ;
logEnabled = ( options || { } ) . log ;
logId = iframeId ;
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 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 ( Function . prototype . bind && settings [ iframeId ] ) { //Ignore unpolyfilled IE8.
settings [ iframeId ] . iframe . iFrameResizer = {
close : closeIFrame . 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 ( ) ;
}
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 ) {
for ( var option in defaults ) {
if ( defaults . hasOwnProperty ( option ) ) {
settings [ iframeId ] [ option ] = options . hasOwnProperty ( option ) ? options [ option ] : defaults [ option ] ;
}
}
}
function getTargetOrigin ( remoteHost ) {
return ( '' === remoteHost || 'file://' === remoteHost ) ? '*' : remoteHost ;
}
function processOptions ( options ) {
options = options || { } ;
settings [ iframeId ] = {
firstRun : true ,
iframe : iframe ,
remoteHost : iframe . src . split ( '/' ) . slice ( 0 , 3 ) . join ( '/' )
} ;
checkOptions ( 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 ( ) ) {
processOptions ( options ) ;
setScrolling ( ) ;
setLimits ( ) ;
setupBodyMarginValues ( ) ;
init ( createOutgoingMsg ( iframeId ) ) ;
setupIFrameObject ( ) ;
} else {
warn ( iframeId , 'Ignored iFrame, already setup.' ) ;
}
}
function debouce ( fn , time ) {
if ( null === timer ) {
timer = setTimeout ( function ( ) {
timer = null ;
fn ( ) ;
} , time ) ;
}
}
/* istanbul ignore next */ //Not testable in PhantomJS
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 ) ;
}
}
for ( var settingId in settings ) {
checkIFrame ( settingId ) ;
}
}
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 = window . MutationObserver || window . WebKitMutationObserver ;
if ( MutationObserver ) createMutationObserver ( ) ;
}
function resizeIFrames ( event ) {
function resize ( ) {
sendTriggerMsg ( 'Window ' + event , 'resize' ) ;
}
log ( 'window' , 'Trigger event: ' + event ) ;
debouce ( resize , 16 ) ;
}
/* istanbul ignore next */ //Not testable in PhantomJS
function tabVisible ( ) {
function resize ( ) {
sendTriggerMsg ( 'Tab Visable' , 'resize' ) ;
}
if ( 'hidden' !== document . visibilityState ) {
2022-06-08 10:36:39 +00:00
log ( 'document' , 'Trigger event: Visibility change' ) ;
2022-01-13 13:00:31 +00:00
debouce ( resize , 16 ) ;
}
}
function sendTriggerMsg ( eventName , event ) {
function isIFrameResizeEnabled ( iframeId ) {
return settings [ iframeId ] &&
'parent' === settings [ iframeId ] . resizeFrom &&
settings [ iframeId ] . autoResize &&
! settings [ iframeId ] . firstRun ;
}
for ( var iframeId in settings ) {
if ( isIFrameResizeEnabled ( iframeId ) ) {
trigger ( eventName , event , document . getElementById ( iframeId ) , iframeId ) ;
}
}
}
function setupEventListeners ( ) {
addEventListener ( window , 'message' , iFrameListener ) ;
addEventListener ( window , 'resize' , function ( ) { resizeIFrames ( 'resize' ) ; } ) ;
addEventListener ( document , 'visibilitychange' , tabVisible ) ;
addEventListener ( document , '-webkit-visibilitychange' , tabVisible ) ; //Andriod 4.4
addEventListener ( window , 'focusin' , function ( ) { resizeIFrames ( 'focus' ) ; } ) ; //IE8-9
addEventListener ( window , 'focus' , function ( ) { resizeIFrames ( 'focus' ) ; } ) ;
}
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 ) { 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 ( ) ;
} else {
window . iFrameResize = window . iFrameResize || factory ( ) ;
}
} ) ( ) ;