2016-11-11 9 views
0

すべての段落(タグコンテンツ)を取り込んで、各単語をボタンに入れるGoogle Chrome拡張機能を開発しています。それは私が取り組んでいる大きなプログラムの一部です。私はJSFiddleにアプリのその部分の作業コピーを持っています。ウェブページの段落の各単語をそのテキストを含むボタンに置​​き換えます。

ここで、そのコードをChrome拡張機能に移植しようとしています。しかし、私は自分のバックグラウンドスクリプトからDOMにアクセスすることができないので、私のコードでそれを操作することができます(私の関数では)。私はまだ機能を呼び出すことさえしていません。なぜなら、最初にDOMを編集するはずがないから、のbackground.jsの中で私は理解できないからです。ここで

は私のコードです:

manifest.jsonを

{ 
    "manifest_version": 2, 
    "name": "Test Extension", 
    "version": "1", 
    "background": { 
    "persistent": false, 
    "scripts": ["background.js","jquery-3.0.0.min.js","TextSplitter.js"] 
    }, 
    "content_scripts": [{ 
    "matches": ["<all_urls>"], 
    "js": ["content.js"] 
    }], 
    "browser_action": { 
    "default_title": "Test Extension" 
    }, 
    "permissions": ["activeTab","tabs"] 
} 

content.js

// Listen for messages 
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { 
    // If the received message has the expected format... 
    if (msg.text === 'report_back') { 
     // Call the specified callback, passing 
     // the web-page's DOM content as argument 
     sendResponse(document); 
    } 
}); 

background.js

// A function to use as callback 
function doStuffWithDom(domContent) { 
    console.log('I received the following DOM content:\n'); 
    console.log(JSON.stringify(domContent)); 
    var domAccess = $(domContent); 
    var myText = $(domAccess).find("p").text(); 
    console.log("THIS IS MY TEXT: " + myText); 
} 

chrome.tabs.onUpdated.addListener(function (tabID, info, tab) { 
    console.log("Status: " + info.status); 
    if (info.status == "complete") { 
     chrome.tabs.sendMessage(tab.id, { text: 'report_back' }, doStuffWithDom); 
    } 
}); 

TextSplitter.js

function FormatText(domObject) { 
    var pElements = []; // Holds the split paragraphs for each p tag 
    var pElementIndex = 0; 

    //Loop through each p tag in web page 
    $("p").each(function (webPElementIndex, webPElement) { 
     var jQObjWebPElement = $(webPElement);// Convert p element to jQuery Obj 
     // split current paragraph element text into an array of seperate words 
     pElements[webPElementIndex] = jQObjWebPElement.text().split(" "); 
    }); 

    //Clear text out of all p elements 
    $("p").empty(); 

    //Loop through p elements in the webpage to add back text with spans around each word 
    $("p").each(function (webPElementIndex, webPElement) { 
     // convert current web page element to jQuery Obj 
     var jQObjWebPElement = $(webPElement); 
     // Loop through each word stored in each stored paragraph element 
     $.each(pElements[pElementIndex], function (pElementWordIndex, pElementWord) { 
      var jQObjPElementWord = $(pElementWord); // convert element to jQuery object 
      jQObjWebPElement.append($("<button>") 
          .text(pElements[pElementIndex][pElementWordIndex])); 
     }); 
     pElementIndex = pElementIndex + 1; 
    }); 
} 

私は特にChromeの拡張機能では、一般的にはDOMでの作業に非常に新しいですと自分の無知をご容赦ください。

+2

