开发者

Can you select the script element that included the JavaScript? [duplicate]

开发者 https://www.devze.com 2023-03-21 20:44 出处:网络
This questi开发者_开发技巧on already has answers here: Closed 10 years ago. Possible Duplicate: How may I reference the script tag that loaded the currently-executing script?
This questi开发者_开发技巧on already has answers here: Closed 10 years ago.

Possible Duplicate:

How may I reference the script tag that loaded the currently-executing script?

Is there a way to select the script element that included a particular script without giving it a known attribute of any sort?

This example will alert the window object because it's being called in the global context:

<script>
  alert(this);
</script>

This example wont work as the name of the script could change (for convenience i'm assuming jQuery is included):

<script type="text/javascript" src="/foo/bar/baz.js"></script>
//baz.js
$('[src^="baz.js"]');

This example is sub-optimal as it relies on the id attribute:

<script type="text/javascript" id="foo">
  $('#foo');
</script>


I'm hesitant to answer my own question in this case because I don't have an answer that works 100% of the time, but I've ironed out the bugs enough to have a stable solution.

@Shef's answer is halfway to what I wanted/needed.

Generic JS Version:

function getActiveScript()
{
  var s;
  s=document.getElementsByTagName('script');
  return s[s.length - 1];
}

The issue with the above code is that it will select the last script on the page no matter when it was executed. This is a major issue if the calling script was included after page load.

As I can't directly select the script element (unless another solution presents itself), I'd rather not select anything if the script is being added after page load.

Pure JS Answer:

function getActiveScript()
{
  var r,s;
  r = document.readyState;
  if ( r && r != 'complete' )
  {
    s = document.getElementsByTagName('script');
    return s.length ? s[s.length - 1] : null;
  }
  return;
}

In the new version, document.readyState is checked to make sure that the document hasn't finished loading. Additionally on browsers where document.readyState isn't used, it will fail out (I can't think of any browsers that don't use document.readyState these days).

One caveat to this solution is that it may be possible to dynamically insert a script element into an earlier part of the document, which then gets executed before document.readyState is 'complete'. If the script were to use this code, it could possibly be referencing the wrong script. I haven't checked this issue yet. Typically I add new script tags with document.body.appendChild (or equivalent in a library), so it's not that big an issue to me.

Another possible loophole is if a new script has been appended to document.body before getActiveScript has been called. Again, I haven't tested it, but it may mean that the last selected script evaluates to on that's different than the one being executed.


Actual Usage:

The question was asked of why I wanted to select the currently evaluating script element. Although "Because I can" would probably be understood, I did have a legitimate reason to want to use this feature/functionality/dirty-nasty-hack.

I created a (couple) jQuery plugin(s) to do what I originally wanted.

jQuery Plugin: jquery.activescript.js

(function($){
  "use strict";
  $.activeScript = function(){
    var r;
    r=document.readyState;
    return r && r != 'complete' ? $('script:last') : $();
  };
})(jQuery);

jQuery Plugin: jquery.activescript.plugin.js

by default works for jQuery UI

(function($){
  "use strict";
  var plugins,d,p,$p;
  d = $.activeScript().data();
  plugins = d.plugins || 'draggable droppable resizable selectable sortable accordion autocomplete button datepicker dialog progressbar slider tabs';
  plugins=plugins.split(' ');
  $(function(){
    while(p=plugins.pop())
    {
      $p=$(d[p+'Selector']);
      if ($p[p])$p[p]();
    }
  });
})(jQuery);

The way you'd use jquery.activescript.plugin.js is as follows:

<script type="text/javascript" src="jquery.activescript.plugin.js"
  data-draggable-selector=".draggable.default"
  data-droppable-selector=".droppable.default"
  data-resizable-selector=".resizable.default"
  data-selectable-selector=".selectable.default"
  data-sortable-selector=".sortable.default"
  data-accordion-selector=".accordion.default"
  data-autocomplete-selector=".autocomplete.default"
  data-button-selector=".button.default"
  data-datepicker-selector=".datepicker.default"
  data-dialog-selector=".dialog.default"
  data-progressbar-selector=".progressbar.default"
  data-slider-selector=".slider.default"
  data-tabs-selector=".tabs.default"></script>

This would allow you to semantically tie in your default plugins to your page without having to muck about in a JS file. If non-defaults are needed, you should muck about in a JS file, so I haven't added any mechanism for specifying options (although a few plugins could really use it).

This same basic activescript mechanism could be used by standalone plugins to have an easier way of overriding defaults.


Inside your included script:

(function($){
    var $current_script = $('script:last');
})(jQuery);

JavaScript is a top to bottom language, so, the last script tag being executed will be the current one.


You could scan the innerHTML of the various scripts, although that won't work too well for included scripts.

$('script').filter(function () {
  return this.innerHTML.indexOf('alert(this)')==0;
});

Also, this would require you to figure out some string unique to that particular script. Unless, of course, you like using magic numbers and would rather just directly access, say, the fourth script on the page. Which'll just be $('script')[3], due to 0-indexing.

0

精彩评论

暂无评论...
验证码 换一张
取 消