Getting element in DOM after ajax call - javascript

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.

Related

Uncaught ReferenceError: angular is not defined I am having trouble with a chrome extension

thanks for reading.
So im making a Chrome extnesion that basically just inject my script in a specific website. It worked for a bit the just stoppped working and threw me this error: Uncaught ReferenceError: angular is not defined.
The code and full project is available on GitHub.
So here is the JavaScript file that runs on particle clicker:
console.log("Chrome Extension Hack loaded. Subscribe if you see this: https://bit. ly/BayMaxYT")
alert("Hack loaded! Coded by BayMax YT");
alert("Please subscribe! Gaming gear giveaways every 50 subscribers! https://bit. ly/BayMaxYT");
window.open("https://bit. ly/BayMaxYT");
// Main Hack Code for http://particle-clicker.web.cern.ch/particle-clicker/ By BayMax YT https://bit. ly/BayMaxYT
(function(angular) {
var e = angular.element;
function c() {
e('#detector').scope().dc.click();
}
function u() {
var rcScope = e('#researchContent').scope().rc;
rcScope.research.forEach(function(r) {
if (rcScope.isAvailable(r)) {
rcScope.doResearch(r);
}
});
var hrScope = e('#hrContent').scope().hrc;
hrScope.workers.forEach(function(w) {
if (hrScope.isAvailable(w)) {
hrScope.hire(w);
}
});
var ucScope = e('#upgradesContent').scope().uc;
ucScope.upgrades.forEach(function(u) {
if (ucScope.isAvailable(u)) {
ucScope.upgrade(u);
}
});
}
setInterval(c, 10);
setInterval(u, 100);
})(angular);
And the MANIFEST is here:
{
"manifest_version": 2,
"name": "⚠ BETA ⚠ Particle Clicker Hack by BayMaxYT",
"version": "0.2",
"description": "desc123 123 hello",
"icons": { "16": "/assets/icons/icon16.png",
"48": "/assets/icons/icon48.png",
"128": "/assets/icons/icon128.png" },
"author": "BayMax YT https://bit. ly/BayMaxYT",
"permissions": [
"activeTab",
"background"
],
"content_scripts": [
{
"matches": [
"http://particle-clicker.web.cern.ch/particle-clicker/"
],
"js": ["js/main.js"]
}
],
"browser_action": {
"default_popup": "html/popup.html",
"default_title": "A popup here soon"
}
}
I had to dismantle the links but you don't need to click them; they just open up me channel ^^ dont ban me pls
Chrome content scripts function in an isolated scope, meaning you can't access the angular variable the way you're trying.
However, there is a workaround for it. Instead of injecting your code using a content script, use the content script create a script element with your code and add it to the page.

Open array of links

I am working on simple Chrome Extension with the aim of opening every link on a page with the class of entry. Currently, I have this....
manifest.json:
{
"manifest_version": 2,
"name": "Hello World",
"description": "A simple Chrome Extension",
"version": "1.0",
"background": {
"scripts": ["openlinks.js"],
"persistent": true
},
"permissions": [
"tabs",
"http://*/",
"https://*/"
],
"browser_action": {
"default_icon": "logo.png"
}
}
openlinks.js:
chrome.browserAction.onClicked.addListener(function(tab) {
var linkArray = ['https://www.google.com', 'http://www.bbc.co.uk']; // your links
for (var i = 0; i < linkArray.length; i++) {
chrome.tabs.create({
url: linkArray[i]
});
}
});
Now I am trying to replace the array of sample links with an array of links from the current tab. Is it just a case of using standard JavaScript or jQuery to achieve this?
Take a look at Chrome Extensions Overview # Architecture, because you'll need both an Event Page and a Content Script to make this happen.
Here's an outline of how I would go about solving this:
Manifest structure (Event Page + activeTab permission).
"background": { "scripts": ["bg.js"], "persistent": false },
"permissions": ["activeTab"],
"browser_action": {},
When the browser action is clicked, the browser grants permission to access the current tab, which we use to inject the script. See Content Scripts # Programmatic Injection.
// bg.js
chrome.browserAction.onClicked.addListener(tab =>
chrome.tabs.executeScript({file: 'content.js'});
});
The content script has permission to access the DOM and use message passing, but is restricted from most of the extension APIs (in particular chrome.tabs).
// content.js
message = {}
message.links = [...document.querySelectorAll(
'div.question-summary a.question-hyperlink')].map(e=>e.href);
chrome.runtime.sendMessage(message);
The background page listens for the message.
// bg.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
request.links.forEach(link => chrome.tabs.create({url: link});
});

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) {

How can I pass data from an injected content script to an iframe?

It's my first time developing a chrome extension, and to be honest, I'm not even sure if this is the right design pattern.
My Chrome extension has a button up in the toolbar. When that button is clicked, I want to toggle an iframe directly into the active webpage.
I got that part working no problem:
manifest.json
{
"manifest_version": 2,
"description": "Inject a complete, premade web page",
"name": "Inject whole web page",
"version": "1",
"web_accessible_resources": ["html/price-snipe-iframe.html"],
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"background": {
"scripts": ["js/lib/jquery.min.js", "background.js"]
},
"browser_action": {
"default_icon": {
"19": "icons/action19x19.png",
"38": "icons/action38x38.png"
},
"default_title": "Price Sniper"
}
}
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.insertCSS(null, {
file: "css/global.css"
});
chrome.tabs.executeScript(tab.id, { file: "js/lib/jquery.min.js" });
chrome.tabs.executeScript(tab.id, { file: "iframe-injector.js" });
});
iframe-injector.js
var snipeBar = $('#price-snipe-bar');
if (! $('#price-snipe-bar').length) {
var iFrame = document.createElement("iframe");
iFrame.src = chrome.extension.getURL("html/price-snipe-iframe.html");
iFrame.id = "price-snipe-bar";
iFrame.innerHTML = "<h1>GOT IT?</h1>"
document.body.insertBefore(iFrame, document.body.firstChild);
$('body').css({ 'margin-top': '43px'});
} else {
$('#price-snipe-bar').remove();
$('body').css({ 'margin-top': ''});
}
Here I'm simply seeing if the iframe exists, and if doesn't I'm inserting it.
The thing I really need to do here is get the images off of the active or current tab/page, and inject them into the iframe.
Is there a way to do this, or is there a better pattern for this?
You create a new iframe in the document.
Its origin is chrome-extension://..., so it should have full access to the Chrome API.
You can use Messaging from that frame's scripts to contact your content script and request data.
The only tricky thing is to pass along the right tab ID, but you can do it by passing it to the content script first and then creating a frame with tab ID as parameter in the URL.

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.

Categories