4

I'm not even sure if this is possible, but is there anyway to set an execution context beyond setting the value for "this"?

The case I am primarily referring to is executing code from one frame in the context of another frame, so that when I access global objects (ex: window, document...) from a function that was defined in frame1, It will be executed in the frame2 environment.

If this is not possible, what are some workarounds? Please don't say "just define the function in the child frame", I'm dealing with a larger application framework, and it would be both pointless and memory inefficient if I had to load up two instances of the entire framework.

EDIT: Here is some code which should demonstrate what I am trying to do. When run, it should show an alert that, if a solution is found, displays "iframe.html" at the end of the location string.

<script>

function run() {
go.call(window.iframe);
}

function go() {
alert(window.location);
}
</script>
<iframe src="iframe.html" name="iframe" onload="run()">

Thanks.

Marshall Brekka
  • 1,156
  • 2
  • 11
  • 15
  • There is always the dreaded *with* statement that can be used to put a different *window* object higher up the scope chain so that global variables will first be searched for on that object and not the local *window* object. – RobG Nov 15 '11 at 02:19

4 Answers4

2

This makes use of the deprecated with statement as well as eval, but it may be the only way to accomplish what you want.

function run() {
    with (window.iframe) {
        eval("(" + go.toString() + ")()");
    }
}

function go() {
    alert(window.location);
}
Eli
  • 431
  • 4
  • 11
1

If you can "frame" your "integration" code in a closure that aliases window to window.iframe, you could achieve what you want:

(function(window) {

  // your integration code...

  // the whole code you want to frame...

  alert(window.location);

})(window.iframe);

But, you have to "frame" all the code you want to interact with.

Also, you can expose "integration" functions for you to call from "outside" by passing other "context" objects in:

var context = {};

(function(window, context) {

  // your integration code...

  context.f = function() { ... };

  // the whole code you want to frame...

  alert(window.location);

})(window.iframe, context);

context.f();
Jordão
  • 55,340
  • 13
  • 112
  • 144
  • 1
    There is no change of "context" here, all that is happening is that functions are called as methods of different objects. The original scope chain is intact. Instead of say *alert* resolving to *window.alert*, it is called instead as *someOObject.alert*, where *someObject* might be a different window object. The context (i.e. the original execution context) is entirely preserved. The only way to change it is to modify the scope chain using *with*. – RobG Nov 15 '11 at 02:23
  • You're right, I'm not changing the _global_ context, I'm just creating a _local_ context that the "framed" code thinks is the _global_ one. You have to pass all references that you want replaced, like `window`, `document` or even `alert`. I just showed `window` though. – Jordão Nov 15 '11 at 02:27
0

Use Function.apply and Function.call.

function foo(x, y, z) {
    console.log(this === someFrame); // true
}

foo.call(someFrame, 1, 2, 3);

EDIT Based on your code sample and comments below, the answer is no. Scripts cannot change the global scope.

lawnsea
  • 6,463
  • 1
  • 24
  • 19
  • As i already said in the question, I need something that affects the broader execution context, not just the values that are accessible with "this". I also updated the question with a small code sample. – Marshall Brekka Nov 15 '11 at 01:42
  • @Iawnsea: I deleted my answer about `with` because it was really not applicable to the question. Thanks for the comments that it's not meant to be used anyway. This is the [link](https://developer.mozilla.org/en/JavaScript/Reference/Statements/with#Description) you posted. Take a look [here](http://stackoverflow.com/questions/61552/are-there-legitimate-uses-for-javascripts-with-statement) for something related. – Jordão Nov 15 '11 at 01:46
  • Why can't you just write `alert(this.window.location);` in go? – lawnsea Nov 15 '11 at 01:48
  • @Jordão: Yeah, I'm aware of that question. IMO, the fact that `with` can be used for a few things doesn't outweigh its downsides. – lawnsea Nov 15 '11 at 01:51
  • I could in this example, but I'm going to be using some external libraries in conjunction with my own framework, so I don't have the option of rewriting lots of code. – Marshall Brekka Nov 15 '11 at 01:51
-1

Include the code in both frames. Then, call the function in the other frame. Let's say there's a top level global function called doWork().

You field a button press in frame2 and you want to execute a function in frame1 (where frame1 is the window object representing frame1). Assuming they are in the same domain and pass the same-origin tests, you can simply reach into frame1 and call doWork() in that frame with:

frame1.doWork();

This works because all top level javascript global variables and functions are properties of the window object for that browser window/frame. Each window/frame has it's own set of top level properties. If you are within the same domain and can get the appropriate window object, you can just call javascript in that window. The javascript must be present in that window. You can't execute javascript from your window in the content of another window, but if you put the code in both windows, you can execute it in either window by starting with the right window object.

How you get the right window object for a particular frame depends upon how your frames are structured.

Again assuming these frames are in the same domain and pass the usual same-origin tests, it would also be possible write a javascript function in frame2 that operates on frame1 contents. For example, you could have this code in frame2:

frame1.document.getElementById("foo").value = "";

So, you couldwrite a function in frame2 that would operate on frame1. You cannot, however, just execute a function from frame2 in the content of frame1 without writing it to know about operating on a different frame.

For example, you could write a function like this that takes the desired window to operate on:

function clearValue(id, win) {
    win.document.getElementById(id).value = "";
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979