About Window onload, ondomready etc - javascript

From Geek Daily :
The onload event does not fire until every last piece of the page is loaded.
Now I have a inframe in my jsf application and I can not replace by any means, this iframe with any other jsf component. I am trying to set the scroll position of the scrollbar resides in that iframe to a particular coordinate when the iframe is loaded. I have tried this:
window.onLoad(onLoad);
function onLoad() {
var frames = window.parent.frames;
var iframe = frames['frameR'];
iframe.contentWindow.scrollTo(0, 200);
}
But it's not working. I placed an alert(iframe) after var iframe = frames['frameR']; and it was displaying a message [object Window] but iframe.contentWindow.scrollTo(0, 200); is not working at all.
Either I am doing something wrong or as all the jsf components are not rendered in the iframe, the iframe's scroll position can be set then.
Is there any way to achieve this functionality?
Is onLoad is the last event before render of all the components?

The method you are looking for is window.onload, note capitalisation.
It is best to set the frame's onload listener from the code going into the iframe. It can be done from the parent document, but if you wait for the main document's load event to make sure the iFrame exists, the iframe's load may have already fired.
You can also use a script element immediately below the iFrame to set it's onload property:
<iframe id="frameR" src="..."></iframe>
<script>
var el = document.getElementById('frameR');
if (el) el.onload = doStuff;
</script>

Related

Nested iframe css manipulation in javascript after load

My goal is to change a fill attribute in a polyline element in an svg sitting in a nested, same-domain, iframe.
When my page loads, I can see the content in the browser. In the chrome console, from javascript, I can access the nested iframe, and the div containing the svg.
document.querySelectorAll('iframe#my-frame')[0]
.contentDocument.querySelectorAll('iframe')[0]
.contentDocument.querySelector('#mydiv')
but the content of that div is evidently not in any dom that I can interrogate. The div is effectively empty, even though it's content is rendered in the browser.
<div id="mydiv"></div>
When I right-click > 'Inspect' the nested iframe, the devtools redirect to the body element of the iframe#document. I am now able to interrogate the div, and manipulate the svg elements' attributes. At this point I can no longer interrogate the parent page, because the window object is now the nested iframe itself--this is not unexpected.
But I can't reset window programmatically, I don't think, i.e., this doesn't work:
window = document.querySelectorAll('iframe#my-frame')[0].contentDocument.querySelectorAll('iframe')[0].contentWindow
Is there a way to programmatically change focus or window of the javascript running in the browser--what I assume is forcing the iframe content into the dom in order to manipulate a css attribute after page load? Remember this is not an iframe domain issue.
You can't access the iframe's content instantly
You need something like a load eventListener to wait until the <iframe> content is fully loaded.
const myFrame = document.querySelector("#my-frame");
myFrame.addEventListener("load", (e) => {
// content loaded - query and manipulate elements
let doc = myFrame.contentDocument;
let iframeSvg = doc.querySelector("svg");
let svgEl = iframeSvg.querySelector("rect");
svgEl.style.fill = "green";
});

How can I check if the contents inside an iframe is fully loaded and the src url is not down(404/not available) using angular?

I have an angular app which is having an iframe that loads a chat bot from an external url.I need to check if the url is fully loaded and the url is not down.
The iframe is initially not loaded on the dom and is only loaded after the user clicks on an icon.Since the iframe takes some time to load initially the iframe space will be empty.I tried showing a loader by setting it as background to the div that contains the iframe but the loader was always running even after the iframe is loaded.
Can somebody please guide me? Im new to angular.Im using agular 5.TIA
The simplest way to do this is to check onload events on iframe. ContentDocument of type Document, readonly, checks this frame contains, if there is any and it is available, or otherwise it will return null.
//Get reference of the iframe with reference variable and call
// onload event on it
iframe.onload = function(){
var that = $(this)[0];
try{
that.contentDocument;
}
catch(err){
//TODO
}
}

How do I run code inside an iFrame that was NOT defined in the iframe?

