How to get input field value from Chrome Extension
Clash Royale CLAN TAG#URR8PPP
How to get input field value from Chrome Extension
I am working to learn how to build a Google Chrome Extension. I have a contact form on a webpage that I'm using for testing. I'm trying to create an extension that will read the input field values from that form. At this time, I have:
manifest.json
"manifest_version": 2,
"name": "Contact Form Friend",
"description": "This extension gets contact form info.",
"version": "1.0",
"browser_action":
"default_icon": "icon.png",
"default_popup": "popup.html"
,
"permissions": [
"activeTab",
"<all_urls>"
]
popup.html
<!doctype html>
<html>
<head>
<title>Getting Started Extension's Popup</title>
<style type="text/css">
body
margin: 10px;
white-space: nowrap;
h1
font-size: 15px;
#container
align-items: center;
display: flex;
justify-content: space-between;
</style>
<script src="popup.js"></script>
</head>
<body>
<h1>Info</h1>
<div id="info">
</div>
</body>
</html>
popup.js
function getHost()
return document.documentElement;
document.addEventListener('DOMContentLoaded', () =>
const infoDisplay = document.getElementById('info');
const scriptToRun = `($getHost)()`;
// Run the script in the context of the tab
chrome.tabs.executeScript(
code: scriptToRun
, (result) =>
var values = ;
var inputFields = result.getElementsByTagName('input');
infoDisplay.innerHTML = 'inputs: ' + inputFields.length;
for (var i = 0; i < inputFields.length; i++)
values.push(inputFields[i].value);
infoDisplay.innerHTML += '<br />fields: ' + values.length;
);
);
When I run this, it acts like it can't access the input fields from the web page the user is on (not the extension's web page). What am I doing wrong? Am I missing a permission? I don't believe so. However, it's not working and I'm not sure why.
Thank you for your help.
@Zach Templeton, here answers to your question: stackoverflow.com/questions/19758028/…
– beaver
Feb 9 at 7:23
5 Answers
5
As reported by Gabriel Bleu you need a content script to interact with web pages inside Chrome tabs.
Here below is an example of Chrome Extension where a content script exposes two "commands" to popup.js.
See code comments for explanation.
manifest.json (similar to yours)
"name": "My ext",
"version": "0.1",
"description": "my desc",
"permissions": [
"activeTab",
"<all_urls>"
],
"icons":
"128": "icon-128.png"
,
"browser_action":
"default_title": "My ext",
"default_icon": "icon.png",
"default_popup": "popup.html"
,
"manifest_version": 2,
"content_security_policy": "script-src 'self' https://ajax.googleapis.com object-src 'self'"
popup.html (similar to yours except for jQuery usage for easy DOM manipulation)
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="application/javascript" charset="utf-8" src="popup.js"></script>
</head>
<body class="body-popup">
<button id="btn_check" class="btn btn-warning">check current tab</button>
<hr>
<div id="pg_url"></div>
<hr>
<div id="log"></div>
</body>
</html>
popup.js
$(function()
$('#btn_check').click(function() checkCurrentTab(); );
);
function checkCurrentTab()
chrome.tabs.query('active': true, 'lastFocusedWindow': true, function (tabs)
var url = tabs[0].url;
console.log("checkCurrentTab: "+url);
$(".pg_url").text(url);
// request content_script to retrieve title element innerHTML from current tab
chrome.tabs.sendMessage(tabs[0].id, "getHeadTitle", null, function(obj)
console.log("getHeadTitle.from content_script:", obj);
log("from content_script:"+obj);
);
);
document.addEventListener('DOMContentLoaded', function ()
chrome.windows.getCurrent(function (currentWindow)
chrome.tabs.query(active: true, windowId: currentWindow.id, function(activeTabs)
// inject content_script to current tab
chrome.tabs.executeScript(activeTabs[0].id, file: 'content_script.js', allFrames: false);
);
);
);
function log(txt)
var h = $("#log").html();
$("#log").html(h+"<br>"+txt);
content_script.js
// you will see this log in console log of current tab in Chrome when the script is injected
console.log("content_script.js");
chrome.runtime.onMessage.addListener(function(cmd, sender, sendResponse)
console.log("chrome.runtime.onMessage: "+cmd);
switch(cmd)
case "getHtml":
// retrieve document HTML and send to popup.js
sendResponse(title: document.title, url: window.location.href, html: document.documentElement.innerHTML);
break;
case "getHeadTitle":
// retrieve title HTML and send to popup.js
sendResponse(document.getElementsByTagName("title")[0].innerHTML);
break;
default:
sendResponse(null);
);
P.S.: obviously jQuery is not mandatory
This answer doesn't help with what the OP wants to accomplish: reading some
input
values from a webpage. There is no need to overcomplicate things.– Iván Nokonoko
Feb 7 at 19:49
input
Man, you do take criticism badly...
– Iván Nokonoko
Feb 8 at 7:46
If your extension needs to interact with web pages, then it needs a content script. A content script is some JavaScript that executes in the context of a page that's been loaded into the browser. Think of a content script as part of that loaded page, not as part of the extension it was packaged with (its parent extension).
https://developer.chrome.com/extensions/overview#contentScripts
Here is the error you receive:
Error in response to tabs.executeScript: TypeError: result.getElementsByTagName is not a function
at Object.chrome.tabs.executeScript [as callback] (chrome-extension://lmaefdnejmkjjmgalgfofdbobhapfmoh/popup.js:15:32)
at HTMLDocument.document.addEventListener (chrome-extension://lmaefdnejmkjjmgalgfofdbobhapfmoh/popup.js:10:17)
Instead of trying to get the DOM of the current tab in popup.js, I would suggest to use a content script to do the task and send the result as a message to the popup.
manifest.json
"manifest_version": 2,
"name": "Contact Form Friend",
"description": "This extension gets contact form info.",
"version": "1.0",
"browser_action":
"default_icon": "icon.png",
"default_popup": "popup.html"
,
"permissions": [
"activeTab",
"<all_urls>"
],
"content_scripts": [
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"]
]
In the manifest.json file you must add the content script and set the URLs of the sites in which you want to inject the script.
popup.js
document.addEventListener('DOMContentLoaded', () =>
const infoDisplay = document.getElementById('info');
window.addEventListener('DOMContentLoaded', function ()
chrome.tabs.query(active: true, currentWindow: true, function (tabs)
chrome.tabs.sendMessage(tabs[0].id, , function (result)
infoDisplay.innerHTML = result
);
);
);
);
In popup.js send a request to the content script, to get the number of input fields and insert the response into the div
.
div
content.js
chrome.runtime.onMessage.addListener(function (msg, sender, response)
var values = ;
var inputFields = document.getElementsByTagName('input');
var result = 'inputs: ' + inputFields.length;
for (var i = 0; i < inputFields.length; i++)
values.push(inputFields[i].value);
result += '<br />fields: ' + values.length;
response(result)
);
Create a new file, named content.js
. This file will be injected into the webpage and it listens to messages from the popup.js. When a message arrives it computes the response and sends it back to popup.js.
content.js
To learn more about content scripts, check out the documentation.
The main problem of your approach is that you try to send a DOM tree via message/sendResponse from content script to popup/background in order to process it there. You cannot send DOM trees via message/sendResponse.
A better approach would be to handle the DOM in the content script and send back the desired information (in your case, the input
values) to the popup/background page.
input
One possible way to do it would be:
popup.js
document.addEventListener('DOMContentLoaded', () =>
const infoDisplay = document.getElementById('info');
const scriptToRun = `
var values = ;
var inputFields = document.getElementsByTagName('input');
for (var i = 0; i < inputFields.length; i++)
values.push(inputFields[i].value);
values;`; //all this code will be run on the tab page
//and the array "values" will be returned.
chrome.tabs.executeScript(
code: scriptToRun
, (result) =>
infoDisplay.innerHTML = `There are: $result[0].length inputs, with these values: <ol><li>$result[0].join("<li>")`;
);
);
I have solved it. Check my answer and solution here:
Get input value Chrome Extension
Hope it helps
Here is my popup.js
let $token1= $('#token1').val();
let $token2= $('#token2').val();
let $token3= $('#token3').val();
if(true)
chrome.runtime.sendMessage( token: ['tokens', $token1 = $('#token1').val(), $token2 = $('#token2').val(), $token3 = $('#token3').val()],
myFunction());
And here is the background.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse)
if(message.token[0] == "tokens")
let $token1 = message.token[1];
let $token2 = message.token[2];
let $token3 = message.token[3];
chrome.tabs.executeScript(file: "file.js", myFunction());
);
and inputs html
<input type="text" id="token1" value="token1">
<input type="text" id="token2" value="token2">
<input type="text" id="token3" value="token3">
Welcome to Stack Overflow! While links are great way of sharing knowledge, they won't really answer the question if they get broken in the future. Add to your answer the essential content of the link which answers the question. In case the content is too complex or too big to fit here, describe the general idea of the proposed solution. Remember to always keep a link reference to the original solution's website. See: How do I write a good answer?
– sɐunıɔןɐqɐp
51 mins ago
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
– Roshana Pitigala
37 mins ago
this provide the answer, this is my question, and my solution... I don't care about reputation there, and hope my solution somebody helps ...+
– 3113
33 mins ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Does the code in your extension even get executed? Or is just that the DOM is not the one you were expecting?
– marcofo88
Feb 8 at 8:54