2010-11-13 3 views
7

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

Вот методы Я рассматривающие:

  1. Включить элемент с идентификатором = «Локатор» прямо над сценарием. Проблемы:
    • Мне не нравится дополнительная разметка
    • Если я повторно использую виджет на странице, у нескольких элементов будет одинаковый идентификатор «Локатор». Я думал о добавлении строки в сценарий для удаления идентификатора, когда-то используемого, но все же ...
  2. Добавить id в сценарий. Вопросы:
    • хотя это, кажется, работает, атрибут ID не является допустимым для сценария элемента
    • же вопрос, как и выше, несколько элементов будут иметь тот же идентификатор, если я повторно использовать скрипт на этой странице.
  3. Используйте getElementsByTagName («script») и выберите последний элемент. Это до сих пор работало для меня, это кажется немного тяжелым, и я не уверен, что он надежный (думая об отложенных сценариях)
  4. document.write: не элегантный, но, похоже, выполняет эту работу.

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

    • Включить в тэгом атрибут, например, цель = «tabify».
    • Используйте getElementsByTagName («script»), чтобы получить все скрипты.
    • Прокрутите скрипты и проверьте атрибут goal = "tabify", чтобы найти мой скрипт.
    • Удалить атрибут цели, если на странице есть другой виджет.
  6. [править] Еще одна идея, также вдохновлена ​​ответов до сих пор:

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

ответ

0

Я просто нашел еще один способ, который, кажется, ответить на мой вопрос:

How to access parent Iframe from javascript

Встраивание скрипта в IFRAME позволяет разместить его в любое время, так как сценарий всегда держит ссылку на своем собственном окне.

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

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

1

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

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

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

+0

хорошо, "тяжелые" по сравнению с прямым getElementById. Но я понимаю, что это не так. – Christophe

1

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

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

+2

Неверно, что 'document.write()' only "работает", когда страница по-прежнему загружается. Если вы выполняете 'document.write()' в скрипте, который вы добавляете на страницу после onload (... или что-то, не уверенное в точном точках перегиба), эффект выглядит так, как если бы предыдущая страница была удалена к тому, что пишут, с результатом будет страница, содержащая * только * код, который был просто записан в документ. –

+0

Ну, я предпочитаю другой путь. Я не сталкивался с тем, что вы описали. В большинстве браузеров при обстоятельствах, которые я видел, они перестанут загружать другие вещи, пока ваш javascript не будет загружен - вот почему это замедляет время загрузки. – aptwebapps

+0

Еще одна проблема, с которой я сталкиваюсь с document.write: могут ли элементы, включенные таким образом, манипулировать методами DOM, как и стандартные элементы? Или есть какие-то ограничения? – Christophe

1

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

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

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


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

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

Это было названо «прямоприменяемой функцией» и гарантирует, что переменные, используемые в сценарии не мешать остальной веб-страницы.

+0

Я использую самопроизвольные функции. Удаление сценария не является вариантом, так как виджет включает взаимодействие. Я думал об использовании класса, но тогда захват элемента не так прост, как с id. Мне нравится идея проверки src или другого атрибута тега скрипта, это может помочь определить правильный. – Christophe

+0

@ Кристофе: Я не имею в виду фактически удаление самого скрипта. После того, как скрипт уже загружен и выполнен, можно удалить элемент сценария, который его загрузил (конечно, после добавления div, который будет содержать динамически сгенерированный код). – PleaseStand

+0

Я написал «еще один атрибут тега скрипта», но потом понял, что их не так много ... Ну, может быть, я мог бы составить такой тип, как Microsoft, для плагина templating jQuery (text/x-jquery- TMPL). – Christophe

4

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

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

Я занимаюсь поддержкой браузера (querySelector), но кроме этого это выглядит очень интересно! Дайте мне время, чтобы полностью это понять ;-). Еще одна проблема, которую я испытываю, заключается в том, что querySelector может возвращать другой скрипт на той же странице, и текущий скрипт никогда не будет выполнен. – Christophe

3

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

+0

Спасибо! К сожалению, не поддерживается всеми основными браузерами. – Christophe

+0

@Christophe Вы можете полилизовать его или использовать ранее существовавший полиполк, но вы правы. –

+0

Я сделал быстрый поиск, но не смог найти полиполк, который работает с IE11. – Christophe

0

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

} 
0

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

  • либо в некоторых JS-скрипт

    dataset['my_prefix_name'] = 'someScriptName' 
    
  • или внутри HTML - в < сценарии > тег

    data-my_prefix_name='someScriptName' 
    

и следующий поиск соответствую priate один обернув над document.scripts массив:

... 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 
    } 
} 
Смежные вопросы