Event/object in JavaScript function - javascript

If I have some HTML like this:
<a onmouseover='SetTopLeft(this);'href='#'>Click me!</a>
Can I get both the object AND the event in the function? So, for example, can I have a method signature like this?
function SetTopLeft(e, o)
...where e is the event and o is 'this'? I may actually not need the object, but I think I probably DO need the event. I wouldn't mind understanding a little better how this works in JavaScript - i.e., when/how can I pass an event and when/how can I pass the calling object? Can I choose which to pass? Can I pass both?
Basically, what I really need to do is get the mouse coordinates within the DIV within which the anchor is located (even if that DIV is only a portion of a web page and whether or not the browser is full-screen) and I'm having a terrible time getting it done. Most of the examples I have seen for getting these coordinates within some element use the event and the pageX and pageY properties of that event.
By the way, this must work in IE 6 onward. Firefox would be good, too. Others are not necessary.

Yes, in the inline code this refers to the HTML DOM object for the element, and event refers to the event object. So you could do the following:
HTML
<a onmouseover='SetTopLeft(event, this);' href='#'>Click me!</a>
JavaScript
function SetTopLeft(e, obj) {...}

In general you should avoid using inline event handlers. It mixes representation (HTML) with logic (JavaScript). quirksmode.org offers a nice collection of articles of all there is to know about event handling.
Since inside an event handler, this typically refers to element the handler is bound to, you can also explicitly set this to the element and pass the event object as first argument:
<a onmouseover='SetTopLeft.call(this, event);'href='#'>Click me!</a>
See .call() [MDN] for more information.
Besides that, if your link is not linking to anything, better use a simple span element or a button and style it accordingly.

Related

How to store html element including its event listeners?

Using and html element's addEventListener has several advantages over using inline events, like onclick.
However, to store the element including its inline event is straight forward, for example, by embedding it in a parent element and storing the parent's innerHTML.
Is it possible to do something similar when using event listeners?
Edit:
I realized that my question is not sufficiently explained. So here some additions.
By "store" I mean a way to get the information holding the element and the event listener.
The analogue with inline events is easy: just embed in a parent element and save the parent's innerHTML (string) somewhere, for example in a database, and recreate the element later by loading the string and applying it to the innerHTML of some element.
But how would one do the analogue with elements when using event listeners? One cannot just use the innerHTML since then the events are not stored.
I hope this clarifies my question a bit.
Edit 2
With the help of comments I have made some unsuccessful attempts.
It is possible to get store the information of an element using createDocumentFragment() or element.cloneNode(true).
However, the first method does not work for external storage since, if I understood correctly, will contain only a pointer. Here is an example:
https://jsfiddle.net/hcpfv5Lu/
The second method does not work either. I am not fully sure why, but if I JSON.stringify the clone it "vanishes". Here is an example:
https://jsfiddle.net/3af001tq/
You could use a document fragment to store the DOM node in a JavaScript variable which can then be appended to a DOM element when required.
https://developer.mozilla.org/en/docs/Web/API/Document/createDocumentFragment
Yes.
You can use something like.
<ul>
<li id="list">Some data</li>
<li>Dumy</li>
</ul>
then in your javascript file,
document.getElementById("list").addEventListener("click", function(){
var htmlMarkUp = this.parentNode.innerHTML;
});
This would store the html content of ul in var htmlMarkUp.

Why does Chrome use `with` for inline events

