Access iframe after it just was appended - javascript

My version that does not work:
$(window).on('load', function() {
var $iframe = $("<iframe>",
{id:"up2europe",
marginheight:"5",
marginwidth:"5",
src:"https://www.up2europe.eu/widget/go/181d4bdc08289da3d78b79ee5f9e7e2d"
});
$(".sidebar__right:first").append($iframe).on('load', function()
alert(document.getElementbyId("#up2europe").documentElement.title);
});
});
So... I'm trying to access the title of the iframe...to check if it was loaded properly.

There are more a couple of things wrong with your code:
You use $("...").append($iframe) which returns $("...") after the iframe is appended. That means that your load event is attached to $("...") rather than the iframe which is the logical thing to do in this case. To achieve that use $iframe.appendTo("..."), so that the return value of the method is $iframe.
You use getElementbyId inside the aforementioned load event listener which is basically the wrong way to write getElementById.
The argument you pass to alert inside the event listener isn't an effective way to get the title of the document of the iframe.
So, by correcting the above errors the code becomes:
$(window).on('load', function() {
/* Create the iframe. */
var $iframe = $("<iframe>", {
id: "up2europe",
marginheight: "5",
marginwidth: "5",
src: "https://www.up2europe.eu/widget/go/181d4bdc08289da3d78b79ee5f9e7e2d"
});
/* Using 'appendTo' ensures we add the 'load' event listener to the iframe. */
$iframe.appendTo(".sidebar__right:first").on('load', function() {
/* 'this' refers to the iframe. */
alert(this.contentDocument.title);
});
Note: In order to actually get the title of the document of the iframe both the content of the iframe and the parent window must be served by the same domain, otherwise your code will fail due to the Same-Origin Policy.
Snippet:
(Getting the document title fails due to the same-origin policy; read the error thrown.)
$(window).on('load', function() {
/* Create the iframe. */
var $iframe = $("<iframe>", {
id: "up2europe",
marginheight: "5",
marginwidth: "5",
src: "https://www.up2europe.eu/widget/go/181d4bdc08289da3d78b79ee5f9e7e2d"
});
/* Using 'appendTo' ensures we add the 'load' event listener to the iframe. */
$iframe.appendTo(".sidebar__right:first").on('load', function() {
/* 'this' refers to the iframe. */
alert(this.contentDocument.title);
});
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class = "sidebar__right"></div>
Resource: You can read more about the Same-Origin Policy here.
If you only want to check whether the content of an iframe has loaded, you don't need to check its document's title, but rather simply attach a load event`:
$iframe.on("load", function () {
// code to execute after it's loaded.
});

I believe this is the right method to add an element with jQuery. Check out from this LINK.
Code:
$(window).on('load', function() {
var iframe = document.createElement('iframe');
$(iframe).css({'marginheight':'5px','marginwidth':'5px'});
$(iframe).attr({'src':'https://www.up2europe.eu/widget/go/181d4bdc08289da3d78b79ee5f9e7e2d','id':'up2europe','title':'Im iframe'});
$(".sidebar__right").append(iframe);
$(iframe).ready(function(){
alert($(iframe).attr('title'));
});
});

Related

Permission denied when implementing JavaScript within an iframe from the parent page

I am trying to implement JavaScript within an iframe from the parent page. I read Invoking JavaScript code in an iframe from the parent page, however, get the following error.
Error: Permission denied to access property "showIt"
document.getElementById('targetFrame').contentWindow.showIt();
I've tried implementing this both on jsfiddle as well as my server (don't know if it matters, but it uses https), but get the same results. I've also tried removing the $(function(){}) wrapper on the child iframe, but no change.
My actual application is described below.
How can this be accomplished?
My Application:
I have my parent page https://jsfiddle.net/5f4ct5ph/6/) which contains an iframe.
<iframe width="100%" height="300" src="https://jsfiddle.net/5f4ct5ph/5/embedded/result/" id="targetFrame"></iframe>
<button id="show">Show</button>
<button id="hide">Hide</button>
$(function () {
$('#show').click(function () {
document.getElementById('targetFrame').contentWindow.showIt();
});
$('#hide').click(function () {
document.getElementById('targetFrame').contentWindow.hideIt();
});
});
The iframe page (https://jsfiddle.net/5f4ct5ph/5/) contains a tinymce editor.
<div id="content">Initial content goes here</div>
#content {height:200px;width:400px;border: 1px solid;}
$(function () {
tinymce.init({
selector: "#content",
width : 400,
height: 200,
setup : function(ed) {
ed.on('init', function(e) {
e.target.hide();
});
}
});
function showIt() {
tinymce.get('content').show();
};
function hideIt() {
tinymce.get('content').hide();
};
});
fiddle.jshell.net (the parent document domain) is different to jsfiddle.net (your iframe domain).
I've changed your code to point to the jshell.net url instead (You can get this by using the URL of the frame in the bottom right of jsfiddle rather than the address bar).
https://jsfiddle.net/GarryPas/5f4ct5ph/7/
showIt() and hideIt() don't seem to be defined (because they are inside an anonymous function). Change this:
$(function () {
...
function showIt() {
tinymce.get('content').show();
};
function hideIt() {
tinymce.get('content').hide();
};
});
To this:
$(function () {
...
});
function showIt() {
tinymce.get('content').show();
}
function hideIt() {
tinymce.get('content').hide();
}
Then remove my alerts and put back your original code which I commented out.
Normally, if iframe and parent are on same domain, it should work, but there are restriction to communication from window to window. You can try using postMessage, like this:
In your parent page, in the click event, instead of calling the function directly, you could do this:
child_window = document.getElementById('targetFrame').contentWindow;
child_window.postMessage("showit" or "hideit", your_domain);
The in you iframe:
window.addEventListener("message", check_message, false);
function check_message(event){
switch(event.data){
case "showit":
showIt();
break;
case "hideit":
hideIt();
break;
default:
breaks;
}
Make sure your functions showIt and hideIt are available from where you call check_message.
Again, there may be another problem, it's hard to tell with the embedded jsfiddle, but in any case, when dealing with iframes and javascript, postMessage is often more flexible and secure than accessing functions and variables directly.

Callback when embedded Google Calendar has loaded

I am loading an embedded Google calendar the standard way:
<iframe id="calendar" src="https://www.google.com/calendar/embed...></iframe>
I want to apply some style changes after the load event using jQuery, e.g.:
$('iframe#calendar').contents().find('.blahblah').css("display", "none");
I presumably need to use an interval loop:
var interval_calendar = setInterval(function(){
if ($('#calendar').SOMETHING) {
clearInterval(interval_calendar);
$('iframe#calendar').contents().find('.blahblah').css("display", "none");
}
} ,200);
How can I check that the calendar is loaded? Basically, I need the SOMETHING.
Thanks.
Try
var iframe = $("<iframe>", {
"id" : "calendar",
"src" : "https://www.google.com/calendar/embed...",
"target" : "_top"
})
// `iframe` `load` `event`
.on("load", function (e) {
$(e.target)
.contents()
.find(".blablah")
.css("display", "none");
return false
});
// $(element).append($(iframe))
jsfiddle http://jsfiddle.net/guest271314/a3UL5/
You could use load to execute a function when your iframe is done loading...
$("#calendar").load( function () {
// do something once the iframe is loaded
});
I can not find any good JavaScript Event solution, but you can use your idea:
var interval_calendar = setInterval(function(){
if ($('#calendarTitle').html()!= "") {
clearInterval(interval_calendar);
alert();
}
} ,200);
The calendarTitle id is shown on the page only when the whole calendar loaded.
In the other hand I don't know if you can access the calendar attributes, as they are protected. You can only access the iframe content that was loaded from your host. With an alert()
it works, but if you try to access any inside content you will get a SecurityError message into console.

Call function inside iframe

im trying to do something here. I have a document which I set an array. Then, jquery takes this array and appends an iframe for each value:
<script>
var containers = new Array("test1", "test2");
</script>
This results is 2 iframes, identified by id with his name. Ok. perfect, working. Then, inside of each iframe, it calls a document. Inside this document, I have a function called play().
I am testing play() by returning an alert. Whenever I click on a button, it works:
$("#viewport .next").click(function(){
document.getElementById(containers[current]).contentWindow.play();
});
This works. Perfectly. But I it put this function to trigger on document ready, it doesnt works.
$(function() {
document.getElementById(containers[current]).contentWindow.play();
});
It returns to me:
Uncaught TypeError: Object [object Window] has no method 'play'
Whats am I doing wrong guys?
Thanks!
EDIT
Tried to apply onload on iframe. Didnt work.
var initialFrame = containers[qual];
initialFrame.onload = function() {
document.getElementById(initialFrame).contentWindow.play();
};
EDIT2
For some reason, it started working. Thanks!
Wait for the load event of the iframe first.
initialFrame.addEventListener("load", function() {
initialFrame.contentWindow.play();
});
You would generally listen for the iframe's load event like this:
$("#iframe").load(function(){
// iframe is loaded
});
... but I had trouble with this recently so I instead checked for the contents of the iframe over and over until it had loaded, like this:
function loadFrame() {
if($('body', $('#iframe').contents()).length != 1) {
setTimeout(loadFrame,500);
}
else {
// iframe is loaded
}
};
loadFrame();
Not sure if this is the best solution, but it works.

jQuery iframe load() event?

Does anyone know if there is such a thing?
I have a iframe that's being inserted with $.ajax() and I want to do some stuff after the contents from the iframe are completely loaded:
....
success: function(html){ // <-- html is the IFRAME (#theiframe)
$(this).html(html); // $(this) is the container element
$(this).show();
$('#theiframe').load(function(){
alert('loaded!');
}
....
it works, but I see the IFRAME is loaded twice (the alert also shows twice).
use iframe onload event
$('#theiframe').on("load", function() {
alert(1);
});
If possible, you'd be better off handling the load event within the iframe's document and calling out to a function in the containing document. This has the advantage of working in all browsers and only running once.
In the main document:
function iframeLoaded() {
alert("Iframe loaded!");
}
In the iframe document:
window.onload = function() {
parent.iframeLoaded();
}
Along the lines of Tim Down's answer but leveraging jQuery (mentioned by the OP) and loosely coupling the containing page and the iframe, you could do the following:
In the iframe:
<script>
$(function() {
var w = window;
if (w.frameElement != null
&& w.frameElement.nodeName === "IFRAME"
&& w.parent.jQuery) {
w.parent.jQuery(w.parent.document).trigger('iframeready');
}
});
</script>
In the containing page:
<script>
function myHandler() {
alert('iframe (almost) loaded');
}
$(document).on('iframeready', myHandler);
</script>
The iframe fires an event on the (potentially existing) parent window's document - please beware that the parent document needs a jQuery instance of itself for this to work. Then, in the parent window you attach a handler to react to that event.
This solution has the advantage of not breaking when the containing page does not contain the expected load handler. More generally speaking, it shouldn't be the concern of the iframe to know its surrounding environment.
Please note, that we're leveraging the DOM ready event to fire the event - which should be suitable for most use cases. If it's not, simply attach the event trigger line to the window's load event like so:
$(window).on('load', function() { ... });
That's the same behavior I've seen: iframe's load() will fire first on an empty iframe, then the second time when your page is loaded.
Edit: Hmm, interesting. You could increment a counter in your event handler, and a) ignore the first load event, or b) ignore any duplicate load event.
Without code in iframe + animate:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
function resizeIframe(obj) {
jQuery(document).ready(function($) {
$(obj).animate({height: obj.contentWindow.document.body.scrollHeight + 'px'}, 500)
});
}
</script>
<iframe width="100%" src="iframe.html" height="0" frameborder="0" scrolling="no" onload="resizeIframe(this)" >
You may use the jquery's Contents method to get the content of the iframe.
If you want it to be more generic and independent, you can use cookie. Iframe content can set a cookie. With jquery.cookie and a timer (or in this case javascript timer), you can check if the cookie is set each second or so.
//token should be a unique random value which is also sent to ifame to get set
iframeLoadCheckTimer = window.setInterval(function () {
cookieValue = $.cookie('iframeToken');
if (cookieValue == token)
{
window.clearInterval(iframeLoadCheckTimer );
$.cookie('iframeToken', null, {
expires: 1,
path: '/'
});
}
}, 1000);

Define an event on iFrame element with jQuery

I try to define a live event on img tags store on a iFrame. For example, I would like obtain a simple javascript alert box when I click a image on my iFrame.
Do you know how i can define the events for the iFrame, because I would like to put a thing like $('img').live("click",function().... but only for the elements on iFrame.
Please note: img tags are dynamically added on my iFrame after page load.
Thanks for your help.
Nicolas
You can do it if you
make sure that the page in the iframe has its own copy of jQuery loaded [ed.: only really necessary for jQuery operations internal to the frame's page itself]
from the outer document, work into the iframe document like this:
$('#iframeId').contents().find('img') // ...
The other solutions here are largely myopic, as what you are trying to do is fairly complicated in the underlying javascript.
I'd suggest using jquery context as well - and I'd strongly suggest waiting for the iframe to totally load or else none of the previous suggestions could work anyway...
$("#frame").ready(function () { //wait for the frame to load
$('img', frames['frame'].document).bind("click",function(){
alert('I clicked this img!');
});
});
This should generally work UNLESS you update the iframe or refresh it, in which case all the event bindings will fail... and worse yet the .live events don't appear to be supported in iframes - at least not for me.
$("iframe").contents().find("img")
This will target images within the iFrame. But be aware that jquery will only traverse the iFrame if it is not a violation of the browser's (or jquery's) cross-site policy.
That means if the iframe is google.com, you can't touch the inner DOM.
jQuery.bind() won't work with external documents. At least in jQuery 1.6.2.
However you can bind to DOM events:
$("iframe").contents().find("img").onclick = function() { // do your staff here };
If you do not have full list of images at the moment, you can use events propogation:
$("iframe").contents().find("body").onclick = function() { // do your staff here };
It will work event with custom events:
$("iframe").contents().find("body").onmyevent = function() { // do your staff here };
One more thing to remember... frame content is loaded asynchronously. So bind your handlers AFTER your iframe content is loaded:
var $iframe = $("iframe");
$iframe.bind("load", null, funcion(e) {
$iframe.contents().find("body").onclick = function() { // do your staff here };
});
For more complicated cases handle your images clicks inside iframe, and trigger your custom events that you can later handle on the body level. Especially if you have totally dynamic content and want to bind to 'live' events inside iframe.
you can fire event innner like this:
parent.$('#dlg').trigger('onTitle');
then hold event like this:
$('#dlg').bind('onTitle', function(){ alert(); });
this worked for me. NB: make sure you have referenced jquery library on the iframe page as well.
$(document).ready(function(){
$('#iframeid').load(function(){ //make sure that all elements finish loading
$('#iframeid').contents().find('img').live({
click: function(){
alert('clicked img');
}
});
});
});

Categories

Resources