.click(function()) not being called - javascript

I'm trying to make an chrome extention with the last.fm api, and I've succesfully placed down the folliwing div in the page I want it to be shown.
<div id="showLastFMInfo" Title="More info about song" class="LastFMButtonDown">»</div>
but when I click on it, nothing happens, this is the JS used:
$(document).ready(function () {
// this get executed
$('#meta-frame').append('<div id="showLastFMInfo" Title="More info about song" class="LastFMButtonDown">»</div>');
// this won't work if I click on my button
$("#showLastFMInfo").click(function(){
console.log("Click");
});
});
so you can see the first lines get executed but the .click() doesn't react.
this is my manifest.json:
{
"content_scripts": [ {
"js": [ "jquery.js", "lastfm.api.cache.js","lastfm.api.md5.js", "lastfm.api.js","lastFMLink.js", "script.js"],
"css": [ "LastFMLink.css" ],
"run_at": "document_end"
} ],
"name": "Plug.Dj VS last.Fm",
"description": "Implement information about the artist",
"icons": { "16": "cookie.png", "48": "cookie.png", "128": "cookie.png" },
"version": "0.0.1",
"web_accessible_resources": [ "lastFMLink.js" ],
"manifest_version": 2
}
Does anyone has a idea what I'm doing wrong?

You're appending it, so it's dynamic, and you need a delegated event handler:
$('#meta-frame').on('click', '#showLastFMInfo', function(){
console.log("Click");
});
on the other hand, attaching the event handler after the element is appended should work as well?

for dinamically generated contents use on of these
$("a.offsite").live("click", function(){ alert("Goodbye!"); }); // jQuery 1.3+
$(document).delegate("a.offsite", "click", function(){ alert("Goodbye!"); }); // jQuery 1.4.3+
$(document).on("click", "a.offsite", function(){ alert("Goodbye!"); }); // jQuery 1.7+
live and delegate are deprecated, so using .on() is recommended.

Use document or the closest static element
$(document).on('click','#showLastFMInfo',function(){
});

Related

Getting element in DOM after ajax call

There is a lot question and answers about that question, but I'm not being able to make it work for my case.
My extension gets the positions (1,2,...,100) on the scores pages of a game. When I first load the page I get the first 100 positions, but there are more pages, the problem is that the other pages are called with ajax and I cannot get them after the ajax call.
I came to conclusion that I could use Mutation Observers to detect changes in DOM, but I tried a lot of different codes and they all seem to not work.
My manifest.json file:
{
"manifest_version": 2,
"name": "Ogame Fleet Counter",
"short_name": "OFC",
"version": "1.0",
"icons": { "16": "16.png",
"48": "48.png",
"128": "128.png"
},
"browser_action": {
"default_icon": "48.png"
},
"background": {
"scripts": ["js/background.js"]
},
"content_scripts": [
{
"matches":[
"https://*.ogame.gameforge.com/game/index.php?page=shipyard*",
"https://*.ogame.gameforge.com/game/index.php?page=highscore"
],
"js": ["js/jquery.js", "js/content.js"]
}
]
}
My background.js file:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: "js/jquery.js" }, function() {
chrome.tabs.executeScript(null, { file: "js/content.js" });
});
});
var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++)
insertedNodes.push(mutation.addedNodes[i]);
})
});
observer.observe(document, { childList: true });
console.log(insertedNodes);
My extension consists in only background.js, the content.js (content script) and jquery.js.
I tried much more codes and tried changed my own, no luck. Could I use another method than Mutation Observers ? Adding onclick function in all buttons to trigger my content script maybe? Appreciate some help.
Edit: So I saw on the DOM that I need to catch: <span class=" activePager">1</span> changing, the number 1 there represents page one when I click on page two it changes to 2.
You need use your Mutation Observer on content script, because changes are happens there.
After this, you can send these changes to the Background page and process it from there.

Chrome Extension to trigger click event on icon press

