【问题标题】:Unable to append <img> into <span> in content script of Chrome extension无法在 Chrome 扩展的内容脚本中将 <img> 附加到 <span>
【发布时间】:2015-10-16 07:48:32
【问题描述】:

我正在尝试将 &lt;img&gt; 元素附加到我的 chrome 扩展的内容脚本中的 &lt;span&gt; 中。但是,似乎只有当我追加到documentbody 时,追加才有效,如content-script.js 中所述。要重现这一点,请单击以下链接并打开开发工具:

http://kart.finn.no/?mapType=norge&tab=soek_i_annonser&searchKey=search_id_realestate_lettings&mapTitle=Kart+over+bolig+til+leie+&ztr=1&

搜索&lt;img&gt;,其idseenIcon。它将在附加到 body 时定义,但在所有其他情况下 undefined

manifest.json

{
    "manifest_version": 2,

    "name": "Finn.no Property Blacklist",
    "description": "Hides finn.no property search results that you've marked as \"seen\".",
    "version": "1.0",

    "permissions": [
        "activeTab",
        "http://kart.finn.no/*",
        "storage"
    ],
    "content_scripts": [
        {
            "matches": ["http://kart.finn.no/*"],
            "js": ["content-script.js"]
        }
    ],
    "web_accessible_resources": [
        "*.png"
    ]
}

content-script.js

console.log("content script!")

function getIconSpanIfExists() {
    var spanClassName = "imagePoi";
    var matchingElements = document.getElementsByClassName(spanClassName);
    if (matchingElements.length > 1) {
        console.error(failureMessage("wasn't expecting more than one element with class name " + spanClassName));
        return null;
    }

    if (matchingElements.length === 0) {
        return null;
    }

    return matchingElements[0].parentNode;
}

function htmlReady() {
    return getIconSpanIfExists();
}

function addIcons() {
    var iconSpan = getIconSpanIfExists();

    // Append into body - works.
//    var icon = document.createElement("img");
//    icon.id = "seenIcon";
//    icon.src = chrome.extension.getURL("seen.png");
//    document.body.appendChild(icon);
//    console.log("appended " + icon.id + " into body");

    // Append into span - doesn't work, even though it says childNodes.length is 2.
    var icon = document.createElement("img");
    icon.id = "seenIcon";
    icon.src = chrome.extension.getURL("seen.png");
    icon.style.left = "200px";
    icon.style.top = "200px";
    iconSpan.appendChild(icon);
    console.log("appended " + icon.id + " into span with class imagePoi" + " new children: " + iconSpan.childNodes.length);

    // Modify innerHTML of span - doesn't work, even though innerHTML has the icon.
//    iconSpan.innerHTML += "\n<img id=\"seenIcon\""
//        + "src=\"" + chrome.extension.getURL("seen.png") + "\""
//        + "style=\"left: 200px; top: 200px;\">";
//    console.log(iconSpan.parentNode.id, iconSpan.innerHTML);
}

function init() {
    console.log("initialising content script");

    if (!htmlReady()) {
        console.log("not all HTML is loaded yet; waiting");

        var timer = setInterval(waitForHtml, 200);

        function waitForHtml() {
            console.log("waiting for required HTML elements...");
            if (htmlReady()) {
                clearInterval(timer);
                console.log("... found them!");
                addIcons();
            }
        }

        return;
    }
}

if (document.readyState === "complete") {
    console.log("document is complete")
    init();
} else {
    console.log("document is not yet ready; adding listener")
    window.addEventListener("load", init, false);
}

seen.png

为什么更改没有反映在 DOM 中?

【问题讨论】:

    标签: javascript html dom google-chrome-extension content-script


    【解决方案1】:

    该节点由站点重新创建,因此您需要在它首次出现后稍等片刻,然后才添加新图像。

    我已经使用 MutationObserver 使用简单的用户脚本对其进行了测试,每次将 .imagePoi 添加到文档时都会添加新图标,包括前两次出现以及随后的放大/缩小。

    setMutationHandler(document, '.imagePoi', function(observer, node) {
      node.parentNode.insertAdjacentHTML('beforeend',
        '<img src="http://www.dna-bioscience.co.uk/images/check-mark.gif">');
    });
    
    function setMutationHandler(baseNode, selector, cb) {
      var ob = new MutationObserver(function(mutations) {
        for (var i=0, ml=mutations.length, m; (i<ml) && (m=mutations[i]); i++)
          for (var j=0, nodes=m.addedNodes, nl=nodes.length, n; (j<nl) && (n=nodes[j]); j++)
            if (n.nodeType == 1) 
              if (n = n.matches(selector) ? n : n.querySelector(selector))
                if (!cb(ob, n))
                  return;
      });
      ob.observe(baseNode, {subtree:true, childList:true});
    }
    

    您可以利用.imagePoi 的突变记录的target 在其类列表中具有finnPoiLayer 这一事实来简化处理程序。但是当站点布局稍有变化时,它很容易崩溃。

    【讨论】:

    • 我最初使用MutationObserver,最后得到了几个看起来与上面的setMutationHandler() 函数非常相似的函数链,所以我按照this 的建议切换到一个简单的计时器。我不知道您可以观察到使用MutationObserver 添加嵌套子级...我看到subtree 参数对于避免这些链可能非常有用。 :)
    • 我试过了,但仍然没有使用我的原始链接为我创建 &lt;img&gt;。我在load 回调和insertAdjacentHTML() 调用之前添加了几个console.log()s,但没有打印任何内容。我还给了&lt;img&gt;id,但在页面加载后找不到它。
    • 您的代码可以使用if (document.readyState === "complete") 检查,谢谢!如果其他人有同样的问题,可能值得将其添加到您的答案中。
    • 对了,为什么第一次断开?让它保持连接还不够吗?
    • 我断开它以跳过第一次做这项工作,但显然不需要。
    猜你喜欢
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 2021-06-15
    • 1970-01-01
    • 2014-11-01
    相关资源
    最近更新 更多