I need to run code as if it were running inside an iframe that is on the page, meaning that when I use window inside that code, it should use the iframe's window object. It is not an iframe I created, so my function is not defined inside it.
var myfunction = function () { // defined in parent, not in the iframe
console.log(window); // window here should be the iframe's window object, not the parent/
window.document.body.appendChild("Appending to iframe body");
}
// Need to somehow run this function inside the iframe
myfunction(); // as if I did this inside the iframe
I need this exact code to run inside the iframe, I know that I can use to fix this myself
frames["FrameName"].document.body.appendChild("Appending to iframe body");
but that won't fix my problem.
This is because I did not write the code myself, there is a module called Opentip that I use to create tool tips. I need to set a tooltip on an element inside the iframe; however, Opentip uses the window object in it's code to be able to create the tooltip properly.
So I need to run
Opentip(myelement, data);
as if I were running it inside the iframe, but without defining it inside the iframe.
So the Opentip function needs to use the iframe window, rather than the parent window.
The code provided is of course untested. This is answer is assuming:
OP circumstances are that the requirements of same origin policy are met.
OP cannot edit the child page directly.
OP cannot use Ajax.
Resources
Dyn-Web
Javascript injected into iframe of same origin not working
Injecting Javascript to Iframe
Snippet
//A//Ref to iframe
var iFrm = document.getElementById('iFrm')
//B//Listen for load event
iFrm.addEventListener('load', function(e) {
//C//Ref to iframe Window
var iWin = iFrm.contentWindow;
//D//Ref to iframe Document
var iDoc = iFrm.contentDocument? iFrm.contentDocument:iFrm.contentWindow.document;
//E//Ref element targeted by Opentip--replace {{>SEL<}} with appropriate selector
var iTgt = document.querySelector({{>SEL<}});
//F//Create, configure, deploy, and inject <script> tag to iframe <head>
var iNode = document.createElement(`script`);
iNode.src = "https://cdn.jsdelivr.net/opentip/2.4.6/opentip-native.min.js";
iDoc.head.appendChild(iNode);
//G//Call Opentip from iframe Window, and hopefully in iframe's context
iFrm.contentWindow.Opentip = function(iTgt, data);
}
/* Notes */
/*//F//Alternative to target iframe <head>:
window.frames["iFrm"].document.getElementsByTagName("head")[0];*/
/*//If not successful in accuirring iframe, try replacing all
"document." with "contentWindow", "contentDocument", or "contentWindow.document"*/
<iframe id="iFrm" name="iFrm" src="/"></iframe>
<!--Optionally you can add an onload event to the iframe itself
<iframe id="iFrm" name="iFrm" src="/"></iframe>
-->

Ensuring that onLoad of an IFRAME doesn't execute too soon

I just discovered that the source of my issues is that the parent HTML makes calls to controls in a child IFRAME but is too quick about that and, sometimes, the super onLoad attempts to do so before the sub onLoad had a chance to add stuff to the DOM.
What can I do about it?
I've tried to set up some kind of feed-back from onLoad in the child. Failed miserably with so many strange errors that they can be summarized by dude, just please don't.
I've tried to set up a delayer, which is ugly of epic proportions and not 100% reliable.
EDIT:
In onload I do this:
var stuff = getReferenceToStuff();
var someDiv = stuff.contentWindow.document.getElementById("someDiv");
someDiv.className = "classy";
The problem is that sometimes the reference someDiv is null and sometimes (often when I reload the page by F5), it points to the correct element. I know it's because the contents of the IFRAME are a bit slower.
So my questions is this. How can I ensure that onload is postponed until the embedded IFRAME component's onload ensures that it's been loaded and all the components are there?
The onLoad event isn't always working correctly on document. It works correctly on each element though.
var iframes = document.getElementsByTagName('iframe'),
counter = 0,
max = iframes.length;
[].forEach.call(iframes, iLoaded);
function iLoaded() {
if (++counter === max) {
callback();
}
}
function callback() {
// All the iframes are loaded
}
When using window.onload all content of the body, including content of the iframes and all other resources like images, should be loaded before the onload is fired. However, some browsers have had problems with timing on firing onload, i.e. different browsers trigger the event in different stage of page parsing.
If you're using DOMContentLoaded or jQuery's $(document).ready(), only the HTML of the main page is loaded, but some resources are still under work (including iframe's content loading). I'm not aware what happens if you attach an inline listener for the iframe element itself.
If there's timing problems, maybe not trigger the function needing iframe reference in main window at all. Instead invoke that function in main window in irame's window.onload. But even this won't tackle the problem, if you're using some asynchronous technique to populate the iframe. In this case you need to invoke the function in main window after all requests have been completed.
(Now you maybe also know, what are the codesnippets I'd like to see in your post : ) ).
I have 2 solutions to your problem:
If you are on HTML5, use window.postMessage. Just message from iFrame to the parent in the onload of iFrame. Parent should register handler in <script> tag, that appears before iFrame.
Add a callback function to window in the '' tag before iFrame. This function is called by iFrame when it's load is complete. Here is the basic template.
Here is the sample template:
<script>
window.iframeCallback = function(message) {
// first clear the temp function we added to the window
// It is a bad practice to corrupt the global namespace
delete window.iframeCallback;
// you do your work here
};
</script>
..
..
<!-- iFrame should appear after the above script-->
<iframe/>

How to force an iFrame to reload once it loads

I have numerous iframes that load specific content on my pages. Both the parent and iframe are on the same domain.
I have a scrollbar inside the iframe that doesn't seem to load correctly in all browsers. But when I refresh the iframe it loads perfect. I have no idea why it does this.
I have used the meta refresh, which works but I don't want the page to refresh constantly, just once.
The solution I'm looking for will reload the iFrame content after the iFrame is opened, with a minimal delay.
Edit
I realized that my page loads all of my iframes when the index is loaded. The iframes appear in a jQuery overlay, which is also loaded but visibility:hidden until called. So on this call is when I would want the iframe to be reloaded.
Could anyone help me come up with a Javascript function that reloads the iFrame when I click the link to the iFrame? I've gotten close but I know nothing about js and I keep falling short. I have a function that reloads the page, but I can't figure out how to get it called just once.
I have this so far:
<script type="text/javascript">
var pl;
var change;
pl=1;
function ifr() {
if (pl=1) {
document.location.reload([true]);
alert("Page Reloaded!");
change=1;
return change;
}
change+pl;
}
So basically it uses the document.location.reload which works to reload the page. I'm trying to then make pl change to something other than 1 so the function doesnt run again. I've been calling this JS from the body with onLoad.
All the leads on this went dead, but I did find a code snippet that worked. Not written by me, and I don't remember where it came from. Just posting to help someone should they ever have the same question.
<div class="overlay-content"> //Content container needed for CSS Styling
<div id="Reloader">
//iFrame will be reloaded into this div
</div>
//Script to reload the iframe when the page loads
<script>
function aboutReload() {
$("#Reloader").html('<iframe id="Reloader" height="355px" width="830px" scrolling="no" frameborder="0" src="about.html"></iframe>');
}
</script>
</div>
Basically just loads the iFrame source when the window with the iFrame opens, as opposed to the iFrame loading when the original page loads.
Beyond the scope of the original question, however this jQuery snippit works with cross domain iframe elements where the contentDocument.location.reload(true) method won't due to sandboxing.
//assumes 'this' is the iframe you want to reload.
$(this).replaceWith($(this).clone()); //Force a reload
Basically it replaces the whole iframe element with a copy of itself. We're using it to force resize embedded 3rd party "dumb" widgets like video players that don't notice when their size changes.
On the iframe element itself, set an onload:
iframe.onload = function() {this.contentWindow.location.reload(); this.onload = null;};
(Only works if the iframe's location is in the same domain as the main page)
Here's a complete solution to the original question:
<iframe onload="reloadOnce(this)" src="test2.html"></iframe>
<script>
var iframeLoadCount = 0;
function reloadOnce(iframe) {
iframeLoadCount ++;
if (iframeLoadCount <= 1) {
iframe.contentWindow.location.reload();
console.log("reload()");
}
}
</script>
The updated question is not really clear (what's "the link to the iFrame" and where is it in your snippet?), but you have a few issues with the code:
"calling this JS from the body with onLoad", assuming you mean an iframe's body, means the variable you're hoping to use to avoid infinite reloading will get clobbered along with the rest of the iframe's page when it's reloaded. You need to either load a slightly different URL in the iframe (and check the URL on iframe's onload before reloading) or put the flag variable in the outer page (and access it with parent.variableName - that should work I think)
if (pl=1) { should use ==, as = is always an assignment.
change+pl; has no effect.

Categories