2

According to this page I should be able to call parameters and functions of child windows, but it is not working for me.

var w = window.open("index.html");
console.log(w);
console.log(w.foo);

console.log(w) shows that there is a function named foo but console.log(w.foo) outputs undefined. Is this a security issue?


EDIT Here is some more functionality:

child.html (omitting the body):

<head>
 <script type="text/javascript"> 
  test = 123 ;
  function foo(arg){
   //do something
  }
 </script>
</head>

parent.html:

var w = window.open("child.html");
console.log(w);
//outputs all the methods and parameters
console.log(w.foo);
//outputs 'undefined'
console.log(w.test);
//outputs 'undefined'

EDIT 2 Also I should explain why I need to pass arguments as someone will inevitably ask me why I can't 'just hard code it'. I have an HTML canvas element, and every time the user right clicks, there is a right click menu with the option 'list shapes underneath'.

When the user clicks this menu item, I want to pass a list of all the shapes underneath that click and to display it in a new window. Here are the problems I am facing:

  1. I can't pass it as an argument b/c I don't know whether the window has been loaded (I can't seem to change the onload function either)

  2. I can't have the child window query the parent window b/c the right click menu disappears after clicking it.

Community
  • 1
  • 1
puk
  • 16,318
  • 29
  • 119
  • 199
  • Do you mean a jsfiddle example or just a self contained script? – puk Jul 24 '11 at 23:47
  • I have no idea how I would implement an example on jsfiddle – puk Jul 24 '11 at 23:48
  • I believe they have a usage FAQ. Either way, we can't help without knowing what your code looks like. – Lightness Races in Orbit Jul 24 '11 at 23:49
  • I updated it with some more information – puk Jul 24 '11 at 23:53
  • 1
    There shouldn't be a security issue if the parent and child window both contain pages from the same domain. Has the child page (index.html) finished loading at the point that you try to access its function(s)? I generally find it easiest to either have the child page request values it needs from the parent, like `x = window.opener.parentFunction();`, or tell the parent that it is ready (at the end of child's onload:) `window.opener.childLoaded();` and have the parent wait for that function call before it tries to manipulate the child. – nnnnnn Jul 24 '11 at 23:54
  • Just saw your update. What happens if you actually call `w.foo()` rather than logging the function itself as `w.foo`? – nnnnnn Jul 24 '11 at 23:56
  • nnnn, if I call w.foo() I get `Uncaught TypeError: Object [object DOMWindow] has no method 'foo'` – puk Jul 24 '11 at 23:59
  • wrt to the child page not having finished loading, I tried a 10 second delay before the console.log statement but the problem persisted, I'll try the child request method as well – puk Jul 25 '11 at 00:00
  • does the child window have the same domain name? – Ibu Jul 25 '11 at 00:21
  • I'm testing this on my home system. I am logging in via my local ip address, and both files are in the same folder, if that helps. – puk Jul 25 '11 at 00:25
  • Your approach to use a delay is good and should work(it takes some time to load a window). Please provide more information about how/where you call `window.open()` and `setTimeout()` , it may be a scope-issue in `setTimeout()` – Dr.Molle Jul 25 '11 at 01:03
  • I tried using the delay method. I set the child window's onload function to `onload = "loaded=true"` and then I called setTimeout with a 1000 ms frequency and a function which checks `w.loaded==true`. If it has loaded, I try setting a property, and/or calling a property and still I get nowhere. – puk Jul 25 '11 at 01:29

2 Answers2

3

The problem is that you are not giving the DOM of the child window a chance to load before trying to inspect its contents.

console.log(w) appeared to work by displaying Window or similar immediately, but in fact it's just that by the time your human fingers got around to expanding the item details in the console, the properties and methods were present.

When I inject a delay with help from a Firebug breakpoint, I can see the child window's properties like this just fine.

This question talks about adding onLoad event listeners for children. Using its accepted answer, how about:

<script type="text/javascript">
// parent.html
var w;

function lol() {
    console.log(w.foo);
    console.log(w.test);
}

w = window.open("child.html");
console.log(w);
w.addEventListener('load', lol, true);
</script>

(I was also able to achieve success with a 1s setTimeout delay.)

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • I'll give it a shot, although I doubt it will work since a 10s timeout delay didn't work for me... WOW it actually worked – puk Jul 25 '11 at 01:44
  • @puk: Whatever you did to implement the 10s timeout was wrong. Again, you haven't shown us, so we can't tell you what that was. – Lightness Races in Orbit Jul 25 '11 at 01:49
  • Well it worked somewhat. It works for `foo` and `test` because they are hard coded. But if, for example, I do `function lol(){ w.xyz = 123; console.log(w.xyz)}` the output is still `undefined`. – puk Jul 25 '11 at 01:59
  • @puk: I'm not sure whether you're allowed to inject new properties into a child window. – Lightness Races in Orbit Jul 25 '11 at 02:06
  • Is there any way to 'ask' the child to inject new properties into itself? ie. `w.addEventListener('load', lol, true, args)`? I have to step out, will check again in a few hours. – puk Jul 25 '11 at 02:15
  • @puk: Why do you want to do this? – Lightness Races in Orbit Jul 25 '11 at 02:21
  • Tomalak: I have a value that constantly changes and it's difficult to keep a global copy of it (see EDIT2 of my question). I need some way to pass the correct copy to the child window. – puk Jul 25 '11 at 05:55
  • OK turns out one IS allowed to inject properties into a new window. The problem is what I was injecting was itself undefined. I have a helper function which retrieves shapes like so `$$('shapeName')` and I was trying to access property `test` of it and pass it to the child window like so `$$('shapName').test` but instead I had `'shapeName'.test` and for some reason their was no syntax error. – puk Jul 25 '11 at 06:10
  • @puk: Strings are objects with properties. :) Consider, for example, `var bool = "myString".match(/someRegex/);` – Lightness Races in Orbit Jul 25 '11 at 14:01
  • I see. I'm not a big fan of some of javascript's choices. I'm a Python man myself. I think a line should be drawn differentiating objects from literals. But I won't get into that. Thanks for your help. – puk Jul 25 '11 at 18:53
  • @puk: Strictly speaking there is a line, but implicit conversions blur it in practice. – Lightness Races in Orbit Jul 26 '11 at 00:07
-2

The answer is rather simple if you look at your code logically

The following two calls will only work inside the window you open.

console.log(w.foo);
//outputs 'undefined'
console.log(w.test);
//outputs 'undefined'

i.e.

console.log(foo);

in the parent window javascript, and

console.log(window.parent.foo);

in the child window javascript.

eaglestorm
  • 1,192
  • 1
  • 13
  • 32
  • I am not familiar with `window.parent`. Do you mean `window.opener`? – puk Jul 25 '11 at 00:21
  • 2
    I'm really sorry eaglstorem but I am not following your logic. `foo` is defined in the child window, why would the parent call `console.log(foo)` and the child call `console.log(window.opener.foo)` – puk Jul 25 '11 at 00:27
  • @eaglestorm: He wants to access the properties of the child window from the parent window. And I think you have it backward as to where `foo` is declared. – Lightness Races in Orbit Jul 25 '11 at 01:31
  • My bad I did get it backwards – eaglestorm Jul 25 '11 at 02:26