web-dev-qa-db-fra.com

Modifier le contenu DOM avec Chrome

Je crée une extension Chrome. J'essaie de faire communiquer mon application avec chaque page de l'extension et la page que l'utilisateur affiche dans le navigateur. J'ai besoin d'accéder au dom depuis le extension, puis mettez-le à jour.

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

et la page actuelle consultée par l'utilisateur.

Mon objectif est au chargement de la page de modifier le dom et de montrer à l'utilisateur la nouvelle version de la page avant de la voir. dans popup.js les utilisateurs sont autorisés à saisir des mots clés dans la fenêtre contextuelle. Les mots-clés sont enregistrés dans localStorage et lorsqu'ils consultent le Web, les mots-clés sont censurés hors de leur vue en masquant la div parent des mots-clés si elle se trouve sur les pages qu'ils consultent.

J'ai besoin d'aide pour communiquer chaque page et je pense que la façon dont je cache les divs parents dans popup.js ne fonctionnera pas. Je suis confus sur la façon d'effectuer l'action sur le dom par l'avant.

Envoyer le dom à l'arrière-plan.js Recherchez des mots clés sur la page et changez leurs divs parent en masqués. Repoussez le dom sur la page de visualisation.

Je pense que cette ligne indique que si je correspond à une URL, lancez mon application, mais je ne suis pas sûr.

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

Mon 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

Vous devez utiliser cette requête pour envoyer des données au DOM à partir de l'onglet actuel affiché.

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

et dans le custom.js fichier, vous pouvez écrire votre fonction que vous souhaitez appliquer sur l'élément DOM. comme si vous voulez cacher quelque chose que vous avez besoin de cette requête dans custom.js. Donc, si vous souhaitez utiliser cet exemple, vous devrez le modifier en fonction de vos besoins.

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

Vous devez envoyer une commande à partir de background.js ou popup.js, la recevoir et changer le dom dans content.js. Le code suivant illustre un scénario simple: Cliquez sur browserAction et ajoutez un div à la page actuelle. Vous pouvez utiliser la même logique pour afficher/masquer tous les éléments.

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

J'essaie de répondre à cette question aussi simple que jamais, car en apportant moins de modifications à votre code, vous apprendrez rapidement le chemin à suivre.

Normalement, j'écris les lignes de code suivantes lorsque l'utilisateur final appuie sur un bouton START de la fenêtre contextuelle (reportez-vous à votre popup.js):

 chrome.runtime.sendMessage ({clé: 'popupInit'}, fonction (réponse) {
; 
}); 
 window.close (); // cette ligne ferme le popup 

Ce qui est très important, c'est de comprendre que la réponse n'est pas un système de communication mais simplement une réponse à la volée provenant de l'auditeur correspondant. L'auditeur pour moi est le background.js. Dans ce fichier, vous pouvez profiter du localStorage afin d'avoir quelque chose comme:

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;
    }
  }
});

Le chrome.tabs.onUpdated.addListener est important car chaque fois que la page active actuelle est mise à jour, vous pouvez envoyer le message au script de contenu en obtenant les valeurs du localstorage, la même chose se produit lorsque le popup est fermé et s'il y a des mots dans le localstorage vous pouvez utiliser le chrome.runtime.onMessage.addListener pour écouter le signal: popup fermé alors commencez le travail dans le script de contenu en lui envoyant un message avec le tableau de mots.

Jetons maintenant un œil à votre fichier 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";

J'essaie de cacher toute la page: faites attention à cela car cela peut être compliqué (rappelez-vous que l'utilisateur final doit toujours voir quelque chose pendant le chargement de la page ...).

Après, le content.js attend un message venant de l'arrière-plan et lorsque cela se produit, le script de contenu commence son travail! C'est tout.

Désolé pour la confusion dans mon écriture. Si vous avez besoin d'aide, faites le moi savoir. J'ai testé votre ext et l'ai corrigé dans les endroits que vous pouvez voir.

Pour la communication entre les composants dans une extension chrome, vous devez vous souvenir:

  • l'arrière-plan est le grand auditeur
  • le popup communique avec le fond
  • le fond communique avec le contenu

Pour envoyer/recevoir des messages, vous pouvez consulter messagerie Chrome

  1. la fonction chrome.runtime.sendMessage ({message d'accueil: "bonjour"}, fonction (réponse) {console.log (response.farewell);}); est usend d'envoyer
  2. chrome.runtime.onMessage.addListener est le serveur (récepteur)

Le sendResponse et la réponse sont utilisés juste pour un contrôle à la volée concernant la communication: quelque chose comme: Bonjour -> Ok j'ai compris, maintenant je continue par moi-même.

J'ai également complété votre pièce de remplacement Word!

3
gaetanoM