Accessing a javascript function in a nested iframe in IE - javascript

I currently have a page structure that consists of a page(Parent) that includes an iframe(iframe0) and inside that iframe I have another iframe(iframe1). In iframe1 I have a javascript function that I am trying to call from Parent. In Firefox/Chrome/Safari I am able to call this function with the following code:
frames["iframe0"]["iframe1"].functionName();
However, in Internet Explorer the above code does not work and it returns the error "Object doesn't support this property or method". I have tried some other ways to access the method with them all returning the same error.
window.frames.iframe0[iframe1].functionName();
window.iframe0.iframe1.functionName();
window.frames.iframe0.frames.iframe1.functionName();
I even tried calling a function in iframe0 that called the function in iframe1 and that didn't even work.
Anyone have any idea on how to access a javascript function that is nested in an iframe that is 2 levels deep?
Thanks.
Update:
After looking into the problem further, I have found that the problem I am dealing with is not related what I have asked. The answer ylebre gave below answers the question I have asked, and there for will me marked as the answer. I will probably start another question describing my problem in more detail.

I've provided an example using 3 HTML files. The outermost is test.html which has an iframe containing iframe1.html. In turn, iframe1.html contains an iframe containing iframe2.html. I'm hoping this is the kind of setup that you have in mind.
Basicly, you can call the iframe function using iframe.contentWindow.myfunc();
Using contentWindow.document you can then access the second level iframe.
The example function 'doit()' calls a function in the parent, first iframe and second iframe.
Hope this helps!
<!------- test.html -------->
<html>
<head>
<script type="text/javascript">
function parent_function() {
alert('parent');
}
function doit() {
parent_function();
document.getElementsByTagName('iframe')[0].contentWindow.iframe1_function();
document.getElementsByTagName('iframe')[0].contentWindow.document.getElementsByTagName('iframe')[0].contentWindow.iframe2_function();
}
</script>
</head>
<body>
main
do it
<iframe src='iframe1.html'>
</body>
</html>
<!------- iframe1.html -------->
<html>
<head>
<script type="text/javascript">
function iframe1_function() {
alert('iframe1');
}
</script>
</head>
<body>
frame1
<iframe src='iframe2.html'>
</body>
</html>
<!------- iframe2.html -------->
<html>
<head>
<script type="text/javascript">
function iframe2_function() {
alert('iframe2');
}
</script>
</head>
<body>
frame2
</body>
</html>

A fast way to select an iframe is to select it in the dom explorer, then in the js console, you can run $0.contentWindow.myFunction()

Related

How to add a javascript function inside the body of iframe

i have a html file with iframe and button in it, Is there a way to add a javascript function inside the body of iframe after I click the button?. Here is my code. Thanks
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script>
function callMe() {
var frame = $('iframe'),
contents = frame.contents(),
body = contents.find('body');
var script2 = document.createElement("script");
script2.type = "text/javascript";
script2.text = " function setEmployeeId(){var employeeId = 0;};"
$(body).append(script2);
};
</script>
<title>sample</title>
</head>
<body>
<iframe src="page2.html">
</iframe>
<button onClick="callMe();">click</button>
</body>
</html>
The result I want is to be like this.
<html>
<head>
<title>sample</title>
</head>
<body>
<iframe>
<html>
<head>
<title></title>
</head>
<body>
<script>
function setemployeeId() {
var employeeId = 0;
};
</script>
</body>
</html>
</iframe>
</body>
</html>
Hopefully you can clarify a few things for me as we go, but I think I have some bad news for you.
Any content that is loaded in an iframe cannot truly edited unless you own the page that is being loaded, in that case you can just bake in whatever you need into the loaded page.
HOWEVER!
You can still access elements in the iframe by using the contentWindow attribute. That is all laid out for you here: How to pick element inside iframe using document.getElementById
Once you've got the element you want to work with, you can create a function in the parent window and then add a call to the parent window's function using window.parent. That's outlined here: Calling a parent window function from an iframe
So if you wanted to make a button in an iframe alter the contents of the iframe you could use
var elem = document.getElementById('myframe1').contentWindow.document.getElementById('myButton')
and then create a function in your parent window
function changeIt(){
document.getElementById('thingToChangeInIframe_ItsIDintheIframe').property = 'value';
}
and append it to the button with the code
elem.setAttribute('onclick', 'changeIt();');
If you have any clarifications to what you need just comment and we'll work those out. I'm sorry this doesn't use much jQuery but that's not really my forte, but I think the pure javascript is relatively self explanatory.
EDIT: I should clarify that if the iframe is on another domain then your options are pretty much all eliminated. For security reasons you can't mess with the settings on other people's pages when you load them in an iframe.

