Event not triggering on a content scripts Chrome extension - javascript

I'm building a content scripts Chrome extension. I've dynamically added a button to a webpage, however the event listener on this button won't trigger.
Here is manifest.json:
{
"manifest_version": 2,
"name": "my extension",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
],
"content_scripts": [
{
"matches": ["http://127.0.0.1:8000/*"],
"js": ["jquery.js", "script.js"],
"run_at": "document_end"
}
]
}
This is script.js:
document.body.style.backgroundColor = "yellow";
var button = $('<input id="btn" type="button"/>');
$("body").append(button);
$("#btn").on("click", function(){
document.body.style.backgroundColor = "red";
});
The button is added to the page and background changes to yellow, but it doesn't change to red when clicking button.

If the suspected issue is with the button ID - note that you don't need the ID at all.
document.body.style.backgroundColor = "yellow";
var button = $('<input id="btn" type="button"/>');
$("body").append(button);
button.on("click", function(){ // Notice you don't need to search for it again!
document.body.style.backgroundColor = "red";
});
However, in this case you'll need to keep the button variable to find it again.

This unique id may help you ;)
document.body.style.backgroundColor = "yellow";
uniqueId = 'btn' + Date.now();
var button = $('<input id="' + uniqueId + '" type="button"/>');
$("body").append(button);
$("#" + uniqueId).on("click", function(){
document.body.style.backgroundColor = "red";
});

Related

Google Chrome Extension: How to create a right click extension with hierarchy branches?

I want to be able to add multiple options to my right click extension. I currently have one and it works as should, but I copied a simple tutorial and need a bit more guidance. Thank you for any assistance.
// Set up context menu at install time.
chrome.runtime.onInstalled.addListener(function() {
var context = "selection";
var title = "Search on blah blah";
var id = chrome.contextMenus.create({"title": title, "contexts":[context],
"id": "context" + context});
});
// add click event
chrome.contextMenus.onClicked.addListener(onClickHandler);
// The onClicked callback function.
function onClickHandler(info, tab) {
var sText = info.selectionText;
var url = "https://www.google.com/search?q=" + encodeURIComponent(sText);
window.open(url, '_blank');
};
Take a look at chrome.contextMenus.create, you can create a child context menu item (hierachy branches) by setting parentId
// Set up context menu at install time.
chrome.runtime.onInstalled.addListener(function() {
var context = "selection";
var title = "Search on blah blah";
var id = chrome.contextMenus.create({"title": title, "contexts":[context],
"id": "context" + context});
var child1_id = chrome.contextMenus.create({"title": "child1", "parentId": id, "contexts":[context],
"id": "child1_id"});
var child2_id = chrome.contextMenus.create({"title": "child2", "parentId": id, "contexts":[context],
"id": "child2_id"});
});
// add click event
chrome.contextMenus.onClicked.addListener(onClickHandler);
// The onClicked callback function.
function onClickHandler(info, tab) {
var sText = info.selectionText;
var url = "https://www.google.com/search?q=" + encodeURIComponent(sText);
window.open(url, '_blank');
};

XMLHttpRequest in Firefox on websites meta information

I am new to Firexfox Add-On development and I would like to parse meta-tags from a website in the internet. My Firefox Add-On development environment is setup completely and a panel in the toolbar appears as it should be. When I open the panel the current visited website should be read by its meta-tags. In the following you will see amazon.de as example.
This is how my main.js file looks like:
var { ToggleButton } = require('sdk/ui/button/toggle');
var panels = require("sdk/panel");
var self = require("sdk/self");
var button = ToggleButton({
id: "my-button",
label: "my button",
icon: {
"16": "./icon-16.png",
"32": "./icon-32.png",
"64": "./icon-64.png"
},
onChange: handleChange
});
var panel = panels.Panel({
contentURL: self.data.url("panel.html"),
onHide: handleHide
});
function handleChange(state) {
if (state.checked) {
panel.show({
position: button
});
}
}
function handleHide() {
button.state('window', {checked: false});
}
And this is the panel where the current visited website should be read by its meta-tags:
<script>
// https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript
var req = new XMLHttpRequest();
req.open("GET", "http://www.amazon.de/Apple-Smartphone-Retina-Display-Megapixel-Bluetooth/dp/B00F8JF2OM/", false);
req.send(null);
var xmlDoc = req.responseXML;
var nsResolver = xmlDoc.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement);
//XPath 'html//meta[#name="title"]/#content'
var itemIterator = xmlDoc.evaluate('html//meta[#name="title"]/#content', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null );
var thisHeading = itemIterator.iterateNext();
var alertText = 'Items:\n'
while (thisHeading) {
alertText += thisHeading.textContent + '\n';
thisHeading = itemIterator.iterateNext();
}
</script>
I don't get any errors and don't get any alert or output data.
However the Firfox XPath add-on tells me the path is correct and shows the data.

Trouble removing event listener

