Attach an event handler to HTML rendered in an IFrame - javascript

I am working on designing a react application that will be used to view a number of different types of files, from a known source. The user will search, be presented with a list of results, and then upon clicking one of the results, I will fetch the file, and want to display it on the screen as well. These files are all HTML/XML.
On top of this, I want to attach event handlers to certain tags within the file itself. (ie. attaching an onClick listener to all <p> tags, for example)
The obvious answer would be to use an iframe, however then the event handlers become a problem. Using dangerouslySetInnerHTML also works, however if there's a better solution I would love to know about it. Any Ideas?

You can fire events from an iframe and handle it by its parent by using this code
//iframe
function buttonClick() {
parent.$(parent.document).trigger('eventhandler');
}
<button onclick="buttonClick()">Button</button>
//parent
$(document).on('eventhandler', function () {
alert('event fired');
});
Just add the event handler in parent file and add your logic in it and then add event trigger in child iframe file or you can also follow this link.

Related

Is it possible to get all DOMS to the whole web-site (not just one route)

I have a web-page (front-end in Angular 2), and I attach a simple external javascript script to the HEAD of the index.html.
Now, I want from this external javascript to attach some functions to onclick events to some buttons.
The problem is that, I have many routes to this website and at each route I have different buttons.
The external javascript obviously initializes once on the webpage load, and I can't bind other DOMS that belong to other routes.
For example if I am to route /login, and attach onclick to button with idlogin, and refresh the page then OK the javascript will work.
But if I am at route /login and attach onclick to button register with idregister (which belongs to different route eg /register) and refresh the page then the javascript won't work because the button register doenst belong to this route. And if I change the route to /register then again, the javascript won't work.
So one possible solution would be, upon the load of external javascript to get ALL the DOMS to ALL the whole web-page (from all routes) and then to bind the functions I want.
Can I do that?
Thanks in advance!
EDIT: Mind you that the binding of onclick to some button must happen on the external javascript. I can't write . All the DOM binding must happen dynamically on the script.
You need to use event delegation. Here is a simple example about that approach:
/**
* Example of DOM event delegation
* #author: Georgi Naumov
* gonaumov#gmail.com for contacts and suggestions
**/
window.addEventListener('click', function(event) {
if(event.target && event.target.tagName && event.target.tagName === 'INPUT') {
console.log('button is clicked');
}
});
This snippet will execute something for all buttons including buttons that have created in the future.
More information you can see here:
What is DOM Event delegation?
You probably can use some conditions to separate only buttons which you need.
Just bear in the mind:
This is not Angular way. Probably will be better if you have some solution on routing level.

Is there any way to preempt an event handler created with window.addEventListener?

[edit: adding more details about the scenario]
I am creating a tool which an app can include using a script tag; this tool adds an overlay to their app; that overlay includes a canvas and controls that I render onto the canvas. I would like the tool to be able to capture all input events and either handle them (if occurring over one of the rendered controls) and stop propagation to the app, or pass them on to the app (if not occurring over one of the rendered controls).
I am able to preempt all of the host app's input events except when the app registers an event on window using capturing, as follows:
window.addEventListener("mousedown", (e) => console.log("hi"), true);
Is there a way for my tool to inject a function that gets called before that?
No. If an event listener has been attached to the window in the capturing phase, there is no way to get any other listeners in ahead of it. This is because the window will be the first node to be notified of any events and the listeners are triggered in the order they were added. (I'm guessing this was done deliberately y the designer of the tool you're using. Not very end-user-friendly, IMO.)
The only way around it would be if you had a reference to the bound function, in which case you could use removeEventListener, add your own listener, then re-bind the original one. This seems unlikely, however, in your code.
You need one of your script tags to appear first in the page, ideally in the <head>. Then you get to attach your listener first.

jQuery(document).on('click.classname'.......)?

