Рекомендуемый метод поиска текущего скрипта?

Я пишу сценарий, который должен добавить элементы DOM на страницу, в том месте, где находится скрипт (виджет-подобный подход). Как лучше всего это сделать?

вот методы, которые я рассматриваю:

  1. включить элемент с идентификатором= "Locator"прямо над скриптом. Проблемы:
    • мне не нравится дополнительная разметка
    • если я повторно использую виджет на странице, несколько элементов будут иметь один и тот же идентификатор" локатора". Я думал о добавлении строки в скрипт для удаления идентификатора, который когда-то использовался, но все же...
  2. добавить код в скрипт. Проблемы:
    • несмотря на то, что он, кажется, работает, атрибут id недопустим для элемента сценария
    • та же проблема, что и выше, несколько элементов будут иметь тот же идентификатор, если я повторно использую скрипт на странице.
  3. используйте getElementsByTagName ("скрипт") и выберите последний элемент. Это сработало для меня до сих пор, это просто кажется немного тяжело, и я не уверен, что это надежно (думая об отложенных скриптах)
  4. документ.напишите: не элегантно, но, кажется, делает свою работу.

  5. [Edit] основываясь на ответе idealmachine, я думаю еще об одном варианте:

    • включить в тег скрипта атрибут, например goal= "tabify".
    • используйте getElementsByTagName ("скрипт"), чтобы получить все скрипты.
    • цикл через скрипты и проверить атрибут goal= "tabify", чтобы найти мой скрипт.
    • удалите атрибут цели, если на странице есть другой виджет.
  6. [Edit] еще одна идея, также вдохновленная ответами до сих пор:

    • используйте getElementsByTagName ("скрипт"), чтобы получить все скрипты.
    • цикл через скрипты и проверьте innerHTML, чтобы найти мой скрипт.
    • в конце скрипта удалите тег скрипта, если есть другой виджет на страницах.

8 ответов


это работает с несколькими копиями одного и того же кода на странице, а также с динамически вставленным кодом:

<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>

"из коробки": документ.currentScript (не поддерживается IE)


Я работал на OnlyWire в которой указано, как их основной сервис, виджет для размещения на вашем сайте.

мы используем var scripts = document.getElementsByTagName("script"); var thisScript = scripts[scripts.length - 1]; трюк, и он, кажется, работает довольно хорошо. Тогда мы используем thisScript.parentNode.insertBefore(ga, thisScript); чтобы вставить все, что мы хотим перед ним, в дерево DOM.

Я не уверен, что понимаю, почему вы считаете это "тяжелым" решением... он не включает итерацию, это чистое кросс-браузерное решение, которое отлично интегрируется.


или document.write или выбор последнего элемента скрипта будет работать для синхронно загруженные скрипты на большинстве веб-страниц. Тем не менее, есть несколько вариантов, которые я могу думать о том, что вы не рассматривали для асинхронной загрузки:

  • добавлять div С class="Locator" перед тем, как сценарий. HTML классы имеет то преимущество, что дубликаты не недействительным. Конечно, чтобы справиться с несколькими виджетами, вы захотите изменить имя класса элемента при добавлении HTML-элементов, чтобы вы не добавляли их дважды. (Обратите внимание, что элемент также может быть членом нескольких классов; это список, разделенный пробелом.)

  • проверка src каждого элемента скрипта может гарантировать, что код отслеживания (например Google Analytics legacy tracking code) и другие скрипты, загруженные в самом конце страницы, не помешают вашему скрипту работать должным образом при асинхронной загрузке используемый. Опять же, чтобы обработать несколько виджетов, вам может потребоваться удалить элементы скрипта, когда вы закончите с ними (то есть когда необходимый код был добавлен на страницу).


один последний комментарий, который я сделаю (хотя вы, возможно, уже знаете об этом), заключается в том, что при кодировании виджета вы нужно чтобы объявить все ваши переменные, используя var и заключите весь код в: (JSLint может помочь проверить это)

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

этот называется "самоисполняющейся функцией" и гарантирует, что переменные, используемые в вашем скрипте, не будут мешать остальной части веб-страницы.


Если вы уроните <script> tag in или a <div class="mywidget">, вы добавляете что-то к разметке. Лично я предпочитаю последнее, так как сам скрипт добавляется только один раз. Слишком много сценариев в теле страницы может замедлить время загрузки страницы.

но если вам нужно добавить тег скрипта, где будет виджет, я не вижу, что не так с использованием document.write() разместить div.


Я только что нашел другой метод, который, кажется, отвечает на мой вопрос:

как получить доступ к родительскому Iframe из javascript

встраивание скрипта в iframe позволяет найти его в любое время, так как скрипт всегда сохраняет ссылку на собственное окно.

Я голосую за этот лучший подход, так как он всегда будет работать независимо от того, сколько раз вы добавляете скрипт на страницу (думаю, виджет). Вы можете прокомментировать.

Что подтолкнуло меня рассмотреть iframes в первую очередь был эксперимент, который я сделал, чтобы построить гаджет Google.


во многих случаях это хорошо работает (hud.js-это имя 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; 
      }

 }

также вы можете добавить имя отдельного скрипта внутри них.

  • или внутри JS-скрипт

     dataset['my_prefix_name'] = 'someScriptName'
    
  • или внутри HTML-код - в теге

     data-my_prefix_name='someScriptName'
    

и следующий поиск соответствующий, зацикливаясь документ.скрипты время:

 ... 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
    }
 }