Popup window accessing parent dom - javascript

I have a popup window that needs to access the parent dom to generate a print page. The structure of the print page is significantly different then the structure of the parent so a print css would not solve the problem. I basically want to popup a window and then have that window grab some data from the parent of even access the dom from the popup and generate the print page without having to go to the server again. Any ideas how i can achieve this?
Im using the standard
window.open()
to pop up a window. I need this solution to not be a hack and be cross browser compatible with all major browsers.
Thanks in advance!

Sajjan's answer is a start, but better make sure your objects are available before you try to access them:
var opener = window.opener;
if(opener) {
var oDom = opener.document;
var elem = oDom.getElementById("your element");
if (elem) {
var val = elem.value;
}
}
Otherwise, you do run the risk that the opener doesn't respond to your initial call, and that you can't get the element from it.
As jQuery, I think (based on an answer, here: how to access parent window object using jquery?):
var opener = window.opener;
if(opener) {
var elem = opener.$("#elementId");
if (elem) {
var val = elem.val(); // I forgot we're dealing with a jQuery obj at this point
}
}

window.opener.document.getElementById("your element").value

According to MDN, window.open() will return you a handle to the new window.
var popUpHandle = window.open();
With this handle you should be able to access the DOM of the PopUp. It is possible vice-versa using the already mentioned window.opener. Refer again to MDN:
var originalWindow = window.opener;
Still, your favorite search engine will provide you more details, as this is topic is fairly old and your approach has already been done a million times or more.

parent.document helped in my case.
var elem = parent.document.getElementById("overlay_modal");
if (elem) {
alert('setting attribute');
elem.setAttribute("onclick", "Windows.close('2', event);");
}

Related

How to get original native method if it has been overridden? [duplicate]

If I have something like
alert = 0;
in another script.
This is in another script is and my code cannot load before that script.
How can I call the original alert method in my script?
Before overriding the original alert, save it.
var origAlert = alert;
alert = 0;
origAlert("foo");
Demo: http://jsfiddle.net/jfriend00/tnNE7/
If you can't save the original value, the only other way I know of to get access to it is in an iframe. Here's an example:
alert = 0;
var iframe = document.createElement("iframe");
iframe.height = 0;
iframe.width = 0;
document.body.appendChild(iframe);
iframe.contentWindow.alert.call(window, "foo");​
Working example: http://jsfiddle.net/jfriend00/waMEV/
I haven't tried this in all browsers, but it works in Chrome, IE and Firefox and I think it should work in other browsers.
Ok, I'm the first to admit this is an ugly answer, but it seems to work:
alert = 0;
var win = window.open(),
method = win.alert;
win.close();
method.call(window, "my message");
Fiddle here. Essentially, you make a new window instance and steal its alert method. The downside is that you actually have to open a new browser window, albeit briefly. I doubt this is actually a practical solution to your problem - depends what other site you're trying to work with, and how much you care about how your solution looks to the end user.
Edit: This is a combo of the above answer and jfriend00's answer, which solves the "open a new window" problem. I think this is a somewhat better option, as a) it doesn't rely on the iframe still being in the DOM when you need to call the method, and b) it should be generalizable to any window method, which jfriend00's answer probably isn't.
alert = 0;
// make a new window instance in an iframe
var iframe = document.createElement("iframe");
iframe.height = iframe.width = 0;
document.body.appendChild(iframe);
// steal the method
var method = iframe.contentWindow.alert;
// remove the evidence
document.body.removeChild(iframe);
// now use the method for your own purposes
function myAlert(message) {
method.call(window, message);
}
myAlert("foo");

QuerySelector for Web Elements Inside iframe