I was reading through MaterializeCSS's js files, in its "cards.js" file, there are these lines:
$(document).on('click.card', '.card', function (e) {
//something
});
I am not unfamiliar with jQuery's .on() function, but I never used custom event as the first parameter. What I don't understand is there seems to be nowhere defining this custom event click.card(if it is a custom event), because I only load this card.js and another velocity.min.js file from the MaterializeCSS package besides jQuery, and I searched velocity.min.js there is nothing related to this event. It seems to me that the custom event is in this pattern:original event.classname, but I tried replacing card with other class name and it didn't work.
I tried to look for more information about how to define a custom event but couldn't find anything useful.
My question is how to find where this custom event is defined.
This is not a custom event, this is a DOM event with a namespace:
click is the DOM event, and card the event namespace.
If you have multiple handlers on the same element, this can help you discern them. You could remove only this listener (and leave all other click listeners):
$(document).off('click.card');
And you can trigger them manually using $('...').trigger:
$('.card').trigger('click.card'); // only triggers this specific click listener, not the others
You can find out more about event namespaces here.

Logging hyperlink clicks on my website

I have a website, where I allow other developers to host content.
My aim is to log clicks on every hyperlink (even the content that is hosted by other developers) ,which exists on the page.
My initial approach was as follows:
$('a').click(function(event)
{
//do my logging
return true;
}
);
Now with the above approach , I am facing the following issues:
Developers may have images inside the anchor link, so the events target is an image rather than href
Many developers have their own way of handling an href click , using an onclick event rather than a simply href='' attr
Some developers add their custom attr , to the tag, and have custom functions to handle the clicks
so basically , the issue is , there is a huge variety of anchor tags available, and logging clicks is not as simple.
Many cases allowed me to log the data I wanted, but a few cases , broke the code badly.
My aim to post on this forum was:
to discuss what is the right approach to do hyperlink clicks logging in a dynamic environment
is there a plugin out there , which allows a functionality like this.
I know facebook and google have this , but they have a totol control, on what is being hosted in their environments.
Any help is greatly appreciated.
Adding a click handler to every link is not a good idea. You should make use of event delegation (which will only attach one event handler at the root of the document):
$(document).delegate('a', 'click', function(event) {
// logging
});
Update (17.12.2011):
Since jQuery 1.7, one would use .on() [docs]:
$(document).on('click', 'a', function(event) {
// logging
});
Regarding your problems:
Developers may have images inside the anchor link, so the events target is an image rather than href
Events bubble up as long as propagation is not canceled. It depends on what you want to log. With delegate the event.target property will point to the image, but this (inside the handler) will point to the a element.
So you should have no problems here (example: http://jsfiddle.net/cR4DE/).
But that also means to you will miss clicks if the developers cancel the propagation.
(Side note: You could solve this letting the event handler fire in the capturing phase, but IE does not support this (hence jQuery does not either).)
Many developers have their own way of handling an href click , using an onclick event rather than a simply href='' attr
This will not touch existing event handlers.
Some developers add their custom attr , to the tag, and have custom functions to handle the clicks
Not sure what you mean here.
It also depends on how the other content is included. E.g. the above code won't track clicks in iframes.
In your logging code you should check for the bad cases and deal accordingly.
For example in your first case i you get the image and walk the dom up until i would find an a tag and log the href from there.
There will be some cases in which you will not be able to do the logging but if they are small compared with the cases you can do that you will be fine :).

Jquery AJAX and figuring out how NOT to nest callbacks for multiple reloads.

I have a site with a few containers that need to load content dynamically via AJAX.
Most of the links inside of the containers actually load new data in that same container.
I.E: $("#navmenu_item1").click(function() { $("#navmenu").load(blah); });
When I click on a link, lets say "logout," and the menu reloads with the updated login status, none of the links now work because I would need to add a new .click into the callback code.
Now with repeated clicks and AJAX requests I am not sure how to move forward from here, as I am sure nested callbacks are not optimal.
What would be the best way to do this?
Do I include the .click event inside the actual AJAX file being pulled from the server, instead of within index.php?
Or can I somehow reload the DOM?
Thanks for the help!
You're looking for the .live function, which will handle an event for all elements that match a selector, no matter when they were created.
Since you're reloading a particular element, you can store the event listener there using .delegate() like this:
$("#navmenu").delegate("#navmenu_item1", "click", function() {
$("#navmenu").load(blah);
});
This works by listening for the click to bubble up to the #navmenu element and executing any handlers that match the selector. The .delegate() format is .delegate(selector, event, handler).
Since you're loading inside #navmenu, the event handlers on that actual element won't get blown away like they do on the children that are replaced inside, so the clicks will now work for current or future elements inside #navmenu.

Categories