I'm trying to make an extension for Chrome, so that when the icon is clicked, it triggers a click event on a div in the relevant webpages. I can't figure it out. Can anyone see or tell me what I'm doing wrong? Is this even possible?
Manifest.json
{
"name": "Name",
"version": "1.0",
"manifest_version": 2,
"icons": {
"128": "icon128.png",
"48": "icon.png"
},
"browser_action": {
"name": "Name"
},
"background":{
"scripts":["background.js"]
},
"permissions":["https://inbox.google.com/*"] //Put All your URL here
}
background
chrome.browserAction.onClicked.addListener(function (tab) {
if (tab.url.indexOf("https://inbox.google.com/*") != -1) {
chrome.tabs.executeScript(tab.id, {
"file": "clicky.js"
}, function () {
console.log("Script Executed .. ");
});
}
});
js
$('.b2')[0].click()
You're not including jquery in your manifest.json and you don't have access to the page's jQuery instance (read this), so you can't use jQuery on your content scripts.
Assuming there's an element with the 'b2' class present, change the code in clicky.js to this and it should work:
var btn = document.querySelector('.b2');
if(btn){
btn.click();
}
EDIT
Also, in your background.js, remove the wildcard when you call indexOf:
if (tab.url.indexOf("https://inbox.google.com/") != -1) {

Chrome extension: Execute only on current domain name once browser action is clicked

Here is my scenario: By clicking the browser icon, I create a sidebar (html and css) next to the whole page, thus creating two columns (one is my sidebar, the other one is the actual page).
What I to achieve is having the sidebar stay when I reload the page or navigate to another page WITHIN the same domain. What I have right now is just the creation of the sidebar, but I have to click the browser action every time I navigate or reload the web page.
Manifest:
{
"name": "apdrop",
"version": "0.1",
"manifest_version": 2,
"description": "first prototype for apdrop extension",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_icon": "icons/icon19.png",
"default_title": "apdrop"
},
"permissions": [
"background",
"tabs",
"http://*/*/",
"https://*/*/"
]
}
Background.js
function injectedScript(tab, method){
chrome.tabs.insertCSS(tab.id, {file:"style.css"});
//chrome.tabs.insertCSS(tab.id, {file:"bootstrap.css"});
chrome.tabs.executeScript(tab.id, { file: 'jquery-2.1.1.min.js'});
//chrome.tabs.executeScript(tab.id, { file: 'bootstrap.min.js'});
chrome.tabs.executeScript(tab.id, { file: 'inject.js'});
}
function click(tab){
console.log("browser action clicked");
injectedScript(tab, 'click');
//alert("action button was clicked");
}
chrome.browserAction.onClicked.addListener(click);
Inject.js
var ev = $("body > *");
if (!document.getElementById('contentxf343487d32'))
{
ev.wrapAll("<div id='insidecontent65675f526567'>");
$("#insidecontent65675f526567").wrapAll("<div id='contentxf343487d32'>");
$("<div id='sidebar343gf87897fh'><div id='insidesidebar87678bbbb'><p>this is my name</p></div></div>").insertBefore("#contentxf343487d32");
}
else
{
$("#sidebar343gf87897fh").remove();
$("#insidecontent65675f526567").unwrap();
$("#insidecontent65675f526567 > div").unwrap();
}
Hope this helps clarify a bit more.
The simplest strategy would be to save state in domain's sessionStorage and have a "detector" script that re-injects your UI.
Add setting the state in your content script:
// inject.js
if (!document.getElementById('contentxf343487d32'))
{
// ...
sessionStorage["contentxf343487d32"] = true;
}
else
{
// ...
sessionStorage["contentxf343487d32"] = false;
}
Add a "detector" script:
// detect.js
if(sessionStorage["contentxf343487d32"])
{
chrome.runtime.sendMessage({injectSidebar: true});
}
Always inject the script on page load, via the manifest (and change to a better permission):
"content_scripts" : [
{
"matches": ["<all_urls>"],
"js": ["detect.js"]
}
],
"permissions": [
"background",
"tabs",
"<all_urls>"
]
In the background, inject the script upon message:
// background.js
chrome.runtime.onMessage.addListener( function (message, sender, sendResponse){
if(message.injectSidebar)
{
click(sender.tab);
}
});
If you need more persistence than sessionStorage provides, use localStorage. If you need a different logic, you can still use this skeleton of a detector signalling the background.

Access DOM elements through chrome extension

