mirror of
				https://github.com/Telecominfraproject/wlan-cloud-lib-poco.git
				synced 2025-11-04 04:28:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			443 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			443 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
 * File: iframeReizer.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
 | 
						|
 */
 | 
						|
;(function() {
 | 
						|
    'use strict';
 | 
						|
 | 
						|
	var
 | 
						|
		count                 = 0,
 | 
						|
		firstRun              = true,
 | 
						|
		msgHeader             = 'message',
 | 
						|
		msgHeaderLen          = msgHeader.length,
 | 
						|
		msgId                 = '[iFrameSizer]', //Must match iframe msg ID
 | 
						|
		msgIdLen              = msgId.length,
 | 
						|
		page                  =  '', //:'+location.href, //Uncoment to debug nested iFrames
 | 
						|
		pagePosition          = null,
 | 
						|
		requestAnimationFrame = window.requestAnimationFrame,
 | 
						|
		resetRequiredMethods  = {max:1,scroll:1,bodyScroll:1,documentElementScroll:1},
 | 
						|
		settings              = {},
 | 
						|
 | 
						|
		defaults              = {
 | 
						|
			autoResize                : true,
 | 
						|
			bodyBackground            : null,
 | 
						|
			bodyMargin                : null,
 | 
						|
			bodyMarginV1              : 8,
 | 
						|
			bodyPadding               : null,
 | 
						|
			checkOrigin               : true,
 | 
						|
			enablePublicMethods       : false,
 | 
						|
			heightCalculationMethod   : 'offset',
 | 
						|
			interval                  : 32,
 | 
						|
			log                       : false,
 | 
						|
			maxHeight                 : Infinity,
 | 
						|
			maxWidth                  : Infinity,
 | 
						|
			minHeight                 : 0,
 | 
						|
			minWidth                  : 0,
 | 
						|
			scrolling                 : false,
 | 
						|
			sizeHeight                : true,
 | 
						|
			sizeWidth                 : false,
 | 
						|
			tolerance                 : 0,
 | 
						|
			closedCallback            : function(){},
 | 
						|
			initCallback              : function(){},
 | 
						|
			messageCallback           : function(){},
 | 
						|
			resizedCallback           : function(){}
 | 
						|
		};
 | 
						|
 | 
						|
	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 log(msg){
 | 
						|
		if (settings.log && (typeof console === 'object')){
 | 
						|
			console.log(msgId + '[Host page'+page+']' + msg);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	function iFrameListener(event){
 | 
						|
		function resizeIFrame(){
 | 
						|
			function resize(){
 | 
						|
				setSize(messageData);
 | 
						|
				setPagePosition();
 | 
						|
				settings.resizedCallback(messageData);
 | 
						|
			}
 | 
						|
 | 
						|
			syncResize(resize,messageData,'resetPage');
 | 
						|
		}
 | 
						|
 | 
						|
		function closeIFrame(iframe){
 | 
						|
			var iframeID = iframe.id;
 | 
						|
 | 
						|
			log(' Removing iFrame: '+iframeID);
 | 
						|
			iframe.parentNode.removeChild(iframe);
 | 
						|
			settings.closedCallback(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['max'+Dimension]),
 | 
						|
				min  = Number(settings['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(){
 | 
						|
 | 
						|
			var
 | 
						|
				origin     = event.origin,
 | 
						|
				remoteHost = messageData.iframe.src.split('/').slice(0,3).join('/');
 | 
						|
 | 
						|
			if (settings.checkOrigin) {
 | 
						|
				log(' Checking connection is from: '+remoteHost);
 | 
						|
 | 
						|
				if ((''+origin !== 'null') && (origin !== remoteHost)) {
 | 
						|
					throw new Error(
 | 
						|
						'Unexpected message received from: ' + origin +
 | 
						|
						' for ' + messageData.iframe.id +
 | 
						|
						'. Message was: ' + event.data +
 | 
						|
						'. This error can be disabled by adding the checkOrigin: false option.'
 | 
						|
					);
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			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};
 | 
						|
 | 
						|
			if (retCode){
 | 
						|
				log(' Ignoring init message from meta parent page');
 | 
						|
			}
 | 
						|
 | 
						|
			return retCode;
 | 
						|
		}
 | 
						|
 | 
						|
		function forwardMsgFromIFrame(){
 | 
						|
			var msgBody = msg.substr(msg.indexOf(':')+msgHeaderLen+6); //6 === ':0:0:' + ':' (Ideas to name this magic number most welcome)
 | 
						|
 | 
						|
			log(' MessageCallback passed: {iframe: '+ messageData.iframe.id + ', message: ' + msgBody + '}');
 | 
						|
			settings.messageCallback({
 | 
						|
				iframe: messageData.iframe,
 | 
						|
				message: msgBody
 | 
						|
			});
 | 
						|
			log(' --');
 | 
						|
		}
 | 
						|
 | 
						|
		function checkIFrameExists(){
 | 
						|
			if (null === messageData.iframe) {
 | 
						|
				throw new Error('iFrame ('+messageData.id+') does not exist on ' + page);
 | 
						|
			}
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		function scrollRequestFromChild(){
 | 
						|
			log(' Reposition requested from iFrame');
 | 
						|
			pagePosition = {
 | 
						|
				x: messageData.width,
 | 
						|
				y: messageData.height
 | 
						|
			};
 | 
						|
			setPagePosition();
 | 
						|
		}
 | 
						|
 | 
						|
		function actionMsg(){
 | 
						|
			switch(messageData.type){
 | 
						|
				case 'close':
 | 
						|
					closeIFrame(messageData.iframe);
 | 
						|
					settings.resizedCallback(messageData); //To be removed.
 | 
						|
					break;
 | 
						|
				case 'message':
 | 
						|
					forwardMsgFromIFrame();
 | 
						|
					break;
 | 
						|
				case 'scrollTo':
 | 
						|
					scrollRequestFromChild();
 | 
						|
					break;
 | 
						|
				case 'reset':
 | 
						|
					resetIFrame(messageData);
 | 
						|
					break;
 | 
						|
				case 'init':
 | 
						|
					resizeIFrame();
 | 
						|
					settings.initCallback(messageData.iframe);
 | 
						|
					break;
 | 
						|
				default:
 | 
						|
					resizeIFrame();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		var
 | 
						|
			msg = event.data,
 | 
						|
			messageData = {};
 | 
						|
 | 
						|
		if (isMessageForUs()){
 | 
						|
			log(' Received: '+msg);
 | 
						|
			messageData = processMsg();
 | 
						|
			ensureInRange('Height');
 | 
						|
			ensureInRange('Width');
 | 
						|
 | 
						|
			if ( !isMessageFromMetaParent() && 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 position: '+pagePosition.x+','+pagePosition.y);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	function setPagePosition(){
 | 
						|
		if(null !== pagePosition){
 | 
						|
			window.scrollTo(pagePosition.x,pagePosition.y);
 | 
						|
			log(' Set position: '+pagePosition.x+','+pagePosition.y);
 | 
						|
			pagePosition = null;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	function resetIFrame(messageData){
 | 
						|
		function reset(){
 | 
						|
			setSize(messageData);
 | 
						|
			trigger('reset','reset',messageData.iframe);
 | 
						|
		}
 | 
						|
 | 
						|
		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 (' + messageData.iframe.id +
 | 
						|
				') ' + dimension +
 | 
						|
				' set to ' + messageData[dimension] + 'px'
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
		if( settings.sizeHeight) { setDimension('height'); }
 | 
						|
		if( settings.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){
 | 
						|
		log('[' + calleeMsg + '] Sending msg to iframe ('+msg+')');
 | 
						|
		iframe.contentWindow.postMessage( msgId + msg, '*' );
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	function setupIFrame(){
 | 
						|
		function setLimits(){
 | 
						|
			function addStyle(style){
 | 
						|
				if ((Infinity !== settings[style]) && (0 !== settings[style])){
 | 
						|
					iframe.style[style] = settings[style] + 'px';
 | 
						|
					log(' Set '+style+' = '+settings[style]+'px');
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			addStyle('maxHeight');
 | 
						|
			addStyle('minHeight');
 | 
						|
			addStyle('maxWidth');
 | 
						|
			addStyle('minWidth');
 | 
						|
		}
 | 
						|
 | 
						|
		function ensureHasId(iframeID){
 | 
						|
			if (''===iframeID){
 | 
						|
				iframe.id = iframeID = 'iFrameResizer' + count++;
 | 
						|
				log(' Added missing iframe ID: '+ iframeID +' (' + iframe.src + ')');
 | 
						|
			}
 | 
						|
 | 
						|
			return iframeID;
 | 
						|
		}
 | 
						|
 | 
						|
		function setScrolling(){
 | 
						|
			log(' IFrame scrolling ' + (settings.scrolling ? 'enabled' : 'disabled') + ' for ' + iframeID);
 | 
						|
			iframe.style.overflow = false === settings.scrolling ? 'hidden' : 'auto';
 | 
						|
			iframe.scrolling      = false === settings.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.bodyMargin)) || ('0'===settings.bodyMargin)){
 | 
						|
				settings.bodyMarginV1 = settings.bodyMargin;
 | 
						|
				settings.bodyMargin   = '' + settings.bodyMargin + 'px';
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		function createOutgoingMsg(){
 | 
						|
			return iframeID +
 | 
						|
				':' + settings.bodyMarginV1 +
 | 
						|
				':' + settings.sizeWidth +
 | 
						|
				':' + settings.log +
 | 
						|
				':' + settings.interval +
 | 
						|
				':' + settings.enablePublicMethods +
 | 
						|
				':' + settings.autoResize +
 | 
						|
				':' + settings.bodyMargin +
 | 
						|
				':' + settings.heightCalculationMethod +
 | 
						|
				':' + settings.bodyBackground +
 | 
						|
				':' + settings.bodyPadding +
 | 
						|
				':' + settings.tolerance;
 | 
						|
		}
 | 
						|
 | 
						|
		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.heightCalculationMethod in resetRequiredMethods){
 | 
						|
					resetIFrame({
 | 
						|
						iframe:iframe,
 | 
						|
						height:0,
 | 
						|
						width:0,
 | 
						|
						type:'init'
 | 
						|
					});
 | 
						|
				}
 | 
						|
			});
 | 
						|
			trigger('init',msg,iframe);
 | 
						|
		}
 | 
						|
 | 
						|
		var
 | 
						|
            /*jshint validthis:true */
 | 
						|
			iframe   = this,
 | 
						|
			iframeID = ensureHasId(iframe.id);
 | 
						|
 | 
						|
		setScrolling();
 | 
						|
		setLimits();
 | 
						|
		setupBodyMarginValues();
 | 
						|
		init(createOutgoingMsg());
 | 
						|
	}
 | 
						|
 | 
						|
	function checkOptions(options){
 | 
						|
		if ('object' !== typeof options){
 | 
						|
			throw new TypeError('Options is not an object.');
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	function createNativePublicFunction(){
 | 
						|
		function init(element){
 | 
						|
			if('IFRAME' !== element.tagName.toUpperCase()) {
 | 
						|
				throw new TypeError('Expected <IFRAME> tag, found <'+element.tagName+'>.');
 | 
						|
			} else {
 | 
						|
				setupIFrame.call(element);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		function processOptions(options){
 | 
						|
			options = options || {};
 | 
						|
 | 
						|
			checkOptions(options);
 | 
						|
 | 
						|
			for (var option in defaults) {
 | 
						|
				if (defaults.hasOwnProperty(option)){
 | 
						|
					settings[option] = options.hasOwnProperty(option) ? options[option] : defaults[option];
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return function iFrameResizeF(options,selecter){
 | 
						|
			processOptions(options);
 | 
						|
			Array.prototype.forEach.call( document.querySelectorAll( selecter || 'iframe' ), init );
 | 
						|
		};
 | 
						|
	}
 | 
						|
 | 
						|
	function createJQueryPublicMethod($){
 | 
						|
		$.fn.iFrameResize = function $iFrameResizeF(options) {
 | 
						|
			options = options || {};
 | 
						|
			checkOptions(options);
 | 
						|
			settings = $.extend( {}, defaults, options );
 | 
						|
			return this.filter('iframe').each( setupIFrame ).end();
 | 
						|
		};
 | 
						|
	}
 | 
						|
 | 
						|
	setupRequestAnimationFrame();
 | 
						|
	addEventListener(window,'message',iFrameListener);
 | 
						|
 | 
						|
	if (window.jQuery) { createJQueryPublicMethod(jQuery); }
 | 
						|
 | 
						|
	if (typeof define === 'function' && define.amd) {
 | 
						|
		define(function (){ return createNativePublicFunction(); });
 | 
						|
	} else {
 | 
						|
		window.iFrameResize = createNativePublicFunction();
 | 
						|
	}
 | 
						|
 | 
						|
})();
 |