Edit: New title.
What I'm looking for is a document.querySelector for elements inside an iframe.
I've done quite a bit of Googling for an answer and finally I'm stumped.
I'm trying to query inside an iframe. I'm building string selectors to be used in Selenium and usually I just inspect the element with Firebug, and use document.querySelectorAll("theStringIBuid");
But it doesn't work with elements inside iframes. I've tried all of the below to get an element "radiobutton1" inside the "page-iframe" iframe.
var elem1 = ".page-iframe";
console.log(elem1);
var elem2 = ".radiobutton1";
console.log(elem2);
document.querySelectorAll(elem1+elem2+"");
document.querySelectorAll('.page-iframe').contentWindow.document.body.querySelectorAll('.radiobutton1')
document.getElementById('.page-iframe').contentWindow.document.body.innerHTML;
[].forEach.call( document.querySelectorAll('.page-iframe'),
function fn(elem){
console.log(elem.contentWindow.document.body.querySelectorAll('.radiobutton1')); });
var contentWindow = document.getElementById('.page-iframe').contentWindow
var contentWindow = document.querySelectorAll('.page-iframe')
var contentWindow = document.querySelectorAll('.page-iframe')[0].contentWindow
Thanks-
simple es6 adapted from h3manth:
document.querySelectorAll('iframe').forEach( item =>
console.log(item.contentWindow.document.body.querySelectorAll('a'))
)
if the original page's url isn't at the same domain with the iframe content, the javascript will treat the iframe as a black box, meaning it will not see anything inside it.
You can do this:
document.querySelector("iframe").contentWindow.document.querySelector("button")
https://m.youtube.com/watch?v=-mNp3-UX9Qc
You can simply use
document.querySelector("iframe").contentDocument.body.querySelector("#btn")
First query selector is to select the iframe. Then we can access ifram dom using content document and use the 2nd query selector to select the element inside iframe.
Here's a snippet for diving into same-origin frames (ie-compatible ES5):
function findInFramesRec(selector, doc) {
var hit = doc.querySelector(selector);
if (hit) return hit;
var frames = Array.prototype.slice.call(doc.frames);
for(var i = 0; (i < frames.length) && !hit ; i++) {
try {
if (!frames[i] || !frames[i].document) continue;
hit = findInFramesRec(selector, frames[i].document);
} catch(e) {}
}
return hit;
}
This dives into both frameset frames and iframes alike. It may even survive (though not enter) cross origin frames.

Call native browser function, even after it has been overridden

If I have something like
alert = 0;
in another script.
This is in another script is and my code cannot load before that script.
How can I call the original alert method in my script?
Before overriding the original alert, save it.
var origAlert = alert;
alert = 0;
origAlert("foo");
Demo: http://jsfiddle.net/jfriend00/tnNE7/
If you can't save the original value, the only other way I know of to get access to it is in an iframe. Here's an example:
alert = 0;
var iframe = document.createElement("iframe");
iframe.height = 0;
iframe.width = 0;
document.body.appendChild(iframe);
iframe.contentWindow.alert.call(window, "foo");​
Working example: http://jsfiddle.net/jfriend00/waMEV/
I haven't tried this in all browsers, but it works in Chrome, IE and Firefox and I think it should work in other browsers.
Ok, I'm the first to admit this is an ugly answer, but it seems to work:
alert = 0;
var win = window.open(),
method = win.alert;
win.close();
method.call(window, "my message");
Fiddle here. Essentially, you make a new window instance and steal its alert method. The downside is that you actually have to open a new browser window, albeit briefly. I doubt this is actually a practical solution to your problem - depends what other site you're trying to work with, and how much you care about how your solution looks to the end user.
Edit: This is a combo of the above answer and jfriend00's answer, which solves the "open a new window" problem. I think this is a somewhat better option, as a) it doesn't rely on the iframe still being in the DOM when you need to call the method, and b) it should be generalizable to any window method, which jfriend00's answer probably isn't.
alert = 0;
// make a new window instance in an iframe
var iframe = document.createElement("iframe");
iframe.height = iframe.width = 0;
document.body.appendChild(iframe);
// steal the method
var method = iframe.contentWindow.alert;
// remove the evidence
document.body.removeChild(iframe);
// now use the method for your own purposes
function myAlert(message) {
method.call(window, message);
}
myAlert("foo");

Pass argument array to window.open like window.showModalDialog [duplicate]

