How can I start a function everytime the page loads? - javascript

(Sorry in advance if there are any english mistake)
Hi everyone, I'm working on a simple Chrome extension to edit some graphics and texts related fields of a website (Freshdesk) that I can't modify from the website itself because the code is proprietary.
My problem is, to make the function that replace the texts be active everytime the pages are displayed, I'm using a setInterval() with 100 ms of delay, which kinda does the job but it's not optimal, because the function runs like thousands of times in a few seconds.
function main() {
console.log('main started');
setInterval(changeText, 100); //(Not optimized)
}
function changeText() {
// replace 'Group' with 'Sector'' in the ticket tab visual
$('.ember-power-select-placeholder.label-field').each(function(x){
var new_text = $(this).text().replace("Group", "Sector");
$(this).text(new_text);
console.log('function started');
})
}
main();
As you can see from the screenshots and the code above, in this simple case I wanna change the text from
Group
to
Sector
and, as you can see, the code works, but if we take a look at the console.. (this is after like 5 seconds).
I already tried some function to make the js run as soon as the page loads just once, but none of them seem to work for me.
Do you have any tip to fix this situation?
EDIT: Here is the manifest.json too
{
"name": "DAN-Patch",
"version": "1.0",
"manifest_version": 2,
"permissions": [
"webNavigation",
"activeTab",
"background",
"tabs"
],
"content_scripts": [
{
"run_at": "document_idle",
"matches": ["https://gestionaledan.freshdesk.com/*", "https://gestionaledan.freshworks.com/*"],
"js": ["jquery-3.5.1.min.js", "content.js"],
"css": ["stylesheet.css"]
}
]
}

use this to reduce the number of processes:
function main() {
console.log('main started');
let exa = setInterval(function () {
let el = $('.ember-power-select-placeholder.label-field'),
all = 0;
el.each(function () {
if ($(this).text() == "Group") {
// replace 'Group' with 'Sector'' in the ticket tab visual
var new_text = $(this).text().replace("Group", "Sector");
$(this).text(new_text);
console.log('function started');
all ++;
}
});
if (all == 0) {
clearInterval(exa);
}
}, 100); //(Not optimized)
}
main();

Related

refresh page until it changes chrome extension

i'm building extension for google chrome that refresh page until it changes its link.
I tried this code but it didn't worked:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (/^https:\/\/meet.google.com\/lookup/.test(changeInfo.url)) {
var intervalId = window.setInterval(function() {
var code = 'window.location.reload(); ';
chrome.tabs.executeScript(tab.id, {code: code});
}, 30000);
}
else {
window.clearInterval(intervalId)
}
});
i want to stop refresh when meet.google.com/lookup/ changes in another link, that could be also meet.google.com or meet.google.com/abcdef/.
So it refresh the page, but when the link of google meet changes, it keeps to refresh page. How can i solve? Thanks everyone!
P.S: I added my answer on a comment for be more understandable
I am assuming your aim is to keep refreshing a tab unless its location is meet.google...(the regex you have used), every thirty seconds.
If that is your aim, the problem here, is that the intervalID is lost once the event listener is executed. So, you need to maintain the intervalID outside of the listener scope so that you can clear it when that tab changes the URL.
I have the code below, try this
var intervalMap = {};
function handleUpdated(tabId, changeInfo, tabInfo) {
if (changeInfo.url) {
console.log("Tab: " + tabId + " URL changed to " + changeInfo.url);
if (changeInfo.url.indexOf("https://meet.google.com/?authuser") > -1) {
console.log("Found URL to reload. Added interval");
var intervalId = window.setInterval(function () {
var code = "window.location.reload(); ";
chrome.tabs.executeScript(tabId, { code: code });
}, 3000);
//Save the intervalId to our map
intervalMap[tabId] = intervalId;
} else if (intervalMap[tabId]) {
//Take interval ID from map and clear it
console.log("Tab changed to differente URL. Removed interval");
window.clearInterval(intervalMap[tabId]);
}
}
}
chrome.tabs.onUpdated.addListener(handleUpdated);
Manifest (Version 2)
{
"name": "Test",
"version": "1.0",
"manifest_version": 2,
"background": {
"scripts": ["background.js"]
},
"permissions": ["background", "tabs", "https://meet.google.com/*"]
}
Edit: Have updated the code to add relevant console logs. Added manifest to ensure that required permissions are added

Mozilla Extension Alert every 30min

Hi i wanted to create extension that will trigger alert every 30mins to remind me check my posture. But i got stuck. I dont know how to make it so that alert triggers only in tab that im currently in. Now it triggers in every tab i have opened. Can someone help me please? Thanks.
As im thinking right now this way it will start new cycle every time i open new tab right? So im gonna see it in 30min only if i stay in that current tab.
setInterval(function() {
alert("Posture!");
}, 5000);
{
"name": "Posture Checker",
"version": "1.0",
"manifest_version": 2,
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["posturecheck.js"]
}
]
}
You can check if a tab is in focus by checking if document.hidden.
if (document.hidden) {
// Document/tab/window is hidden
} else {
// Document/tab/window is visible
}
Alternatively, you can also check document.visibiliyState, but it does not return a boolean but a string value that you need to check against:
if (document.visibilityState === 'hidden') {
// Document/tab/window is hidden
} else if (document.visibilityState === 'visible') {
// Document/tab/window is visible
}

