Modify DOM content with Chrome extension

I am creating a Chrome extension. I am trying to connect my application to every page in the extension and the page that the user is viewing in the browser. I need to access dom from an extension and then update it.

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

and the current page that the user is viewing.

My goal is to load the page in order to change the dom and show the user a new version of the page before she sees it. in popup.js users are allowed to enter keywords in a popup window. Keywords are stored in localStorage , and while they browse the web, the keywords are censored from their view, causing the parent div to hide the keywords if they are found on any pages that they browse.

I need help getting each page to share data, and I think the way I hide parent divs in popup.js will not work. I am confused about how to perform an action on dom from the front.

Send dom to background.js Find the keywords on the page and change their parent divs to hidden ones. click home back to the watch page.

I think this line says that if I map any URL, then run my application, but I'm not sure.

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

My manifest is .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 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 structure if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) { // Collect the necessary data // (For your specific requirements `document.querySelectorAll(...)` // should be equivalent to jquery `$(...)`) 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); } }); 
+17
javascript jquery google-chrome google-chrome-extension
Dec 26 '15 at 0:44
source share
3 answers

You need to use this query to send data to the DOM from the currently viewed tab.

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

and in the custom.js file you can write the function that you want to apply to the DOM element. for example, if you want to hide something that you need this request in custom.js . Therefore, if you want to use this example, you will need to modify it to suit your requirements.

 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 = "" } } } 
+10
Jan 7 '16 at 22:46
source share

I am trying to answer this question as simple as before, because by making fewer changes to the code, you will quickly learn to follow it.

I usually write the following lines of code when the end user presses the START button when popping up (see your popup.js):

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

What is very important is to understand that the answer is not a communication system, but simply an on-the-fly response from the corresponding listener. The listener for me is background.js. In this file, you can take advantage of localStorage to have something like:

 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 is important because every time the current current page is refreshed, you can send a message to the content script by getting values ​​from localstorage, the same thing happens when the popup closes, and if there are words in localstorage, you can use chrome.runtime.onMessage.addListener to listen for the signal: the pop-up window closes, so start the work in the script content by sending it a message with an array of words.

Now look at your content.js file.

 // Listen for messages from the backgound.js chrome.runtime.onMessage.addListener(function (msg, sender, response) { // First, validate the message 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"; 

I am trying to hide the whole page: pay attention to this because it can be difficult (remember that the end user should always see something while loading the page ...).

After that, content.js waits for a message coming from the background, and when this happens, the contents of the script will start working! It's all.

Sorry for the confusion in my letter. If you need any other help, let me know. I checked your ext and fixed it in places you can see.

To communicate between the components in the chrome extension, remember:

  • background is a big listener
  • Background Interaction
  • background communicates with content

To send / receive messages, you can take a look at Chrome messages

  • function chrome.runtime.sendMessage ({greeting: "hello"}, function (response) {console.log (response.farewell);}); heading off
  • chrome.runtime.onMessage.addListener - this is the server (receiver)

Sending the answer and the answer are used only to check on the fly regarding the connection: something like: Hello → Good, I understand, Now I continue myself.

I also filled out the word replacing the part!

+3
Jan 06 '16 at 19:14
source share

You should send a command from background.js or popup.js, having received it and changing dom in content.js. The following code demonstrates a simple scenario: Click the browserAction button and add a div to the current page. You can use the same logic to show / hide any elements.

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"}); }); 
+1
Jan 04 '16 at 5:50
source share



All Articles