Working of an iframe

Here is a snippet of code that uses a script to populate the contents of an iframe:
<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
$(document).ready(function() {
$('iframe').contents().find('body').html('<script>console.log($("div"))<\/script>');
});
</script>
</head>
<body>
<div>Test</div>
<iframe />
</body>
</html>
When executed we see that the iframe has access to the parent's DOM and we see the div being selected by the jQuery selector. The iframe does not have jQuery included but it can access the jQuery object of the parent.
However if we write the same thing via an iframe src inclusion, the behavior is different:
test.html:
<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</head>
<body>
<div>Test</div>
<iframe src="another.html">
</body>
</html>
another.html:
<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
$(document).ready(function() {
console.log($('div'));
});
</script>
</head>
<body>
</body>
</html>
We now see that the page does not list any divs. Further, if we don't include the jQuery js in the child page, it would throw an error.
Note that both pages are in the same domain, so we don't have same-origin policy issues.
My questions are:
Why is the behavior different for the 2 - a. manipulating the iframe DOM from the parent and b. including the iframe content via a src?
Is there a way to make the parent have access to the child and NOT vice-versa?
So the first bit of code gives 1 and the second bit of code gives 0?
That seems correct.
In the first example $ is bound to the parent frame. In the second example, since you have a new instance of jQuery it's bound to the iframe.
In:
$(document).ready(function() {
$('iframe').contents().find('body').html('<script>console.log($("div"))<\/script>');
});
jQuery's html function will do an eval on the script-part of the inserted HTML. That eval will run in the scope of the parent so it uses the parent instance of $.
If you just moved the script to the iframe it will fail because it doesn't have access to $.

Can't import javascript code with innerHTML

