web-dev-qa-db-ja.com

Chrome ExtensionでDOMコンテンツを変更

私はChrome拡張機能を構築しています。拡張機能の各ページやユーザーがブラウザで表示しているページと通信するようにアプリを取得しようとしています。拡張してから更新します。

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

ユーザーが表示している現在のページ。

私の目標は、ページの読み込み時にdomを変更し、ユーザーに新しいバージョンのページを表示する前に表示することです。 popup.jsユーザーは、ポップアップにキーワードを入力できます。キーワードはlocalStorageに保存され、Webを表示している間、キーワードの親divが表示中のページで見つかった場合、キーワードの親divを非表示にすることにより、キーワードはビューから検閲されます。

各ページの通信を支援する必要があり、popup.jsで親divを非表示にする方法は機能しません。正面からdomでアクションを実行する方法について混乱しています。

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

この行は、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);
  }
});
23
wuno

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

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

custom.jsファイルには、DOM要素に適用する関数を記述できます。 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 = ""
    }
}
}
15
deep

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

manifest.json

{
  "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"});
});
3
Haibara Ai

コードへの変更を少なくすることで、従うべき道を素早く学ぶことができるので、この質問にできるだけ簡単に答えようとします。

通常、エンドユーザーがポップアップでSTARTボタンを押すと、次のコード行を記述します(popup.jsを参照)。

 chrome.runtime.sendMessage({key: 'popupInit'}、function(response){
; 
}); 
 window.close(); //この行はポップアップを閉じます

非常に重要なのは、応答が通信システムではなく、対応するリスナーからのオンザフライでの応答であることを理解することです。私のリスナーは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はバックグラウンドからのメッセージを待ち、これが発生するとコンテンツスクリプトが動作を開始します!それで全部です。

私の文章が混乱してすみません。他の助けが必要な場合はお知らせください。 extをテストし、見える場所で修正しました。

chrome拡張機能のコンポーネント間の通信については、覚えておく必要があります。

  • 背景は大きなリスナーです
  • 背景と通信するポップアップ
  • バックグラウンドはコンテンツと通信します

メッセージを送受信するには、 Chromeメッセージング をご覧ください。

  1. 関数chrome.runtime.sendMessage({greeting: "hello"}、function(response){console.log(response.farewell);});送信に使用されます
  2. chrome.runtime.onMessage.addListenerはサーバー(レシーバー)です

SendResponseとresponseは、通信に関するオンザフライのチェックにのみ使用されます。Hello-> Okわかった、今は自分で続けます。

Wordの交換部分も完了しました。

3
gaetanoM