jQuery select pre-exising button in chrome extension

I want to make an extension that changes the title on Chrome's built in stopwatch when i start and stop it. I am getting an error trying to retrieve the button's class. The JavaScript works when pasted in the browser console so I think the problem is with the json file.
Here is my JavaScript.
var title = document.querySelector("title");
var button = document.querySelector(".act-desktop-button");
var flip = true;
button.addEventListener("click", function(){
flip =! flip;
console.log(flip);
if(flip === true){
title.textContent = "OFF";
} else{
title.textContent = "ON";
}
});
and here is my json
{
"name": "Stopwatch Tracker",
"version": "1.0",
"description": "works with chromes built in stopwatch feature. Changes the
title of the page to 'ON' or 'OFF' depending on if the stopwatch is
running.",
"permissions":[
"tabs",
"*://*.google.com/search?q=stopwatch*"
],
"content_scripts": [
{
"matches": ["*://*.google.com/search?q=stopwatch*"],
"js": ["background.js"]
}
],
"manifest_version": 2
}
I am receiving this error:
I think, what is the most important part here is to make sure that you have checked the value of button to be not null before adding an event listener.
Just like this:
var button = document.querySelector(".act-desktop-button");
var flip = true;
if (button){
button.addEventListener("click", function(){
...
})};
Try also to check this SO post as this is related to your question.

Chrome extension run Javascript on X next tabs

I'm making an extension and I can't understand how to do the following -
My extensions currently open X amount of tabs, according to a specific text. Now I want it to run a specific script in every new tab it opens.
Manifest.json:
{
"name": "Asaf Feedback Opener",
"version": "1",
"manifest_version" : 2,
"description": "Opens any View Item on the current page",
"background" : {
"scripts" : ["background.js"]
},
"browser_action": {
"default_icon": "icon.png"
},
"permissions": ["activeTab", "tabs"]
}
Now it runs the following code in the current page of clicking:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "testScript.js"});
});
Javascript:
var links = document.getElementsByTagName("a");
numofview = 0;
for (i = 0; i < links.length; i++)
{
if (links[i].innerHTML.startsWith("View Item"))
{
numofview = numofview+1;
window.open(links[i].getAttribute("href"), "_blank");
}
}
Now, In the above JS It opens links in a new tab. I want the next code to run in every tab that the previous code had opened:
var soldlinks = document.getElementsByTagName("a");
for (i = 0; i < soldlinks.length; i++)
{
if (soldlinks[i].innerHTML.endsWith("sold"))
{
var soldlength = soldlinks[i].innerHTML.length
var amount = soldlinks[i].innerHTML.substring(0,soldlength-5);
if (Number(amount) >= 5)
window.open(soldlinks[i].getAttribute("href"), "_self");
else
window.close()
}
}
I actually don't know JS or the chrome extensions coding language at all, I've been improvising with google to get this far.
Both scripts work in separate, I don't how to go forward from here.
Make your injected content scripts only collect and return the URLs to the background page script by leaving the data as the last expression in the file (see the code below). It will be available in executeScript's callback parameter which is an array of results per each frame in a tab so our data is inside its element 0 (main frame is 0 = the page itself).
The background page script will open the tabs and use executeScript to inject the new content script into the opened tabs. This will require additional permissions in manifest.json for the opened sites or all URLs if you don't know which sites may be referred:
"permissions": ["<all_urls>", "tabs"]
Use an event page that's automatically unloaded when your extension is not used.
"background" : {
"scripts" : ["event.js"],
"persistent": false
},
event.js (previously background.js now renamed for clarity):
chrome.browserAction.onClicked.addListener(collectViewItems);
function collectViewItems(tab) {
chrome.tabs.executeScript(tab.id, {file: 'collect-view-items.js'}, results => {
results[0].forEach(openViewItem);
});
}
function openViewItem(url) {
chrome.tabs.create({url, pinned: true, active: false}, collectSoldItems);
}
function collectSoldItems(tab) {
chrome.tabs.executeScript(tab.id, {file: 'collect-sold-items.js'}, results => {
chrome.tabs.remove(tab.id);
results[0].forEach(openSoldItem);
});
}
function openSoldItem(url) {
chrome.tabs.create({url, active: false});
}
collect-view-items.js:
[...document.links]
.filter(a => a.textContent.trim().startsWith('View Item'))
.map(a => a.href);
collect-sold-items.js:
[...document.links]
.filter(a => a.textContent.trim().endsWith('sold') && parseInt(a.textContent) >= 5)
.map(a => a.href);
ES2015 syntax is used, available in modern browsers by default.