I've built a webpage that is basically a main-page with a div that is filled with different pages by using AJAX. This basically works by loading pages into a div by using innerHTML. One problem I ran into was when a page with javascript is loaded into that div all of the other code runs fine; just the javascript doesnt work.
Main-page(index.php):
<html>
<head>
<script type="text/java">
////bunch of functions////
////Ends up that page_request on this instance is 'graph.php'////
document.getElementById('mydiv').innerHTML=page_request.responseText
</script>
</head>
<body>
<div id="mydiv"><div>
</body>
</html>
Child-page(loaded in div(graph.php)):
<html>
<head>
<link rel="stylesheet" href="mystyle.css" type="text/css" media="screen" />
<script src="other_stuff.js"></script>
</head>
<body>
<script>
///bunch of script////
</script>
</body>
</html>
Now when loading the page itself (opening graph.php) I notice that everything works fine; it is just when I import graph.php to index.php through innerHTML into my div it does not work (no errors just nothing is shown). I have read through many other posts and guides and did not come up with any distictive solution; thinks I have seen were:
Put eval() around my code [I saw on a guide that this could lead
to malicious user attacks].
Create the scripts on the main page then just import the data using:
document.createElement() and .parentNode.insertBefore()
Create a listener and call the functions when I open graph.php
And this good example
Even though I am not 100% sure how this example could work because I have php populate information for the javascript to collect and then make my graph on graph.php; so if I put that function into index.php the php will already be loaded so I would have to refresh the page or call them to update information somehow. Just for some context I am ok at php but I am new and struggle with javascript so I do not know what solution would fit my situation or work the best. Any tips/examples would be greatly appreciated, thank you for your time.
From you code snippets it seems you're looking to embed complete pages within the main page. If that's the case, a more straightforward approach would be to use an iframe element instead.
For example:
...
<div id="main-page-container">
<iframe src="some-path/graph.php" scrolling="no" frameborder="no"></iframe>
</div>
...
See reference and usage example.
I would suggest using jQuery's .load() function for this.
Take a look here: jQuery API
Older browsers such as IE8 and below don't allow you insert a string that contains javascript and execute it, in any form.
Take for instance:
function addScriptText(js_code) {
var element = document.createElement("script");
element.innerHTML = js_code;
document.head.appendChild(element);
}
will not work in IE8 and below.
You must use eval to accomplish this:
function addScriptText(js_code) {
window.eval.call(window, js_code);
}
Otherwise you need to dynamically request an external js file such as:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "externalScript.js";
document.getElementsByTagName("head")[0].appendChild(script);
Note: The page you are loading (page2.html in this example) must be on the same domain as the page that is loading it (page1.html in this example)
Working solution with jQuery:
Page 1:
<!DOCTYPE html>
<html>
<head>
<title>Page 1</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("#page2").load("page2.html");
});
</script>
</head>
<body>
<h1>Page 1 Header</h1>
<div id="page2">
</div>
</body>
</html>
Page 2:
<h2>Page 2 Header</h2>
<script type="text/javascript">
alert("Page 2 loaded and javascript executed!");
</script>

How to call a JavaScript function, declared in <head>, in the body when I want to call it

I have a working JavaScript function declared in the head of an HTML page. I know how to create a button and call the function when the user clicks the button. I want to call it myself some where on the page:
myfunction();
How do I do it?
You can call it like that:
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript">
var person = { name: 'Joe Blow' };
function myfunction() {
document.write(person.name);
}
</script>
</head>
<body>
<script type="text/javascript">
myfunction();
</script>
</body>
</html>
The result should be page with the only content: Joe Blow
Look here: http://jsfiddle.net/HWreP/
Best regards!
I'm not sure what you mean by "myself".
Any JavaScript function can be called by an event, but you must have some sort of event to trigger it.
e.g. On page load:
<body onload="myfunction();">
Or on mouseover:
<table onmouseover="myfunction();">
As a result the first question is, "What do you want to do to cause the function to execute?"
After you determine that it will be much easier to give you a direct answer.
Just drop
<script>
myfunction();
</script>
in the body where you want it to be called, understanding that when the page loads and the browser reaches that point, that's when the call will occur.
You can also put the JavaScript code in script tags, rather than a separate function. <script>//JS Code</script> This way the code will get executes on Page Load.

javascript tag trigger - code position on page

i use that tag to alert me when a tag has been shows up
<html>
<head>
</head>
<body>
<script type="text/javascript">
document.getElementsByTagName('iframe')[0].onload = function() {
alert('loaded');
}
</script>
<iframe></iframe>
</body>
</html>
strange , since this code working :
<html>
<head>
</head>
<body>
<iframe></iframe>
<script type="text/javascript">
document.getElementsByTagName('iframe')[0].onload = function() {
alert('loaded');
}
</script>
</body>
</html>
why the Js need to under the tag to work?
what's the problem here?
Because the code in a script tag is executed immediately. And in the first example the iframe doesn't exist at that time. But what you can do is to wrap you code into an onload (for the main page) event. E.g.:
window.onload = function() {
//your code
}
Then it doesn't matter where the code is placed.
Iframe tag does not exist at the moment you are trying to access it.
You may check that by simply alerting array length, like
alert(document.getElementsByTagName('iframe'));
Have you thought about executing your javascript after the page is loaded? You may use some frameworks like jQuery to facilitate crossbrowser issues. Or just put all your javascript code to the very bottom of body.

Categories