Seditio Source
Root |
./othercms/ips_4.3.4/applications/cms/interface/external/external.js
/*
 * IPS external widgets loader
 *
 * https://www.invisioncommunity.com
 */
( function () {
"use strict";

var _baseURL = '';
var _widgets = {};
var _scriptAttributes = {};

/**
* Initialization
*/
var initialize = function () {
// Get our script attributes
var thisScript = getOurScript();
_scriptAttributes = getAttributesFrom( thisScript );

// Set our base URL
_baseURL = _scriptAttributes.src.replace( 'external.js', 'external.php' );

// Main message handler
eventHandler.on( window, 'message', function (e) {
try {
var pmData = JSON.parse( e.data );
} catch (err) {
return;
}

if( typeof pmData.method == 'undefined' || typeof pmData.widgetID == 'undefined' || typeof pmData.blockID == 'undefined' ){
return;
}

// Ensure this is a valid frame
if( typeof _widgets[ pmData.widgetID ] == 'undefined' ){
return;
}

if( pmData.method && typeof messageEvents[ pmData.method ] != 'undefined' ){
messageEvents[ pmData.method ].call( this, pmData );
}
});

// We need to find the IPS widgets on the page
var widgets = document.getElementsByClassName('ipsExternalWidget');

if( !widgets.length ) {
utils.log("No widgets found.");
return;
}

for( var i = 0; i < widgets.length; i++ ){
createWidget( widgets[i] );
};

while( widgets.length ){
widgets[0].parentElement.removeChild( widgets[0] );
}
};

/**
* Handles events from the iframe
*
*/
var messageEvents = {
/**
* iframe tells us we're ready; if we need to send styles, do that now
*
* @param {object} data Data object
* @returns {void}
*/
iframeReady: function (data) {
var thisWidgetInfo = _widgets[ data.widgetID ];

utils.log( thisWidgetInfo );

// Do we need to send probed styles?
if( thisWidgetInfo.useStyles ){
_postMessage( data.widgetID, 'probedStyles', {
text: thisWidgetInfo['text'],
font: thisWidgetInfo['font'],
link: thisWidgetInfo['link']
});
}
},

/**
* iframe has sent a size; resize it to fit
*
* @param {object} data Data object
* @returns {void}
*/
iframeSize: function (data) {
var block = document.getElementById( 'ipsFrame_' + data.widgetID );
block.style.height = parseInt( data.size ) + 'px';
},

/**
* Link clicked inside iframe; open it in parent
*
* @param {object} data Data object
* @returns {void}
*/
goToLink: function (data) {
window.location = data.link;
}
};

/**
* Creates a widget in the page, replacing the element in the param
*
* @param {element} widget
* @returns {void}
*/
var createWidget = function (widget) {
var widgetAttributes = getAttributesFrom( widget );

// Make sure we have a block ID
if( typeof widgetAttributes.id == 'undefined' || typeof widgetAttributes['data-blockid'] == 'undefined' ){
utils.error("Widget class found but no block ID available.");
return;
}

var widgetID = widgetAttributes.id.replace( 'block_', '' );
var blockID = widgetAttributes['data-blockid'];
var blockParams = widgetAttributes['data-blockparams'];

_widgets[ widgetID ] = {
blockID: blockID
};

// Create the iframe to replace this
var iframe;

iframe = document.createElement('iframe');
iframe.src = _baseURL + '?widgetid=' + widgetID + '&blockid=' + blockID + ( blockParams ? '&' + blockParams : '' );
iframe.id = 'ipsFrame_' + widgetID;
iframe.scrolling = 'no';
iframe.style.width = '100%';
iframe.style.border = '0';
iframe.style.opacity = '1';

// Do we need to probe for some styles
if( typeof widgetAttributes['data-inheritstyle'] != 'undefined' ){
var styles = _createStyleProbes( widget );

_widgets[ widgetID ]['useStyles'] = true;
_widgets[ widgetID ]['link'] = styles.link;
_widgets[ widgetID ]['text'] = styles.text;
_widgets[ widgetID ]['font'] = styles.font;
}

// Now insert the iframe
widget.parentElement.insertBefore( iframe, widget );
};

/**
* Create elements and probe for some key styles that we'll share with the iframes
*
* @returns {void}
*/
var _createStyleProbes = function (element) {
var styles = {};

//=====
// First, a simple link
var a = document.createElement('a');
utils.insertBefore( a, element );

styles['link'] = utils.getStyle( a, 'color' );
a.parentNode.removeChild( a );

//=====
// Next create a paragraph
var p = document.createElement('p');
utils.insertBefore( p, element );

styles['font'] = utils.getStyle( p, 'font-family' );
styles['text'] = utils.getStyle( p, 'color' );
p.parentNode.removeChild( p );

return styles;
};

/**
* Returns the attributes on the given element
*
* @param {element} element
* @returns {object} The attributes in key/value pairs
*/
var getAttributesFrom = function (element) {
if( typeof element == 'undefined' ){
return;
}

var attributes = {};

if( element.hasAttributes() ){
var _attr = element.attributes;

for( var i = 0; i < _attr.length; i++ ){
attributes[ _attr[ i ].name.toLowerCase() ] = _attr[ i ].value;
}
}

return attributes;
};

/**
* Finds and returns our script
*
* @param {element} element
* @returns {object} The attributes in key/value pairs
*/
var getOurScript = function () {
return document.getElementById('ipsWidgetLoader');
};

/**
* Posts a message to the iframes
*
* @param {number} [pageNo] Page number to load
* @returns {void}
*/
var _postMessage = function (iframeID, method, data) {
var iframe = document.getElementById( 'ipsFrame_' + iframeID );
iframe.contentWindow.postMessage( JSON.stringify( utils.extendObj( data || {}, {
method: method,
widgetID: iframeID
})), '*' );
};

var utils = {
/*
* Cross-browser 'dom ready' event handler to init the page
*/
/*! contentloaded.min.js - https://github.com/dperini/ContentLoaded - Author: Diego Perini - License: MIT */
contentLoaded: function (b,i) {
var j=false,k=true,a=b.document,l=a.documentElement,f=a.addEventListener,h=f?'addEventListener':'attachEvent',n=f?'removeEventListener':'detachEvent',g=f?'':'on',c=function(d){if(d.type=='readystatechange'&&a.readyState!='complete')return;(d.type=='load'?b:a)[n](g+d.type,c,false);if(!j&&(j=true))i.call(b,d.type||d)},m=function(){try{l.doScroll('left')}catch(e){setTimeout(m,50);return}c('poll')};if(a.readyState=='complete')i.call(b,'lazy');else{if(!f&&l.doScroll){try{k=!b.frameElement}catch(e){}if(k)m()}a[h](g+'DOMContentLoaded',c,false);a[h](g+'readystatechange',c,false);b[h](g+'load',c,false)}
},

/**
* Extend an object with another object
*
* @param {object} originalObj Original object
* @param {object} newObj New object
* @returns {void}
*/
extendObj: function (originalObj, newObj) {
for( var i in newObj ){
if( newObj.hasOwnProperty(i) ){
originalObj[i] = newObj[i];
}
}

return originalObj;
},

/**
* Log to console if supported
*
* @param {string} message Message to log
* @returns {void}
*/
log: function (message) {
if( window.console ){
console.log( message );
}
},

/**
* Error to console if supported
*
* @param {string} message Message to log
* @returns {void}
*/
error: function (message) {
if( window.console ){
console.error( message );
}
},

/**
* A simple method to insert an element before another element
*
* @param {element} elem The new element
* @param {element} existing The existing element, before which the new will be inserted
* @returns {void}
*/
insertBefore: function (elem, existing) {
existing.parentNode.insertBefore( elem, existing );
},

/**
* Returns a style property value for the given element and style
*
* @param {element} elem Element whose style is to be fetched
* @param {string} style Property to fetch
* @returns {mixed}
*/
getStyle: function (elem, style) {
return window.getComputedStyle( elem, null ).getPropertyValue( style );
}
};

/**
* Event handling
*
*/
// http://www.anujgakhar.com/2013/05/22/cross-browser-event-handling-in-javascript/
var eventHandler = {
on: function (el, ev, fn) {
if( window.addEventListener ){
el.addEventListener( ev, fn, false );
} else if( window.attachEvent ){
el.attachEvent( 'on' + ev, fn );
} else {
el[ 'on' + ev ] = fn;
}
},

off: function (el, ev, fn) {
if( window.removeEventListener ){
el.removeEventListener( ev, fn, false );
} else if( window.detachEvent ) {
el.detachEvent( 'on' + ev, fn );
} else {
elem[ 'on' + ev ] = null;
}
},

stop: function (ev) {
var e = ev || window.event;
e.cancelBubble = true;
if( e.stopPropagation ){
e.stopPropagation();
}
}
};

// Once the DOM is ready we'll initialize our widgets
utils.contentLoaded( window, function () {
initialize();
});
}() );