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.
Related
I am trying to write a greasemonkey script which adds an onClick listener on a button (define below) and do some specific things. I was trying to get this button obj using document.getElementsByTagName but it returned null. I tried to iterate over document.anchors and it returned null as well. how can i get this element object and add onclick event to it.
<a class="editicon" aria-label="Edit this field" role="button" href="#"><img src="https://url-to/images/edit.png?3423434"></a>
There is already an onclick added to this object, I don't want to replace it.
UPDATE
Adding my Greasemonkey script
// ==UserScript==
// #name cr
// #namespace my_namespace
// #version 1
// #grant none
// ==/UserScript==
(function(){
console.log('test ...')
var editicon = document.getElementsByTagName('editicon');
console.log(editicon);
})();
First, your question talks about a button, but your code does not include one. Instead of using an <a> element and then disabling its native navigation function with href="#", it would be semantically better to use an actual <button> element.
Second, you should not use inline HTML event attributes (onclick, onmouseover, etc.) as they:
Create "spaghetti code" that doesn't scale, is hard to read, leads to duplication and doesn't follow the "separation of concerns" methodology.
Create global anonymous wrapper functions around your event attribute value that alter the this binding of your code.
Don't follow the W3C Event Standard of using the addEventListener() API.
Now, there are several ways to get a reference to a DOM element and some are better than others depending on your HTML structure and how many elements you are trying to get. document.getElementsByTagName() returns a "node list" of all the elements that were found. Even if no elements were found, you still get this list as the returned object (the list will just be empty when no elements were found). To extract a particular element from the result, you'll need to pass an index into that list, which is an "array-like" object. Additionally, getElementsByTagName returns a "live" node list, meaning that it will re-scan the document upon every interaction to ensure that the most current list is provided. While this can be beneficial in some circumstances, it comes with a performance cost.
This, for example, would extract the first a element in the document:
var myElement = document.getElementsByTagName("a")[0];
But, since you are only expecting a single element, that is overkill. To get just one element, and if that element has an id attribute on it, you can/should use: document.getElementById("theIdHere"); as getElementById() is generally the fastest way to find a single element in your HTML structure.
Additionally, there are other ways to get an element or elements, like querySelector() and querySelectorAll(), which allow you to use CSS selector syntax in your JavaScript queries.
For your code, see the following snippet:
// Get a reference to the first <button> element in the document
var b = document.querySelector("button");
// Or, if the element has an id, the best solution would be:
var b = document.getElementById("btn");
// Add a click event handler to the element
b.addEventListener("click", handleClick);
// Function that will be called when anchor is clicked
function handleClick(){
alert("You clicked me!");
}
button { background-color:rgba(0,0,0,0); }
img { width: 50px; }
<button class="editicon" aria-label="Edit this field" role="button" id="btn"><img src="https://s-media-cache-ak0.pinimg.com/736x/5a/42/c6/5a42c6224e3ce7fa9837965270bfcdd9--smiley-face-images-smiley-faces.jpg"></button>
I am playing around with the JQuery keyword this.
I have come across something I do not understand.
Here is my code:
<body>
<a id="link_1">jQuery.com</a>
<!-- adding JQUERY -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<!-- my JavaScript -->
<script>
$("a").attr("href", "target_1");
$("a").attr("new_attribute", "new_attribute_value");
$(function ($) {
$("a").mouseenter(function(){
alert(this.id);
alert(this.href);
alert(this.new_attribute);
});
});
</script>
</body>
I want JQuery to return the id, href and my new_attribute as an alert message.
I can call the id on the keyword 'this' (with this.id) and it works as expected.
I can also call the href on the keyword this (with this.href) and it works as expected (even though I set the value of href with JQuery only (an not inline)).
However with the new attribute "new_attribute" this kind of set & get does not work as expected.
my question: What am I doing wrong? Is it only possible to call 'certain /limited' attributes on the keyword 'this'.
It's because new_attribute is not a valid attribute.
Some built in attributes are mapped to properties, and when you do
this.id
you're really getting the id property, not the attribute, as that would be
this.getAttribute('id')
you could do
this.getAttribute('new_attribute')
but you should really be using data-* attributes, and not make up your own, but jQuery's data() maps data internally and doesn't add attributes, but in your case that's probably what you want, just store arbitrary data on the element
$("a").attr("href", "target_1");
$("a").data("new_attribute", "new_attribute_value");
$(function ($) {
$("a").mouseenter(function(){
alert(this.id);
alert(this.href);
alert( $(this).data('new_attribute') );
});
});
In this context this points to HTMLAnchorElement object, and the problem here is the difference between HTMLElement attributes and their properties. Simply saying, attributes are rendered as a part of HTML, and used for additional object declarative configuration from the side of HTML markup.
On the other hand, there are properties of the object, which not always have corresponding attributes. Sometimes they do, but in most cases - they don't.
You can set any arbitrary attribute to HTMLElement like you did with new_attribute, but this custom attribute value will not become an object property. So reading such custom attribute as property will yield undefined.
"this" refers to the DOM element (try console.log(this)). An Element exposes its id attribute, as you can see here : https://developer.mozilla.org/en-US/docs/Web/API/element
Since it is an A element, it also exposes its href attribute. But it never knows your custom attribute. So it can't expose it.
Try this in you event handler :
var $this = $(this);
alert($this.attr('new_attribute'));
You need to treat this as a selector, so write it like $(this)
Your problem is that you set an attribute with the attr() method but you're querying (getting) it with a call to an equivalent method to jQuery'sprop().
Since this is a non standard attribute, the main interface for the anchor <a> element HTMLAnchorElement or other interfaces that it inherits from in the DOM don't have/implement a new_attribute property in place, your this.new_attribute would always return undefined.
However, if you'd like to keep experimenting with the this keyword, you could try something along these lines this.attributes['new_attribute']and you won't have any unpleasant surprises in your coding excursion anymore :)
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.
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.
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