9 changed files with 1370 additions and 33 deletions
Split View
Diff Options
-
707examples/assets/library/iframe-content.js
-
642examples/assets/library/iframe.js
-
1examples/components/button.html
-
1examples/components/card.html
-
1examples/components/input.html
-
1examples/components/menu.html
-
2examples/components/site.html
-
5examples/components/table.html
-
43examples/theming.html
@ -0,0 +1,707 @@ |
|||
/* |
|||
* File: iframeResizer.contentWindow.js |
|||
* Desc: Include this file in any page being loaded into an iframe |
|||
* to force the iframe to resize to the content size. |
|||
* Requires: iframeResizer.js on host page. |
|||
* Author: David J. Bradshaw - dave@bradshaw.net |
|||
* Contributor: Jure Mav - jure.mav@gmail.com |
|||
* Contributor: Ian Caunce - ian@hallnet.co.uk |
|||
*/ |
|||
|
|||
;(function() { |
|||
'use strict'; |
|||
|
|||
var |
|||
autoResize = true, |
|||
base = 10, |
|||
bodyBackground = '', |
|||
bodyMargin = 0, |
|||
bodyMarginStr = '', |
|||
bodyPadding = '', |
|||
calculateWidth = false, |
|||
doubleEventList = {'resize':1,'click':1}, |
|||
eventCancelTimer = 128, |
|||
height = 1, |
|||
firstRun = true, |
|||
heightCalcModeDefault = 'offset', |
|||
heightCalcMode = heightCalcModeDefault, |
|||
initLock = true, |
|||
initMsg = '', |
|||
inPageLinks = {}, |
|||
interval = 32, |
|||
logging = false, |
|||
msgID = '[iFrameSizer]', //Must match host page msg ID
|
|||
msgIdLen = msgID.length, |
|||
myID = '', |
|||
publicMethods = false, |
|||
resetRequiredMethods = {max:1,scroll:1,bodyScroll:1,documentElementScroll:1}, |
|||
resizeFrom = 'parent', |
|||
targetOriginDefault = '*', |
|||
target = window.parent, |
|||
tolerance = 0, |
|||
triggerLocked = false, |
|||
triggerLockedTimer = null, |
|||
width = 1; |
|||
|
|||
|
|||
function addEventListener(el,evt,func){ |
|||
if ('addEventListener' in window){ |
|||
el.addEventListener(evt,func, false); |
|||
} else if ('attachEvent' in window){ //IE
|
|||
el.attachEvent('on'+evt,func); |
|||
} |
|||
} |
|||
|
|||
function formatLogMsg(msg){ |
|||
return msgID + '[' + myID + ']' + ' ' + msg; |
|||
} |
|||
|
|||
function log(msg){ |
|||
if (logging && ('object' === typeof window.console)){ |
|||
console.log(formatLogMsg(msg)); |
|||
} |
|||
} |
|||
|
|||
function warn(msg){ |
|||
if ('object' === typeof window.console){ |
|||
console.warn(formatLogMsg(msg)); |
|||
} |
|||
} |
|||
|
|||
|
|||
function init(){ |
|||
log('Initialising iFrame'); |
|||
readData(); |
|||
setMargin(); |
|||
setBodyStyle('background',bodyBackground); |
|||
setBodyStyle('padding',bodyPadding); |
|||
injectClearFixIntoBodyElement(); |
|||
checkHeightMode(); |
|||
stopInfiniteResizingOfIFrame(); |
|||
setupPublicMethods(); |
|||
startEventListeners(); |
|||
inPageLinks = setupInPageLinks(); |
|||
sendSize('init','Init message from host page'); |
|||
} |
|||
|
|||
function readData(){ |
|||
|
|||
var data = initMsg.substr(msgIdLen).split(':'); |
|||
|
|||
function strBool(str){ |
|||
return 'true' === str ? true : false; |
|||
} |
|||
|
|||
myID = data[0]; |
|||
bodyMargin = (undefined !== data[1]) ? Number(data[1]) : bodyMargin; //For V1 compatibility
|
|||
calculateWidth = (undefined !== data[2]) ? strBool(data[2]) : calculateWidth; |
|||
logging = (undefined !== data[3]) ? strBool(data[3]) : logging; |
|||
interval = (undefined !== data[4]) ? Number(data[4]) : interval; |
|||
publicMethods = (undefined !== data[5]) ? strBool(data[5]) : publicMethods; |
|||
autoResize = (undefined !== data[6]) ? strBool(data[6]) : autoResize; |
|||
bodyMarginStr = data[7]; |
|||
heightCalcMode = (undefined !== data[8]) ? data[8] : heightCalcMode; |
|||
bodyBackground = data[9]; |
|||
bodyPadding = data[10]; |
|||
tolerance = (undefined !== data[11]) ? Number(data[11]) : tolerance; |
|||
inPageLinks.enable = (undefined !== data[12]) ? strBool(data[12]): false; |
|||
resizeFrom = data[13]; |
|||
} |
|||
|
|||
function chkCSS(attr,value){ |
|||
if (-1 !== value.indexOf('-')){ |
|||
warn('Negative CSS value ignored for '+attr); |
|||
value=''; |
|||
} |
|||
return value; |
|||
} |
|||
|
|||
function setBodyStyle(attr,value){ |
|||
if ((undefined !== value) && ('' !== value) && ('null' !== value)){ |
|||
document.body.style[attr] = value; |
|||
log('Body '+attr+' set to "'+value+'"'); |
|||
} |
|||
} |
|||
|
|||
function setMargin(){ |
|||
//If called via V1 script, convert bodyMargin from int to str
|
|||
if (undefined === bodyMarginStr){ |
|||
bodyMarginStr = bodyMargin+'px'; |
|||
} |
|||
chkCSS('margin',bodyMarginStr); |
|||
setBodyStyle('margin',bodyMarginStr); |
|||
} |
|||
|
|||
function stopInfiniteResizingOfIFrame(){ |
|||
document.documentElement.style.height = ''; |
|||
document.body.style.height = ''; |
|||
log('HTML & body height set to "auto"'); |
|||
} |
|||
|
|||
|
|||
function addTriggerEvent(options){ |
|||
function addListener(eventName){ |
|||
addEventListener(window,eventName,function(e){ |
|||
sendSize(options.eventName,options.eventType); |
|||
}); |
|||
} |
|||
|
|||
if(options.eventNames && Array.prototype.map){ |
|||
options.eventName = options.eventNames[0]; |
|||
options.eventNames.map(addListener); |
|||
} else { |
|||
addListener(options.eventName); |
|||
} |
|||
|
|||
log('Added event listener: ' + options.eventType); |
|||
} |
|||
|
|||
function initEventListeners(){ |
|||
addTriggerEvent({ eventType: 'Animation Start', eventNames: ['animationstart','webkitAnimationStart'] }); |
|||
addTriggerEvent({ eventType: 'Animation Iteration', eventNames: ['animationiteration','webkitAnimationIteration'] }); |
|||
addTriggerEvent({ eventType: 'Animation End', eventNames: ['animationend','webkitAnimationEnd'] }); |
|||
addTriggerEvent({ eventType: 'Device Orientation Change', eventName: 'deviceorientation' }); |
|||
addTriggerEvent({ eventType: 'Transition End', eventNames: ['transitionend','webkitTransitionEnd','MSTransitionEnd','oTransitionEnd','otransitionend'] }); |
|||
addTriggerEvent({ eventType: 'Window Clicked', eventName: 'click' }); |
|||
//addTriggerEvent({ eventType: 'Window Mouse Down', eventName: 'mousedown' });
|
|||
//addTriggerEvent({ eventType: 'Window Mouse Up', eventName: 'mouseup' });
|
|||
if('child' === resizeFrom){ |
|||
addTriggerEvent({ eventType: 'IFrame Resized', eventName: 'resize' }); |
|||
} |
|||
} |
|||
|
|||
function checkHeightMode(){ |
|||
if (heightCalcModeDefault !== heightCalcMode){ |
|||
if (!(heightCalcMode in getHeight)){ |
|||
warn(heightCalcMode + ' is not a valid option for heightCalculationMethod.'); |
|||
heightCalcMode='bodyScroll'; |
|||
} |
|||
log('Height calculation method set to "'+heightCalcMode+'"'); |
|||
} |
|||
} |
|||
|
|||
function startEventListeners(){ |
|||
if ( true === autoResize ) { |
|||
initEventListeners(); |
|||
setupMutationObserver(); |
|||
} |
|||
else { |
|||
log('Auto Resize disabled'); |
|||
} |
|||
} |
|||
|
|||
function injectClearFixIntoBodyElement(){ |
|||
var clearFix = document.createElement('div'); |
|||
clearFix.style.clear = 'both'; |
|||
clearFix.style.display = 'block'; //Guard against this having been globally redefined in CSS.
|
|||
document.body.appendChild(clearFix); |
|||
} |
|||
|
|||
function setupInPageLinks(){ |
|||
|
|||
function getPagePosition (){ |
|||
return { |
|||
x: (window.pageXOffset !== undefined) ? window.pageXOffset : document.documentElement.scrollLeft, |
|||
y: (window.pageYOffset !== undefined) ? window.pageYOffset : document.documentElement.scrollTop |
|||
}; |
|||
} |
|||
|
|||
function getElementPosition(el){ |
|||
var |
|||
elPosition = el.getBoundingClientRect(), |
|||
pagePosition = getPagePosition(); |
|||
|
|||
return { |
|||
x: parseInt(elPosition.left,10) + parseInt(pagePosition.x,10), |
|||
y: parseInt(elPosition.top,10) + parseInt(pagePosition.y,10) |
|||
}; |
|||
} |
|||
|
|||
function findTarget(location){ |
|||
var hash = location.split("#")[1] || ""; |
|||
var hashData = decodeURIComponent(hash); |
|||
|
|||
function jumpToTarget(target){ |
|||
var jumpPosition = getElementPosition(target); |
|||
|
|||
log('Moving to in page link (#'+hash+') at x: '+jumpPosition.x+' y: '+jumpPosition.y); |
|||
sendMsg(jumpPosition.y, jumpPosition.x, 'scrollToOffset'); // X&Y reversed at sendMsg uses height/width
|
|||
} |
|||
|
|||
var target = document.getElementById(hashData) || document.getElementsByName(hashData)[0]; |
|||
|
|||
if (target){ |
|||
jumpToTarget(target); |
|||
} else { |
|||
log('In page link (#' + hash + ') not found in iFrame, so sending to parent'); |
|||
sendMsg(0,0,'inPageLink','#'+hash); |
|||
} |
|||
} |
|||
|
|||
function checkLocationHash(){ |
|||
if ('' !== location.hash && '#' !== location.hash){ |
|||
findTarget(location.href); |
|||
} |
|||
} |
|||
|
|||
function bindAnchors(){ |
|||
function setupLink(el){ |
|||
function linkClicked(e){ |
|||
e.preventDefault(); |
|||
|
|||
/*jshint validthis:true */ |
|||
findTarget(this.getAttribute('href')); |
|||
} |
|||
|
|||
if ('#' !== el.getAttribute('href')){ |
|||
addEventListener(el,'click',linkClicked); |
|||
} |
|||
} |
|||
|
|||
Array.prototype.forEach.call( document.querySelectorAll( 'a[href^="#"]' ), setupLink ); |
|||
} |
|||
|
|||
function bindLocationHash(){ |
|||
addEventListener(window,'hashchange',checkLocationHash); |
|||
} |
|||
|
|||
function initCheck(){ //check if page loaded with location hash after init resize
|
|||
setTimeout(checkLocationHash,eventCancelTimer); |
|||
} |
|||
|
|||
function enableInPageLinks(){ |
|||
if(Array.prototype.forEach && document.querySelectorAll){ |
|||
log('Setting up location.hash handlers'); |
|||
bindAnchors(); |
|||
bindLocationHash(); |
|||
initCheck(); |
|||
} else { |
|||
warn('In page linking not fully supported in this browser! (See README.md for IE8 workaround)'); |
|||
} |
|||
} |
|||
|
|||
if(inPageLinks.enable){ |
|||
enableInPageLinks(); |
|||
} else { |
|||
log('In page linking not enabled'); |
|||
} |
|||
|
|||
return { |
|||
findTarget:findTarget |
|||
}; |
|||
} |
|||
|
|||
function setupPublicMethods(){ |
|||
if (publicMethods) { |
|||
log('Enable public methods'); |
|||
|
|||
window.parentIFrame = { |
|||
close: function closeF(){ |
|||
sendMsg(0,0,'close'); |
|||
}, |
|||
getId: function getIdF(){ |
|||
return myID; |
|||
}, |
|||
moveToAnchor: function moveToAnchorF(hash){ |
|||
inPageLinks.findTarget(hash); |
|||
}, |
|||
reset: function resetF(){ |
|||
resetIFrame('parentIFrame.reset'); |
|||
}, |
|||
scrollTo: function scrollToF(x,y){ |
|||
sendMsg(y,x,'scrollTo'); // X&Y reversed at sendMsg uses height/width
|
|||
}, |
|||
scrollToOffset: function scrollToF(x,y){ |
|||
sendMsg(y,x,'scrollToOffset'); // X&Y reversed at sendMsg uses height/width
|
|||
}, |
|||
sendMessage: function sendMessageF(msg,targetOrigin){ |
|||
sendMsg(0,0,'message',JSON.stringify(msg),targetOrigin); |
|||
}, |
|||
setHeightCalculationMethod: function setHeightCalculationMethodF(heightCalculationMethod){ |
|||
heightCalcMode = heightCalculationMethod; |
|||
checkHeightMode(); |
|||
}, |
|||
setTargetOrigin: function setTargetOriginF(targetOrigin){ |
|||
log('Set targetOrigin: '+targetOrigin); |
|||
targetOriginDefault = targetOrigin; |
|||
}, |
|||
size: function sizeF(customHeight, customWidth){ |
|||
var valString = ''+(customHeight?customHeight:'')+(customWidth?','+customWidth:''); |
|||
lockTrigger(); |
|||
sendSize('size','parentIFrame.size('+valString+')', customHeight, customWidth); |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
|
|||
function initInterval(){ |
|||
if ( 0 !== interval ){ |
|||
log('setInterval: '+interval+'ms'); |
|||
setInterval(function(){ |
|||
sendSize('interval','setInterval: '+interval); |
|||
},Math.abs(interval)); |
|||
} |
|||
} |
|||
|
|||
function setupInjectElementLoadListners(mutations){ |
|||
function addLoadListener(element){ |
|||
if (element.height === undefined || element.width === undefined || 0 === element.height || 0 === element.width){ |
|||
log('Attach listerner to '+element.src); |
|||
addEventListener(element,'load', function imageLoaded(){ |
|||
sendSize('imageLoad','Image loaded'); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
mutations.forEach(function (mutation) { |
|||
if (mutation.type === 'attributes' && mutation.attributeName === 'src'){ |
|||
addLoadListener(mutation.target); |
|||
} else if (mutation.type === 'childList'){ |
|||
var images = mutation.target.querySelectorAll('img'); |
|||
Array.prototype.forEach.call(images,function (image) { |
|||
addLoadListener(image); |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function setupMutationObserver(){ |
|||
|
|||
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; |
|||
|
|||
function createMutationObserver(){ |
|||
var |
|||
target = document.querySelector('body'), |
|||
|
|||
config = { |
|||
attributes : true, |
|||
attributeOldValue : false, |
|||
characterData : true, |
|||
characterDataOldValue : false, |
|||
childList : true, |
|||
subtree : true |
|||
}, |
|||
|
|||
observer = new MutationObserver(function(mutations) { |
|||
sendSize('mutationObserver','mutationObserver: ' + mutations[0].target + ' ' + mutations[0].type); |
|||
setupInjectElementLoadListners(mutations); //Deal with WebKit asyncing image loading when tags are injected into the page
|
|||
}); |
|||
|
|||
log('Enable MutationObserver'); |
|||
observer.observe(target, config); |
|||
} |
|||
|
|||
if (MutationObserver){ |
|||
if (0 > interval) { |
|||
initInterval(); |
|||
} else { |
|||
createMutationObserver(); |
|||
} |
|||
} |
|||
else { |
|||
warn('MutationObserver not supported in this browser!'); |
|||
initInterval(); |
|||
} |
|||
} |
|||
|
|||
|
|||
// document.documentElement.offsetHeight is not reliable, so
|
|||
// we have to jump through hoops to get a better value.
|
|||
function getBodyOffsetHeight(){ |
|||
function getComputedBodyStyle(prop) { |
|||
function convertUnitsToPxForIE8(value) { |
|||
var PIXEL = /^\d+(px)?$/i; |
|||
|
|||
if (PIXEL.test(value)) { |
|||
return parseInt(value,base); |
|||
} |
|||
|
|||
var |
|||
style = el.style.left, |
|||
runtimeStyle = el.runtimeStyle.left; |
|||
|
|||
el.runtimeStyle.left = el.currentStyle.left; |
|||
el.style.left = value || 0; |
|||
value = el.style.pixelLeft; |
|||
el.style.left = style; |
|||
el.runtimeStyle.left = runtimeStyle; |
|||
|
|||
return value; |
|||
} |
|||
|
|||
var |
|||
el = document.body, |
|||
retVal = 0; |
|||
|
|||
if (('defaultView' in document) && ('getComputedStyle' in document.defaultView)) { |
|||
retVal = document.defaultView.getComputedStyle(el, null); |
|||
retVal = (null !== retVal) ? retVal[prop] : 0; |
|||
} else {//IE8
|
|||
retVal = convertUnitsToPxForIE8(el.currentStyle[prop]); |
|||
} |
|||
|
|||
return parseInt(retVal,base); |
|||
} |
|||
|
|||
return document.body.offsetHeight + |
|||
getComputedBodyStyle('marginTop') + |
|||
getComputedBodyStyle('marginBottom'); |
|||
} |
|||
|
|||
function getBodyScrollHeight(){ |
|||
return document.body.scrollHeight; |
|||
} |
|||
|
|||
function getDEOffsetHeight(){ |
|||
return document.documentElement.offsetHeight; |
|||
} |
|||
|
|||
function getDEScrollHeight(){ |
|||
return document.documentElement.scrollHeight; |
|||
} |
|||
|
|||
//From https://github.com/guardian/iframe-messenger
|
|||
function getLowestElementHeight() { |
|||
var |
|||
allElements = document.querySelectorAll('body *'), |
|||
allElementsLength = allElements.length, |
|||
maxBottomVal = 0, |
|||
timer = new Date().getTime(); |
|||
|
|||
for (var i = 0; i < allElementsLength; i++) { |
|||
if (allElements[i].getBoundingClientRect().bottom > maxBottomVal) { |
|||
maxBottomVal = allElements[i].getBoundingClientRect().bottom; |
|||
} |
|||
} |
|||
|
|||
timer = new Date().getTime() - timer; |
|||
|
|||
log('Parsed '+allElementsLength+' HTML elements'); |
|||
log('LowestElement bottom position calculated in ' + timer + 'ms'); |
|||
|
|||
return maxBottomVal; |
|||
} |
|||
|
|||
function getAllHeights(){ |
|||
return [ |
|||
getBodyOffsetHeight(), |
|||
getBodyScrollHeight(), |
|||
getDEOffsetHeight(), |
|||
getDEScrollHeight() |
|||
]; |
|||
} |
|||
|
|||
function getMaxHeight(){ |
|||
return Math.max.apply(null,getAllHeights()); |
|||
} |
|||
|
|||
function getMinHeight(){ |
|||
return Math.min.apply(null,getAllHeights()); |
|||
} |
|||
|
|||
function getBestHeight(){ |
|||
return Math.max(getBodyOffsetHeight(),getLowestElementHeight()); |
|||
} |
|||
|
|||
var getHeight = { |
|||
offset : getBodyOffsetHeight, //Backward compatability
|
|||
bodyOffset : getBodyOffsetHeight, |
|||
bodyScroll : getBodyScrollHeight, |
|||
documentElementOffset : getDEOffsetHeight, |
|||
scroll : getDEScrollHeight, //Backward compatability
|
|||
documentElementScroll : getDEScrollHeight, |
|||
max : getMaxHeight, |
|||
min : getMinHeight, |
|||
grow : getMaxHeight, |
|||
lowestElement : getBestHeight |
|||
}; |
|||
|
|||
function getWidth(){ |
|||
return Math.max( |
|||
document.documentElement.scrollWidth, |
|||
document.body.scrollWidth |
|||
); |
|||
} |
|||
|
|||
function sendSize(triggerEvent, triggerEventDesc, customHeight, customWidth){ |
|||
|
|||
var currentHeight,currentWidth; |
|||
|
|||
function recordTrigger(){ |
|||
if (!(triggerEvent in {'reset':1,'resetPage':1,'init':1})){ |
|||
log( 'Trigger event: ' + triggerEventDesc ); |
|||
} |
|||
} |
|||
|
|||
function resizeIFrame(){ |
|||
height = currentHeight; |
|||
width = currentWidth; |
|||
|
|||
sendMsg(height,width,triggerEvent); |
|||
} |
|||
|
|||
function isDoubleFiredEvent(){ |
|||
return triggerLocked && (triggerEvent in doubleEventList); |
|||
} |
|||
|
|||
function isSizeChangeDetected(){ |
|||
function checkTolarance(a,b){ |
|||
var retVal = Math.abs(a-b) <= tolerance; |
|||
return !retVal; |
|||
} |
|||
|
|||
currentHeight = (undefined !== customHeight) ? customHeight : getHeight[heightCalcMode](); |
|||
currentWidth = (undefined !== customWidth ) ? customWidth : getWidth(); |
|||
|
|||
return checkTolarance(height,currentHeight) || |
|||
(calculateWidth && checkTolarance(width,currentWidth)); |
|||
} |
|||
|
|||
function isForceResizableEvent(){ |
|||
return !(triggerEvent in {'init':1,'interval':1,'size':1}); |
|||
} |
|||
|
|||
function isForceResizableHeightCalcMode(){ |
|||
return (heightCalcMode in resetRequiredMethods); |
|||
} |
|||
|
|||
function logIgnored(){ |
|||
log('No change in size detected'); |
|||
} |
|||
|
|||
function checkDownSizing(){ |
|||
if (isForceResizableEvent() && isForceResizableHeightCalcMode()){ |
|||
resetIFrame(triggerEventDesc); |
|||
} else if (!(triggerEvent in {'interval':1})){ |
|||
recordTrigger(); |
|||
logIgnored(); |
|||
} |
|||
} |
|||
|
|||
if (!isDoubleFiredEvent()){ |
|||
if (isSizeChangeDetected()){ |
|||
recordTrigger(); |
|||
lockTrigger(); |
|||
resizeIFrame(); |
|||
} else { |
|||
checkDownSizing(); |
|||
} |
|||
} else { |
|||
log('Trigger event cancelled: '+triggerEvent); |
|||
} |
|||
} |
|||
|
|||
function lockTrigger(){ |
|||
if (!triggerLocked){ |
|||
triggerLocked = true; |
|||
log('Trigger event lock on'); |
|||
} |
|||
clearTimeout(triggerLockedTimer); |
|||
triggerLockedTimer = setTimeout(function(){ |
|||
triggerLocked = false; |
|||
log('Trigger event lock off'); |
|||
log('--'); |
|||
},eventCancelTimer); |
|||
} |
|||
|
|||
function triggerReset(triggerEvent){ |
|||
height = getHeight[heightCalcMode](); |
|||
width = getWidth(); |
|||
|
|||
sendMsg(height,width,triggerEvent); |
|||
} |
|||
|
|||
function resetIFrame(triggerEventDesc){ |
|||
var hcm = heightCalcMode; |
|||
heightCalcMode = heightCalcModeDefault; |
|||
|
|||
log('Reset trigger event: ' + triggerEventDesc); |
|||
lockTrigger(); |
|||
triggerReset('reset'); |
|||
|
|||
heightCalcMode = hcm; |
|||
} |
|||
|
|||
function sendMsg(height,width,triggerEvent,msg,targetOrigin){ |
|||
function setTargetOrigin(){ |
|||
if (undefined === targetOrigin){ |
|||
targetOrigin = targetOriginDefault; |
|||
} else { |
|||
log('Message targetOrigin: '+targetOrigin); |
|||
} |
|||
} |
|||
|
|||
function sendToParent(){ |
|||
var |
|||
size = height + ':' + width, |
|||
message = myID + ':' + size + ':' + triggerEvent + (undefined !== msg ? ':' + msg : ''); |
|||
|
|||
log('Sending message to host page (' + message + ')'); |
|||
target.postMessage( msgID + message, targetOrigin); |
|||
} |
|||
|
|||
setTargetOrigin(); |
|||
sendToParent(); |
|||
} |
|||
|
|||
function receiver(event) { |
|||
function isMessageForUs(){ |
|||
return msgID === (''+event.data).substr(0,msgIdLen); //''+ Protects against non-string messages
|
|||
} |
|||
|
|||
function initFromParent(){ |
|||
initMsg = event.data; |
|||
target = event.source; |
|||
|
|||
init(); |
|||
firstRun = false; |
|||
setTimeout(function(){ initLock = false;},eventCancelTimer); |
|||
} |
|||
|
|||
function resetFromParent(){ |
|||
if (!initLock){ |
|||
log('Page size reset by host page'); |
|||
triggerReset('resetPage'); |
|||
} else { |
|||
log('Page reset ignored by init'); |
|||
} |
|||
} |
|||
|
|||
function resizeFromParent(){ |
|||
sendSize('resizeParent','Parent window resized'); |
|||
} |
|||
|
|||
function getMessageType(){ |
|||
return event.data.split(']')[1]; |
|||
} |
|||
|
|||
function isMiddleTier(){ |
|||
return ('iFrameResize' in window); |
|||
} |
|||
|
|||
function isInitMsg(){ |
|||
//test if this message is from a child below us. This is an ugly test, however, updating
|
|||
//the message format would break backwards compatibity.
|
|||
return event.data.split(':')[2] in {'true':1,'false':1}; |
|||
} |
|||
|
|||
if (isMessageForUs()){ |
|||
if (firstRun === false) { |
|||
if ('reset' === getMessageType()){ |
|||
resetFromParent(); |
|||
} else if ('resize' === getMessageType()){ |
|||
resizeFromParent(); |
|||
} else if (event.data !== initMsg && !isMiddleTier()){ |
|||
warn('Unexpected message ('+event.data+')'); |
|||
} |
|||
} else if (isInitMsg()) { |
|||
initFromParent(); |
|||
} else { |
|||
warn('Received message of type ('+getMessageType()+') before initialization.'); |
|||
} |
|||
} |
|||
} |
|||
|
|||
addEventListener(window, 'message', receiver); |
|||
|
|||
})(); |
@ -0,0 +1,642 @@ |
|||
/* |
|||
* File: iframeResizer.js |
|||
* Desc: Force iframes to size to content. |
|||
* Requires: iframeResizer.contentWindow.js to be loaded into the target frame. |
|||
* Author: David J. Bradshaw - dave@bradshaw.net |
|||
* Contributor: Jure Mav - jure.mav@gmail.com |
|||
* Contributor: Reed Dadoune - reed@dadoune.com |
|||
*/ |
|||
;(function() { |
|||
'use strict'; |
|||
|
|||
var |
|||
count = 0, |
|||
firstRun = true, |
|||
logEnabled = 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, |
|||
|
|||
defaults = { |
|||
autoResize : true, |
|||
bodyBackground : null, |
|||
bodyMargin : null, |
|||
bodyMarginV1 : 8, |
|||
bodyPadding : null, |
|||
checkOrigin : true, |
|||
enableInPageLinks : false, |
|||
enablePublicMethods : false, |
|||
heightCalculationMethod : 'offset', |
|||
interval : 32, |
|||
log : false, |
|||
maxHeight : Infinity, |
|||
maxWidth : Infinity, |
|||
minHeight : 0, |
|||
minWidth : 0, |
|||
resizeFrom : 'parent', |
|||
scrolling : false, |
|||
sizeHeight : true, |
|||
sizeWidth : false, |
|||
tolerance : 0, |
|||
closedCallback : function(){}, |
|||
initCallback : function(){}, |
|||
messageCallback : function(){}, |
|||
resizedCallback : function(){}, |
|||
scrollCallback : function(){return true;} |
|||
}; |
|||
|
|||
function addEventListener(obj,evt,func){ |
|||
if ('addEventListener' in window){ |
|||
obj.addEventListener(evt,func, false); |
|||
} else if ('attachEvent' in window){//IE
|
|||
obj.attachEvent('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(' RequestAnimationFrame not supported'); |
|||
} |
|||
} |
|||
|
|||
function getMyID(){ |
|||
var retStr = 'Host page'; |
|||
|
|||
if (window.top!==window.self){ |
|||
if (window.parentIFrame){ |
|||
retStr = window.parentIFrame.getId(); |
|||
} else { |
|||
retStr = 'Nested host page'; |
|||
} |
|||
} |
|||
|
|||
return retStr; |
|||
} |
|||
|
|||
function formatLogMsg(msg){ |
|||
return msgId + '[' + getMyID() + ']' + msg; |
|||
} |
|||
|
|||
function log(msg){ |
|||
if (logEnabled && ('object' === typeof window.console)){ |
|||
console.log(formatLogMsg(msg)); |
|||
} |
|||
} |
|||
|
|||
function warn(msg){ |
|||
if ('object' === typeof window.console){ |
|||
console.warn(formatLogMsg(msg)); |
|||
} |
|||
} |
|||
|
|||
function iFrameListener(event){ |
|||
function resizeIFrame(){ |
|||
function resize(){ |
|||
setSize(messageData); |
|||
setPagePosition(); |
|||
settings[iframeID].resizedCallback(messageData); |
|||
} |
|||
|
|||
ensureInRange('Height'); |
|||
ensureInRange('Width'); |
|||
|
|||
syncResize(resize,messageData,'resetPage'); |
|||
} |
|||
|
|||
function closeIFrame(iframe){ |
|||
var iframeID = iframe.id; |
|||
|
|||
log(' Removing iFrame: '+iframeID); |
|||
iframe.parentNode.removeChild(iframe); |
|||
settings[iframeID].closedCallback(iframeID); |
|||
delete settings[iframeID]; |
|||
log(' --'); |
|||
} |
|||
|
|||
function processMsg(){ |
|||
var data = msg.substr(msgIdLen).split(':'); |
|||
|
|||
return { |
|||
iframe: document.getElementById(data[0]), |
|||
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]); |
|||
|
|||
if (min>max){ |
|||
throw new Error('Value for min'+Dimension+' can not be greater than max'+Dimension); |
|||
} |
|||
|
|||
log(' Checking '+dimension+' is in range '+min+'-'+max); |
|||
|
|||
if (size<min) { |
|||
size=min; |
|||
log(' Set '+dimension+' to min value'); |
|||
} |
|||
|
|||
if (size>max) { |
|||
size=max; |
|||
log(' Set '+dimension+' to max value'); |
|||
} |
|||
|
|||
messageData[dimension]=''+size; |
|||
} |
|||
|
|||
|
|||
function isMessageFromIFrame(){ |
|||
function checkAllowedOrigin(){ |
|||
function checkList(){ |
|||
log(' Checking connection is from allowed list of origins: ' + checkOrigin); |
|||
var i; |
|||
for (i = 0; i < checkOrigin.length; i++) { |
|||
if (checkOrigin[i] === origin) { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
function checkSingle(){ |
|||
log(' Checking connection is from: '+remoteHost); |
|||
return origin == remoteHost; |
|||
} |
|||
|
|||
return checkOrigin.constructor === Array ? checkList() : checkSingle(); |
|||
} |
|||
|
|||
var |
|||
origin = event.origin, |
|||
checkOrigin = settings[iframeID].checkOrigin, |
|||
remoteHost = messageData.iframe.src.split('/').slice(0,3).join('/'); |
|||
|
|||
if (checkOrigin) { |
|||
if ((''+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).substr(0,msgIdLen); //''+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 compatibity.
|
|||
var retCode = messageData.type in {'true':1,'false':1,'undefined':1}; |
|||
|
|||
if (retCode){ |
|||
log(' Ignoring init message from meta parent page'); |
|||
} |
|||
|
|||
return retCode; |
|||
} |
|||
|
|||
function getMsgBody(offset){ |
|||
return msg.substr(msg.indexOf(':')+msgHeaderLen+offset); |
|||
} |
|||
|
|||
function forwardMsgFromIFrame(msgBody){ |
|||
log(' MessageCallback passed: {iframe: '+ messageData.iframe.id + ', message: ' + msgBody + '}'); |
|||
settings[iframeID].messageCallback({ |
|||
iframe: messageData.iframe, |
|||
message: JSON.parse(msgBody) |
|||
}); |
|||
log(' --'); |
|||
} |
|||
|
|||
function checkIFrameExists(){ |
|||
if (null === messageData.iframe) { |
|||
warn(' IFrame ('+messageData.id+') not found'); |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
function getElementPosition(target){ |
|||
var |
|||
iFramePosition = target.getBoundingClientRect(); |
|||
|
|||
getPagePosition(); |
|||
|
|||
return { |
|||
x: parseInt(iFramePosition.left, 10) + parseInt(pagePosition.x, 10), |
|||
y: parseInt(iFramePosition.top, 10) + parseInt(pagePosition.y, 10) |
|||
}; |
|||
} |
|||
|
|||
function scrollRequestFromChild(addOffset){ |
|||
function reposition(){ |
|||
pagePosition = newPosition; |
|||
|
|||
scrollTo(); |
|||
|
|||
log(' --'); |
|||
} |
|||
|
|||
function calcOffset(){ |
|||
return { |
|||
x: Number(messageData.width) + offset.x, |
|||
y: Number(messageData.height) + offset.y |
|||
}; |
|||
} |
|||
|
|||
var |
|||
offset = addOffset ? getElementPosition(messageData.iframe) : {x:0,y:0}, |
|||
newPosition = calcOffset(); |
|||
|
|||
log(' Reposition requested from iFrame (offset x:'+offset.x+' y:'+offset.y+')'); |
|||
|
|||
if(window.top!==window.self){ |
|||
if (window.parentIFrame){ |
|||
if (addOffset){ |
|||
parentIFrame.scrollToOffset(newPosition.x,newPosition.y); |
|||
} else { |
|||
parentIFrame.scrollTo(messageData.width,messageData.height); |
|||
} |
|||
} else { |
|||
warn(' Unable to scroll to requested position, window.parentIFrame not found'); |
|||
} |
|||
} else { |
|||
reposition(); |
|||
} |
|||
|
|||
} |
|||
|
|||
function scrollTo(){ |
|||
if (false !== settings[iframeID].scrollCallback(pagePosition)){ |
|||
setPagePosition(); |
|||
} |
|||
} |
|||
|
|||
function findTarget(location){ |
|||
var hash = location.split("#")[1] || ""; |
|||
var hashData = decodeURIComponent(hash); |
|||
|
|||
function jumpToTarget(target){ |
|||
var jumpPosition = getElementPosition(target); |
|||
|
|||
log(' Moving to in page link (#'+hash+') at x: '+jumpPosition.x+' y: '+jumpPosition.y); |
|||
pagePosition = { |
|||
x: jumpPosition.x, |
|||
y: jumpPosition.y |
|||
}; |
|||
|
|||
scrollTo(); |
|||
log(' --'); |
|||
} |
|||
|
|||
var target = document.getElementById(hashData) || document.getElementsByName(hashData)[0]; |
|||
|
|||
if(window.top!==window.self){ |
|||
if (window.parentIFrame){ |
|||
parentIFrame.moveToAnchor(hash); |
|||
} else { |
|||
log(' In page link #'+hash+' not found and window.parentIFrame not found'); |
|||
} |
|||
} else if (target){ |
|||
jumpToTarget(target); |
|||
} else { |
|||
log(' In page link #'+hash+' not found'); |
|||
} |
|||
} |
|||
|
|||
function actionMsg(){ |
|||
switch(messageData.type){ |
|||
case 'close': |
|||
closeIFrame(messageData.iframe); |
|||
break; |
|||
case 'message': |
|||
forwardMsgFromIFrame(getMsgBody(6)); |
|||
break; |
|||
case 'scrollTo': |
|||
scrollRequestFromChild(false); |
|||
break; |
|||
case 'scrollToOffset': |
|||
scrollRequestFromChild(true); |
|||
break; |
|||
case 'inPageLink': |
|||
findTarget(getMsgBody(9)); |
|||
break; |
|||
case 'reset': |
|||
resetIFrame(messageData); |
|||
break; |
|||
case 'init': |
|||
resizeIFrame(); |
|||
settings[iframeID].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; |
|||
} |
|||
|
|||
var |
|||
msg = event.data, |
|||
messageData = {}, |
|||
iframeID = null; |
|||
|
|||
if (isMessageForUs()){ |
|||
messageData = processMsg(); |
|||
iframeID = messageData.id; |
|||
|
|||
if (!isMessageFromMetaParent() && hasSettings(iframeID)){ |
|||
logEnabled = settings[iframeID].log; |
|||
log(' Received: '+msg); |
|||
|
|||
if ( checkIFrameExists() && isMessageFromIFrame() ){ |
|||
actionMsg(); |
|||
firstRun = false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
function getPagePosition (){ |
|||
if(null === pagePosition){ |
|||
pagePosition = { |
|||
x: (window.pageXOffset !== undefined) ? window.pageXOffset : document.documentElement.scrollLeft, |
|||
y: (window.pageYOffset !== undefined) ? window.pageYOffset : document.documentElement.scrollTop |
|||
}; |
|||
log(' Get page position: '+pagePosition.x+','+pagePosition.y); |
|||
} |
|||
} |
|||
|
|||
function setPagePosition(){ |
|||
if(null !== pagePosition){ |
|||
window.scrollTo(pagePosition.x,pagePosition.y); |
|||
log(' Set page position: '+pagePosition.x+','+pagePosition.y); |
|||
pagePosition = null; |
|||
} |
|||
} |
|||
|
|||
function resetIFrame(messageData){ |
|||
function reset(){ |
|||
setSize(messageData); |
|||
trigger('reset','reset',messageData.iframe,messageData.id); |
|||
} |
|||
|
|||
log(' Size reset requested by '+('init'===messageData.type?'host page':'iFrame')); |
|||
getPagePosition(); |
|||
syncResize(reset,messageData,'init'); |
|||
} |
|||
|
|||
function setSize(messageData){ |
|||
function setDimension(dimension){ |
|||
messageData.iframe.style[dimension] = messageData[dimension] + 'px'; |
|||
log( |
|||
' IFrame (' + iframeID + |
|||
') ' + dimension + |
|||
' set to ' + messageData[dimension] + 'px' |
|||
); |
|||
} |
|||
var iframeID = messageData.iframe.id; |
|||
if( settings[iframeID].sizeHeight) { setDimension('height'); } |
|||
if( settings[iframeID].sizeWidth ) { setDimension('width'); } |
|||
} |
|||
|
|||
function syncResize(func,messageData,doNotSync){ |
|||
if(doNotSync!==messageData.type && requestAnimationFrame){ |
|||
log(' Requesting animation frame'); |
|||
requestAnimationFrame(func); |
|||
} else { |
|||
func(); |
|||
} |
|||
} |
|||
|
|||
function trigger(calleeMsg,msg,iframe,id){ |
|||
if(iframe && iframe.contentWindow){ |
|||
log('[' + calleeMsg + '] Sending msg to iframe ('+msg+')'); |
|||
iframe.contentWindow.postMessage( msgId + msg, '*' ); |
|||
} else { |
|||
warn('[' + calleeMsg + '] IFrame not found'); |
|||
if(settings[id]) delete settings[id]; |
|||
} |
|||
} |
|||
|
|||
|
|||
function setupIFrame(options){ |
|||
function setLimits(){ |
|||
function addStyle(style){ |
|||
if ((Infinity !== settings[iframeID][style]) && (0 !== settings[iframeID][style])){ |
|||
iframe.style[style] = settings[iframeID][style] + 'px'; |
|||
log(' Set '+style+' = '+settings[iframeID][style]+'px'); |
|||
} |
|||
} |
|||
|
|||
addStyle('maxHeight'); |
|||
addStyle('minHeight'); |
|||
addStyle('maxWidth'); |
|||
addStyle('minWidth'); |
|||
} |
|||
|
|||
function ensureHasId(iframeID){ |
|||
if (''===iframeID){ |
|||
iframe.id = iframeID = 'iFrameResizer' + count++; |
|||
logEnabled = (options || {}).log; |
|||
log(' Added missing iframe ID: '+ iframeID +' (' + iframe.src + ')'); |
|||
} |
|||
|
|||
return iframeID; |
|||
} |
|||
|
|||
function setScrolling(){ |
|||
log(' IFrame scrolling ' + (settings[iframeID].scrolling ? 'enabled' : 'disabled') + ' for ' + iframeID); |
|||
iframe.style.overflow = false === settings[iframeID].scrolling ? 'hidden' : 'auto'; |
|||
iframe.scrolling = false === settings[iframeID].scrolling ? 'no' : 'yes'; |
|||
} |
|||
|
|||
//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].bodyMargin)) || ('0'===settings[iframeID].bodyMargin)){ |
|||
settings[iframeID].bodyMarginV1 = settings[iframeID].bodyMargin; |
|||
settings[iframeID].bodyMargin = '' + settings[iframeID].bodyMargin + 'px'; |
|||
} |
|||
} |
|||
|
|||
function createOutgoingMsg(){ |
|||
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].enableInPageLinks + |
|||
':' + settings[iframeID].resizeFrom; |
|||
} |
|||
|
|||
function init(msg){ |
|||
//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.
|
|||
addEventListener(iframe,'load',function(){ |
|||
var fr = firstRun; // Reduce scope of var to function, because IE8's JS execution
|
|||
// context stack is borked and this value gets externally
|
|||
// changed midway through running this function.
|
|||
trigger('iFrame.onload',msg,iframe); |
|||
if (!fr && settings[iframeID].heightCalculationMethod in resetRequiredMethods){ |
|||
resetIFrame({ |
|||
iframe:iframe, |
|||
height:0, |
|||
width:0, |
|||
type:'init' |
|||
}); |
|||
} |
|||
}); |
|||
trigger('init',msg,iframe); |
|||
} |
|||
|
|||
function checkOptions(options){ |
|||
if ('object' !== typeof options){ |
|||
throw new TypeError('Options is not an object.'); |
|||
} |
|||
} |
|||
|
|||
function processOptions(options){ |
|||
options = options || {}; |
|||
settings[iframeID] = {}; |
|||
|
|||
checkOptions(options); |
|||
|
|||
for (var option in defaults) { |
|||
if (defaults.hasOwnProperty(option)){ |
|||
settings[iframeID][option] = options.hasOwnProperty(option) ? options[option] : defaults[option]; |
|||
} |
|||
} |
|||
|
|||
logEnabled = settings[iframeID].log; |
|||
} |
|||
|
|||
var |
|||
/*jshint validthis:true */ |
|||
iframe = this, |
|||
iframeID = ensureHasId(iframe.id); |
|||
|
|||
processOptions(options); |
|||
setScrolling(); |
|||
setLimits(); |
|||
setupBodyMarginValues(); |
|||
init(createOutgoingMsg()); |
|||
} |
|||
|
|||
function throttle(fn,time){ |
|||
if (null === timer){ |
|||
timer = setTimeout(function(){ |
|||
timer = null; |
|||
fn(); |
|||
}, time); |
|||
} |
|||
} |
|||
|
|||
function winResize(){ |
|||
throttle(function(){ |
|||
for (var iframeId in settings){ |
|||
if('parent' === settings[iframeId].resizeFrom){ |
|||
trigger('Window resize','resize',document.getElementById(iframeId),iframeId); |
|||
} |
|||
} |
|||
},66); |
|||
} |
|||
|
|||
function factory(){ |
|||
|
|||
setupRequestAnimationFrame(); |
|||
addEventListener(window,'message',iFrameListener); |
|||
addEventListener(window,'resize', winResize); |
|||
|
|||
function init(element, options){ |
|||
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+'>.'); |
|||
} else { |
|||
setupIFrame.call(element, options); |
|||
} |
|||
} |
|||
|
|||
return function iFrameResizeF(options,target){ |
|||
switch (typeof(target)){ |
|||
case 'undefined': |
|||
case 'string': |
|||
Array.prototype.forEach.call( document.querySelectorAll( target || 'iframe' ), function (element) { |
|||
init(element, options); |
|||
}); |
|||
break; |
|||
case 'object': |
|||
init(target, options); |
|||
break; |
|||
default: |
|||
throw new TypeError('Unexpected data type ('+typeof(target)+').'); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
function createJQueryPublicMethod($){ |
|||
$.fn.iFrameResize = function $iFrameResizeF(options) { |
|||
return this.filter('iframe').each(function (index, element) { |
|||
setupIFrame.call(element, options); |
|||
}).end(); |
|||
}; |
|||
} |
|||
|
|||
if (window.jQuery) { createJQueryPublicMethod(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(); |
|||
} |
|||
|
|||
})(); |
Write
Preview
Loading…
Cancel
Save