I know this this has been asked in numerous posts but honestly I don't get them. I am new to JavaScript, Chrome Extensions and everything and I have this class assignment. So I need to make a plugin that would count DOM objects on any given page using Cross Domain Requests. I've been able to achieve this so far using Chrome Extension API's. Now the problem is I need to show the data on my popup.html page from the contentScript.js file. I don't know how to do that I've tried reading the documentation but messaging in chrome I just can't understand what to do.
following is the code so far.
manifest.json
{ "manifest_version":2, "name":"Dom Reader", "description":"Counts Dom Objects", "version":"1.0", "page_action": { "default_icon":"icon.png", "default_title":"Dom Reader", "default_popup":"popup.html" }, "background":{ "scripts":["eventPage.js"], "persistent":false }, "content_scripts":[ { "matches":["http://pluralsight.com/training/Courses/*", "http://pluralsight.com/training/Authors/Details/*", "https://www.youtube.com/user/*", "https://sites.google.com/site/*", "http://127.0.0.1:3667/popup.html"], "js":["domReader_cs.js","jquery-1.10.2.js"] //"css":["pluralsight_cs.css"] } ], "permissions":[ "tabs", "http://pluralsight.com/*", "http://youtube.com/*", "https://sites.google.com/*", "http://127.0.0.1:3667/*" ]
popup.html
<!doctype html> <html> <title> Dom Reader </title> <script src="jquery-1.10.2.js" type="text/javascript"></script> <script src="popup.js" type="text/javascript"></script> <body> <H1> Dom Reader </H1> <input type="submit" id="readDom" value="Read DOM Objects" /> <div id="domInfo"> </div> </body> </html>
eventPage.js
var value1,value2,value3; chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { if (request.action == "show") { chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { chrome.pageAction.show(tabs[0].id); }); } value1 = request.tElements; });
popup.js
$(function (){ $('#readDom').click(function(){ chrome.tabs.query({active: true, currentWindow: true}, function (tabs){ chrome.tabs.sendMessage(tabs[0].id, {action: "readDom"}); }); }); });
contentScript
var totalElements; var inputFields; var buttonElement; chrome.runtime.onMessage.addListener(function (request, sender, sendResponse){ if(request.action == "readDom"){ totalElements = $("*").length; inputFields = $("input").length; buttonElement = $("button").length; } }) chrome.runtime.sendMessage({ action: "show", tElements: totalElements, Ifields: inputFields, bElements: buttonElement });
Any help would be appreciated and please avoid any noobness I did :)
Type the url in the main input field and choose the method to use: GET/POST/PUT/DELETE/PATCH. Click on the arrow "Send" or press Ctrl+Enter. You'll see info about the response (time, size, type) and you'll be able to see the content response in the response section.
They've set the default shortcut to Ctrl+D . Activating this command will perform a click on the page (or browser) action, opening the popup or whatever the action is configured to do.
Although you are definitely in the right direction (and actually pretty close to the end), there are several (imo) bad practises in your code (e.g. injecting a whole library (jquery) for such a trivial task, declaring unnecessary permissions, making superflous calls to API methods etc).
I did not test your code myself, but from a quick overview I believe that correcting the following could result in a working solution (although not very close to optimal):
"js" [...] The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this array.
(emphasis mine)
onMessage
listener callback.That said, here is my proposed approach:
root-directory/ |__img |__icon19.png |__icon38.png |__manifest.json |__background.js |__content.js |__popup.js |__popup.html
{ "manifest_version": 2, "name": "Test Extension", "version": "0.0", "offline_enabled": true, "background": { "persistent": false, "scripts": ["background.js"] }, "content_scripts": [{ "matches": ["*://*.stackoverflow.com/*"], "js": ["content.js"], "run_at": "document_idle", "all_frames": false }], "page_action": { "default_title": "Test Extension", //"default_icon": { // "19": "img/icon19.png", // "38": "img/icon38.png" //}, "default_popup": "popup.html" } // No special permissions required... //"permissions": [] }
chrome.runtime.onMessage.addListener((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); } });
// 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((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); } });
// Update the relevant fields with the new data. const setDOMInfo = info => { document.getElementById('total').textContent = info.total; document.getElementById('inputs').textContent = info.inputs; document.getElementById('buttons').textContent = info.buttons; }; // Once the DOM is ready... window.addEventListener('DOMContentLoaded', () => { // ...query for the active tab... chrome.tabs.query({ active: true, currentWindow: true }, 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); }); });
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="popup.js"></script> </head> <body> <h3 style="font-weight:bold; text-align:center;">DOM Info</h3> <table border="1" cellpadding="3" style="border-collapse:collapse;"> <tr> <td nowrap>Total number of elements:</td> <td align="right"><span id="total">N/A</span></td> </tr> <tr> <td nowrap>Number of input elements:</td> <td align="right"><span id="inputs">N/A</span></td> </tr> <tr> <td nowrap>Number of button elements:</td> <td align="right"><span id="buttons">N/A</span></td> </tr> </table> </body> </html>
You can use localStorage for that. You can store any data in a hash table format in browser memory and then access it any time. I'm not sure if we can access localStorage from the content script (it was blocked before), try to do it by yourself. Here's how to do it through you background page (I pass data from content script to background page first, then save it in localStorage):
in contentScript.js:
chrome.runtime.sendMessage({ total_elements: totalElements // or whatever you want to send });
in eventPage.js (your background page):
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse){ localStorage["total_elements"] = request.total_elements; } );
Then you can access that variable in popup.js with localStorage["total_elements"].
Maybe you can access localStorage directly from the content script in modern browsers. Then you don't need to pass the data through your background page.
Nice reading about localStorage: http://diveintohtml5.info/storage.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With