0

I have a javascript function like this

function select_term(e){ 
    e = e || window.event;
    var target = e.target || e.srcElement;
    if (target.nodeType == 3) target = target.parentNode;

    console.log(target.innerHTML);
}   

now I call this function

<a href="#" onclick='select_term()' style='text-decoration:none'>{{ descriptor.name|safe }}</a>

So this function is supposed to give me the innerHTML of this anchor element. In principle

$(this).innerHTML 

would do the job, but I don't understand how I can access $(this) in the function?

My problem is that the solution above does not work in all cases, since the descriptor name can look like

<em>test1</em>test2

If the user clicks on test1 the javascript function prints out test1. If the user clicks on test2 the javascript function prints out <em>test1</em>test2. I want always <em>test1</em>test2, since I want the innerHTML of the anchor element.

carl
  • 3,322
  • 6
  • 32
  • 80
  • 3
    `$` is a function that doesn't exist in the native JS environment. Some libraries include a `$` function though. Instead, just do `this.innerHTML`, unless you're using a library where that makes sense. –  Mar 27 '17 at 14:09
  • ...but to access the bound element, pass it. `onclick='select_term(this, event)'`. And then define the function as `function select_term(elem, event) {...` since `this` won't give you the element. –  Mar 27 '17 at 14:11
  • ...aside from all that, I can't tell what you want. –  Mar 27 '17 at 14:14
  • Don't use `this` if you're writing event listeners. The first parameter to an event listener is the event, with `target` being the bound element firing the event. If you use `currentTarget` it references the exact element (i.e. a child element) that's actually firing the event. – Dissident Rage Mar 27 '17 at 14:15

3 Answers3

4

This is because of wrong event property usage. When user clicks on <em> - e.target will be the <em> element, when on <a>(text test2) - e.target is <a>. To prevent such things you just need to use currentTarget property of the event. Try this :

function select_term(e){ 
    var target = e.currentTarget;
    console.log(target.innerHTML);
}   
MysterX
  • 2,238
  • 1
  • 9
  • 11
2

You can pass the element reference to your function like onclick='select_term(this)'.

Check below snippet for example:

function select_term(obj) {
  // Here 'obj' refers to the anchor element
  console.log(obj.innerHTML);
}
<a href="#" onclick='select_term(this)' style='text-decoration:none'>{{ descriptor.name|safe }}</a>
Pugazh
  • 8,943
  • 5
  • 25
  • 49
0

Inside the onclick function, this is the element, and this.innerHTML would give you its inner html.

Inside select_term, this is window, because you've called it without any context. See how does the this keyword work for more details.

$ is an undefined variable. If you've defined it as jQuery, then $(this) would give you a jQuery object wrapped around whatever element this is. $(this).innerHTML would give you undefined because jQuery doesn't provide innerHTML (it does have the html function though).

If you want to get the innerHTML of the a element inside the select_term function, then you have to either:

  • Write JavaScript that isn't mired in the '90s and use addEventListener instead of an onclick attribute
  • Pass the element object to the select_term function

If you want to get the element using your first chunk of code, then you need to do the same thing, only with the event object.

The event handler function gets passed the event object as the first argument automatically, but the onclick function which calls the select_term function is the event handler. select_term itself is not.

function select_term(e) {
  e = e || window.event;
  var target = e.target || e.srcElement;
  if (target.nodeType == 3) target = target.parentNode;

  console.log(target.innerHTML);
}

document.querySelector("a").addEventListener("click", select_term);
<a href="#" style='text-decoration:none'>{{ descriptor.name|safe }}</a>

That said, you can just use currentTarget instead of all the fiddling you are currently using to try to identify the element.

function select_term(e) {
  var target = e.currentTarget;
  console.log(target.innerHTML);
}

document.querySelector("a").addEventListener("click", select_term);
<a href="#" style='text-decoration:none'>{{ descriptor.name|safe }}</a>

NB: If you're writing href="#" then you don't have a link and should not use <a>. Consider <button type="button">...</button> instead.

Community
  • 1
  • 1
Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
  • Using `this` does not necessarily point to the correct object. – Dissident Rage Mar 27 '17 at 14:18
  • @DissidentRage — It points to the object I said it would point to. I don't know what you mean by "correct object" or which of the possible uses of `this` in my answer you are referring to. My conclusion doesn't even use `this` anyway. – Quentin Mar 27 '17 at 14:20
  • The link you've added requires further digestion on the part of the OP to understand how `this` works but in the meantime using `this` in event listeners is an unsafe practice. Edit: No, perhaps you aren't now, but you were using it. – Dissident Rage Mar 27 '17 at 14:24
  • It's perfectly safe to use `this` in event listeners. It usually gives undesirable (but understandable and consistent) results in *delegated* event handlers, but there's no use of delegation here. – Quentin Mar 27 '17 at 14:25