2015-12-26 17 views
17

Chrome拡張機能を構築しています。私は、拡張機能の各ページと、ユーザーがブラウザで表示しているページとの通信をアプリにさせようとしています。私は拡張からdomにアクセスし、それを更新する必要があります。Chrome拡張機能でDOMコンテンツを変更する

manifest.json 
popup.html 
popup.js 
background.js 
content.js 

と現在表示されているページ。

私の目標はページの負荷です。domを変更し、ユーザーに新しいバージョンのページを表示します。 のpopup.jsユーザーは、ポップアップにキーワードを入力することができます。キーワードはlocalStorageに保存され、ウェブを閲覧している間はキーワードが表示されているページに見つかった場合は、そのキーワードの親divを非表示にすることでキーワードを見落とします。

私はそれぞれのページが通信するのを助ける必要があります。私はpopup.jsの親divを隠している方法はうまくいかないと思います。私は正面からドームを操作する方法を混乱させる。

domをbackground.jsに送信 ページでキーワードを検索し、親divを非表示に変更します。 domを表示ページに戻します。

私はこのURLが私のアプリケーションを実行するURLが一致するが、私はわからないと言っていると思います。

"matches": ["*://*/*"], 

マイmanifest.jsonを

{ 
"name": "Wuno Zensoring", 
    "version" : "1.0", 
    "permissions": [ 
    "activeTab", 
    "tabs", 
    "storage" 
    ], 
    "description": "This extension will search the document file for keywords and hide their parent div.", 
    "icons": {     
    "19": "icon19.png", 
    "38": "icon38.png", 
    "48": "icon48.png", 
    "128": "icon128.png" 
    },  
    "background": { 
    "persistent": false, 
    "scripts": ["jquery-1.11.3.min.js","background.js"] 
    }, 
    "content_scripts": [{ 
     "matches": ["*://*/*"], 
     "js":   ["content.js"], 
     "run_at": "document_end", 
     "all_frames": true 
    }], 
    "web_accessible_resources": [ 
     "popup.js", "content.js" 
     ], 
    "browser_action": { 
    "default_icon": "icon.png128", 
    "default_popup": "popup.html", 
    "default_icon": {     
     "19": "icon19.png", 
     "38": "icon38.png", 
     "48": "icon48.png", 
     "128": "icon128.png"   
    } 
    }, 
    "manifest_version": 2 
} 

popup.html

<!doctype html> 
<html> 
    <head> 
    <title>Wuno Zensorship</title> 
    <script src="jquery-1.11.3.min.js"></script> 
     <script src="popup.js"></script> 
    <link rel="stylesheet" type="text/css" href="styles.css"> 
    </head> 
    <body> 
    <img src="icon48.png"> 

<section> 
<form id="form" action="#" method="POST"> 
<input id="description" name="description" type="text" /> 
<input id="add" type="submit" value="Add" /> 
<button id="clearChecked">Clear Checked Items</button> 
<button id="clear">Clear All</button> 
</form> 
<div id="alert"></div> 
<ul id="keyWords"></ul> 
</body> 
</html> 

popup.js

$(document).ready(function() { 
localArray = []; 

if (!localStorage.keyWords) { 
    localStorage.setItem('keyWords', JSON.stringify(localArray)); 
} 

loadKeyWords(); 

function loadKeyWords() { 
    $('#keyWords').html(''); 
    localArray = JSON.parse(localStorage.getItem('keyWords')); 
    for(var i = 0; i < localArray.length; i++) { 
     $('#keyWords').prepend('<li><input class="check" name="check" type="checkbox">'+localArray[i]+'</li>'); 
     } 
    } 

$('#add').click(function() { 
    var Description = $('#description').val(); 
    if($("#description").val() === '') { 
    $('#alert').html("<strong>Warning!</strong> You left the to-do empty"); 
    $('#alert').fadeIn().delay(1000).fadeOut(); 
    return false; 
    } 
    $('#form')[0].reset(); 
    var keyWords = $('#keyWords').html(); 
    localArray.push(Description); 
    localStorage.setItem('keyWords', JSON.stringify(localArray)); 
    loadKeyWords(); 
    return false; 
}); 

$('#clear').click(function() { 
window.localStorage.clear(); 
location.reload(); 
return false; 
}); 

$('#clearChecked').click(function() { 
    currentArray = []; 
    $('.check').each(function() { 
    var $curr = $(this); 
    if (!$curr.is(':checked')) { 
     var value = $curr.parent().text(); 
     currentArray.push(value); 
     localStorage.setItem('keyWords', JSON.stringify(currentArray)); 
     loadKeyWords(); 
    } else { 
     $curr.parent().remove(); 
    } 
    }); 
}); 


// Update the relevant fields with the new data 
function setDOMInfo(info) { 
    $("div p:contains(localStorage.getItem('keyWords')).parent('div').hide()"); 
} 

// Once the DOM is ready... 
window.addEventListener('DOMContentLoaded', function() { 
    // ...query for the active tab... 
    chrome.tabs.query({ 
    active: true, 
    currentWindow: true 
    }, function (tabs) { 
    // ...and send a request for the DOM info... 
    chrome.tabs.sendMessage(
     tabs[0].id, 
     {from: 'popup', subject: 'DOMInfo'}, 
     // ...also specifying a callback to be called 
     // from the receiving end (content script) 
     setDOMInfo); 
    }); 
}); 


}); // End of document ready function 

