Why does Chrome use `with` for inline events - javascript

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.

Related

javascript onclick() event not working in chrome for text within div container

The following is not working in chrome, but works in IE and Firefox:
<div id="removeField" onclick="remove(0);" style="cursor: pointer;">-Remove</div>
The remove() function does not get called. Any idea why?
According to this Chrome bug report, they implemented a remove function which is a spec. Seems that Chrome has a .remove() method that allows you to self-remove elements. You'll probably want to name your function something else. Here's the webkit changelog noting the implementation.
remove is a member function of DOM elements in Chrome. In your console, you can see this by running:
> document.createElement("div").remove
function remove() { [native code] }
In an inline event handler, all the properties (including member functions) of that element are available as top-level variables. Inline code is effectively run inside a with(thisElement) block. In the context of the inline event code, the identifier remove refers to the remove method of the element, not the global-scope remove function.
Change the function name to something that doesn't collide with the method names of the element, or use window.remove explicitly.
(Modified from this previous answer of mine handling a similar case with the start method in IE.)

what's the difference between <a onclick="someFunction"> and <a onclick="someFunction()">

what is the difference between
<a onclick="someFunction">
and
<a onclick="someFunction()">
One uses the parenthesis and not the other, but what are the differences of using either? What is the "correct" option? And what happens if i dont use any href attribute?
As far as I know, in javascript, using something = someFunc(); assigns the return value of that function to the something variable. And using something = someFunc; assigns the function directly (not its result) to that variable (And it's mostly used to assign functions to events). e.g. I can assign a function to a onclick event.
But what I don't understand is what happens when using either in some html element inline event, as in the examples, since the assignation is not to a javascript variable, but to an html attribute, which happens to be an event? Please explain.
And also, is there a difference on assigning a inline onclick function to an anchor (a) that to other elements (e.g. span div label etc)? Do they have the same effect?
Sidenote:
I've been reading here about how to run a function when clicking on a link, and I already understood is that is should not be done "inline", but instead using unobtrusive javascript. (I mention it to avoid debate about that), but in the examples I've seen they don't mention the difference of both options I mention when doing it inline.
Edit: This question was made because here they gave an answer which doesn't use the parenthesis in the function for the event, and nobody mentioned the parenthesis were needed, so I assume it is valid. yet I don't know what is the difference of using () or not.
One uses the parenthesis and not the other, but what are the differences of using either?
<a onclick="someFunction"> won't do anything. The parenthesis cause a function to be called.
Having a statement consisting of nothing but an identifier (be it a function name, variable, or whatever) won't do anything (except throw a reference error if the variable doesn't exist).
And what happens if i dont use any href attribute?
Then I'd question why you were using an <a> element in the first place.
And also, is there a difference on assigning a inline onclick function to an anchor (a) that to other elements (e.g. span div label etc)?
Only that they aren't (by default) focusable elements (nor is an a element without an href attribute), so the click event couldn't be triggered by tabbing to the element and pressing enter. If you want an element that will do something with JS when triggered, and you don't have a sensible fallback for when JS isn't available, use a button.
The value of an event handler attribute is a sequence of Javascript statements, not an expression.
It isn't assigning a function value to the property; it's a piece of code to execute at that event.
Leaving out the parentheses, results in an expression statement that has no effect.
when writing inline on click functions, we assigning the code to be executed in the form of string on click of the element.
It is equivalent to eval('someFunction()');
we cannot write on click='someFunction' since it will be equivalent to eval('someFunction') which would do nothing.
if you intend to bind a click handler to an anchor tag, dont forget to add a href='#' attribute to the anchor tag.
There is no difference between assigning a click handler to span or divs as compared to anchor tag.

What does "this" refer to in an HTML anchor

I am trying to do something in JavaScript before following the link in the href part of a link:
<a href="open.this.page" onclick="doStuff(this);return false; title="follow me">
Question is what does this in doSuff(this) refer to? I was expecting to have to get the href part of the anchor out of it, but when examining it looks like it IS the href and nothing else.
function doSutff(my_arg) {
alert (my_arg);
// do stuff
// follow the href in the link
}
In the above alert I get exactly the href as "http://my.domain/open.this.page".
Is this expected or am I getting it in one browser, but probably not in another?
If that is the normal behavior then how would one get, for example, the rel or title part of an anchor? DOM only?
In this case this refers to the DOM node.
"in the above alert I get exactly the href as "http://my.domain/open.this.page".
Is this expected or am I getting it in one browser, but probably not in another?"
This is expected. The reason you get "http://my.domain/open.this.page" in the alert is that that is what the default .toString() value is of an <a> element.
It's an unusual case. Other elements don't show an attribute as the .toString() representation.
If you want to actually do work with the href, you'd need to do this.toString(), or see below...
"...how would one get, for example, the REL or TITLE part of an anchor?"
To get other attributes or properties, you'd just do it the usual ways.
To get the attribute, you can do:
onclick="doStuff(this.getAttribute('title')); return false;"
Most of the standard attributes map directly to a property on the node, so you could also do this:
onclick="doStuff(this.title); return false;"
Or since you're in an inline handler, you can actually do this:
onclick="doStuff(title); return false;"
The reason that last one works is that handlers assigned from an attribute have a unique scope chain that includes the element itself. This means that properties on the element actually show up as variables.
Note that this doesn't work for any other kind of event handler.
With regard to this, it refers to the element to which the handler is bound.
What happens to the attribute is that it basically becomes the body of a function assigned to the onclick property.
So you end up with something like this:
elem.onclick = function(event) {
doStuff(this);return false; // Your onclick attribute value
}
So you can see that this is actually just the normal value found in an event handler assigned to a property.
Notice also that there's an event parameter defined. This means that you could change your attribute like this:
onclick="doStuff(this, event);return false;"
...and it will pass on that parameter, because now your function looks like this:
elem.onclick = function(event) {
doStuff(this, event);return false; // Your onclick attribute value
}
So you can see that your string is actually referencing the normal event parameter of the function.
This also works in older IE. In IE, the event parameter won't be defined, so it'll pick up the global event object.
// ---------------v----no parameter
elem.onclick = function() {
// v---now it picks up the global event
doStuff(this, event);return false; // Your onclick attribute value
}
this in the context of any event (onclick or otherwise) refers to the DOM element that triggered the event.
In your case, it is the anchor tag itself.

Event/object in JavaScript function

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.

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

Categories

Resources