I am trying to build a chrome extension.
chrome.runtime.onMessage.addListener(gotMessage);
const htmlTag = document.getElementsByTagName("html")[0];
function gotMessage(message, sender, sendResponse) {
let events = ["click"];
if(message.txt == 'start') {
// Attach all events to the window
events.forEach((eventName) => {
htmlTag.addEventListener(eventName, consoles);
});
}
else {
events.forEach((eventName) => {
htmlTag.removeEventListener(eventName, consoles);
});
}
function consoles() {
console.log('test');
}
};
This function attach the events I mentioned in events[] but I cann't detech it in else function. When I pass stop txt, it still displays console log. Consider for if condition, message.txt = 'start' and for else, message.txt = 'stop'. Please suggest me what I am missing here?
Related
I'm writing a tampermonkey script that I want to perform an action when a certain set of keys is pressed (cmd + alt + t). I'm seeing a problem where the code stops executing altogether after I click anywhere on the page and I have to either hard refresh or click a certain place on the page (search bar in CloudWatch) to get it working again.
Here's my code:
(async function() {
var set = new Set();
function funcA() {
console.log('funcA');
}
function funcB() {
console.log('funcB');
if (set.has(91) && set.has(18) && set.has(84)) { // cmd + alt + t
funcA();
}
}
function onKeyUp(e) {
console.log('onKeyUp');
set.clear();
console.log(new Array(...set).join(' '));
}
function onKeyDown(e) {
console.log('onKeyDown');
set.add(e.which);
console.log(new Array(...set).join(' '));
funcB();
}
function init() {
console.log('init');
console.log('Adding event listeners.');
document.addEventListener('keyup', onKeyUp);
document.addEventListener('keydown', onKeyDown);
}
if( document.readyState !== 'loading' ) {
console.log( 'not loading' );
init();
} else {
document.addEventListener('DOMContentLoaded', init);
}
})();
The problem only seems to happen on certain pages, for example in AWS CloudWatch logs.
Any ideas?
I am currently facing an issue where I have event listeners running for my client's website which track all hover and clicks on the website. We have 4 clients and our code works fine on 3 of them but it does not work correctly on the 1 client's website.
We are running the following code when a click is triggered:
async function objectClick(obj) {
var tag = obj.target;
if (tag.nodeName == 'IMG') {
objectName = tag.src;
} else {
objectName = tag.innerText || tag.textContent || tag.value;
}
var data_tag = tag.getAttribute("data-*");
if (data_tag != null) {
if (data_tag.includes("abc")) {
var layout = JSON.parse(window.localStorage.getItem(page));
layout.ctr = 1;
window.localStorage.setItem(page, JSON.stringify(layout))
await sendToHistory(uid, url, JSON.stringify(layout));
} else if (data_tag.includes("reward")) {
var layout = JSON.parse(window.localStorage.getItem(page));
layout.reward = 1;
window.localStorage.setItem(page, JSON.stringify(layout))
await sendToHistory(uid, url, JSON.stringify(layout));
}
}
if (data_tag === "abc" || data_tag === "reward") {
await sendToJourney(uid, "Clicked", -1, tag.nodeName, JSON.stringify({ text: objectName, data_nostra: null }), url, page);
} else {
await sendToJourney(uid, "Clicked", -1, tag.nodeName, JSON.stringify({ text: objectName, data_nostra: data_nostra_tag }), url, page);
}
}
For most of our clients, all the code runs in the function runs, including the sendToJourney function. For this client, after sendToHistory runs, the page switches and sendToJourney is not triggered. Do you know why this is?
sendToJourney and sendToHistory are functions that send some data to an API. Let me know if you need more information. Lastly, the client's website is created using Elementor which is a WordPress plugin. 2 of the other 4 clients also use Elementor but the function is fully executed for them but just not for this 1 client. Is there something that can be preventing the code from fully executing?
We have tried using obj.preventDefault but we cannot get the event to be triggered afterwards once our code is executed so what solution could be use here?
I call objectClick() by attaching an event listener as such:
(async function (document) {
await initData()
var trackable = document.querySelectorAll("img,button,p,h1,h2,h3,h4,h5,h6,a,span,input[type='submit'],[data-*]");
for (var i = 0; i < trackable.length; i++) {
trackable[i].addEventListener('mouseover', onHover, false);
trackable[i].addEventListener('mouseout', offHover, false);
trackable[i].addEventListener('click', objectClick, false);
}
})(document);
This question already has an answer here:
Clipboard Copy / Paste on Content script (Chrome Extension)
(1 answer)
Closed 6 years ago.
Quick summary
The code below is a file called popup.js. It listens for a click, and sends a message to background.js. Background.js executes another script, and a variable is created.
I somehow need to pass this variable back to popup.js, and continue within the userHasClicked function. The way it is now the response I get is "undefined", and there's nowhere to go from there.
var theParent = document.querySelector("#MENY");
theParent.addEventListener("click", userHasClicked, false);
function userHasClicked(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
chrome.runtime.sendMessage({type: "ResponseType", directive: clickedItem}, function(response) {
console.log(response);
this.close();
});
};
e.stopPropagation();
}
Routine:
User clicks on an option in popup.html
Event("click") -> sendmessage("type of click")
background.js listens for the message, and executes content.js
content.js creates the variable and can send it back to anyone who listens.
The problem:
The variable must come as a response argument to step 2 (within eventloop)
Save the response as variable.
document.execCommand("copy").
Done
This code below is the relevant part of background.js.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.type) {
case "ResponseType":
var LoggType = request.directive;
console.log(LoggType)
chrome.tabs.executeScript(null, {
code: 'var LoggType = "'+LoggType+'";'
}, function() {
chrome.tabs.executeScript(null, {file:"content.js"});
});
chrome.runtime.onMessage.addListener(function(req, snd, sndRes) {
if (req.type = "LogIsGenerated") {
var Logg = req.directive;
console.log(Logg);
} sndRes({});
});
if (typeof Logg !== "undefined") {
alert("Feedback from content.js received");
sendResponse({type: "FinalVar", directive: Logg});
}
else {
alert("No feedback received");
sendResponse({});
};
break};
return true;
}
);
content.js ends with this line.
chrome.extension.sendMessage({type: "LogIsGenerated", directive: Logg});
Logg is the variable containing the text string I want to add to the clipboard.
At the moment this the code below alerts for No feedback received.
chrome.runtime.onMessage.addListener(function(req, snd, sndRes) {
if (req.type = "LogIsGenerated") {
var Logg = req.directive;
console.log(Logg);
} sndRes({});
});
if (typeof Logg !== "undefined") {
alert("Feedback from content.js received");
sendResponse({type: "FinalVar", directive: Logg});
}
else {
alert("No feedback received");
sendResponse({});
};
Rob W presented a solution here: Background script can write to clipboard in a very simple manner
Worked excellently.
I'm trying to get some user configs from the background page of my chrome extension to the content script (or popup) but I'm having some problems, I think the problem is that chrome.storage.sync.get is async, I tried using callbacks but I also read that callbacks can't return the value so I have no idea how to solve this.
Here's kinda how the code looks:
popup.js:
(function() {
chrome.runtime.sendMessage({
message: "loadconfig"
}, function(response) {
console.log(response);
if (response.status === 'success') {
console.log(response);
} else {
console.log(response.except);
}
});
})();
background.js
(function() {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
switch (request.message) {
case "loadconfig":
sendResponse(loadStuff());
break;
default:
sendResponse({
reply: null
});
break;
}
});
function loadStuff() {
var to_return_configs = {
blocked_characters: '',
good_post: ''
};
var function_status = 'failed';
var exception = '';
var blocked_characters_parsed, good_post_parsed;
try {
var to_get = ["blocked_characters_saved", "good_post_saved"];
chrome.storage.sync.get(to_get, function(result) {
to_get.forEach(function(got) {
if (got === "good_post_saved") {
to_return_configs.good_post = result[got];
}
if (got === "blocked_characters_saved") {
to_return_configs.blocked_characters = result[got];
}
});
});
exception = '';
function_status = 'success';
} catch (err) {
exception = String(err);
function_status = 'failed';
}
var to_return = {
status: function_status,
configs: to_return_configs,
except: (exception)
};
return to_return;
}
})();
The problem here is that when I'm looking at the popup.js console, "blocked_characters" and "good_post" are both empty.
How can I solve this?
You do not need Message API for communication between Popup and Background. Popup in chrome extension can directly call methods of Background .
You can do something like this
BG = chrome.extension.getBackgroundPage();
And then you can call BG.loadStuff() in your popup js.
From within loadStuff, you can pass a callback which can return data to you. So it should look like
BG.loadStuff(function(items) {
console.log(items);
});
background.js
function loadStuff(cb) {
chrome.storage.sync.get(null, function(superObj) {
cb.call(null, superObj);
});
}
For more understanding, read these
http://blog.papersapp.com/chrome-development-parent-and-child-windows/
https://stackoverflow.com/a/17276475/816213
https://stackoverflow.com/a/17378016/816213
sendResponse(function) becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called). See the reference: onMessage.
Because sendResponse is called asynchronously in chrome.storage.sync.get's callback, you need to return true from the onMessage listener to prevent the function from being invalidated. Code similar is Like:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.message === 'loadconfig') {
sendResponse(loadStuff());
return true;
}
return false;
});
I send a message from a ContextMenu within content.js to background.js. When I send a message, I expect to see an alert of just two variables which are sent with the request. When I send multiple request(few times in a row) I receive alerts including previously sent messages. It seems that all messages are stored somewhere. How do you disable this? I would like to see alerts of only the most recent message.
contents.js:
$(document).mousedown(function(event) {
var url = window.location.href;
var contents = window.getSelection().toString();
switch (event.which) {
case 3:
chrome.runtime.sendMessage({contents: contents, url: url}, function(response) {
//console.log(response.farewell);
});
break;
}
});
background.js
chrome.extension.onMessage.addListener(function (message, sender, sendResponse) {
if (message.url) {
chrome.contextMenus.onClicked.addListener(function testFunc2(info, tab){
alert(message.url);
alert(typeof message.contents);
}
)
}
});
manifest.json
"background": {
"scripts": ["jquery-1.11.1.min.js", "background.js"],
//"page": "background.html",
"persistent": true
},
It's because of this code
chrome.extension.onMessage.addListener(function (message, sender, sendResponse) {
if (message.url) {
chrome.contextMenus.onClicked.addListener(function testFunc2(info, tab){
alert(message.url);
alert(typeof message.contents);
}
)
}
});
What you are saying is that every onMessage event add a listener for onClicked events. So if you send three messages you end up with three testFunc2 methods acting on onClicked events.
Since you are trying to use information from two different asynchronous events. You will have to store one of them temporarily. Something like this would probably work.
var lastMessage;
chrome.extension.onMessage.addListener(function(message, sender, sendResponse) {
if (message.url) {
lastMessage = message;
} else {
lastMessage = undefined;
}
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
if(lastMessage !== undefined) {
testFunc2(message, info, tab);
}
});
function testFunc2(info, tab){
alert(message.url);
alert(typeof message.contents);
// cleanup
lastMessage = undefined;
});