If you take a look at this fiddle in Chrome and click the Trigger text with the js console open you will see this:
What is the reason of all those with blocks and what is it's value?
It looks to me as if it's how the browser creates a function for the event handler when it's specified as an HTML "onclick" attribute. I think what that does is:
make an event handler function with a single parameter for the event object and your supplied code;
make properties of the element (the <a> tag), an empty object (?), and the document object appear to be available symbols for the code in that function.
That is, this[0] is the <a> element itself, this[1] looks like an empty Object instance, and this[2] is the document object. What this means is that in code you write as part of an "onfoo" event handler attribute (and not code in any ordinary event handler bound from straight JavaScript code), it's possible to refer to the properties of the target element (the element for which you're setting the attribute) and the properties of the document element as if they were present in the scope chain.
If you change the code a little:
$('<a href=# onclick="console.log(baseURI);"> ...
then you get the value of the "baseURI" property of the <a> element. No need to prefix "baseURI" with anything that explicitly refers to the DOM node for the <a> element; it's just "there" as if it were declared with var in some enclosing scope.
(checking w3c specs now ...) edit — I haven't found anything that stipulates what symbols are supposed to be available to the script code in event handlers. This is really weird.
edit again — Firefox seems to do the same thing, though I don't see the explicit with statements anywhere.
with moves it's argument on top of scope stack. So it's even higher than global object, function params, etc. No idea why they use it. Perhaps it is a generated code.

Getting event object from setting event via a string

I want to create a div with an onclick event handler like
element.innerHTML = '<div onclick="somefunction(e, 10)"></div>';
where e would be the event object and 10 is some other random argument. I can't seem to find a way to do this. Is it possible?
Note that I do not want to create and then append the child to the parent element separately.
For inline handlers like that you should be able to pass the event object directly if you spell it out in full rather than e (in your actual function definition you can call the corresponding parameter anything you like):
element.innerHTML = '<div onclick="somefunction(event, 10)"></div>';
For other event registration techniques there are other ways to get access to the event object, but inline is kind of a special case that should be the same in all browsers.
For more detail see this page: http://www.quirksmode.org/js/events_access.html

JavaScript events and "srcElement"

I am having a specific problem with the JS event "onclick" and how it works in a very specific case. I have a set of nested DIVs that looks like this (somewhat):
In code:
<div id="A" ...>
<div id="B" ...> </div>
<div id="C" ...> </div>
</div>
The exact position of the DIVs are arbitrary, just know that there are nested DIVs.
DIV A has an onclick event attached to it.
When a user clicks on the divs I intend for the srcElement to without exception be div A.
Or maybe I'm just not using the right property.
Basically I want to be able to get the name of the div whose onclick event was called.
from inside the onclick function
If the onclick is on A, then this in the handler will represent that element.
document.getElementById('A').onclick = function() {
// "this" is the A element
alert( this.id ); // alert the ID attribute of the element
};
Well, divs don't have a name per se in HTML4. They can have a title, though. In JS without a framework, you could get the title this way:
document.getElementById("A").onclick = function() {
alert(this.title);
}
This appears to work well in my tests.
You can use Patrick's solution provided you attach the listener as a property of the element.
If you use IE's attachEvent method, it will not work as it doesn't set the listener's this keyword to the element when called. There are numerous work arounds for that. IE 9 introduces addEventListener, hopefully with the this keyword set per other browsers.
Event.srcElement is the IE equivalent of the W3C Event.target property and is the element on which the event originally occured. For bubbling events, to find the element whose handler called the listener, it is best to set the listener's this keyword in the call so that you can refer to the associated element as 'this'.
Note also that there is no consistency in the order that listeners will be called when attached using attachEvent or addEventListener (HTML5 tries to fix that, but it isn't widely implemented yet and will not fix attachEvent's order anyway).
It is usually best to keep event registration as simple as possible. Once you have a complex system, you'll likelyl need your own event registration and calling system to avoid the various browser peculiarities (there are a number of those).
--
Rob

can I programmatically examine and modify Javascript event handlers on html elements?

I am doing browser automation using C#, and I would like to modify or possibly just eliminate event handlers on some of the html elements in webpages that I am looking at. E.g., suppose there is a button there which might (or might not) have an attached onClick event. How do I go about:
- finding out if there are any event handlers attached to onClick for it?
- removing them?
Replacing element with its own clone should effectively discard all of its event listeners (well, technically listeners are still on an element, but since an element is replaced with its own clone, it looks as if listeners were simply removed):
el.parentNode.replaceChild(el.cloneNode(true), el);
Unfortunately, this won't work in IE, since IE erroneously transfers event listeners of an element on clone. To work around that you can reassign innerHTML of element's parentNode:
el.parentNode.innerHTML = el.parentNode.innerHTML;
Note that this will not only remove event listeners of an element, but also listeners of all of element's siblings.
Alternatively, you can work around IE issue by reassigning outerHTML of an element:
el.outerHTML = el.outerHTML;
This depends on how the event handlers have been attached to the element.
If they are attached using addEventListener or one of the proprietary addWhatever listener methods, there is no way to list them.
If they are attached by modifying the event property, ie. node.onclick = whatever, then you can read the value of the property to get the function and it'll work the same as any other JS func.
There is a third way too:
You can override the default addEventHandler/addListener behavior if the code you automate uses those. By doing this, you can replace the default behavior by one which pushes each handler into an array, which you can then loop over yourself.
The following code might work:
var oldAddEventListener = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function(event, handler, bubbling) {
/* do whatever you want with event parameters */
oldAddEventListener.call(this, event, handler, bubbling);
}
As far as I know, it's not currently possible to use javascript to get all the event handlers attached to an element.
See this link for more info:
http://www.howtocreate.co.uk/tutorials/javascript/domevents

Categories

Resources