Recommended method to locate the current script?

筅森魡賤 提交于 2019-12-05 02:12:35

Out of the box : document.currentScript (not supported by IE)

I've worked for OnlyWire which provides, as their main service, a widget to put on your site.

We use the var scripts = document.getElementsByTagName("script"); var thisScript = scripts[scripts.length - 1]; trick and it seems to work pretty well. Then we use thisScript.parentNode.insertBefore(ga, thisScript); to insert whatever we want before it, in the DOM tree.

I'm not sure I understand why you consider this a "heavy" solution... it doesn't involve iteration, it's a pure cross-browser solution which integrates perfectly.

This works with multiple copies of same code on page as well as with dynamically inserted code:

<script type="text/javascript" class="to-run">
(function(self){
    if (self == window) {
        var script = document.querySelector('script.to-run');
        script.className = '';
        Function(script.innerHTML).call(script);
    } else {
        // Do real stuff here. self refers to current script element.
        console.log(1, self);
    }
})(this);
</script>

Either document.write or picking the last script element will work for synchronously loaded scripts in the majority of web pages. However, there are some options I can think of that you did not consider to allow for async loading:

  • Adding a div with class="Locator" before the script. HTML classes has the advantage that duplicates are not invalid. Of course, to handle the multiple widget case, you will want to change the element's class name when done adding the HTML elements so you do not add them twice. (Note that it is also possible for an element to be a member of multiple classes; it is a space-separated list.)

  • Checking the src of each script element can ensure that tracking code (e.g. Google Analytics legacy tracking code) and other scripts loaded at the very end of the page will not prevent your script from working properly when async loading is used. Again, to handle the multiple widget case, you may need to remove the script elements when done with them (i.e. when the desired code has been added to the page).


One final comment I will make (although you may already be aware of this) is that when coding a widget, you need to declare all your variables using var and enclose all your code within: (JSLint can help check this)

(function(){
    ...
})();

This has been called a "self-executing function" and will ensure that variables used in your script do not interfere with the rest of the Web page.

aptwebapps

Whether you drop a <script> tag in or a <div class="mywidget">, you're adding something to the markup. Personally, I prefer the latter as the script itself is only added once. Too many scripts in the page body can slow down the page load time.

But if you need to add the script tag where the widget is going to be, I don't see what's wrong with using document.write() to place a div.

Christophe

I just found another method that seems to answer my question:

How to access parent Iframe from javascript

Embedding the script in an iframe allows to locate it anytime, as the script always keeps a reference to its own window.

I vote this the best approach, as it'll always work no matter how many times you add the script to the page (think widget). You're welcome to comment.

What pushed me to consider iframes in the first place was an experiment I did to build a Google gadget.

In many cases this work well (hud.js is the name of the scipt):

var jsscript = document.getElementsByTagName("script"); 
for (var i = 0; i < jsscript.length; i++) { 
      var pattern = /hud.js/i; 
      if ( pattern.test( jsscript[i].getAttribute("src") ) )
      {
         var parser = document.createElement('a');
         parser.href = jsscript[i].getAttribute("src");
         host = parser.host; 
      }

 }

Also you can add individual script's name inside them.

  • either inside some js-script

     dataset['my_prefix_name'] = 'someScriptName'
    
  • or inside HTML - in the <script> tag

     data-my_prefix_name='someScriptName'
    

and next search appropriate one by looping over document.scripts array:

 ... function(){
    for (var i = 0, n = document.scripts.length; i < n; i++) {
        var prefix = document.scripts[i].dataset['my_prefix_name']
        if (prefix == 'whatYouNeed') 
           return prefix
    }
 }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!