Browse Source

Add fix for iframes in chrome

pull/2330/head
jlukic 9 years ago
parent
commit
d5e0225f3f
9 changed files with 1370 additions and 33 deletions
  1. 707
      examples/assets/library/iframe-content.js
  2. 642
      examples/assets/library/iframe.js
  3. 1
      examples/components/button.html
  4. 1
      examples/components/card.html
  5. 1
      examples/components/input.html
  6. 1
      examples/components/menu.html
  7. 2
      examples/components/site.html
  8. 5
      examples/components/table.html
  9. 43
      examples/theming.html

707
examples/assets/library/iframe-content.js

@ -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);
})();

642
examples/assets/library/iframe.js

@ -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();
}
})();

1
examples/components/button.html

@ -23,6 +23,7 @@
<!--- Example Libs -->
<link rel="stylesheet" type="text/css" href="../../dist/components/popup.css">
<script src="../assets/library/jquery.min.js"></script>
<script src="../assets/library/iframe-content.js"></script>
<script src="../assets/show-examples.js"></script>
<script type="text/javascript" src="../../dist/components/popup.js"></script>

1
examples/components/card.html

@ -26,6 +26,7 @@
<!--- Component JS -->
<script src="../assets/library/jquery.min.js"></script>
<script src="../assets/library/iframe-content.js"></script>
<script type="text/javascript" src="../../dist/components/popup.js"></script>
<script type="text/javascript" src="../../dist/components/dimmer.js"></script>
<script type="text/javascript" src="../../dist/components/rating.js"></script>

1
examples/components/input.html

@ -24,6 +24,7 @@
<!--- Component JS -->
<script src="../assets/library/jquery.min.js"></script>
<script src="../assets/library/iframe-content.js"></script>
<script type="text/javascript" src="../../dist/components/popup.js"></script>
<script type="text/javascript" src="../../dist/components/dropdown.js"></script>
<script type="text/javascript" src="../../dist/components/transition.js"></script>

1
examples/components/menu.html

@ -23,6 +23,7 @@
<!--- Example Libs -->
<link rel="stylesheet" type="text/css" href="../../dist/components/popup.css">
<script src="../assets/library/jquery.min.js"></script>
<script src="../assets/library/iframe-content.js"></script>
<script src="../assets/show-examples.js"></script>
<script type="text/javascript" src="../../dist/components/popup.js"></script>

2
examples/components/site.html

@ -12,6 +12,8 @@
<link rel="stylesheet" type="text/css" href="../../dist/components/site.css">
<link rel="stylesheet" type="text/css" href="../../dist/components/grid.css">
<script src="../assets/library/iframe-content.js"></script>
<style>
.color.grid {
margin: -1.5em;

5
examples/components/table.html

@ -21,6 +21,7 @@
<!--- Component JS -->
<script src="../assets/library/jquery.min.js"></script>
<script src="../assets/library/iframe-content.js"></script>
<script type="text/javascript" src="../../dist/components/popup.js"></script>
<script type="text/javascript" src="../../dist/components/transition.js"></script>
@ -36,10 +37,6 @@
<!--- Example Javascript -->
<script>
$(document)
.ready(function() {
})
;
</script>
</head>

43
examples/theming.html

@ -11,6 +11,7 @@
<link rel="stylesheet" type="text/css" href="../dist/semantic.css">
<script src="assets/library/jquery.min.js"></script>
<script src="assets/library/iframe.js"></script>
<style type="text/css">
body > .ui.container {
@ -45,29 +46,6 @@
table-layout: fixed;
}
</style>
<script>
$(document)
.ready(function() {
function fitContent() {
$(this)
.removeAttr('style')
.css('height', $(this).contents().outerHeight() + 20)
;
};
$(window)
.on('resize', function() {
$('iframe').each(fitContent);
})
;
$('iframe')
.on('load', fitContent)
;
})
;
</script>
</head>
<body>
@ -76,28 +54,35 @@
<h1>Theming Examples</h1>
<h2 class="ui dividing header">Site</h2>
<iframe src="components/site.html"></iframe>
<iframe src="components/site.html" width="100%" scrolling="no"></iframe>
<h2 class="ui dividing header">Menu</h2>
<iframe src="components/menu.html"></iframe>
<iframe src="components/menu.html" width="100%" scrolling="no"></iframe>
<h2 class="ui dividing header">Buttons</h2>
<iframe src="components/button.html"></iframe>
<iframe src="components/button.html" width="100%" scrolling="no"></iframe>
<h2 class="ui dividing header">Table</h2>
<iframe src="components/table.html"></iframe>
<iframe src="components/table.html" width="100%" scrolling="no"></iframe>
<h2 class="ui dividing header">Input</h2>
<iframe src="components/input.html"></iframe>
<iframe src="components/input.html" width="100%" scrolling="no"></iframe>
<h2 class="ui dividing header">Card</h2>
<iframe src="components/card.html"></iframe>
<iframe src="components/card.html" width="100%" scrolling="no"></iframe>
</div>
<script>
$('iframe').iFrameResize({
autoResize: true,
heightCalculationMethod: 'bodyScroll'
});
</script>
</body>
</html>
Loading…
Cancel
Save