I have a page which spawns a popup browser window. I have a JavaScript variable in the parent browser window and I would like to pass it to the popped-up browser window.
Is there a way to do this? I know this can be done across frames in the same browser window but I'm not sure if it can be done across browser windows.
Putting code to the matter, you can do this from the parent window:
var thisIsAnObject = {foo:'bar'};
var w = window.open("http://example.com");
w.myVariable = thisIsAnObject;
or this from the new window:
var myVariable = window.opener.thisIsAnObject;
I prefer the latter, because you will probably need to wait for the new page to load anyway, so that you can access its elements, or whatever you want.
Provided the windows are from the same security domain, and you have a reference to the other window, yes.
Javascript's open() method returns a reference to the window created (or existing window if it reuses an existing one). Each window created in such a way gets a property applied to it "window.opener" pointing to the window which created it.
Either can then use the DOM (security depending) to access properties of the other one, or its documents,frames etc.
Yes, scripts can access properties of other windows in the same domain that they have a handle on (typically gained through window.open/opener and window.frames/parent). It is usually more manageable to call functions defined on the other window rather than fiddle with variables directly.
However, windows can die or move on, and browsers deal with it differently when they do. Check that a window (a) is still open (!window.closed) and (b) has the function you expect available, before you try to call it.
Simple values like strings are fine, but generally it isn't a good idea to pass complex objects such as functions, DOM elements and closures between windows. If a child window stores an object from its opener, then the opener closes, that object can become 'dead' (in some browsers such as IE), or cause a memory leak. Weird errors can ensue.
Passing variables between the windows (if your windows are on the same domain) can be easily done via:
Cookies
localStorage. Just make sure your browser supports localStorage, and do the variable maintenance right (add/delete/remove) to keep localStorage clean.
One can pass a message from the 'parent' window to the 'child' window:
in the 'parent window' open the child
var win = window.open(<window.location.href>, '_blank');
setTimeout(function(){
win.postMessage(SRFBfromEBNF,"*")
},1000);
win.focus();
the to be replaced according to the context
In the 'child'
window.addEventListener('message', function(event) {
if(event.srcElement.location.href==window.location.href){
/* do what you want with event.data */
}
});
The if test must be changed according to the context
In your parent window:
var yourValue = 'something';
window.open('/childwindow.html?yourKey=' + yourValue);
Then in childwindow.html:
var query = location.search.substring(1);
var parameters = {};
var keyValues = query.split(/&/);
for (var keyValue in keyValues) {
var keyValuePairs = keyValue.split(/=/);
var key = keyValuePairs[0];
var value = keyValuePairs[1];
parameters[key] = value;
}
alert(parameters['yourKey']);
There is potentially a lot of error checking you should be doing in the parsing of your key/value pairs but I'm not including it here. Maybe someone can provide a more inclusive Javascript query string parsing routine in a later answer.
You can pass variables, and reference to things in the parent window quite easily:
// open an empty sample window:
var win = open("");
win.document.write("<html><body><head></head><input value='Trigger handler in other window!' type='button' id='button'></input></body></html>");
// attach to button in target window, and use a handler in this one:
var button = win.document.getElementById('button');
button.onclick = function() {
alert("I'm in the first frame!");
}
Yes, it can be done as long as both windows are on the same domain. The window.open() function will return a handle to the new window. The child window can access the parent window using the DOM element "opener".
For me the following doesn't work
var A = {foo:'bar'};
var w = window.open("http://example.com");
w.B = A;
// in new window
var B = window.opener.B;
But this works(note the variable name)
var B = {foo:'bar'};
var w = window.open("http://example.com");
w.B = B;
// in new window
var B = window.opener.B;
Also var B should be global.
Alternatively, you can add it to the URL and let the scripting language (PHP, Perl, ASP, Python, Ruby, whatever) handle it on the other side. Something like:
var x = 10;
window.open('mypage.php?x='+x);
I have struggled to successfully pass arguments to the newly opened window.
Here is what I came up with :
function openWindow(path, callback /* , arg1 , arg2, ... */){
var args = Array.prototype.slice.call(arguments, 2); // retrieve the arguments
var w = window.open(path); // open the new window
w.addEventListener('load', afterLoadWindow.bind(w, args), false); // listen to the new window's load event
function afterLoadWindow(/* [arg1,arg2,...], loadEvent */){
callback.apply(this, arguments[0]); // execute the callbacks, passing the initial arguments (arguments[1] contains the load event)
}
}
Example call:
openWindow("/contact",function(firstname, lastname){
this.alert("Hello "+firstname+" "+lastname);
}, "John", "Doe");
Live example
http://jsfiddle.net/rj6o0jzw/1/
You can use window.name as a data transport between windows - and it works cross domain as well. Not officially supported, but from my understanding, actually works very well cross browser.
More info here on this Stackoverflow Post
Yes browsers clear all ref. for a window. So you have to search a ClassName of something on the main window or use cookies as Javascript homemade ref.
I have a radio on my project page. And then you turn on for the radio it´s starts in a popup window and i controlling the main window links on the main page and show status of playing and in FF it´s easy but in MSIE not so Easy at all. But it can be done.
The window.open() function will also allow this if you have a reference to the window created, provided it is on the same domain.
If the variable is used server side you should be using a $_SESSION variable (assuming you are using PHP).

Can I pass a JavaScript variable to another browser window?

