Can't catch jQuery DOM Event that is inside an iframe - javascript

I have an <iframe> that contains a particular webpage. In that iframed webpage, the following Event trigger is setup via jQuery:
console.log($('.myElement').trigger('testEvent'));
This event is triggered every ~20 seconds.
Back on the parent page, when the page first loads, I setup an Event Handler for the event:
$('iframe').load(function(){
console.log("Iframe loaded");
$('iframe').contents().find('.myElement').on('testEvent', function(e) {
console.log("Event Fired!", e);
});
});
So once the iframe is loaded, the event handler is setup.
For some reason, the event handler never runs. The event is definitely being triggered because I see the result of the console.log() in the console. I don't see any errors or anything in the console.
Also I can manually trigger it and see that the handler is working:
$('iframe').contents().find('.myElement').trigger('testEvent');
What am I doing wrong here?

I figured it out. So the parent document and the iframe content document each have their own jQuery instance. Apparently it's not (easily?) possible for one instance of jQuery to listen for events triggered by the other instance of jQuery. My problem in the parent document was this:
$('iframe').contents().find('.myElement').on('testEvent', function(e,data) {});
Here I'm trying to use the the parent jQuery to handle the event. This won't work. I have to use vanilla JavaScript:
document.getElementById('#my_iframe').contentWindow.$('.myElement').on('testEvent'), function(e,data) {});
So here I'm using vanilla JavaScript to get to the iframe contents and then the jQuery from that point on is the iframe's jQuery instance, which is the same instance of jQuery that the trigger happens on.
This worked perfectly!

Related

Adding `click` event to child of `iframe` of `iframe` - not woking

I am trying to add a click event to one of the element which is nested inside of a iframe of iframe.
this is a iframe .ssueContentIframe under this, there is another iframe added as #SmartReportTabContent1 so inside of the second iframe element, I am trying to add a click event like this:
Basically, I don't know when both of iframe will be loaded and all elements will available, for future I am adding:
$('.ssueContentIframe').contents().find( '#SmartReportTabContent1' ).find('.ui-grid-selection-row-header-buttons.ui-grid-icon-ok.ui-grid-row-selected').on('click', function(){
alert('Hi');
});
But not working. what is the correct way to wait until both of iframe exist and add the click event to one of the element here?
Thanks in advance!
You need to use "contents" on the second iframe as well. to wait for it to load, you can use the "ready" event on the second iframe.
eg:
$("#SmartReportTabContent1").find("iframe").ready(function (){
// do something once the iframe is loaded
});
Update
refer to this question
Well I edit this, first do a load of the first iframe and check it loaded well, then do the function on click on the element.
$(function(){
$('#foo1').load(function(){
alert("Loaded");
$('#foo1').contents().find('iframe').contents().find('#test').on('click', function(event) {
alert("Working");
});
});
});
I tested it on my computer and worked perfectly, remember addind the library, if you don't add a library it won't work.
Just change the ID i used to your IDs.

How to attach events to a colorbox popup in backbone?

I'm having a lot of issues with events triggering in my colorbox popup. Currently, there is a backbone view taking care of a user profile page. There is a gallery of photos, that when clicked, opens a colorbox that contains the photo, as well as comments, comment input form, and like buttons.
The html I put into the colorbox is a hidden div on the template itself. Everything displays just fine, but clicking things don't trigger anything. I figured I would try to attach the event handlers to the html I pass into the colorbox function, since I'm guessing the pop up colorbox is not considered to be in the backbone view's dom. The function is below, which the Backbone view triggers of a click event on an img. The var photoBox is the html I want to be displayed in the colorbox. I tried to attach event handlers to the photoBox, but to no avail.
popColorbox: function(event) {
var photoID = $(event.currentTarget).parent().attr('data-id');
var photoBox = $("#inline_example" + photoID).parent().html();
$(photoBox).on('click', '.unlike', function(){
console.log("hello");
alert("hello");
});
$(photoBox).on('click', '.like', function(){
console.log("hello");
alert("hello");
});
$.colorbox({html: photoBox});
}
Your first assumption as to why the events aren't being triggered is correct. In backbone view's the events are delegated to their root el, as such since the colorBox's elements are not children of the view's el its events aren't being triggered.
The reason why your events aren't being fired when you try binding directly to the photoBox I think is because the colorBox plug-In expects a string of html which it uses to build up it's html (as opposed to just attaching the nodes you pass in).
In order to trigger your events you will need to bind them to some existing higher element on the DOM, in this case you might need to go up to the document.
$(document).on('click', '.unlike', function(){
console.log("hello");
alert("hello");
});
$(document).on('click', '.like', function(){
console.log("hello");
alert("hello");
});
Maybe here the event listener is added on html rather than a selector. Please look at jQuery documentation on adding an event listener. http://api.jquery.com/on/

Click event doesn't fire on element

