1

UPDATE: The back-end service was powered by an ASP.Net AJAX Web Service proxy.

1) The main page has two global objects, one for the back end connections (Svc) and another for handling the DOM (Main). It also dynamically loads documents into an iframe.

2) These iframes need to access services provided by Svc, and also supply a callback function.

3) The problem - passing a function created in the iframe to the parent frame, it's treated as an object not a function and cannot be invoked.

Can anyone provide a better solution than what I've got currently in the iframe:

var Main = parent.Main,
    Svc = parent.Svc;

Svc.method(data, Main.createCallback(
    function(response) {}
));

and in the parent frame:

Main.createCallback = function(func) {
    return function() {
        func.apply(func, arguments);
    }
}
Matty F
  • 3,763
  • 4
  • 30
  • 48
  • I'm fairly sure that functions are objects... I've not had any problems before using `parent` from the iframe. – Niet the Dark Absol Nov 15 '10 at 04:37
  • Yeah using parent is fine, it's just trying to pass a function as a callback to the parent frame isn't working. – Matty F Nov 15 '10 at 04:39
  • I'm not entirely sure what the code is supposed to be doing. I also think that the code in the parent frame doesn't work because func is not in the scope of the returned function (in fact this could be the cause of the problem). – Niet the Dark Absol Nov 15 '10 at 04:42
  • The code I've pasted currently works fine, I'm just sure there's a better less complicated way of doing it. The code in the parent frame works because func was defined as a parameter of createCallback, and the returned function has access to the context it was created in. This context includes the function passted to createCallback and stored in func – Matty F Nov 15 '10 at 04:43
  • 1
    Huh... which I'd known that functions have access to the context they were created in... -goes back to get rid of all the eval's he had used before- – Niet the Dark Absol Nov 15 '10 at 04:53
  • eval is evil ;) read the Douglas Crockford book JavaScript the Good Parts. Best tech book I've ever read – Matty F Nov 15 '10 at 04:55

5 Answers5

1

if you override the iFrame's function from the main, the main scope will then be used. The inverse problem can be seen here, in your case, you just override the frame's function itself i.e:

document.getElementById('yourFrameID').contentWindow.targetFunctionInFrame = targetFunctionInMain;

Bonus: if you can modify the iFrame's code, I would suggest to:

In the frame:

  • make a placeholder function callbackParent() {}
  • add a call to this function into your iframe code, so that you just have to override the callbackParent from your main.

In the main:

  • make the function which should be invoked function doStuff() {}
  • override the function as described above document.getElementById('yourFrameID').contentWindow.callBackParent = doStuff;
Sellorio
  • 1,806
  • 1
  • 16
  • 32
Flavien Volken
  • 19,196
  • 12
  • 100
  • 133
0

My guest is that Svc.method is making some checks to see if the callback has some criteria before calling it. This criteria might be that the callback function must created by the same framework (here it's ASP.Net). You have to find what that criteria is. if "Main.createCallback" works, it's because it's meeting that criteria.

Dominique Fortin
  • 2,212
  • 15
  • 20
0

I use iframes to modularize my app too.
They are a kind of includes embedding all CSS, HTML and JS for a module.

My first attempts were by returning a function too, but then I found it quite hard for sharing scopes. Now I make directly a reference to the main parent object in the iframe.

eg:

var Svc = parent.Svc, JSON = parent.JSON, $ = parent.$;
Svc.module1 = {
  method1:function(arg){
    ...
  },
  ...
}

The global var JSON and jQuery references are here to have them available inside the methods.

Mic
  • 24,812
  • 9
  • 57
  • 70
-1

Sorry but your all wrong... add this....

const event = new CustomEvent('MSGSent', { detail: "fff variable" });

Call it like this....use a global variable for detail... like an array []

window.dispatchEvent(event);

Now after the iframe loads add this code and you get an Object back in the main page....

iframe.onload = function() {
        try {
            iframe.contentWindow.addEventListener('MSGSent',function(e){
                alert(e.detail);
                
               });   
        } catch (error) { 
        }   
    };
-2

The problem is ASP.Net AJAX Web Service proxies, which don't appear to support calling the web service from an iframe with an inline callback function.

Matty F
  • 3,763
  • 4
  • 30
  • 48