background.js

chrome.runtime.onMessage.addListener(function (msg, sender) { 
    // First, validate the message's structure 
    if ((msg.from === 'content') && (msg.subject === 'showPageAction')) { 
    // Enable the page-action for the requesting tab 
    chrome.pageAction.show(sender.tab.id); 
    } 
}); 

content.js

// Inform the background page that 
// this tab should have a page-action 
chrome.runtime.sendMessage({ 
    from: 'content', 
    subject: 'showPageAction' 
}); 

// Listen for messages from the popup 
chrome.runtime.onMessage.addListener(function (msg, sender, response) { 
    // First, validate the message's structure 
    if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) { 
    // Collect the necessary data 
    // (For your specific requirements `document.querySelectorAll(...)` 
    // should be equivalent to jquery's `$(...)`) 
    var domInfo = { 
     total: document.querySelectorAll('*').length, 
     inputs: document.querySelectorAll('input').length, 
     buttons: document.querySelectorAll('button').length 
    }; 

    // Directly respond to the sender (popup), 
    // through the specified callback */ 
    response(domInfo); 
    } 
}); 
+2

背景のページに新しいDOMを作成してコンテンツスクリプトに送るのではなく、ほとんどのページを壊すでしょう。 DOMの操作は、(例えば、スクリプトを必要なロジックでページに挿入するなどして)実行されます。 – gkalpak

+1

コンテンツスクリプトにDOM操作ロジックを置き、HTMLを送信したり、バックグラウンドページやポップアップページでフィルタリングしてコンテンツスクリプトに戻したりする代わりに、キーワードを送信するだけです。 – gkalpak

+0

あなたの問題を完全に解決するわけではありませんが、このソリューションを見て、テキストコンテナhttp://stackoverflow.com/a/18089011/1705006を検索することをお勧めします。直接の親ノードを検索する方が、divノードより効率的で論理的です。 – karmiphuc

答えて

11

表示されている現在のタブからDOMにデータを送信するには、このクエリを使用する必要があります。

chrome.tabs.executeScript(null, { 
     code: 'var config = ' + JSON.stringify(getKeywords) 
    }, function() { 
     chrome.tabs.executeScript(null, {file: 'custom.js'}); 
    }); 

、あなたはあなたがDOM要素に適用することに機能書くことができcustom.jsファイルインチcustom.jsでクエリを必要とするものよりも隠す場合は好きです。したがって、その例を使用する場合は、要件に応じて変更する必要があります。

var all = document.getElementsByTagName("div"); 
var searchValue=config.toString().split(','); 
alert('Example:' + searchValue[0]); 
for(j=0; j < searchValue.length; j++) { 
for(i=0; i < all.length; i++) { 
    if(all[i].innerHTML.indexOf(searchValue[j]) > -1){ 
    all[i].innerHTML = "" 
    } 
} 
} 
1

あなたはそれを受けて、background.jsまたはpopup.jsからコマンドを送信し、content.jsでDOMを変更する必要があります。 次のコードは、単純なシナリオを示しています。browserActionをクリックし、現在のページにdivを追加します。同じロジックを使用して、要素を表示/非表示にすることができます。

{ 
    "name": "Test", 
    "version": "1.0", 
    "permissions": [ 
    "tabs" 
    ], 
    "description": "Test", 
    "background": { 
    "persistent": false, 
    "scripts": [ 
     "background.js" 
    ] 
    }, 
    "content_scripts": [ 
    { 
     "matches": [ 
     "*://*/*" 
     ], 
     "js": [ 
     "content.js" 
     ], 
     "run_at": "document_end", 
     "all_frames": true 
    } 
    ], 
    "browser_action": { 
    "title": "Test" 
    }, 
    "manifest_version": 2 
} 

background.js

chrome.browserAction.onClicked.addListener(function() { 
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { 
     chrome.tabs.sendMessage(tabs[0].id, {command: "append"}, function(response) { 
      console.log(response.result); 
     }); 
    }); 
}); 

content.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 
    console.log(request.command); 

    var div = document.createElement('div'); 
    var label = document.createElement('span'); 
    label.textContent = "Hello, world"; 
    div.appendChild(label); 
    document.body.appendChild(div); 

    sendResponse({result: "success"}); 
}); 
+0