I am building a Windows 8.1 Store application with WinJS. When the user queries some search results show up in a <p class="searchresults">content</p> tag.
I'd like to add an event handler to the .searchresults class. I've done the following:
$('.searchresults').on('click', function() {
console.log("clicked");
});
I've tried even without .on()
$('.searchresults').click(function() {
console.log("clicked");
});
However the event never gets fired. I've set up a breakpoint, so I can see when it fires - but that never happens
I've tried to add an event handler via the WinJS way:
Microsoft.Maps.Events.addHandler(document.getElementsByClassName("searchresults"), 'click', myfunc);
Without success.
Any ideas why this is happening?
I will guess that you are creating the <p class="searchresults">content</p> object AFTER you try to install the event handler (a common problem with dynamic content). That will not work with normal event handling because the DOM object does not exist when you try to add the event handler to it.
If this is the case, then you need to use delegated event handling like this:
$(document.body).on('click', '.searchresults', function() {
console.log("clicked");
});
This will allow you to dynamically create the searchresults content at any time and the event handler will still fire via event delegation (events propagate up to their parents).
You haven't shown the HTML around the search results content, but the most optimal way to do this is to select the closest static parent to the search results (a parent that is not dynamically created and already exists at the time you attach the event handler) and attach the event to that:
$(closest static parent selector).on('click', '.searchresults', function() {
console.log("clicked");
});

Detect DOMContentLoaded in iframe

I was surprised to find the following doesn't appear to work, insofar as the DOMContentLoaded event doesn't fire (this.els is an object of elements).
this.els.stage_ifr.prop('src', 'templates/'+ee.globals.creating+'/item'+this.id);
this.els.stage_ifr[0].addEventListener('DOMContentLoaded', function() {
alert('loaded!');
}, false);
The page loads into the iframe fine, but no callback. The DOM level zero onload, however, works.
this.els.stage_ifr[0].onload = function() { alert('loaded!'); }; //<-- fires
A workaround is to prepare a globally-accessible jQuery deferred object in the parent page and resolve it via a DOM-ready event fired from the page called into the iframe, rather than listening for DOM-ready from the parent.
Paraent page:
dfd = new $.Deferred;
dfd.done(function() { alert("frame page's DOM is ready!"); });
Frame page:
$(function() { window.parent.dfd.resolve(); });
Nonetheless it would be good to know what's up with the first approach...
In the process of answering this question, I discovered the reason your DOMContentLoaded event listener doesn't work. It appears to me that you have two issues.
First, you're trying to listen for the DOMContentLoaded event on the iFrame itself. That isn't an iFrame event. It is a document event. So you have to reach into the iFrame to get the contentWindow and then get the document from that. That leads into the second issue.
Second, when an iFrame is first created, it has a dummy document in it that is NOT the same document as will eventually be there when dynamic content is loaded via the .src attribute. So, even if you did:
this.els.stage_ifr.contentWindow.document
to get the document in the iFrame, it will not necessarily be the right document and thus the DOMContentLoaded event won't fire on it (I've seen this behavior in Chrome).
MDN says that one can listen for the DOMFrameContentLoaded event on the iFrame itself and this will correspond with when the underlying document actually gets DOMContentLoaded. Unfortunately, I can't get this event to work in any browser. So, at this moment, the only work-around I know of is to either trigger the load event from within the iFrame itself where it can listen to its own DOMContentLoaded event (it can call out to the parent window if need be) or to just listen for the load event on the iFrame object and know that it won't fire until resources such as style sheets and images in the iFrame are also loaded.
Anyway, I thought I'd explain some of what was going on with your initial code and offer another solution even though this question was posted more than a year ago (though never answered).
Update:
I've developed a method of tracking DOMContentLoaded for an iFrame loaded with the same origin as its parent. You can see the code here.
After trying different options I found that the following code works for me:
var iframe = document.getElementById("app-frame-id");
iframe.contentWindow.addEventListener("DOMContentLoaded", onFrameDOMContentLoaded, true);
function onFrameDOMContentLoaded () {
console.log("DOMContentLoaded");
};
If your page and the iframe are on the same domain you have to wait for the original page to fire DOMContentLoaded first, then attach a DOMContentLoaded event listener on the iframe's Window (not Document).
Given you have an iframe as follows,
<iframe id="iframe-id" name="iframe-name" src="..."></iframe>
the next snippet will allow you to hook into the iframe's DOMContentLoaded event:
document.addEventListener('DOMContentLoaded', function () {
var iframeWindow = frames['iframe-name'];
// var iframeWindow = document.querySelector('#iframe-id').contentWindow
// var iframeWindow = document.getElementById('iframe-id').contentWindow
iframeWindow.addEventListener('DOMContentLoaded', function () {
console.log('iframe DOM is loaded!');
});
});
This might be more of a hack, but helped me solve a similar issue.
I am listening for onmouseenter of the frame content now.
This event triggers ahead of load (if the user moves the mouse). But as in my case I need the event for initialising a context menu, using the mouse was a precondition anyway.
It even triggers when the frame content changes under the mouse.

Jquery live not working in IE

I have some code that works fine in FF but not in IE. I have read other posts saying that the Jquery live method does not support change events but I am using a click event. Here is my code, it is inside $(document).ready(function():
$("a").live("click", function(e) {
alert("link clicked");
//do stuff
});
If FF the alert is fired but not in IE. When I use $("a").click it works fine, the problem is that I need to the function to be applied to links that do not exist when the page is first loaded (they will be created via ajax calls at a later stage).
Do I have any options here. We are using jquery-1.4.1.min.js.
Thanks in advance
if those links are within a specific content, you can use:
$('#link_container_id').delegate('a', 'click', function(e){
alert('link clicked');
});
.delegate() will watch if there are any events (click in your case) bubbling up, if so it checks for the target and compares it to 'a' in your case. Should work, but untested.
Elements should exist in the DOM at the moment you attach the live event. If later they are recreated (for example in an ajax callback) you don't need to reattach the event handler again. If elements don't exist at page load you can attach the live event when they are loaded, but if you do this then probably you no longer need the live event as you can directly attach the click event.

Categories