2015-07-25 12 views
1

Я пытаюсь добавить элемент <img> в файл <span> в скрипте содержимого моего расширения chrome. Однако кажется, что приложение добавляет эффект только тогда, когда я добавляю в body из document, как описано в content-script.js. Для воспроизведения этого нажмите на следующую ссылку и открытой средства разработки:Не удалось добавить <img> в <span> в сценарии содержимого расширения Chrome

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

Поиск для <img> которого id является seenIcon. Он будет определен при добавлении в 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

seen.png

Почему изменения не отражаются в DOM?

ответ

3

Узел воссоздан сайтом, поэтому вам нужно немного подождать после его первого появления и только затем добавить новое изображение.

Я проверил его с помощью простого пользовательского слова с 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 «s-х target имеет finnPoiLayer в своем списке класса. Но он будет склонен ломаться, когда макет сайта немного изменится.

+0

Первоначально я использовал MutationObserver и получил несколько цепей функций, которые очень похожи на функцию setMutationHandler(), указанную выше, поэтому я переключился на простой таймер согласно [this] (http: // stackoverflow .com/questions/13917047/how-to-get-a-content-script-to-load-after-a-pages-javascript-has-execute/13917682 # comment51201657_13917682) совет. Я не знал, что вы можете наблюдать, как вложенные дети добавляются с помощью 'MutationObserver' ... Я вижу, что аргумент' поддерева 'мог бы быть весьма полезен, чтобы избежать этих цепей. :) – Mitch

+0

Я пробовал это, но '' все еще не создается для меня, используя мою исходную ссылку. Я добавил пару 'console.log()' 'в обратном вызове' load' и перед вызовом 'insertAdjacentHTML()', но ничего не было напечатано. Я также дал '' '' id', но не смог найти его после загрузки страницы. – Mitch

+0

Ваш код работает с 'if (document.readyState ===" complete ")' check, thanks! Возможно, стоит добавить это к вашему ответу, если у кого-то другая проблема. – Mitch

 Смежные вопросы

  • Нет связанных вопросов^_^