Is there a way to for a parent to know when a child window has loaded it's content? Without any script in the child.
Here is my current code:
var printWindow = window.open('', '_blank');
printWindow.document.write(clonedElement.html());
printWindow.onreadystatechage = function() {
console.log('this does not work.');
};
You have the same events that fire on window, so you could get the load event if you opened the page with the html there already, e.g.
var b = new Blob([clonedElement.html()], {type: 'text/html'}),
uri = URL.createObjectURL(b),
printWindow;
printWindow = window.open(uri, '_blank');
printWindow.addEventListener('load', function () {
URL.revokeObjectURL(uri); // release these
b = null; // from memory
// do something else
});
Please be aware that there will be a race condition here (though you'll almost always win it, i.e. if the page loads and the event fires between opening and adding the listener)
Alternatively, without the race
var b = new Blob([clonedElement.html()], {type: 'text/html'}),
uri = URL.createObjectURL(b),
printWindow = window.open('', '_blank');
printWindow.addEventListener('load', function () {
URL.revokeObjectURL(uri); // release these
b = null; // from memory
// do something else
});
printWindow.location = uri;
It seems that you might be facing a cross domain policy problem here. The parent and child pages have to be hosted in the same domain. Browsers, like chrome for instance, won't allow it where as FF can be more lenient in some cases. You should look into 'enabling CORS' and this link should help you as well:
Waiting for child window loading to complete
Related
I need to trigger a url validation check onclick of the url before loading the page. If the url is not valid or cannot be reached I need to display an alert.
When I use i.onload it keeps waiting for it to load. If it never loads it also never produces an error to be caught by i.onerror. If the link loads properly everything works well.
html:
<a id={UrlToTest} onClick={this.testUrl}>{UrlToTest}</a>
javascript:
testURL(e) {
var targetURL = e.target.id;
var i = document.createElement('iframe');
i.style.display = 'none';
i.src = targetURL;
document.body.appendChild(i);
i.onload = function() {
//setTimeout(function(){
i.parentNode.removeChild(i);
return window.open(targetURL, '_blank');
//}, 5000);
};
i.onerror = function(){
alert('The link didn"t load');
};
}
If I insert console.log's it remains waiting for onload to trigger. If I allow the link to open without testing in a hidden iframe it will display 'unable to connect' immediately, or 404 error, etc. This error is never received when checked within the iframe.
Welcome to Stack Overflow :)
I believe your issue is that you set your onload and onerror after you set the src.
Think of it this way - your browser is trying to load (or error) the iframe as soon as possible, once the src is set, the browser starts his work, if an error (or success) is thrown before the onload was set, there's nothing to catch it.
TLDR - I think that switching the order (setting onload and onerror first) should resolve your problem.
Edit --
So I misunderstood the question, yes there are situations where nothing comes back from the iframe, specifically I could reproduce that with this code on the console here in stack overflow:
var targetURL = 'localhost:1'
var i = document.createElement('iframe');
i.onload = function() {
alert('The link did load');
};
i.onerror = function(){
alert('The link did NOT load');
};
i.src = targetURL;
document.body.appendChild(i);
the above code will not fire any event.
I'm not aware of why this is exactly happening, but maybe you should use a setTimeout timer to timeout the whole operation
let timer = setTimeout(() => {
alert('Error opening page');
}, 5000);
var targetURL = 'localhost:1'
var i = document.createElement('iframe');
i.onload = function() {
alert('The link did load');
clearTimeout(timer);
};
i.onerror = function(){
alert('The link did NOT load');
clearTimeout(timer);
};
i.src = targetURL;
document.body.appendChild(i);
I dug a bit deeper, turns out there's a bug for Chrome on this matter
https://bugs.chromium.org/p/chromium/issues/detail?id=365457
Unfortunately it seems that 'this is the spec', from the bug report:
I have discussed this with Adam Barth, and we have confirmed that the
behaviour described here is the behaviour described in the Living HTML
specification.
As follows: The specification requires that all HTML elements support
on onerror event. However, it does NOT require that all elements
supporting network fetches raise fire a simple event called onerror.
That is, elements must support allowing applications to set error
handlers, but there is no (generic) requirement that the event be
raised, in either HTML or the Fetch specification.
If I add this code between a <script> and a </script>:
function test()
{
var newWindow = window.open("https://stackoverflow.com/", "a", "width = 600,height = 400");
document.write(newWindow.location.href);
document.write(newWindow.innerWidth);
}
test();
And the output is "about:blank" and 0, though I think it should be "https://stackoverflow.com/" and 600.
I am so confused about this and waiting for a explanation.
AND: if I do want to get the URL of the new window, how should I do?
MANY THANKS.
You can capture these values asynchronously if you wait on the load event:
var newWindow = window.open('http://www.stackoverflow.com', 'a', 'width=600,height=400')
newWindow.addEventListener('load', function () {
console.log(newWindow.location.href);
console.log(newWindow.innerWidth);
});
However, as James Thorpe points out, this will only work if the new window is in the same domain as the page where the script is running, and this happens asynchronously, so whatever you're trying to accomplish by using document.write() might not work.
I have a html page. In the body of the page I am calling onload event which calls javascript function to open a pop up window. here is the code:
var newWindow = null;
function launchApplication()
{
if ((newWindow == null) || (newWindow.closed))
{
newWindow = window.open('abc.html','','height=960px,width=940px');
}
}
when I move to another page, and come back to that page again, popup reopens, although it is already opened. Please guide me to proper direction so that if pop up is already open then it should not open again. I tried document.referred but it requires the site online, currently I am working offline.
newWindow = window.open('abc.html','com_MyDomain_myWindowForThisPurpose','height=960px,width=940px');
Give the window a name. Basing the name on your domain like this, prevents the chances of you picking a name someone else happened to choose.
Never make up a name that begins with _, those are reserved for special names the browser treats differently (same as with the "target" attribute of anchor elements).
Note that if the window of that name was opened with different options (e.g. different height), then it'll keep those options. The options here will only take effect if there is no window of that name, so you do create a new one.
Edit:
Note that the "name" is of the window, not of the content. It doesn't affect the title (newWindow.document.title will affect that, as of course will code in abc.html). It does affect other attempts to do stuff across windows. Hence another window.open with the same name will reuse this window. Also a link like clicky! will re-use it. Normal caveats about browsers resisting window-opening in various scenarios (popup-blocking) apply.
To open a window and keep a reference to it between page refresh.
var winref = window.open('', 'MyWindowName', '');
if(winref.location.href === 'about:blank'){
winref.location.href = 'http://example.com';
}
or in function format
function openOnce(url, target){
// open a blank "target" window
// or get the reference to the existing "target" window
var winref = window.open('', target, '');
// if the "target" window was just opened, change its url
if(winref.location.href === 'about:blank'){
winref.location.href = url;
}
return winref;
}
openOnce('http://example.com', 'MyWindowName');
You can check if the window is open or closed by re-assigning a reference to it when it closes. Example:
var newWindow;
var openWindow = function(){
newWindow = newWindow || window.open('newpage.html');
newWindow.focus();
newWindow.onbeforeunload = function(){
newWindow = null;
};
};
Use the "closed" property: if a window has been closed its closed property will be true.
https://developer.mozilla.org/en-US/docs/Web/API/Window/closed
When you move on another page (on the same domain), you can re-set the window.open variable with popup page like this :
https://jsfiddle.net/u5w9v4gf/
Step to try :
Click on Run (on jsfiddle editor).
Click on Try me (on preview).
Click on Run to move on another page, the variable will be re-set.
Code :
window.currentChild = false;
$("#tryme").click(function() {
if (currentChild) currentChild.close();
const child = window.open("about:blank", "lmao", 'width=250,height=300');
currentChild = child;
//Scrope script in child windows
child.frames.eval(`
setInterval(function () {
if (!window.opener.currentChild)
window.opener.currentChild = window;
}, 500);
`);
});
setInterval(function() {
console.log(currentChild)
if (!currentChild || (currentChild && currentChild.closed))
$("p").text("No popup/child. :(")
else
$("p").text("Child detected !")
}, 500);
I'm writing a Firefox add-on that do something after the webpage is completely loaded.My current code is
var target = this;
const STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
const STATE_IS_WINDOW = Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW;
const STATE_IS_DOCUMENT = Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT;
const locationChangeListener = {
onStatusChange: function(){},
onProgressChange: function(){},
onLocationChange: function(aWebProgress, aRequest, aLocation){},
onStateChange: function(aWebProgress, aRequest, aFlag, aStatus){
if((aFlag & STATE_STOP) && (aFlag & STATE_IS_WINDOW)){
//Do something in here
}
},
onSecurityChange: function(){}
};
gBrowser.addProgressListener(locationChangeListener);
It works fine. But sometimes, for example webpage with AJAX call, this event fired several times for one web page.
Is there any way to detect if the webpage is completely loaded or not?
If you are only interested in detecting when the page has completely loaded and not the intermediary steps it is easier to listen for load events, with something like (code from https://developer.mozilla.org/en/Code_snippets/Tabbed_browser):
function examplePageLoad(event) {
if (event.originalTarget instanceof HTMLDocument) {
var win = event.originalTarget.defaultView;
if (win.frameElement) {
// Frame within a tab was loaded. win should be the top window of
// the frameset. If you don't want do anything when frames/iframes
// are loaded in this web page, uncomment the following line:
// return;
// Find the root document:
win = win.top;
}
}
}
// do not try to add a callback until the browser window has
// been initialised. We add a callback to the tabbed browser
// when the browser's window gets loaded.
window.addEventListener("load", function () {
// Add a callback to be run every time a document loads.
// note that this includes frames/iframes within the document
gBrowser.addEventListener("load", examplePageLoad, true);
}, false);
...
// When no longer needed
gBrowser.removeEventListener("load", examplePageLoad, true);
...
gBrowser is a global var in the main firefox window (if your code is running from an overlay of browser.xul you should see it). If not (running in a sidebar for example), you can get a reference to the main window:
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
mainWindow.gBrowser.addEventListener (...)
We are use window.open for open popup. But then we want find it and close. Unfortunately we can`t save this popup handle to variable.
P.S. How get list of all windows?
This should work:
var wh = window.open(..)
wh is the handle to the popup window.
If you have control over the page that loads the script, you could do something like this. Warning: this is a really scary and generally bad thing to do:
<script>
var windowHandles = {};
(function() {
var realOpen = window.open;
window.open = function(url, name, features) {
windowHandles[name] = realOpen(url, name, features);
};
})();
</script>
That will build an object (windowHandles) in which the handles for each opened window will be saved.
Put that script in your page before the script that opens the other window is loaded.
I found not perfect solution, but it work.
win = window.open(null, 'Window1');
This code search search window with this name and return handler, but if window is closed it open empty popup.
I Think this is temporary solution
I don't like this solution. Fixing the script to give you a handle would be a better bet.
<button onclick="go()">Go</button>
<button onclick="stop()">Stop</button>
<script type="text/javascript">
function go() {
// Existing function. It opens a window with a name.
window.open('http://google.com', 'test', 'width=300,height=300');
}
var foo;
function stop() {
// Open a new window with the same name. It replaces the existing window.
// Since it opens a local document, the Same Origin Policy does not apply.
// ... and we can capture its return value to grab a handle on an existing
// window
foo = window.open('black-local-page.html', 'test', 'width=300,height=300');
// Give the local page time to load
setTimeout(continue_stopping, 500);
}
function continue_stopping() {
// Call window.open() on the window
foo.close();
}
</script>