Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
110
rated 0 times [  117] [ 7]  / answers: 1 / hits: 27793  / 12 Years ago, tue, june 12, 2012, 12:00:00

I have this code inside a iframe:



window.addEventListener('message', function(e){

if(e.data == 'test')
console.log(e);

}, false);


and this inside the parent document:



$('#the_iframe').get(0).contentWindow.postMessage('test', 'http://localhost/');


So the parent document sends a test message to the iframe and it works.



But how can I define a function in the parent document, and somehow send this function through postMessage to the iframe, which will execute the function locally?



The function does some changes to the document like this:



var func = function(){
$(#some_div).addClass('sss');
}


(#some_div exists in the iframe, not the parent document)


More From » jquery

 Answers
37

There's nothing that would prevent you from passing a stringified function as postmessage event data. Implementation is trivial, for any function declaration like



function doSomething(){
alert(hello world!);
}


You could encodeURI its string interpretation:



console.log(encodeURI(doSomething.toString()));
//function%20doSomething()%20%7B%0A%20%20%20%20alert(%22hello%20world!%22);%0A%7D


It can then be executed as part of a closure - something not overly imaginative like



eval('('+decodeURI(strCallback)+')();');


There's a fiddle'd proof of concept without the cross-frame architecture - I'll see if I can put together a postMessage version, but it would be non-trivial to host w/jsfiddle



Update



As promised, a full mockup that works (links below). With correct event.origin checks this would be sufficiently inpenetrable, but I know for the fact that our security team would never let eval into production like this :)



Given the option I'd suggest the functionality be normalized across the two pages so that only a parametric message would need to be passed (i.e. pass arguments not functions); however there are definitely a few scenarios where this is a preferred approach.



Parent code:



document.domain = fiddle.jshell.net;//sync the domains
window.addEventListener(message, receiveMessage, false);//set up the listener

function receiveMessage(e) {
try {
//attempt to deserialize function and execute as closure
eval('(' + decodeURI(e.data) + ')();');
} catch(e) {}
}


Iframe code:



document.domain = fiddle.jshell.net;//sync the domains
window.addEventListener(message, receiveMessage, false);//set up the listener

function receiveMessage(e) {
//reply with a serialized function
e.source.postMessage(serializeFunction(doSomething), http://fiddle.jshell.net);
}

function serializeFunction(f) {
return encodeURI(f.toString());
}

function doSomething() {
alert(hello world!);
}


Prototype mockup: parent code and iframe code.


[#84955] Monday, June 11, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
mariamiyanab

Total Points: 75
Total Questions: 102
Total Answers: 92

Location: British Indian Ocean Territory
Member since Tue, Feb 22, 2022
2 Years ago
;