私の状況を使用するために示した例を変更することはできますか? – wuno

3

manifest.jsonを私はあまり変更を行っているため、これまでと同じように、単純なこの質問に答えることを試みますあなたのコードには、あなたが従うべき道を速く学ぶでしょう。

通常、エンドユーザーがポップアップでSTARTボタンを押すと、次のコード行が書き込まれます(ポップアップを参照してください)。JS):

 
chrome.runtime.sendMessage({key: 'popupInit'}, function (response) { 
; 
}); 
window.close(); // this line closes the popup 

何非常に重要なことは、応答は、通信システムが、対応するリスナーから来たその場で簡単に答え以外であることを理解することです。 私のリスナーはbackground.jsです。あなたのようなものを持つことができるように、あなたがのlocalStorageについての利点がかかる場合があります。このファイルで :

chrome.tabs.onUpdated.addListener(function(tabid, changeInfo, tab) { 
    if (typeof changeInfo.status == 'string' && changeInfo.status == 'complete') { 
    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { 
     var keyString = JSON.parse(localStorage.getItem('keyWords')); 
     chrome.tabs.sendMessage(tabs[0].id, {key: 'init', wordToHide: keyString}, function (response) { 
     ; 
     }); 
    }); 
    } 
}); 

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 
    var rq = request.key; 
    if (rq != undefined && typeof rq == 'string') { 
    switch (rq) { 
     case 'popupInit': 
     chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { 
      var keyString = JSON.parse(localStorage.getItem('keyWords')); 
      chrome.tabs.sendMessage(tabs[0].id, msgToSend, function(response) { 
      ; 
      }); 
     }); 
     break; 
    } 
    } 
}); 

たびにアクティブ現在のページはあなたが更新されるためchrome.tabs.onUpdated.addListenerが重要ですlocalstorageから値を取得するコンテンツスクリプトにメッセージを送信することができます。ポップアップが閉じられたときに同じことが起こり、localstorageに単語がある場合は、chrome.runtime.onMessage.addListenerを使用してシグナルを待ち受けます。コンテンツスクリプトで作業を開始し、単語の配列を含むメッセージを送信します。

ここで、content.jsファイルを見ていきましょう。

// Listen for messages from the backgound.js 
chrome.runtime.onMessage.addListener(function (msg, sender, response) { 
    // First, validate the message's structure 
    if ((msg.key === 'init') && (Object.prototype.toString.call(msg.wordToHide) === '[object Array]')) { 

    var elements = document.querySelectorAll("body, body *"); 
    var results = []; 
    var child; 
    var regwordToHide = []; 
    if (msg.wordToHide.length > 0) { 
     msg.wordToHide.forEach(function(element, index, array) { 
     regwordToHide.push(new RegExp('\\b' + element + '\\b', 'g')); 
     }); 
    } 
    for(var i = 0; i < elements.length; i++) { 
     child = elements[i].childNodes[0]; 
     if (elements[i].hasChildNodes() && child.nodeType == 3) { 
     var nodeStr = child.textContent; 
     if (nodeStr.trim().replace(/\n\r\t/g, '').length > 0 && nodeStr.trim().charAt(0) != '<') { 
      regwordToHide.forEach(function(element, index, array) { 
      nodeStr = nodeStr.replace(element, ''); 
      }); 
      child.textContent = nodeStr; 
     } 
     } 
    } 
    document.getElementsByTagName("html")[0].style.visibility = "visible"; 
    } 
}); 
document.getElementsByTagName("html")[0].style.visibility = "hidden"; 

私は、ページ全体を隠そう:それは複雑になる可能性があるため(....ページのロード中に、エンドユーザーは常に何かを見なければならない覚えている)これに注意を払います。

その後、content.jsはバックグラウンドからのメッセージを待っています。このとき、コンテンツスクリプトが作業を開始します。 それだけです。

私の文章では混乱して申し訳ありません。他の助けが必要なら私に知らせてください。私はあなたの内線をテストし、あなたが見ることができる場所で修正しました。

あなたが覚えておく必要がChromeの拡張機能のコンポーネント間の通信のために:

  • 背景が大きなリスナー
  • でポップアップが背景
  • と背景をcomunicateコンテンツ
  • と通信

メッセージを送受信するには、Chrome messaging

  1. 関数chrome.runtime.sendMessage({greeting: "hello"}、function(response){ console.log(response.farewell); }); > - こんにちは:ような何か:
  2. chrome.runtime.onMessage.addListenerを送信するためにUSENDはサーバー(受信機)
  3. sendResponse

と応答が通信に関するオンザフライでのチェックのためだけに使用されているがされています私は理解しました。今、私は自分で続けます。

あなたの言葉の交換部分も完成しました!

関連する問題