Trying to get my feet wet with Chrome Extensions. I created a tab limiter, but its buggy.
I want the event of clicking the browser action icon to toggle on and off the extension. I believe I have that set up properly. When toggled on, it creates a listener from the chrome.tabs API, but when toggled off, I'm having a hard time removing this listener.
I've tried some of the common answers on Stack Overflow (one is shown below) for removing listeners, but none are functioning properly for me.
Here is the background.js
var tabUrls, bookmarkFolder, currentWindow;
var toggle = false;
chrome.browserAction.onClicked.addListener(function(tab){
toggle = !toggle;
if(toggle) {
chrome.browserAction.setBadgeText({"text": "ON"});
console.log("I'm listening to the browser action");
runExtension();
} else {
console.log("i shouldn't be working now.");
chrome.browserAction.setBadgeText({"text": ""});
// Need to remove the listener somehow. This isn't working.
chrome.tabs.onCreated.addListener(doStuff);
}
});
// Functions
// Potential function to removeListener. Not working.
function doStuff(tab){
chrome.tabs.onCreated.removeListener(doStuff);
}
var runExtension = function(){
chrome.tabs.onCreated.addListener(function(tab){
// Find and set reference to the current window
chrome.windows.getCurrent(function(window){
currentWindow = window;
});
// Logic to limit tabs (remove window, create bookmarks, play audio, manipulate DOM on new window)
chrome.tabs.getAllInWindow(function(tabs) {
tabUrls = lengthRequirement(tabs);
console.log(tabUrls);
if (typeof tabUrls != "string") {
createBookmarkFolder(tabUrls);
chrome.windows.remove(currentWindow.id);
playAudioClip();
chrome.windows.create({ "url": "http://www.justinstewart.info/"});
chrome.tabs.executeScript({file: "content_script.js"});
}
});
});
}
var playAudioClip = function(){
var audio = new Audio("audio_file.mp3");
audio.play();
}
var createBookmarkFolder = function(tabUrls){
chrome.bookmarks.create(
{'title': "Caroline Strikes Again # " + new Date()},
function(bookmark){
createBookmarks(tabUrls, bookmark);
}
)
}
var createBookmarks = function(urls, folder){
for(i=0; i<urls.length; i++) {
chrome.bookmarks.create({
'parentId': folder.id,
'url': urls[i][0],
'title': urls[i][1]
})
}
}
var lengthRequirement = function(tabsArray){
if (tabsArray.length > 9) {
var urls = [];
for(i=0; i<tabsArray.length; i++) {
info = [];
info.push(tabsArray[i].url);
info.push(tabsArray[i].title);
urls.push(info);
}
return urls;
} else {
return "Not there yet.....";
}
}
manifest.json file:
{
"manifest_version": 2,
"name": "Caroline",
"version": "0.2",
"description": "A fun tab limiter to help increase productivity and focus.",
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_icon": "icon48.png",
"default_title": "Sweet Caroline"
},
"permissions": [
"tabs", "bookmarks", "*://*/"
]
}
Any help is greatly appreciated!
.removeListener(func) will only remove a listener if func is identical to one of the previously added event listeners.
First, remove the anonymous function within runExtension, because if it is anonymous, you cannot get a reference to the function object any more:
var runExtension = function(){
chrome.tabs.onCreated.addListener(function(tab){
...
});
};
Then, replace runExtension() with .addListener(runExtension);, and use .removeListener(runExtension); whenever you want to remove the listener:
chrome.browserAction.onClicked.addListener(function(tab){
toggle = !toggle;
if (toggle) {
...
chrome.tabs.onCreated.addListener(runExtension);
} else {
...
chrome.tabs.onCreated.removeListener(runExtension);
}
});

Context menu not being loaded by extension