I'm trying to access some DOM elements from a webpage:
<html>
<button id="mybutton">click me</button>
</html>
I want to access the innerHTML ("click me") through a chrome extension:
chrome.browserAction.onClicked.addListener(function(tab) {
var button = document.getElementById("mybutton");
if(button == null){
alert("null!");
}
else{
alert("found!");
}
});
When I click the extension, the popup says: "null".
My manifest.json:
{
"name": "HackExtension",
"description": "Hack all the things",
"version": "2.0",
"permissions": [
"tabs", "http://*/*"
],
"background": {
"scripts": ["contentscript.js"],
"persistent": false
},
"browser_action": {
"scripts": ["contentscript.js"],
"persistent": false
},
"manifest_version": 2
}
The solution:
You need a manifest file, a background script and a content script. This is not really clear in the documentation that you have to use it and also, how to use it. For alerting the full dom, see here. Because I have a hard time finding a complete solution that actually works and not just snippets that are useless for newbies, like me, I included a specific solution:
manifest.json
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["file:///*"],
"js": ["content.js"]
}],
"browser_action": {
"default_title": "Test Extension"
},
"permissions": ["activeTab"]
}
content.js
/* Listen for messages */
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
/* If the received message has the expected format... */
if (msg.text && (msg.text == "report_back")) {
/* Call the specified callback, passing
the web-pages DOM content as argument */
sendResponse(document.getElementById("mybutton").innerHTML);
}
});
background.js
/* Regex-pattern to check URLs against.
It matches URLs like: http[s]://[...]stackoverflow.com[...] */
var urlRegex = /^file:\/\/\/:?/;
/* A function creator for callbacks */
function doStuffWithDOM(element) {
alert("I received the following DOM content:\n" + element);
}
/* When the browser-action button is clicked... */
chrome.browserAction.onClicked.addListener(function(tab) {
/*...check the URL of the active tab against our pattern and... */
if (urlRegex.test(tab.url)) {
/* ...if it matches, send a message specifying a callback too */
chrome.tabs.sendMessage(tab.id, { text: "report_back" },
doStuffWithDOM);
}
});
index.html
<html>
<button id="mybutton">click me</button>
</html>
Just save the index.html somewhere and load in the folder as an extension, containing the three other files. Open the index.html and push the extension button. It should show "click me".
Starting with Manifest V3, your content scripts won't be able to access anything generated by other loaded scripts and using a trick like inlining a your code inside <script> tag won't work due to stricter CSP rules. This caused me a lot of head ache since I couldn't figure out how to access library-generated DOM properties similar to React or Redux DevTools.
Instead, you have to now inject your script inside the service_worker with eg:
chrome.scripting.registerContentScripts([
{
id: 'inject',
matches: ['<all_urls>'],
js: ['inject.js'],
runAt: 'document_end',
world: 'MAIN'
}
])
Notice the 'MAIN' property, not the default 'ISOLATED'. Then inside my inject.js I do whatever, eg:
window.addEventListener('load', () => {
findReact()
})
Also you have to add the script to the manifest.json:
"web_accessible_resources": [
{
"resources": ["inject.js"],
"matches": ["<all_urls>"],
"extension_ids": []
}
],
"externally_connectable": {
"ids": ["*"]
},
Not sure is "externally_connectable" needed. And you need to add at least "scripting" permissions. I used the React DevTools migration as my source https://github.com/facebook/react/pull/25145

How to get notified on window resize in chrome browser

I am writing an extension for the Chrome browser where I want to add an event listener for the window resize event. My method is being executed for the window load event, but not being executed for the resize event.
Below is the code for my manifest.json file
{
"name": "A browser action",
"version": "1.0",
"background": { "scripts": ["background.js"] },
"permissions": [
"tabs", "http://*/*"
],
"manifest_version": 2
}
Below is the code for my background.js file.
var myExtension =
{
init: function()
{
// The event can be DOMContentLoaded, pageshow, pagehide, load or unload.
alert("ASHSIH");
window.addEventListener("resize", this.onmyPageResize, false);
},
onmyPageResize: function(aEvent)
{
alert("RESIZED");
}
}
window.addEventListener("load", function load(event){
window.removeEventListener("load", load, false); //remove listener, no longer needed
myExtension.init();
},false);
Chrome-o-Tile is one example of an extension which listens resize in its content script.
In manifest.json:
"content_scripts": [
{
"js": ["contentscript.js"],
"run_at": "document_start",
"matches": [
"<all_urls>"
]
}
],
In contentscript.js:
'use strict';
var timeoutId = 0;
window.addEventListener('resize', function() {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(function() {
chrome.runtime.sendMessage({method: 'resize'});
timeoutId = 0;
}, 100);
}, false);
In background.js:
chrome.runtime.onMessage.addListener(function requested(request) {
if (request.method === 'resize') {
...
}
)};
There is also an open issue to implement chrome.windows.onResize event for Chrome extensions.
The background.js file cannot capture resize events in the browser. You would need to inject a content script for that.
For future readers of this question, the chrome.windows API provides an onBoundsChanged event:
onBoundsChanged (Since Chrome 86)
Fired when a window has been resized; this event is only dispatched when the new bounds are committed, and not for in-progress changes.
https://developer.chrome.com/extensions/windows#event-onBoundsChanged
This is how the event can be used: chrome.windows.onBoundsChanged.addListener( callback() )
(Make sure the manifest.json file declares the tabs permission)
{
"name": "My extension",
...
"permissions": ["tabs"],
...
}
You can use jQuery's bind() function.. http://api.jquery.com/bind/
$(window).bind('resize', function () {
//do something here
});

Categories