[extensions overview](https://developer.chrome.com/extensions/overview#arch)を参照してください:コンテンツスクリプトが必要です。 – wOxxOm

+0

バックグラウンドスクリプトを削除し、機能をコンテンツスクリプトに移動します。あなたのバックグラウンドスクリプトはDOMに直接アクセスできないので、コンテンツスクリプトでHTMLの処理と変更を行う必要があります。メッセージングパス不要 – nick

答えて

3

あなたのコードは、いくつかの領域で非常に複雑に見えます。特に、DOMはコンテンツスクリプトからのみ操作できます。コメントにwOxxOmが記載されているので、Chrome extension architecture overviewを読むことをお勧めします。それは、物事が一般的にどのように行われ/整理されるかを理解するのに役立つ全体的なアーキテクチャ情報を持っています。

次の完全な拡張機能(ChromeとFirefoxでテスト済み)は、空白文字(または行/段落の先頭または末尾)で囲まれた非空白文字をすべて<button>に変更します。これは、ブラウザのユーザーインターフェイスでactionButtonがクリックされたときに実行されます。

actionButtonをクリックすると、contentScript.jsファイルが挿入されます。コンテンツスクリプトは変更を行い、終了します。この機能のために、単純な機能を実行するためにメッセージを受け取るのを待っているページに座っているコンテンツスクリプトは必要ありません。実際にコードで記述/表示された以上のことをしているかもしれませんが、質問に記載されている機能については、tabs.executeScript()というスクリプトを注入するほうが、より良い、より複雑でない、より効率的な選択です。

私はjQueryを使用しないことを選択しました。 jQueryは多くのものに適しています。この例では、株式JavaScriptを使用して同じことを達成する代わりに、わずか数文字を保存するために90 KiBのコードをロードすることのトレードオフが好きではありませんでした。

ボタン化を実行するために使用しているコードをよく見ていませんでした。私はすでにanother answerのコードを持っていて、このタスクを実行するために簡単に適応することができました。あなたの質問は、あなたのボタン化コードの機能性ではなく、DOMを操作する方法に関するものだったので、私はすでに慣れ親しんだコードを使用することにしました。

アクションに拡張:

button-izing example.com

manifest.jsonを

{ 
    "description": "Inject content script to make all words in <p> elements buttons", 
    "manifest_version": 2, 
    "name": "Button all words in <p>", 
    "version": "0.1", 

    "permissions": [ 
     "activeTab" 
    ], 

    "background": { 
     "scripts": [ 
      "background.js" 
     ] 
    }, 

    "browser_action": { 
     "default_icon": { 
      "32": "myIcon.png" 
     }, 
     "default_title": "Make Buttons" 
    } 
} 

background.js

chrome.browserAction.onClicked.addListener(function(tab) { 
    //Inject the script to change the text in <p> to buttons 
    chrome.tabs.executeScript(tab.id,{file: 'contentScript.js'}); 
}); 

contentScript.js

(function(){ 
    function handleTextNode(textNode) { 
     if(textNode.nodeName !== '#text' 
      || textNode.parentNode.nodeName === 'SCRIPT' 
      || textNode.parentNode.nodeName === 'STYLE' 
     ) { 
      //Don't do anything except on text nodes, which are not children 
      // of <script> or <style>. 
      return; 
     } 
     let origText = textNode.textContent; 
     let newHtml=origText.replace(/(^|\s)(\S+)(?=\s|$)/mg, '$1<button>$2</button>'); 
     //Only change the DOM if we actually made a replacement in the text. 
     //Compare the strings, as it should be faster than a second RegExp operation and 
     // lets us use the RegExp in only one place for maintainability. 
     if(newHtml !== origText) { 
      let newSpan = document.createElement('span'); 
      newSpan.innerHTML = newHtml; 
      textNode.parentNode.replaceChild(newSpan,textNode); 
     } 
    } 

    //Find all text node descendants of <p> elements: 
    let allP = document.querySelectorAll('p'); // Get all <p> 
    let textNodes = []; 
    for (let p of allP) { 
     //Create a NodeIterator to get the text nodes descendants of each <p> 
     let nodeIter = document.createNodeIterator(p,NodeFilter.SHOW_TEXT); 
     let currentNode; 
     //Add text nodes found to list of text nodes to process below. 
     while(currentNode = nodeIter.nextNode()) { 
      textNodes.push(currentNode); 
     } 
    } 
    //Process each text node 
    textNodes.forEach(function(el){ 
     handleTextNode(el); 
    }); 
})(); 

myIcon.png:ノードのテキストを変更するhandleTextNodeのコードをanother answer of mineのコードから変更された

Icojam-Weathy-24-tornado.png

関連する問題