I'm following this tutorial on how to create a context menu when a user right clicks on selected text, the menu offers the user the option to send the text to a server:
http://vikku.info/programming/chrome-extension/get-selected-text-send-to-web-server-in-chrome-extension-communicate-between-content-script-and-background-page.htm#Comments
Here are the files:
The myscript.js file:
document.addEventListener('mouseup',function(event)
{
var sel = window.getSelection().toString();
alert('selection is '+sel)
if(sel.length)
chrome.extension.sendRequest({'message':'setText','data': sel},function(response){})
})
The background.html file:
<script>
var seltext = null;
chrome.extension.onRequest.addListener(function(request, sender, sendResponse)
{
switch(request.message)
{
case 'setText':
window.seltext = request.data
break;
default:
sendResponse({data: 'Invalid arguments'});
break;
}
});
function savetext(info,tab)
{
var jax = new XMLHttpRequest();
jax.open("POST","http://localhost/text/");
jax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
jax.send("text="+seltext);
jax.onreadystatechange = function() { if(jax.readyState==4) { alert(jax.responseText); }}
}
alert('here')
var contexts = ["selection"];
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
chrome.contextMenus.create({"title": "Send to Server", "contexts":[context], "onclick": savetext});
}
</script>
The manifest.json file:
<script>
var seltext = null;
chrome.extension.onRequest.addListener(function(request, sender, sendResponse)
{
switch(request.message)
{
case 'setText':
window.seltext = request.data
break;
default:
sendResponse({data: 'Invalid arguments'});
break;
}
});
function savetext(info,tab)
{
var jax = new XMLHttpRequest();
jax.open("POST","http://localhost/text/");
jax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
jax.send("text="+seltext);
jax.onreadystatechange = function() { if(jax.readyState==4) { alert(jax.responseText); }}
}
alert('here')
var contexts = ["selection"];
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
chrome.contextMenus.create({"title": "Send to Server", "contexts":[context], "onclick": savetext});
}
</script>
The popup.html file:
<body>
Just a sample popup
</body>
In myscript.js the function document.addEventListener('mouseup',function(event) is called every time a mouseup event is fired ed but I think this should be called if the user decides to send the request to the server. The context menu should be fired when the user right clicks selected text but I don't know why this is occurring? I needed to update the manifest version to 2.
i don't know, if i got you right...the user select text, press the right mouse button and than you want to do "something"...
try this:
'get the right mouse click
window.oncontextmenu = function ()
{
showSelection(); // call a function or do something here
return false; // cancel the default right click mouse menu (necessary)
}
'in the function get the selected text and do something
function showSelection()
{
var sel = window.getSelection().toString();
alert('selection is '+sel);
.....
}
i understood that your problem is that context menu is not firing... for that you need to do small changes to your manifest
add manifest vesrion as 2
change background_page as background which is a key and value as {scripts:["background.js"]}
create a new javascript file with name as background.js and copy the script tag which is there in background html.i added manifest and javascript. let me know if you found any difficulty.
manifest:
{
"name": "Word Reminder",
"version": "1.0",
"manifest_version": 2,
"description": "Word Reminder.",
"browser_action": {
"default_icon": "images/stick-man1.gif",
"popup":"popup.html"
},
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/myscript.js"]
}
],
"permissions": [
"http://*/*",
"https://*/*",
"contextMenus",
"tabs"
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
}
background.js(new file in the same folder should contain below code):
var seltext = null;
chrome.extension.onRequest.addListener(function(request, sender, sendResponse)
{
switch(request.message)
{
case 'setText':
window.seltext = request.data
break;
default:
sendResponse({data: 'Invalid arguments'});
break;
}
});
function savetext(info,tab)
{
var jax = new XMLHttpRequest();
jax.open("POST","http://localhost/text/");
jax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
jax.send("text="+seltext);
jax.onreadystatechange = function() { if(jax.readyState==4) { alert(jax.responseText); }}
}
var contexts = ["selection"];
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
chrome.contextMenus.create({"title": "Send to Server", "contexts":[context], "onclick": savetext});
}

Keycode not working in chrome extension

I am writing a chrome extension which should change the content-type of http responses. It is working fine. Now, I want to control it using keypress i.e. user should be able to bypass the default action of extension on keypress. I tried this, but it doesn't work:
background.js
var enableEXT = true;
window.onkeydown = function()
{
console.log('Testing hello');
if (event.keyCode == 70)
enableEXT = false;
console.log(event.keyCode);
console.log(enableEXT);
};
window.onkeyup = function()
{
enableEXT = true;
console.log(event.keyCode);
};
chrome.webRequest.onHeadersReceived.addListener(function(details) {
for (var i = 0; i < details.responseHeaders.length; ++i)
{
if (details.responseHeaders[i].name.toLowerCase() == 'content-type' && !enableEXT)
details.responseHeaders[i].value = 'application/xyz';
}
return {responseHeaders: details.responseHeaders};
}, {urls: ["<all_urls>"]}, ['blocking', 'responseHeaders']);
Try using a content script, injected into the web page, instead of a background script. Use this in your manifest.json:
"content_scripts" : [{
"js" : ["myScript.js"]
}]
"permissions": [
"tabs", "http://*/*", "https://*/*"
]
However, chrome extensions are sandboxed from other scripts in the page. However, you do have access to the DOM and you can inject your own tags. So, create a new <script> tag and append it to the DOM, and the new script (script.js) it references can include the event listeners you want.
background.js:
chrome.runtime.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
enableEXT = msg.enableEXT;
});
});
chrome.webRequest.onHeadersReceived.addListener(function(details) {
for (var i = 0; i < details.responseHeaders.length; ++i)
{
if (details.responseHeaders[i].name.toLowerCase() == 'content-type' && !enableEXT)
details.responseHeaders[i].value = 'application/xyz';
}
return {responseHeaders: details.responseHeaders};
}, {urls: ["<all_urls>"]}, ['blocking', 'responseHeaders']);
myScript.js:
//to inject into the page
var s = document.createElement('script');
s.src = chrome.extension.getURL("script.js");
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
//to communicate with our background
var port = chrome.runtime.connect();
window.addEventListener("message", function(event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
port.postMessage(event.data);
}
}, false);
script.js:
window.onkeydown = function()
{
if (event.keyCode == 70)
window.postMessage({ enableEXT: true, "*");
};
window.onkeyup = function()
{
window.postMessage({ enableEXT: false, "*");
};
To communicate between your injected code, your content script, and your background page is a very awkward situation, but can be dealt with, with all the postMessage APIs...
Add a parameter named event to the event handlers you assign to the events like this:
window.onkeydown = function(event)
{
console.log(event.keyCode);
};

Categories