CheapSteaks
CheapSteaks

Reputation: 5011

Is there a way to get the DOM element that contained the inline JS script that called a function?

For example

<script>
function foo(){...}
</script>

<div><script>foo();</script></div>
<span><script>foo();</script></span>

and I wanted to have foo return "abc" when called from a div, return "123" when called from a span.

Is this possible?

Upvotes: 3

Views: 1923

Answers (5)

Will Manley
Will Manley

Reputation: 2484

Use document.currentScript. "It’s been available across browsers since July 2015.".

Example:

function rand_color() {
  return '#' + Math.floor(Math.random() * (1 << 24)).toString(16);
}
<h1>Hello
  <script>
    var h1 = document.currentScript.parentElement;
    window.setInterval(() => h1.style.color = rand_color(), 1000)
  </script>
</h1>

Upvotes: 0

gblazex
gblazex

Reputation: 50109

After reading your comment I think you should do something else:

  1. create empty elements where your ads should appear (#ad1_empty, #ad2_empty, ...)
  2. place your ad code at the bottom of the page hidden (#ad1_full, #ad2_full, ...)
  3. when the document is ready, replace all empty elements with the real ones

// code

<div id="ad_empty"><!-- placeholder --></div>
<div id="ad_content" style="display: none;">
    <script src="[ad resource]"></script>
    <script>inline ad script</script>
</div>

<script>
function replace( oldel, newel, show ) {
  if ( typeof newel == "string" ) 
    newel = document.getElementById( newel );
  if ( typeof oldel == "string" ) 
    oldel = document.getElementById( oldel );
  if ( newel && oldel )
    oldel.parentNode.replaceChild( newel, oldel );
  if ( show ) 
    newel.style.display = "";
}

window.onload = function() {
    replace( "ad_empty",  "ad_content",  true );
    replace( "ad_empty2", "ad_content2", true );
};
</script>

It is possible to do what you originally wanted, btw (but it's useless)

function foo() {

  var scripts = document.getElementsByTagName("script");
  var parent = scripts[scripts.length-1].parentNode;
  var tag = parent.nodeName.toUpperCase();

  if (tag == "DIV") {
    alert("called from a <div>");
  } else if (tag == "SPAN") {
    alert("called from a <span>");
  }
}

Upvotes: 2

SLaks
SLaks

Reputation: 887413

You can just get the last element currently in the DOM.

The code in an inline <script> block executes as the browser parses the page. Therefore, the last DOM element will be just before the script.

Upvotes: 3

Nick Craver
Nick Craver

Reputation: 630389

There isn't a way to do this, script can be called in many different ways, there just isn't enough need for this to put it in the spec in any way.

I would imagine there's a much simpler way overall to do what you're trying to accomplish, embedding <script> inside individual elements and basing anything off the <script> element's location doesn't' seem like a sound approach.

So...what are you trying to ultimately accomplish here?

Upvotes: 0

casablanca
casablanca

Reputation: 70701

No, this is not possible. You would have to manually pass some kind of parameter to identify where it was called from.

Upvotes: 0

Related Questions