1

I have a very basic question about using the "this" keyword to retrieve a DOM element.

Consider the following HTML/Javascript:

<div class="container">
    <div class="regular-div">
        <script type="text/javascript">
            console.log(this);
        </script>
        Here is a div withOUT onclick
    </div>
    <div class="onclick-div" onclick="console.log(this)">
        Here is a div with onclick
    </div>
</div>

While clicking the "onclick-div" it does return the DOM object for that div. However, the console.log event calls 'this' indirectly in the "regular-div" and returns window.

Is it possible to get "this" DOM object when 'this' is called indirectly? My purpose is I want to fire a function in line in the HTML, but need to send the function "this". Here's an example of what i'm trying to do:

<div class="container">
    <div class="regular-div">
        <script type="text/javascript">
            loadSomeHTML(this, varA, varB, varC);
        </script>
    </div>
</div>

Thanks everyone for any clarification of how "this" works in the above context.

jreidko
  • 77
  • 7
  • 1
    Have you checked [this question](http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work)? – raina77ow Aug 31 '15 at 18:08

4 Answers4

3

In your first example, the script isn't in any way associated with the div. It's just been output within the div, but it's not connected to it. The script runs as the page is being parsed.

Is it possible to get "this" DOM object without a user interaction?

If you mean inline with the parsing of the HTML, you could do this:

<div class="container">
    <div class="regular-div">
        Here is a div withOUT onclick
    </div>
    <script type="text/javascript">
    (function() {
        var list = document.querySelectorAll('div');
        console.log(list[list.length - 1]);
    })();
    </script>
</div>

Note that the script tag is immediately after the ending </div> tag for the div you're trying to target. The script gets what's currently the last div in the document as of when the script runs. Or of course you could identify the div in some way (a class, for instance) and use that (and then potentially remove it so you could do it again later in the document).

It looks dodgy, but it's perfectly valid cross-browser, and was even recommended at one stage by the Google Closure Library engineers.

Live Example:

<div class="container">
  <div class="regular-div">
    Here is a div withOUT onclick (look in console for result)
  </div>
  <script type="text/javascript">
    (function() {
      var list = document.querySelectorAll('div');
      console.log(list[list.length - 1]);
    })();
  </script>
</div>

Example using a class we move:

<div class="container">
  <div class="target-me">
    The first div
  </div>
  <script type="text/javascript">
    (function() {
      var div = document.querySelector(".target-me");
      div.classList.remove("target-me");
      console.log(div);
    })();
  </script>
  <div class="target-me">
    The second div
  </div>
  <script type="text/javascript">
    (function() {
      var div = document.querySelector(".target-me");
      div.classList.remove("target-me");
      console.log(div);
    })();
  </script>
</div>

Note I didn't use id, because if we used an id and JavaScript wasn't enabled, we'd end up with an invalid document (because it would have multiple elements with the same id). It'd be fine if JavaScript were enabled (because we'd remove the id from earlier ones before later ones were created), but...

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • 1
    Thanks T.J., I had seen the [list.length - 1] approach and indeed thought "that looks funky" so your explanation above provides a lot of context for me. Thank you again for your time, this was hugely helpful. – jreidko Sep 02 '15 at 17:56
2

Javascript has no implicit connection to the HTML DOM. The reason why onclick works the way you want is because the HTML DOM implementation passes the element to the js callback. You need to do something similar in your other case. One way to do this is:

<div class="container">
    <div class="regular-div" id="mydiv">
        <script type="text/javascript">
            loadSomeHTML("#mydiv", varA, varB, varC);
        </script>
    </div>
</div>

Then your js implementation does the lookup to find the element:

function loadSomeHTML(selector, varA, varB, varC) {
    var el = document.querySelector(selector);
    // now el is where you want to insert your HTML
    // ...
}
dbcb
  • 830
  • 6
  • 12
1

The code inside the script tag doesn't have any connection with the tag itself. this should, basically, return the object on which the current function was called, or the global environment, window. In the first div, the code is just executed, on no object, so window is returned. The value of onclick, on the other hand, is treated as a function (with even some parameters, like e), that gets called on the element with the attribute. So, the code in the script element is executed in the global scope, whereas the one in the attribute is in a function scope (that's why all vars are shared across script tags).

IS4
  • 9,770
  • 2
  • 41
  • 69
1

As explained in How may I reference the script tag that loaded the currently-executing script?, the proper way of obtaining a reference to the script element whose code is being executed is

document.currentScript;

Then, to get the parent node of that element, use

document.currentScript.parentNode;

<div class="container">
  <div id="regular-div">
    <script type="text/javascript">
      alert('#' + document.currentScript.parentNode.id);
    </script>
    Here is a div withOUT onclick
  </div>
</div>
Community
  • 1
  • 1
Oriol
  • 225,583
  • 46
  • 371
  • 457