I open a new window using the following code:
purchaseWin = window.open("Purchase.aspx","purchaseWin2", "location=0,status=0,scrollbars=0,width=700,height=400");
I want to access the dom tree of the purchaseWin, e.g.
purchaseWin.document.getElementById("tdProduct").innerHTML = "2";
It doesn't work. I can only do this:
purchaseWin.document.write("abc");
I also try this and it doesn't work too:
$(purchaseWin.document).ready(function(){
purchaseWin.$("#tdProduct").html("2");
});
What should I do?
With jQuery, you have to access the contents of the document of your child window:
$(purchaseWin.document).ready(function () {
$(purchaseWin.document).contents().find('#tdProduct').html('2');
});
Without libraries, with plain JavaScript, you can do it this way:
purchaseWin.onload = function () {
purchaseWin.document.getElementById('tdProduct').innerHTML = '2';
};
I think that the problem was that you were trying to retrieve the DOM element before the child window actually loaded.
Maybe the load event of jQuery works for you as this worked for me in a similar Problem, whereas the ready event did not work:
$(purchaseWin).load(function(){
purchaseWin.$("#tdProduct").html("2");
});
You cannot access the document of a child window if you load a page that does not belong to the domain of the parent window. This is due to the cross-domain security built into Javascript.
(function() {
document.getElementById("theButton").onclick = function() {
var novoForm = window.open("http://jsbin.com/ugucot/1", "wFormx", "width=800,height=600,location=no,menubar=no,status=no,titilebar=no,resizable=no,");
novoForm.onload = function() {
var w = novoForm.innerWidth;
var h = novoForm.innerHeight;
novoForm.document.getElementById("monitor").innerHTML = 'Janela: '+w+' x '+h;
};
};
})();
Related
Trying pass variable from one iframe to another. Sound weird but I made a picture to make it clear:
My first try to add new srcrip to the new iframe. Looks like its work, but new variable undefined.
var creativeFrame = parentDocument.getElementById('iframe2');
var creativeWindow = parentDocument.getElementById('iframe2').contentWindow;
var creativeDocument = creativeFrame.document;
var myFunction = function() {
var iFrameHead = creativeFrame.document.getElementsByTagName("head")[0];
var myscript = creativeBody.createElement('script');
myscript.type = 'text/javascript';
myscript.text = 'var a = 2';
iFrameHead.appendChild(myscript);
};
if(creativeFrame.addEventListener) {
creativeFrame.addEventListener('load', myFunction, true);
} else if(creativeFrame.attachEvent) {
creativeFrame.attachEvent('onload', myFunction);
}
</script>
Window.postMessage() is the recommended way to pass data from one Window object (tab, window, iframe...) to another. Minimal use case:
An event listener must be present in the script of the iframe: window.addEventListener('message', console.log);
The parent window, given a window reference to the iframe, can then send message to the iframe: myIframe.postMessage('hello world', '*')
I'd like to open a new window, this window has a list of objects, and these objects should be filtered based on a selection from the previous window. I figured I can filter the list through a function, but how do I run said function?
This is what I am able to do:
var popup = window.open('pageURL');
$(popup.document).ready(function() {
// this is where function should be
popup.alert('HelloWorld');
});
But how do I change the alert to a function?
If I have a function on my other app , function test() { alert('HelloWorld'};
How do I run this function from my first app?
Swapping popup.alert('HelloWorld'); with popup.test(); did not work.
You need the reference to the window opened to call functions in the new window, like:
var oNewWindow = window.open("new.window.url", "mywindow");
oNewWindow.onload = function(){oNewWindow.window.newWindowFunction();};
I ended up with this solution
var popup = window.open('http://s234-0057/actiontracker/SiteAssets/Avvik/html/app.aspx');
var readyStateCheckInterval = setInterval(function() {
if (popup.document.readyState === "complete") {
clearInterval(readyStateCheckInterval);
popup.test();
}
}, 50);
Where I check if the popup window is ready, and when it is, cancel check and run function. Solution is from top answer on this question, by #this.lau_
You can write it like this:
function myFunction(){
alert('HelloWorld');
}
var popup = window.open('pageURL');
$(popup.document).ready(function() {
popup.eval(myFunction + "");
popup.myFunction();
});
myFunction in file that contains this code will run in page with pageURL address.
I open a new window using the following code:
purchaseWin = window.open("Purchase.aspx","purchaseWin2", "location=0,status=0,scrollbars=0,width=700,height=400");
I want to access the dom tree of the purchaseWin, e.g.
purchaseWin.document.getElementById("tdProduct").innerHTML = "2";
It doesn't work. I can only do this:
purchaseWin.document.write("abc");
I also try this and it doesn't work too:
$(purchaseWin.document).ready(function(){
purchaseWin.$("#tdProduct").html("2");
});
What should I do?
With jQuery, you have to access the contents of the document of your child window:
$(purchaseWin.document).ready(function () {
$(purchaseWin.document).contents().find('#tdProduct').html('2');
});
Without libraries, with plain JavaScript, you can do it this way:
purchaseWin.onload = function () {
purchaseWin.document.getElementById('tdProduct').innerHTML = '2';
};
I think that the problem was that you were trying to retrieve the DOM element before the child window actually loaded.
Maybe the load event of jQuery works for you as this worked for me in a similar Problem, whereas the ready event did not work:
$(purchaseWin).load(function(){
purchaseWin.$("#tdProduct").html("2");
});
You cannot access the document of a child window if you load a page that does not belong to the domain of the parent window. This is due to the cross-domain security built into Javascript.
(function() {
document.getElementById("theButton").onclick = function() {
var novoForm = window.open("http://jsbin.com/ugucot/1", "wFormx", "width=800,height=600,location=no,menubar=no,status=no,titilebar=no,resizable=no,");
novoForm.onload = function() {
var w = novoForm.innerWidth;
var h = novoForm.innerHeight;
novoForm.document.getElementById("monitor").innerHTML = 'Janela: '+w+' x '+h;
};
};
})();
I am opening a new window when a button is clicked and then appending the content from this window to the window that has been opened, the jQuery code that I'm using is:
$(".printBtn").on("click", function () {
var w = window.open("", "Purchase Report", "width=800, height=1100");
var wi = $(window);
$(w.document.body).append(wi.find("#datatable_example"));
return false;
});
The problem is, a new window does open but the content from the parent window is not being appended to the newly opened window. I then tried to append wi.find("#datatable_example").html() but that didn't work either.
Can any one please have a look and tell me what I am doing wrong here?
UPDATE
Tried the following from the "duplicate question", but didn't work:
$(".printBtn").on("click", function () {
var w = window.open("", "Purchase Report", "width=800, height=1100");
$(w.document).ready(function () {
$(w.document.body).contents().append($(window).find("#datatable_example"));
});
return false;
});
The problem was, I was using var wi = $(window) instead of var wi = $(window.document). Here is the working code:
$(".printBtn").on("click", function () {
var w = window.open("", "Purchase Report", "width=800, height=1100");
var wi = $(window.document);
$(w.document.body).append(wi.find("#datatable_example"));
return false;
});
The root of your problem is same origin policy that won't let you observe load events for external domains. If you try this in developer console while browsing SO, everything's fine:
var child = window.open( 'http://stackoverflow.com' );
child.onload = function() {
alert( 'Popup loaded!' ); // Fired!
};
However if you try to open a page from other domain, it fails:
var child = window.open( 'http://stackexchange.com' );
child.onload = function() {
// It's not gonna be fired unless you run it from stackexchange.com.
alert( 'Popup loaded!' );
};
The same thing happens when you call window.open() or window.open( '' ) as it tries to load about:blank page which is out of your domain's scope and that's why your browser won't fire attached events (same for child.addEventListener( 'load' )). Also note that the protocol must match as well.
The workaround introduces setTimeout to run the callback in a separate JS thread, hopefully late enough to have DOM ready at that time:
var child = window.open();
setTimeout( function() {
var doc = child.document,
p = doc.createElement( 'p' );
p.innerHTML = 'Hello world!';
doc.body.appendChild( p );
} );
It works for me in latest Chrome, however different browsers sometimes do strange thing in such edge cases so you may need to tune this code with greater delay, sequential check or something else if it fails in your case.
So go ahead and tell us if it worked for you as I'm curious whether such workaround is fine for production code ;)
I'm desperate having spent well over an hour trying to troubleshoot this. I am trying to access a node in the DOM which is created from an ASP.NET control. I'm using exactly the same id and I can see that they match up when looking at the HTML source code after the page has rendered. Here's my [MODIFIED according to suggestions, but still not working] code:
ASP.NET Header
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
<script type="text/javascript">
$(document).ready(
var el = document.getElementById('<%= txtBox.ClientID %>');
el.onchange = alert('test!!');
)
</script>
</asp:Content>
ASP.NET Body
<asp:TextBox ID="txtBox" runat="server"></asp:TextBox>
Resulting Javascript & HTML from above
<script type="text/javascript">
$(document).ready(
var el = document.getElementById('MainContent_txtBox');
el.onchange = alert('test!!');
)
</script>
...
<textarea name="ctl00$MainContent$txtBox" id="MainContent_txtBox"></textarea>
I can only assume that the script is loading before the control id has been resolved, yet when I look at the timeline with Chrome's "Inspect Element" feature, it appears that is not the case. When I created a regular textarea box to test and implement the identical code (different id of course), the alert box fires.
What on earth am I missing here? This is driving me crazy >.<
EDIT: Wierd code that works, but only on the initial page load; firing onload rather than onchange. Even jQuery says that .ready doesn't work properly apparently. Ugh!!
$(document).ready(function() {
document.getElementById('<%= txtBox.ClientID %>').onchange = alert('WORKING!');
})
Assuming the rendered markup does appear in that order, the problem is that the element doesn't yet exist at the time your JavaScript is attempting to locate it.
Either move that JS below the element (preferably right at the end of the body) or wrap it in something like jQuery's document ready event handler.
Update:
In response to your edits, you're almost there but (as others have mentioned) you need to assign a function to the onchange event, not the return result of alert(). Something like this:
$(document).ready(function() {
// Might as well use jQuery to attach the event since you're already using
// it for the document ready event.
$('#<%= txtBox.ClientID %>').change(function() {
alert('Working!');
});
});
By writing onchange = alert('Working');, you were asking JavaScript to assign the result of the alert() method to the onchange property. That's why it was executing it immediately on page load, but never actually in response to the onchange event (because you hadn't assigned that a function to run onchange).
Pick up jQuery.
Then you can
$(function()
{
var el = document.getElementById('<%= txtBox.ClientID %>');
el.onclick() { alert('test!!'); }
});
Other answers have pointed out the error (attempting to access DOM nodes before they are in the document), I'll just point out alternative solutions.
Simple method
Add the script element in the HTML below the closing tag of the element you wish to access. In its easiest form, put it just before the closing body tag. This strategy can also make the page appear faster as the browser doesn't pause loading HTML for script. Overall load time is the same however, scripts still have to be loaded an executed, it's just that this order makes it seem faseter to the user.
Use window.onload or <body onload="..." ...>
This method is supported by every browser, but it fires after all content is loaded so the page may appear inactive for a short time (or perhaps a long time if loading is dealyed). It is very robust though.
Use a DOM ready function
Others have suggested jQuery, but you may not want 4,000 lines and 90kb of code just for a DOM ready function. jQuery's is quite convoluted so hard to remove from the library. David Mark's MyLibrary however is very modular and quite easy to extract just the bits you want. The code quality is also excellent, at least the equal of any other library.
Here is an example of a DOM ready function extracted from MyLibrary:
var API = API || {};
(function(global) {
var doc = (typeof global.document == 'object')? global.document : null;
var attachDocumentReadyListener, bReady, documentReady,
documentReadyListener, readyListeners = [];
var canAddDocumentReadyListener, canAddWindowLoadListener,
canAttachWindowLoadListener;
if (doc) {
canAddDocumentReadyListener = !!doc.addEventListener;
canAddWindowLoadListener = !!global.addEventListener;
canAttachWindowLoadListener = !!global.attachEvent;
bReady = false;
documentReady = function() { return bReady; };
documentReadyListener = function(e) {
if (!bReady) {
bReady = true;
var i = readyListeners.length;
var m = i - 1;
// NOTE: e may be undefined (not always called by event handler)
while (i--) { readyListeners[m - i](e); }
}
};
attachDocumentReadyListener = function(fn, docNode) {
docNode = docNode || global.document;
if (docNode == global.document) {
if (!readyListeners.length) {
if (canAddDocumentReadyListener) {
docNode.addEventListener('DOMContentLoaded',
documentReadyListener, false);
}
if (canAddWindowLoadListener) {
global.addEventListener('load', documentReadyListener, false);
}
else if (canAttachWindowLoadListener) {
global.attachEvent('onload', documentReadyListener);
} else {
var oldOnLoad = global.onload;
global.onload = function(e) {
if (oldOnLoad) {
oldOnLoad(e);
}
documentReadyListener();
};
}
}
readyListeners[readyListeners.length] = fn;
return true;
}
// NOTE: no special handling for other documents
// It might be useful to add additional queues for frames/objects
else {
if (canAddDocumentReadyListener) {
docNode.addEventListener('DOMContentLoaded', fn, false);
return true;
}
return false;
}
};
API.documentReady = documentReady;
API.documentReadyListener = documentReadyListener;
API.attachDocumentReadyListener = attachDocumentReadyListener;
}
}(this));
Using it for your case:
function someFn() {
var el = document.getElementById('MainContent_txtBox');
el.onclick = function() { alert('test!!');
}
API.attachDocumentReadyListener(someFn);
or an anonymous function can be supplied:
API.attachDocumentReadyListener(function(){
var el = document.getElementById('MainContent_txtBox');
el.onclick = function() { alert('test!!');
};
Very simple DOM ready functions can be done in 10 lines of code if you just want one for a specific case, but of course they are less robust and not as reusable.