【问题标题】:Unable to access DOM elements in Firefox Add-on content script无法访问 Firefox 附加内容脚本中的 DOM 元素
【发布时间】:2014-12-22 17:26:56
【问题描述】:

使用 Firefox 34 和插件 SDK 1.17。

我正在使用 SDK 的 page-mod 来附加内容脚本。在内容脚本中,我在尝试访问 DOM 元素时看到了非常奇怪的行为。

main.js

pageMod.PageMod({
    include: "somewebsite",
    contentScriptWhen: 'end',
    contentScriptFile: [data.url("stuff.js")]
});

stuff.js

log(document.getElementsByTagName("body")); // empty object
log(document.getElementById("SomeIdThatShouldBeThere")); // empty object
log(document.getElementsByTagName("li")); // x amount of empty objects...

这将按预期工作:

document.body.style.border = "5px solid red";

对于我得到的空对象我也可以做

obj.style.border = ...

它会起作用,看到 html 元素会改变边框颜色等。但我无法读取元素的属性,所以我在盲目工作。

我读到有人说从内容脚本修改 DOM 有一些限制,但我显然连最基本的事情都做不了。这应该支持还是不支持?

edit:最终我注意到元素位于正确的位置并且我可以读取它们的属性,但是记录元素仍然只会打印一个空对象...这意味着元素的每个所需属性都必须单独打印.至少它有效,但可能会更好。

【问题讨论】:

  • 你试过用unsafeWindow.document代替document吗?
  • 好像没什么区别。
  • 顺便说一句,您的代码中有错字。它应该是getElementById,而不是getElementsById(注意s)。但我不明白为什么getElementsByTagName 返回空对象。您是否在控制台中看到这些空对象?
  • squint:我得到了页面上应该显示的元素的实际数量。就在我打印单个元素时,它看起来像一个没有任何属性的空对象。属性仍然可以正常访问
  • 不知道如果你最终得到了这个,但我遇到了同样的问题并且做了更多的研究我怀疑它与内容脚本如何与 DOM 隔离有关@ 987654321@

标签: firefox firefox-addon-sdk content-script


【解决方案1】:

如果要将对象从 do​​m 输出到控制台,请使用:

unsafeWindow.console.log(document.getElementById("SomeIdThatShouldBeThere"));
// Or map it in your contentscript file for less typing
var log = unsafeWindow.console.log;
log(document.getElementById("SomeIdThatShouldBeThere"));

这也可以工作,而无需进入 about:config 并添加值为“all”的首选项“extensions.sdk.console.logLevel”,因此您可以记录任何您想要的消息。

但是,如果你还运行 sdk cmd 控制台,这会输出一个错误,但我认为这没什么好担心的,所有代码执行都没有问题。

编辑: 刚刚发现当我将它映射到var log时,如果没有打开firebug控制台,它会导致加载项停止工作,并且在打开firefox控制台时仍然无法工作。但是做一个海峡 unsafeWindow.console.log(foo) 工作正常。

【讨论】:

    【解决方案2】:

    我也有同样的问题。它使基本的脚本编写更加繁琐。

    试试这个(来自http://louisremi.com/2011/12/07/mozilla-addons-interactions-between-content-scripts-and-pages/

    "内联脚本注入

    这样做的正确方法是在页面中注入内联脚本和/或使用 customEvents。内联脚本是第三级脚本,可用于在全局范围内创建变量或函数:

    // Quotes nesting would be a real mess now,
    // let's use a separate file loaded as a contentScriptFile
    var script = document.createElement( "script" );
    script.innerHTML = "var test =" + JSON.stringify( anyValue )+";";
    document.body.appendChild( script );
    

    验证此代码将输出警告,因为插件不应创建脚本标签。但这仍然是 unsafeWindow 最安全的替代方案。

    自定义事件

    customEvents 与鼠标事件非常相似,不同之处在于它们是通过编程方式触发的,并且它们可以在内容脚本和页面之间双向传输任意(jsonable)数据:

    // inline script in example.com/index.html
    var evt = document.createEvent("CustomEvent");
    evt.initCustomEvent( "transData", true, false, jsonableValue );
    window.dispatchEvent(evt);
    // in contentScript.js
    window.addEventListener( "transData", function( event ) {
      // the data is available in the detail property of the event
      self.port.emit( "transData", event.detail );
    });"
    

    【讨论】:

      【解决方案3】:

      我在插件的内容脚本中遇到了同样的问题。出于某种未知原因,如果您将object 的值复制到新对象,则可以将它们打印到控制台。您可以创建一个简单的函数作为解决方法:

      function getLoggableObject(obj){
          var loggable={};
          for(var key in obj){
              loggable[key]=obj[key];
          }
          return loggable;
      }
      

      下面是调用这个函数的例子:

       console.log("default  : ", $("table")[0]);
       console.log("loggable : ", getLoggableObject($("table")[0]));
      

      以及这些日志语句的输出:

      "default  : " Object {  }
      "loggable : " Object { createCaption: "function createCaption() {
          [native code]
      }", deleteCaption: "function deleteCaption() {
          [native code]
      }", createTHead: "function createTHead() {
          [native code]
      }", deleteTHead: "function deleteTHead() {
          [native code]
      }", createTFoot: "function createTFoot() {
          [native code]
      }", deleteTFoot: "function deleteTFoot() {
          [native code]
      }", createTBody: "function createTBody() {
          [native code]
      }", insertRow: "function insertRow() {
          [native code]
      }", deleteRow: "function deleteRow() {
          [native code]
      }", caption: null, 210 more… }
      

      【讨论】:

        【解决方案4】:

        变化:

        log(document.getElementsByTagName("body")); // empty object
        log(document.getElementById("SomeIdThatShouldBeThere")); // empty object
        log(document.getElementsByTagName("li")); // x amount of empty objects...
        

        变成这样:

        console.log(document.getElementsByTagName("body")); // empty object
        console.log(document.getElementById("SomeIdThatShouldBeThere")); // empty object
        console.log(document.getElementsByTagName("li")); // x amount of empty objects...
        

        【讨论】:

        • 我做了 var log = console.log;在一开始的时候。但无论如何我回家后都会尝试,永远不知道。
        • 抱歉耽搁了。它没有任何区别
        猜你喜欢
        • 1970-01-01
        • 2017-07-23
        • 1970-01-01
        • 1970-01-01
        • 2012-12-21
        • 1970-01-01
        • 2013-04-13
        • 1970-01-01
        • 2018-01-29
        相关资源
        最近更新 更多