forked from inedu/frameTalk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathframeTalk.min.js
38 lines (38 loc) · 9.5 KB
/
frameTalk.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
(function(window){"use strict";var frameTalk,hasBeenInit=!1,windowFromId,uniqueId=getRandomInt(1000,9999),useOfPromises=!0,promisesTable=[0],repeatersTable=[0],checkTimer=500;function getRandomInt(min,max){return Math.floor(Math.random()*(max-min+1))+min}
function say(what){console.log(what)}
function debugSay(what){if(frameTalk.debugging){console.log("frameTalk debug ["+windowFromId+"("+uniqueId+")] says: ");console.log(what)}}
function findPostMsgFn(where){if(where.postMessage)
return where;if(where.contentWindow&&where.contentWindow.postMessage)
return where.contentWindow;if(document.getElementById(where)!=null){return document.getElementById(where).contentWindow}
return null}
function newPromiseInd(){var l=promisesTable.length,r=new $.Deferred();promisesTable[l]=r;return l}
function findPostTarget(frameId){var wObj=window.document.getElementById(frameId);if(wObj&&wObj.contentWindow){return wObj}else{wObj=window.parent.document.getElementById(frameId);if(wObj&&wObj.contentWindow){return wObj}else{wObj=window.document.getElementsByName(frameId)[0];if(wObj&&wObj.contentWindow){return wObj}else{wObj=window.parent.document.getElementsByName(frameId)[0];if(wObj&&wObj.contentWindow){return wObj}else{return null}}}}}
function handshakeFallback(toWindow,fromId){toWindow=findPostMsgFn(toWindow);if(!toWindow){debugSay('handshakeFallback needs a window object with postMessage defined');return}
if(window.top===window){debugSay("starting handshakeFallback from top window");windowFromId="@@top@@"}else{debugSay("starting handshakeFallback from iframe: "+fromId);windowFromId=fromId}
frameTalk.sendMessage(toWindow,"handshake",[windowFromId])}
function sendOutHandShake(toWindow,windowFromId,hsPromiseInd){debugSay("sending handshake, promise index: "+hsPromiseInd);frameTalk.sendMessage(toWindow,"handshake",[windowFromId],hsPromiseInd)}
function rejectPromise(promiseInd,failMsg){if(typeof promisesTable[promiseInd]=='object'){clearInterval(repeatersTable[promiseInd]);promisesTable[promiseInd].reject(failMsg);promisesTable[promiseInd]="rejected";repeatersTable[promiseInd]="cleared"}}
function safeParseJson(jsonString){try{return window.JSON.retrocycle(JSON.parse(jsonString))}catch(error){return null}}
function receiveMessage(event){var eventObjData=safeParseJson(event?.data)
if(eventObjData==null)return;var theFunction=eventObjData.theFunction,theParams=eventObjData.theParams,windowId=eventObjData.windowId,promiseInd=eventObjData.promiseInd,frameIdToReply=eventObjData.fromId,theObject=eventObjData.theObject,wObj,theBindingObject,fn;debugSay(event);debugSay('msg received, parsed:');debugSay(eventObjData);if(!theFunction){debugSay("parameter 'theFunction' not found in postMessage. May not came via frameTalk. Aborted")
return}
if(windowId==uniqueId){debugSay('msg rejected as echo');return}
if(theFunction=="handshake"){var frameIdToReply=theParams[0];if(!frameIdToReply){debugSay("handshake needs iFrame id as second parameter in order to complete reply")}
if(frameIdToReply==="@@top@@"){wObj=window.top;frameTalk.sendMessage(wObj,"replyHandshake",[0],promiseInd)}else{wObj=findPostTarget(frameIdToReply);if(wObj){frameTalk.sendMessage(wObj.contentWindow,"replyHandshake",[1],promiseInd)}else{debugSay("could not find handshake receiver")}}}else if(theFunction=="replyHandshake"){if(!promiseInd){debugSay("got handshake reply with no promise index");if(theParams[0]===0){debugSay("HandShake with top window completed.")}else{debugSay("HandShake completed.")}}else{debugSay("got handshake reply, promise index: "+promiseInd);promisesTable[promiseInd].resolve(!0);promisesTable[promiseInd]="success";clearInterval(repeatersTable[promiseInd]);repeatersTable[promiseInd]="cleared"}}else if(theFunction=="replyPromiseOk"){debugSay("promise resolved, index: "+promiseInd);promisesTable[promiseInd].resolve(theParams);promisesTable[promiseInd]="success"}else if(theFunction=="replyPromiseFail"){debugSay("promise rejected, index: "+promiseInd);promisesTable[promiseInd].reject(theParams);promisesTable[promiseInd]="fail"}else if(promiseInd){debugSay("promise request received, index: "+promiseInd);fn=eval("window."+theFunction);if(typeof fn==="function"){fn.apply(this,theParams).then(function(data){returnPromise("replyPromiseOk",frameIdToReply,data)},function(err){returnPromise("replyPromiseFail",frameIdToReply,err)})}else{debugSay("receiveMessage: function not found")}}else{fn=eval("window."+theFunction);theBindingObject=(theObject?eval("window."+theObject):this);if(typeof fn==="function"){debugSay("receiveMessage: bindingObjectToThis === window? "+theBindingObject===window);fn.apply(theBindingObject,theParams)}else{debugSay("receiveMessage: function not found")}}
function returnPromise(theFunction,where,data){if(where==="@@top@@"){wObj=window.top;frameTalk.sendMessage(wObj,theFunction,[data],promiseInd)}else{wObj=findPostTarget(where);if(wObj){frameTalk.sendMessage(wObj.contentWindow,theFunction,[data],promiseInd)}else{debugSay("could not find reply receiver")}}}}
if(typeof JSON.decycle!=='function'){JSON.decycle=function decycle(object){'use strict';var objects=[],paths=[];return(function derez(value,path){var i,name,nu;if(typeof value==='object'&&value!==null&&!(value instanceof Boolean)&&!(value instanceof Date)&&!(value instanceof Number)&&!(value instanceof RegExp)&&!(value instanceof String)){for(i=0;i<objects.length;i+=1){if(objects[i]===value){return{$ref:paths[i]}}}
objects.push(value);paths.push(path);if(Object.prototype.toString.apply(value)==='[object Array]'){nu=[];for(i=0;i<value.length;i+=1){nu[i]=derez(value[i],path+'['+i+']')}}else{nu={};for(name in value){if(Object.prototype.hasOwnProperty.call(value,name)){nu[name]=derez(value[name],path+'['+JSON.stringify(name)+']')}}}
return nu}
return value}(object,'$'))}};if(typeof JSON.retrocycle!=='function'){JSON.retrocycle=function retrocycle($){'use strict';var px=/^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;(function rez(value){var i,item,name,path;if(value&&typeof value==='object'){if(Object.prototype.toString.apply(value)==='[object Array]'){for(i=0;i<value.length;i+=1){item=value[i];if(item&&typeof item==='object'){path=item.$ref;if(typeof path==='string'&&px.test(path)){value[i]=eval(path)}else{rez(item)}}}}else{for(name in value){if(typeof value[name]==='object'){item=value[name];if(item){path=item.$ref;if(typeof path==='string'&&px.test(path)){value[name]=eval(path)}else{rez(item)}}}}}}}($));return $}}
frameTalk={getId:function(){return uniqueId},debugging:!0,failTimeLimit:5000,init:function(){if(!(window.JSON&&window.JSON.parse&&window.JSON.stringify)){debugSay("No init, JSON missing, please load JSON2");return!1}
if(!hasBeenInit){if(window.addEventListener){window.addEventListener("message",receiveMessage,!1);hasBeenInit=!0;window.frameTalkReady=!0}else if(window.attachEvent){window.attachEvent("onmessage",receiveMessage);hasBeenInit=!0;window.frameTalkReady=!0}else{debugSay("could not attach event listener")}}else{debugSay("already init")}
debugSay("init ready, window unique Id: "+uniqueId);return!0},sendMessage:function(where,theFunction,theParams,promiseInd,theObjectToBindToThis){try{if(typeof theFunction!="string"){debugSay("sendMessage second param must be a function's name (string)");return}
if(typeof theParams!="object"){theParams=[theParams]}
where=findPostMsgFn(where);if(!where){debugSay("sendMessage first param must be a window object with postMessage defined.");return}
var myMsgObj={"theFunction":theFunction,"theParams":theParams,"windowId":uniqueId,"promiseInd":promiseInd,"theObject":theObjectToBindToThis};var myMsg=window.JSON.stringify(JSON.decycle(myMsgObj));where.postMessage(myMsg,'*')}catch(err){debugSay("sendMessage error: "+err.message)}},sendPromise:function(where,fromId,theFunction,theParams){var thisSendPromiseInd=newPromiseInd(fromId),failMsg;if(typeof theFunction!="string"){failMsg="sendPromise third param must be a function's name (string)";debugSay(failMsg);setTimeout(function(){rejectPromise(thisSendPromiseInd,failMsg)},500);return promisesTable[thisSendPromiseInd].promise()}
if(typeof theParams!="object"){theParams=[theParams]}
where=findPostMsgFn(where);if(!where){failMsg="sendPromise first param must be a window object with postMessage defined.";debugSay(failMsg);setTimeout(function(){rejectPromise(thisSendPromiseInd,failMsg)},500);return promisesTable[thisSendPromiseInd].promise()}
var myMsgObj={"theFunction":theFunction,"theParams":theParams,"windowId":uniqueId,"promiseInd":thisSendPromiseInd,"fromId":fromId};var myMsg=window.JSON.stringify(myMsgObj);where.postMessage(myMsg,'*');return promisesTable[thisSendPromiseInd].promise()},handshake:function(toWindow,fromId){var hsPromiseInd=newPromiseInd(),failMsg;toWindow=findPostMsgFn(toWindow);if(!toWindow){failMsg='handshake needs a window object with postMessage defined';setTimeout(function(){rejectPromise(hsPromiseInd,failMsg)},500);return promisesTable[hsPromiseInd].promise()}
if(window.top===window){debugSay("starting handshake from top window");windowFromId="@@top@@"}else{debugSay("starting handshake from iframe: "+fromId);windowFromId=fromId}
repeatersTable[hsPromiseInd]=setInterval(function(){sendOutHandShake(toWindow,windowFromId,hsPromiseInd)},checkTimer);failMsg="handshake timeout. You can change timeout on frameTalk.failTimeLimit";setTimeout(function(){rejectPromise(hsPromiseInd,failMsg)},frameTalk.failTimeLimit);return promisesTable[hsPromiseInd].promise()}};if(typeof window.jQuery!=="function"){useOfPromises=!1;frameTalk.handshake=handshakeFallback;debugSay("caution, since no jQuery found, handshake functionality will not include promises")}
frameTalk.init();window.frameTalk=frameTalk}(window))