I want to send some data via postMessage from a page to another one which have different domains. However, I cannot achieve that since the code inside $(yo.document).load never runs; I tried the commented version as well. Here is my code:
<a onclick="popupCenter('http://localhost:58810');" href="javascript:void(0);">CLICK</a>
<script>
function popupCenter(url) {
const yo = window.open(url);
$(yo.document).load(function() {
//yo.document.onload = function() {
console.log("yo loaded");
yo.postMessage("Hello mate", "*");
});
}
</script>
</body>
</html>
The new window opens normally, however the callback inside load is not called. Any ideas?
Related
I'm dynamically creating menu items to be placed on the menu bar, based on the headers of external files, imported with an XMLHttpRequest(). As I navigate through the different pages, this menu bar is dynamically updated.
This works fine.
I load each document into an individual div element, in a sort of stack of cards, and hide all but the setVisible() page.
window.onload = function(){
loadContent("personalinfo");
loadContent("academicalinfo");
loadContent("employmentinfo");
setVisible("academicalinfo");
/*setMenues("academicalinfo");*/
}
The last action of setVisible() is to call setMenues(), which is responsible for reading all of the headers of said main window. This also works fine-ish.
function loadMenues(file) {
var rightmenu = document.getElementById("right-menu");
while(rightmenu.firstChild){
rightmenu.removeChild(rightmenu.firstChild);
}
[].forEach.call(document.getElementById(file).children,
function(custompaddingchild) {
/* searching for h1 and adding menu items happens here */
}
);
The problem arises when the DOM elements are not loaded yet, as when the page loads. Since there are no ElementsById(file) in the document element until the page is completely rendered, it fails to add the menu items onload.
I have tried adding an EventListener on the "load" event of the window and on the document, I have tried executing the function on the end of the body of the main page, and on the on onload= argument of <body> (which runs even before the subpages are captured, leaving me with a blank page instead of the actual content), but as it seems, none of them seems to happen after the page is completely loaded.
Adding a 2 second delay before running the functions is not an effective solution. Besides, adding a delay to the onload function will not affect the result, and will only increase loading time by two seconds.
Clicking any of the menues which update the menues work as intended. The only problem is onload.
<div class="menu-item" onclick="setVisible('personalinfo');"><span>Personal information</span></div>
How can I make sure the page delays the setVisible() function until after the page is rendered? All the sources I've found claim the "load" event is triggered after the page is rendered, but it doesn't seem to be triggered in my case. The DOMContentLoaded event isn't triggered either, but I suspect I don't want this one. The click event, or a scroll event on the window, in contrast, do trigger correctly.
Mozilla, Window: load event
Javascript.info, Page: DOMContentLoaded, load, beforeunload, unload
Edit: As per request, here is loadContent():
function loadContent(file) {
var request = new XMLHttpRequest();
request.open("GET", file+".html?_=" + new Date().getTime());
request.onreadystatechange=function(){
var loadedcontent = request.responseText;
document.getElementById(file).innerHTML = loadedcontent;
}
request.send();
}
Edit 2:
Full code is available at https://github.com/mazunki/portfolioweb-stackoverflowquestion
You need to use promises: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Try this
function loadContent(file) {
return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest();
request.open("GET", file+".html?_=" + new Date().getTime());
request.onreadystatechange=function(){
var loadedcontent = request.responseText;
document.getElementById(file).innerHTML = loadedcontent;
resolve();
}
request.send();
});
}
window.onload = function(){
// when you finish all the content loading
Promise.all([
loadContent("personalinfo"),
loadContent("academicalinfo"),
loadContent("employmentinfo")
]).then(function() {
// Load menu
setVisible("academicalinfo");
/*setMenues("academicalinfo");*/
})
}
Sorry, but you tried to use the "library" https://github.com/ded/domready ? I think that is the simpliest solutuion for you.
Then you code would be:
function loadMenues(file) {
domready(function () {
var rightmenu = document.getElementById("right-menu");
while(rightmenu.firstChild){
rightmenu.removeChild(rightmenu.firstChild);
}
[].forEach.call(document.getElementById(file).children,
function(custompaddingchild) {/* searching for h1 and adding menu items happens here */ }
);
})
}
While this only stands as a fallback solution, and is not reliable over slow network connections, I solved it by placing the following inside the menuhandling.js file, called with <script src="menuhandling.js" type="text/javascript" defer></script>:
setTimeout(function(){
setVisible("personalinfo")
/*setMenues("personalinfo")*/
},500) // half a second
loadContent() is called for all files in stackhandling.js, with no delay, and not document.onload nor window.onload.
I have a blank page with an iframe that displays a form from an external domain outside my control. I'm trying to write a bit of Javascript/jQuery that will close the window after the form is submitted.
Here's my code:
<body>
<script>
$('iframe input[type="submit"]').on('click', function () {
window.close();
});
</script>
<iframe src="SomeOtherDomain.com"></iframe>
</body>
Nothing happens when I click the button though. What am I doing wrong?
EDIT:
I'm not sure if it makes a difference or not but it looks like the iframe calls a second iframe... I've got an iframe inside an iframe.
I believe you need to provide some time(100 ms) to submit the form data. Please try this by calling the deleteIframeTimer
function deleteIframeTimer(){
var t = setTimeout("deleteIframe()", 100);
}
function deleteIframe() {
var iframe = parent.document.getElementById("myframe");
iframe.parentNode.removeChild(iframe);
}
So long as your iframe src is from the same domain this will work:
$(document).ready(function () {
var f = $('#myframe')[0];
var win = f.contentWindow;
//Created test environment in IFrame with ID "myframe"
$(win.document.body).append('<form><input type="submit" value="click me"/></form>');
$(win.document).on('submit', function () {
setTimeout(function () { $(f).remove(); }, 1000)
});
});
Simply remove the element but remember you can't get the contentDocument from an iframe that is not of the same domain.
Working solution:
https://jsfiddle.net/f3eayurw/
I want to load stackoverflow page and then raise the alert, strictly one after the other, without using frameworks like jQuery etc.
I have gone through the answers here and visited this too.
I ran the following in browser console. The page loads but the alert is not raised. I am using chrome in windows 8.1.
Try #1:
window.location.href = 'https://stackoverflow.com/';
window.onload = function () { alert("It's loaded!") }
Try #2:
window.location.href = 'https://stackoverflow.com/';
if(document.readyState === "complete") {
//Already loaded!
window.onload = function () { alert("It's loaded!") }
}
else {
//Add onload or DOMContentLoaded event listeners here: for example,
window.addEventListener("onload", function () {/* your code here */}, false);
//or
//document.addEventListener("DOMContentLoaded", function () {/* code */}, false);
}
Try #3:
window.location.href = 'https://stackoverflow.com/';
var everythingLoaded = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
clearInterval(everythingLoaded);
alert("It's loaded!");
}
}, 1000);
Try #4:
Tried setTimeout() too but doesn't work either.
I have tried above examples with window.location.replace() also.
How do I make this work?
P.S: I am novice with javascript. The above codes are not mine but I am just trying to work them out. I don't claim to have understood them completely either.
As Barmar pointed out this is not possible. The new page load will remove all JavaScript from the old page. Some alternatives are:
You can open the new page or in a new tab using the window.open api and attach an event handler.
You can load the page inside a frame (if it doesn't have any restrictions preventing that) and add a load event to the frame.
You can load the page using XMLHttpRequest (or a library of your choice) and insert the result into a <div> though not all of it will probably work.
You don't say what you want to do once the page has loaded. In most cases (generally unless you own the second page) it will not be possible to access any information on the second page.
<script type="text/javascript">
function init() {
document.write("www.sabah.com.tr opened..")
}
function start() {
var myWin = window.open("http://www.sabah.com.tr","_blank");
myWin.onload = init; // i think the poroblem is here..
}
setTimeout(start, 5*1000);
</script>
i want to call init function when my new page loaded but there is a problem.. init function didnt call when page loaded.. so how can i call init function?
There are several problems with that code:
The function will be run in the scope of the current page, not the newly opened page.
You can't use document.write after the page has loaded, that will scrap the page and replace it with the string specified.
If the page is loaded from a different domain, you can't access it in any way.
unless the URL you are opening is the same domain, you do not have access to the newly created window object.
Try opening the window first with an empty URL, then performing the operation/attaching the handler, and then loading the content (mywin.location = ...).
Try trigger function
myWin.onload=$('#form_id').trigger('init');
Is there a way to capture when the contents of an iframe have fully loaded from the parent page?
<iframe> elements have a load event for that.
How you listen to that event is up to you, but generally the best way is to:
1) create your iframe programatically
It makes sure your load listener is always called by attaching it before the iframe starts loading.
<script>
var iframe = document.createElement('iframe');
iframe.onload = function() { alert('myframe is loaded'); }; // before setting 'src'
iframe.src = '...';
document.body.appendChild(iframe); // add it to wherever you need it in the document
</script>
2) inline javascript, is another way that you can use inside your HTML markup.
<script>
function onMyFrameLoad() {
alert('myframe is loaded');
};
</script>
<iframe id="myframe" src="..." onload="onMyFrameLoad(this)"></iframe>
3) You may also attach the event listener after the element, inside a <script> tag, but keep in mind that in this case, there is a slight chance that the iframe is already loaded by the time you get to adding your listener. Therefore it's possible that it will not be called (e.g. if the iframe is very very fast, or coming from cache).
<iframe id="myframe" src="..."></iframe>
<script>
document.getElementById('myframe').onload = function() {
alert('myframe is loaded');
};
</script>
Also see my other answer about which elements can also fire this type of load event
Neither of the above answers worked for me, however this did
UPDATE:
As #doppleganger pointed out below, load is gone as of jQuery 3.0, so here's an updated version that uses on. Please note this will actually work on jQuery 1.7+, so you can implement it this way even if you're not on jQuery 3.0 yet.
$('iframe').on('load', function() {
// do stuff
});
There is another consistent way (only for IE9+) in vanilla JavaScript for this:
const iframe = document.getElementById('iframe');
const handleLoad = () => console.log('loaded');
iframe.addEventListener('load', handleLoad, true)
And if you're interested in Observables this does the trick:
import { fromEvent } from 'rxjs';
const iframe = document.getElementById('iframe');
fromEvent(iframe, 'load').subscribe(() => console.log('loaded');
Note that the onload event doesn't seem to fire if the iframe is loaded when offscreen. This frequently occurs when using "Open in New Window" /w tabs.
Step 1: Add iframe in template.
<iframe id="uvIFrame" src="www.google.com"></iframe>
Step 2: Add load listener in Controller.
document.querySelector('iframe#uvIFrame').addEventListener('load', function () {
$scope.loading = false;
$scope.$apply();
});
You can also capture jquery ready event this way:
$('#iframeid').ready(function () {
//Everything you need.
});
Here is a working example:
http://jsfiddle.net/ZrFzF/