查找当前脚本的推荐方法?

发布于 2024-10-02 05:51:35 字数 910 浏览 3 评论 0原文

我正在编写一个脚本,需要将 DOM 元素添加到页面中脚本所在的位置(类似于小部件的方法)。 最好的方法是什么?

以下是我正在考虑的技术:

  1. 在脚本正上方包含一个带有 id="Locator" 的元素。问题:
    • 我不喜欢额外的标记
    • 如果我在页面中重复使用该小部件,则多个元素将具有相同的“定位器”id。我正在考虑在脚本中添加一行来删除曾经使用过的 id,但仍然......
  2. 向脚本添加一个 id。问题:
    • 尽管它似乎有效,但 id 属性对于脚本元素无效
    • 与上面相同的问题,如果我在页面中重复使用脚本,多个元素将具有相同的 id。
  3. 使用 getElementsByTagName("script") 并选择最后一个元素。到目前为止,这对我有用,它看起来有点重,我不确定它是否可靠(考虑延迟脚本)
  4. document.write:不优雅,但似乎可以完成工作。

  5. [编辑]根据idealmachine的回复,我正在考虑另一种选择:

    • 在脚本标记中包含一个属性,例如 goal="tabify"。
    • 使用 getElementsByTagName("script") 获取所有脚本。
    • 循环遍历脚本并检查 goal="tabify" 属性以查找我的脚本。
    • 删除目标属性,以防页面中存在其他小部件。
  6. [编辑]另一个想法,也受到迄今为止回复的启发:

    • 使用 getElementsByTagName("script") 获取所有脚本。
    • 循环遍历脚本并检查innerHTML 以找到我的脚本。
    • 在脚本末尾,删除脚本标记,以防页面中存在其他小部件。

I am writing a script that needs to add DOM elements to the page, at the place where the script is located (widget-like approach).
What is the best way to do this?

Here are the techniques I am considering:

  1. Include an element with an id="Locator" right above the script. Issues:
    • I don't like the extra markup
    • If I reuse the widget in the page, several elements will have the same "Locator" id. I was thinking about adding a line in the script to remove the id once used, but still...
  2. Add an id to the script. Issues:
    • even though it seems to work, the id attribute is not valid for the script element
    • same issue as above, several elements will have the same id if I reuse the script in the page.
  3. Use getElementsByTagName("script") and pick the last element. This has worked for me so far, it just seems a little heavy and I am not sure if it is reliable (thinking about deferred scripts)
  4. document.write: not elegant, but seems to do the job.

  5. [Edit] Based on the reply from idealmachine, I am thinking about one more option:

    • Include in the script tag an attribute, for example goal="tabify".
    • Use getElementsByTagName("script") to get all the scripts.
    • Loop through the scripts and check the goal="tabify" attribute to find my script.
    • Remove the goal attribute in case there's another widget in the page.
  6. [Edit] Another idea, also inspired by the replies so far:

    • Use getElementsByTagName("script") to get all the scripts.
    • Loop through the scripts and check innerHTML to find my script.
    • At the end of the script, remove the script tag in case there's another widget in the page.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

飘过的浮云 2024-10-09 05:51:35

开箱即用:document.currentScript (不是IE 支持)

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

待"谢繁草 2024-10-09 05:51:35

我曾在 OnlyWire 工作过,该公司提供可放置在您网站上的小部件作为其主要服务。

我们使用 var script = document.getElementsByTagName("script"); var thisScript = scripts[scripts.length - 1]; 这个技巧看起来效果很好。然后我们使用 thisScript.parentNode.insertBefore(ga, thisScript); 在 DOM 树中的前面插入我们想要的任何内容。

我不确定我是否理解为什么您认为这是一个“重型”解决方案......它不涉及迭代,它是一个完美集成的纯粹的跨浏览器解决方案。

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.

慈悲佛祖 2024-10-09 05:51:35

这适用于页面上相同代码的多个副本以及动态插入的代码:

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

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>
淤浪 2024-10-09 05:51:35

document.write 或选择最后一个脚本元素将适用于大多数网页中同步加载的脚本。但是,我认为有一些选项您没有考虑允许异步加载:

  • 在脚本之前添加带有 class="Locator"div 。 HTML 类的优点是重复项不会无效。当然,为了处理多个小部件的情况,您需要在添加 HTML 元素后更改元素的类名称,这样就不会添加两次。 (请注意,一个元素也可能是多个类的成员;它是一个以空格分隔的列表。)

  • 检查每个脚本元素的 src 可以确保跟踪代码( 例如 Google Analytics 旧版跟踪代码)和在页面最后加载的其他脚本在使用异步加载时不会阻止您的脚本正常工作。同样,要处理多个小部件的情况,您可能需要在使用完毕后删除脚本元素(当所需的代码已添加到页面时)。


我要提出的最后一个评论(尽管您可能已经意识到这一点)是,在编写小部件时,您需要使用 var 声明所有变量并包含所有变量代码:(JSLint 可以帮助检查这一点)

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

这被称为“自动执行函数”,并将确保脚本中使用的变量不会干扰网页的其余部分。

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.

伏妖词 2024-10-09 05:51:35

无论您放入

但是,如果您需要在小部件所在的位置添加脚本标记,我不明白使用 document.write() 放置 div 有什么问题。

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.

故笙诉离歌 2024-10-09 05:51:35

我刚刚找到了另一种似乎可以回答我的问题的方法:

如何从 javascript 访问父 Iframe

将脚本嵌入到 iframe 中可以随时找到它,因为脚本始终保留对其自己窗口的引用。

我认为这是最好的方法,因为无论您将脚本添加到页面多少次(想想小部件),它总是有效。欢迎您发表评论。

首先促使我考虑 iframe 的是我为构建 Google 小工具所做的一个实验。

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.

著墨染雨君画夕 2024-10-09 05:51:35

在许多情况下,这很有效(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; 
      }

 }

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

 }
蘑菇王子 2024-10-09 05:51:35

您还可以在其中添加单个脚本的名称。

  • 在一些js脚本

     数据集['my_prefix_name'] = 'someScriptName'
    
  • 内,要么在 HTML 内 - 在

并通过循环 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
    }
 }

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
    }
 }
隔岸观火 2024-10-09 05:51:35

我从那时起就无法访问 Internet Explorer,但这应该几乎可以在任何地方工作:

<script src="script.js"
    data-count="30"
    data-headline="My headline"
    onload="uniqueFunctionName(this)"
    defer
    ></script>

并且在 script.js 中:

window.uniqueFunctionName = function (currentScript) {
   var dataset = currentScript.dataset
   console.log(dataset['count'])
   console.log(dataset['headline'])
}

I haven't had access to internet explorer since forever, but this should work pretty much everywhere:

<script src="script.js"
    data-count="30"
    data-headline="My headline"
    onload="uniqueFunctionName(this)"
    defer
    ></script>

and inside script.js:

window.uniqueFunctionName = function (currentScript) {
   var dataset = currentScript.dataset
   console.log(dataset['count'])
   console.log(dataset['headline'])
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文