Chrome Extension workaround with popup html

My project is a Chrome extension that will do the following.
Push the extension icon.
Popup will appear (from popup.html)
5 buttons will be in the popup.
When you click one of the four buttons, one javascript code will be executed.
close popup window.
So depending on the answer of this post over here
Detect a button click in the browser_action form of a Google Chrome Extension
(big ups to Michael for his enormous help)
This example is only for one button. Created it with only one of my javascript code and works perfect.
But when it comes to put all of the 5 buttons i 've tried to make this kind of coding but it didnt work at all (im new at javascript code so dont hate)
Here are the codes
MANIFEST.JSON
{
"background": {
"scripts": [ "background.js" ]
},
"browser_action": {
"default_icon": "img/icon.png",
"default_title": "TITLE",
"default_popup": "popup.html"
},
"icons": {
"128": "img/icon_128.png",
"19": "img/icon19.png",
"38": "img/icon38.png",
"48": "img/icon_48_2.png"
},
"manifest_version": 2,
"name": " NAME",
"description": " DESCR ",
"permissions": [ "activeTab" ],
"version": "2.0"
}
POPUP.HTML
<html>
<head>
<script src="popup.js"></script>
<style type="text/css" media="screen">
body { min-width:250px; text-align: center; }
#click-me-l { font-size: 20px; }
#click-me-f { font-size: 20px; }
</style>
</head>
<body>
<button id='click-me-l'>Click1</button>
<button id='click-me-f'>Click2</button>
</body>
</html>
POPUP.JS
function clickHandler(e) {
chrome.extension.sendMessage({directive: "popup-click-l"}, function(response) {
this.close(); // close the popup when the background finishes processing request
});
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('click-me-l').addEventListener('click', clickHandler);
})
function clickHandler(e) {
chrome.extension.sendMessage({directive: "popup-click-f"}, function(response) {
this.close(); // close the popup when the background finishes processing request
});
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('click-me-f').addEventListener('click', clickHandler);
})
BACKGROUND.JS
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.directive) {
case 1 "popup-click-l":
// execute the content script
chrome.tabs.executeScript(null, { // defaults to the current tab
file: "script1.js", // script to inject into page and run in sandbox
allFrames: true // This injects script into iframes in the page and doesn't work before 4.0.266.0.
});
case 2 "popup-click-f":
// execute the content script
chrome.tabs.executeScript(null, { // defaults to the current tab
file: "script2.js", // script to inject into page and run in sandbox
allFrames: true // This injects script into iframes in the page and doesn't work before 4.0.266.0.
});
sendResponse({}); // sending back empty response to sender
break;
default:
// helps debug when request directive doesn't match
alert("Unmatched request of '" + request + "' from script to background.js from " + sender);
}
}
);
So the codes in the link are working PERFECT for only 1 button.
in this example i am trying to make it work for 2 buttons but i cant find what im doing wrong. If anyone has any idea i would appreciate it.
Thanks a lot for your time!!!
(UPDATE 2. Updated codes for 2 buttons but not working.)
You’re defining clickHandler twice, so only the second one counts. One fix would be:
function clickHandler(e) {
chrome.extension.sendMessage({"directive": e.target.id}, function(response) {
this.close(); // close the popup when the background finishes processing request
});
}
In general, you’re repeating yourself too much. You could combine your DOMContentLoaded events into one:
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('click-me-l').addEventListener('click', clickHandler);
document.getElementById('click-me-f').addEventListener('click', clickHandler);
})
but even better would be to put all the buttons into an array, so that popup.js is now:
function clickHandler(e) {
chrome.extension.sendMessage({"directive": e.target.id}, function(response) {
this.close(); // close the popup when the background finishes processing request
});
}
document.addEventListener('DOMContentLoaded', function () {
var buttons = document.getElementsByTagName("button");
for ( var i = 0 ; i < buttons.length ; i++ ) {
buttons[i].addEventListener('click',clickHandler);
}
})
(And I’d recommend button { font-size: 20px; } in your style instead of five separate ids.)
Finally, your switch statement is buggy. Once you start a case, you’ll keep going until you get to a break, so that case "popup-click-l" hits both cases. You could have a separate executeScript for each case, but even better would be to assign to fileName based on the case, and have a single injection at the end. Or best of all would be to have a javascript object define which files go with which ids, so that background.js is now:
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
var injected = {
"click-me-l": "script1.js",
"click-me-f": "script2.js"
};
chrome.tabs.executeScript(null, {
"file": injected[request.directive],
"allFrames": true
});
sendResponse({});
}
);
Fundamentally, this comes back to a point I made in a comment: browser extensions are a bad way to learn javascript, because you’re learning two separate things at the same time. Your difficulties with switch, {}, and generally following the code is a javascript problem. Not seeing when the console tells you about syntax errors is more of a browser extension problem. And your biggest problem is that you’re not seeing which error is which.

Categories