I have a page which spawns a popup browser window. I have a JavaScript variable in the parent browser window and I would like to pass it to the popped-up browser window.
Is there a way to do this? I know this can be done across frames in the same browser window but I'm not sure if it can be done across browser windows.
Putting code to the matter, you can do this from the parent window:
var thisIsAnObject = {foo:'bar'};
var w = window.open("http://example.com");
w.myVariable = thisIsAnObject;
or this from the new window:
var myVariable = window.opener.thisIsAnObject;
I prefer the latter, because you will probably need to wait for the new page to load anyway, so that you can access its elements, or whatever you want.
Provided the windows are from the same security domain, and you have a reference to the other window, yes.
Javascript's open() method returns a reference to the window created (or existing window if it reuses an existing one). Each window created in such a way gets a property applied to it "window.opener" pointing to the window which created it.
Either can then use the DOM (security depending) to access properties of the other one, or its documents,frames etc.
Yes, scripts can access properties of other windows in the same domain that they have a handle on (typically gained through window.open/opener and window.frames/parent). It is usually more manageable to call functions defined on the other window rather than fiddle with variables directly.
However, windows can die or move on, and browsers deal with it differently when they do. Check that a window (a) is still open (!window.closed) and (b) has the function you expect available, before you try to call it.
Simple values like strings are fine, but generally it isn't a good idea to pass complex objects such as functions, DOM elements and closures between windows. If a child window stores an object from its opener, then the opener closes, that object can become 'dead' (in some browsers such as IE), or cause a memory leak. Weird errors can ensue.
Passing variables between the windows (if your windows are on the same domain) can be easily done via:
Cookies
localStorage. Just make sure your browser supports localStorage, and do the variable maintenance right (add/delete/remove) to keep localStorage clean.
One can pass a message from the 'parent' window to the 'child' window:
in the 'parent window' open the child
var win = window.open(<window.location.href>, '_blank');
setTimeout(function(){
win.postMessage(SRFBfromEBNF,"*")
},1000);
win.focus();
the to be replaced according to the context
In the 'child'
window.addEventListener('message', function(event) {
if(event.srcElement.location.href==window.location.href){
/* do what you want with event.data */
}
});
The if test must be changed according to the context
In your parent window:
var yourValue = 'something';
window.open('/childwindow.html?yourKey=' + yourValue);
Then in childwindow.html:
var query = location.search.substring(1);
var parameters = {};
var keyValues = query.split(/&/);
for (var keyValue in keyValues) {
var keyValuePairs = keyValue.split(/=/);
var key = keyValuePairs[0];
var value = keyValuePairs[1];
parameters[key] = value;
}
alert(parameters['yourKey']);
There is potentially a lot of error checking you should be doing in the parsing of your key/value pairs but I'm not including it here. Maybe someone can provide a more inclusive Javascript query string parsing routine in a later answer.
You can pass variables, and reference to things in the parent window quite easily:
// open an empty sample window:
var win = open("");
win.document.write("<html><body><head></head><input value='Trigger handler in other window!' type='button' id='button'></input></body></html>");
// attach to button in target window, and use a handler in this one:
var button = win.document.getElementById('button');
button.onclick = function() {
alert("I'm in the first frame!");
}
Yes, it can be done as long as both windows are on the same domain. The window.open() function will return a handle to the new window. The child window can access the parent window using the DOM element "opener".
For me the following doesn't work
var A = {foo:'bar'};
var w = window.open("http://example.com");
w.B = A;
// in new window
var B = window.opener.B;
But this works(note the variable name)
var B = {foo:'bar'};
var w = window.open("http://example.com");
w.B = B;
// in new window
var B = window.opener.B;
Also var B should be global.
Alternatively, you can add it to the URL and let the scripting language (PHP, Perl, ASP, Python, Ruby, whatever) handle it on the other side. Something like:
var x = 10;
window.open('mypage.php?x='+x);
I have struggled to successfully pass arguments to the newly opened window.
Here is what I came up with :
function openWindow(path, callback /* , arg1 , arg2, ... */){
var args = Array.prototype.slice.call(arguments, 2); // retrieve the arguments
var w = window.open(path); // open the new window
w.addEventListener('load', afterLoadWindow.bind(w, args), false); // listen to the new window's load event
function afterLoadWindow(/* [arg1,arg2,...], loadEvent */){
callback.apply(this, arguments[0]); // execute the callbacks, passing the initial arguments (arguments[1] contains the load event)
}
}
Example call:
openWindow("/contact",function(firstname, lastname){
this.alert("Hello "+firstname+" "+lastname);
}, "John", "Doe");
Live example
http://jsfiddle.net/rj6o0jzw/1/
You can use window.name as a data transport between windows - and it works cross domain as well. Not officially supported, but from my understanding, actually works very well cross browser.
More info here on this Stackoverflow Post
Yes browsers clear all ref. for a window. So you have to search a ClassName of something on the main window or use cookies as Javascript homemade ref.
I have a radio on my project page. And then you turn on for the radio it´s starts in a popup window and i controlling the main window links on the main page and show status of playing and in FF it´s easy but in MSIE not so Easy at all. But it can be done.
The window.open() function will also allow this if you have a reference to the window created, provided it is on the same domain.
If the variable is used server side you should be using a $_SESSION variable (assuming you are using PHP).

Categories