I am working on some experiments that requires to auto generate IDs for elements, I have decided to go with chrome extension.
However, the content script only got triggered when I land on the homepage of the site (e.g. https://secure.checkout.visa.com/). Once I navigate to other pages (e.g. tap on "Create Account"), the script didn't get triggered, I tried to set a break point on the content script but it only got hit on the home page, but not on create account page.
Any idea what went wrong here? Below is the code:
// manifest.json
{
"manifest_version": 2,
"name": "Chrome Auto Gen ID",
"description": "Generate IDs",
"version": "1.0",
"permissions": ["activeTab"],
"background": {
"scripts": ["event_page.js"],
"persistent": false
},
"browser_action": {
"default_title": "Auto generate ID"
},
"content_scripts": [
{
"matches": ["https://secure.checkout.visa.com/*"],
"js": ["jquery-3.2.1.min.js", "auto_gen_id.js"],
"all_frames": true,
"run_at": "document_idle"
}
]
}
The content script:
// auto_gen_id.js
var divs = document.getElementsByTagName("div");
var inputs = document.getElementsByTagName("input");
var sections = document.getElementsByTagName("section");
var count = 0;
function genId(list) {
for (var i = 0; i < list.length; ++i) {
var element = list[i];
if (element.hasAttribute("id")) {
continue;
}
element.id = "gen-id-" + count++;
}
}
genId(divs);
genId(inputs);
The background script:
// event_page.js
chrome.browserAction.onClicked.addListener(function(tab) {
console.log('Generating IDs on ' + tab.url);
chrome.tabs.executeScript(null, {file: "auto_gen_id.js"});
});
Thanks #makyen and #wOxxOm, followed the suggestions below to solve the problem:
Is there a JavaScript/jQuery DOM change listener
Related
I am making a chrome extension in which I want to change the color of the "Send" button of Compose dialog.
What is the best way to do it?
Thanks in advance!
Update-
Here is the function of content.js I am currently using to change the color-
function modifySendButton(check, form) {
var send_button = $(form).siblings('table').find('div[role="button"][aria-label="Send (Ctrl-Enter)"]');
if (0 === send_button.length) {
send_button = $(this).siblings('table').find('div[role="button"][aria-label="Send (⌘Enter)"]');
}
if (true === check) {
send_button.addClass("active-send-button");
} else {
send_button.removeClass("active-send-button");
}
}
It is changing the Send button color, but I want to know is it the right way to do so?
You can try to use mutation observer inside the content-script.
Complete example:
manifest.json
{
"manifest_version": 2,
"name": "Btn Color",
"description": "",
"version": "1.0.0",
"content_scripts": [{
"js": ["content-script.js"],
"matches": [
"https://mail.google.com/*"
],
"run_at": "document_end"
}],
"permissions": [
"tabs"
]
}
content-script.js
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if(mutation.addedNodes && mutation.addedNodes.length) {
// look for the button
const sendBtn = document.querySelector('.dw [aria-label*="Send"]');
if(sendBtn) {
sendBtn.style.background = 'red'; // set your styles
}
}
});
});
var targetNode = document.body;
observer.observe(targetNode, {childList: true});
Here is the contents of background.js:
var toggle = false;
chrome.browserAction.onClicked.addListener(function(tab) {
toggle = !toggle;
if(toggle) {
var start_working = function() {
chrome.tabs.query({ url: ["http://*/*","https://*/*"], currentWindow: true }, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.executeScript(tabs[i].id, {code : "var enabled = 1;"});
chrome.tabs.executeScript(tabs[i].id, {file: 'js/new.js'});
chrome.browserAction.setIcon({path: "add48.png", tabId:tabs[i].id});
}
});
}
if (!chrome.tabs.onUpdated.hasListener(start_working)) {
chrome.tabs.onUpdated.addListener(start_working);
chrome.tabs.query({url: ["http://*/*","https://*/*"]}, function (tabs) {
console.log('1start_working='+chrome.tabs.onUpdated.hasListener(start_working));
console.log('1toggle='+toggle);
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.executeScript(tabs[i].id, {code : "var enabled = 1;"});
chrome.tabs.executeScript(tabs[i].id, {file: 'js/new.js'});
chrome.browserAction.setIcon({path: "add48.png", tabId:tabs[i].id});
}
}
);
}
} else {
chrome.tabs.onUpdated.removeListener(start_working);
console.log('2start_working='+chrome.tabs.onUpdated.hasListener(start_working));
console.log('2toggle='+toggle);
chrome.tabs.query({url: ["http://*/*","https://*/*"], currentWindow: true }, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.executeScript(tabs[i].id, {code : "var enabled = 0; $('#sort_g').remove();"});
chrome.browserAction.setIcon({path: "add48_off.png", tabId:tabs[i].id});
}
}
);
return false;
}
});
Here is the code of manifest.json:
{
"manifest_version": 2,
"name": "Ds",
"version": "0.2",
"background": {
"scripts": ["background.js"]
},
"icons": {
"48": "add48.png",
"128": "add128.png"
},
"browser_action": {
"default_icon": "add48_off.png"
},
"permissions": [
"tabs",
"notifications",
"*://*/*"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/jquery-2.2.4.min.js"],
"run_at": "document_end",
"all_frames": true
}
],
"web_accessible_resources": ["tpl/panel.html"]
}
When we click on the application icon, we add an element to all the HTML tabs and make the icon "active", and when we click the icon again, we change the icon to gray and remove the html element from all pages.
Also, when updating the html tab, the element should again appear and the extension icon should be active.
All this is implemented, but after disabling the extension, an html element still appears, although the new.js script should not be connected and chrome.tabs.onUpdated.hasListener(start_working)=false
Here's the log after disabling the extension:
background.js:49 2start_working=false
background.js:50 2toggle=false
But when updating the tab anyway, the html element appears on the page
I can not understand why this happens? Moreover, the console shows that after disabling the extension, when updating the page, the new.js script is connected already 3 times.
So I'm trying my hand at a google chrome extension which in theory should be extremely straight forward. I know there are tons of stack queries and I've tried a few, I've even copied and pasted direct solutions for testing and I have been unsuccessful. So here is the project. When a page loads, check the html content, and change the icon programmatically.
This is my content.js
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete' && tab.active) {
var markup = document.documentElement.innerHTML;
var m = markup.indexOf("candy");
if (m > -1) {
chrome.browserAction.setIcon({path: "check.png"});
} else {
chrome.browserAction.setIcon({path: "cross.png"});
}
}
})
This is my manifest.json
{
"manifest_version": 2,
"name": "Tag Analyzer Plugin",
"description": "Check if tag exist on page",
"version": "1.0",
"browser_action": {
"default_icon": "cross.png"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"permissions": ["<all_urls>"]
}
Right now I'm running this item as a content script because as a content script I can use the logic
var markup = document.documentElement.innerHTML;
var m = markup.indexOf("candy");
if (m > -1) {} else {}
However as a content script the chrome API stuff doesn't work. When I run this script as a background script the script works, except that
var markup = document.documentElement.innerHTML;
doesn't return the pages html, it returns the injected script html.
I've read this stack which was informative as to what the difference was and I've read and tested many stacks like here this, without much success. So obviously i'm missing something and doing something wrong. Thank in advanced for any help.
UPDATES:
So I've made some modifications, but it's still not working, though I think that it's closer to working.
As per the comments below I am now using a content script and background script. No errors are being thrown, however the background script isn't doesn't anything.
content.js
var markup = document.documentElement.innerHTML;
var m = markup.indexOf("candy");
if (m > -1) {
chrome.runtime.sendMessage({"found" : true});
} else {
chrome.runtime.sendMessage({"found": false});
}
background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if request.found {
alert("HERE");
chrome.browserAction.setIcon({
path: "check.png",
tabId: sender.tab.id
});
} else {
alert("HERE2");
chrome.browserAction.setIcon({
path: "cross.png",
tabId: sender.tab.id
});
}
});
manifest.json
{
"manifest_version": 2,
"name": "Tag Analyzer Plugin",
"description": "find tag on page",
"version": "1.0",
"browser_action": {
"default_icon": "cross.png"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"permissions": ["<all_urls>"]
}
I've added some alerts on the background.js to see if it was being trigger and nothing, not does the icon change.
I'm building an google extension that inserts html in page and shows a menu on browser action icon click and I don't find way to keep my extension open when I reload the page. So on every reload, we have to active it again from Browser Action icon.
Below the manifest file
{
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "img/icone.png",
"default_title": "show menu"
},
"icons" : {
"128" : "img/icone_128.png",
"48" : "img/icone_48.png",
"32" : "img/icone_32.png",
"24" : "img/icone_24.png",
"16" : "img/icone_16.png"
},
"manifest_version": 2,
"name": "p|layer",
"version": "1.0.4",
"content_scripts": [
{
"matches": [ "<all_urls>"],
"css":["css/grid.css", "css/font-awesome.min.css"],
"js":["js/jquery-1.11.1.min.js","js/jquery-ui.js", "js/jquery.nicefileinput.min.js"]
}
],
"web_accessible_resources": [
"fonts/fontawesome-webfont.woff"
],
"permissions": [ "activeTab"]
}
script (background.js) injecting contentscript
chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
chrome.tabs.executeScript(tab.id,
{"file": "js/contentscript.js"},
function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
chrome.tabs.insertCSS(tab.id, {file: "css/grid.css"});
chrome.tabs.insertCSS(tab.id, {file: "css/font-awesome.min.css"});
chrome.tabs.insertCSS(tab.id, {file: "css/slider.css"});
});
any help will be appreciated
So, from the comments the problem was inferred: your button click activates your content script, but a page reload clears it. Assuming you want the button click to act as a toggle:
1) Always inject the content script / CSS, but don't show the UI immediately:
"content_scripts": [
{
"matches": [ "<all_urls>"],
"css": ["css/grid.css", "css/font-awesome.min.css", "css/slider.css"],
"js": [
"js/jquery-1.11.1.min.js", "js/jquery-ui.js",
"js/jquery.nicefileinput.min.js", "js/contentscript.js"
]
}
],
2) Keep track of "activated" tabs:
var activeTabs = {};
chrome.browserAction.onClicked.addListener( function(tab){
var active;
if(activeTabs[tab.id]){
delete activeTabs[tab.id];
active = false;
} else {
activeTabs[tab.id] = true;
active = true;
}
/* (part 3) */
});
chrome.tabs.onRemoved.addListener( function(tabId){
delete activeTabs[tabId];
});
chrome.tabs.onReplaced.addListener( function(newTabId, oldTabId){
if(activeTabs[oldTabId]) activeTabs[newTabId] = true;
delete activeTabs[oldTabId];
});
3) Use messaging to show/hide UI:
Content script:
chrome.runtime.onMessage.addListener( function(message. sender, sendResponse){
if(message.showUI) showUI();
if(message.hideUI) hideUI();
});
Background script:
chrome.browserAction.onClicked.addListener( function (tab) {
var active;
/* (part 2) */
if(active) {
chrome.tabs.sendMessage(tab.id, {showUI: true});
} else {
chrome.tabs.sendMessage(tab.id, {hideUI: true});
}
});
Additional robustness can be added for the cases of extension reload, but that's the gist of it.
I try make deskotp notification used chrome extension.
I would it can work like this - when user visit recomended page it will be show.
background.js
function show() {
var notification = window.webkitNotifications.createNotification(
'48.png',
'YOUR VISIT PAGE http://stackoverflow.com/!'
);
notification.show();
}
// Conditionally initialize the options.
if (!localStorage.isInitialized) {
localStorage.isActivated = true; // The display activation.
localStorage.frequency = 1; // The display frequency, in minutes.
localStorage.isInitialized = true; // The option initialization.
}
function checkForValidUrl(tabId, changeInfo, tab) {
if (tab.url.indexOf('stackoverflow') > -1) {
if (window.webkitNotifications) {
if (JSON.parse(localStorage.isActivated)) {
show();
}
}
}
}
chrome.tabs.onUpdated.addListener(checkForValidUrl);
manifest.json
{
"name": "YouVisit",
"version": "0.1",
"description":
"Show desktop notification when user visit page",
"icons": {"48": "48.png"},
"permissions": [
"notifications",
"tabs"
],
"background": { "scripts": ["background.js"] },
"manifest_version": 2,
"web_accessible_resources": [
"48.png"
]
}
any ideas why this code doesn't work? can someone give me some literature to make it proper?
You failed to provide the proper arguments for the createNotification() function:
According to the docs:
// Create a simple text notification:
var notification = webkitNotifications.createNotification(
'48.png', // icon url - can be relative
'Hello!', // notification title
'Lorem ipsum...' // notification body text
);