Getting all the hyperlinks title in a webpage using a chrome extension - javascript

I'm working on an application that needs to get all the URL title (one which we see when we hover the mouse on the hyperlink) present in the current tab. I am trying to make a chrome extension for the same. Find relevant files below:
manifest.json
{
"manifest_version": 2,
"name": "Sentiment Analyzer",
"description": "This extension analyzes sentiments of tweets, facebook and instagram posts",
"version": "1.0",
"icons": {
"128": "icon128.png",
"48": "icon48.png",
"16": "icon16.png"
},
"browser_action": {
"default_icon": "icon16.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Sentiment Analyzer</title>
</head>
<body>
<script type="text/javascript" src="popup.js"></script>
<button id="idanalyze"> Analyze </button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('idanalyze').addEventListener('click', function(){
temp = "";
for(i = 0; i < document.links.length; i++)
{
temp += " "+document.links[i].title;
}
alert(temp);
}, false);
}, false);
When I tried the below code in console then it produced expected result i.e. gave title for each hyperlink but when I tried to get the same result using chrome extension it did not work. Any kind of help/suggestion will be appreciated.
temp = "";
for(i = 0; i < document.links.length; i++)
{
temp += " "+document.links[i].title;
}
console.log(temp)

Only content script files are able to manipulate the page DOM, you are trying to access the site DOM from you popup page, so it won't work.
To solve it:
1. create a file and add it to your manifest.
"content_scripts": [
{
"matches": [THE_URLS_YOU_WANT_TO_INJECT_FILE], //can be regex for any url
"js": [YOUR_FILE]
}
]
send message using from you popup file to the content script file using chrome.tab.sendMessage. the message will initialize the function that check the DOM.
listen to message using addEventListener. and run your function the manipulate the DOM.
this is a high level explenation, every thing written in the documnation.
Content script - https://developer.chrome.com/extensions/content_scripts
chrome tabs message - https://developer.chrome.com/extensions/tabs

Related

Chrome extention - How to save changes that were made into storage? [duplicate]

This question already has answers here:
How to store objects in HTML5 localStorage/sessionStorage
(24 answers)
saving and retrieving from chrome.storage.sync
(6 answers)
Closed 1 year ago.
I am new to coding and currently I am trying to build an chrome extension that acts as a little notebook and can store things inside. I have already finished a very raw example but it works totally fine. Right now the biggest obstacle is how to save the changes after closing the popup and the browser. I did some research and found that I can use localStorage to store the data. Yet I am kinda lost and not sure where to start and how to use it.
Here is pretty much everything I have
manifest.json
{
"name": "1st extension",
"description": "Try to build an extention",
"version": "0.1",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_title": "This is my first chrome extention",
},
"permissions": ["storage"],
"options_page": "options.html"
}
popup.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="button.css">
</head>
<body>
<p>Type in something and save it below!</p>
<textarea id="mytext" style="width: 300px;"></textarea>
<button id="submit">Submit</button>
<button id="clear">Clear</button>
<ul id="items"></ul>
<script src="popup.js"></script>
</body>
</html>
popup.js
var myButton1 = document.getElementById("submit");
var myButton2 = document.getElementById("clear");
var itemList = document.getElementById('items');
itemList.addEventListener('click', removeItem);
//add new element into the list
function addItem(input) {
// new element
var li = document.createElement("li");
// new delete button
var deletebutton = document.createElement("button");
//add classes to btn
deletebutton.className = "delete";
// text in the delete buttion
deletebutton.appendChild(document.createTextNode('Delete'))
// text in the new element
li.appendChild(document.createTextNode(input));
// combine text and the delete button
li.appendChild(deletebutton);
// conbine the element to the list
itemList.appendChild(li);
}
//remove item from the list
function removeItem(element){
itemList.removeChild(element.target.parentElement);
}
//clear the textarea
function clear(){
document.getElementById('mytext').value = "";
};
myButton1.onclick = function() {
var myText = document.getElementById('mytext').value;
addItem(myText);
clear();
}
myButton2.onclick = function() {
clear();
}
Using storage is easy...
localStorage.setItem('Phone','1234-5678');
And reading it back...
var Phone=localStorage.getItem('Phone');
But I hope you're aware that the data won't be there in incognito windows and also... some browsers (at least mine) blow all storages away regardless, once you exit the browser.
So it's a very volatile solution and not suitable if you were looking for permanent save to the hard disk.
Let me check the Google APIs to see what else they've got for saving to the HD.
Here's one method, but dealing with blobs is not for novices...
https://developers.google.com/web/updates/2011/08/Saving-generated-files-on-the-client-side

How to build a google chrome extension that checks meta or title tag?

How to build a chrome extension that automatically opens google.com as it sees the title tag or the meta tag contains the word videos?
I am new to building chrome extensions I tried it this way.
background.js
var title = document.title;
var metatags = document.getElementByTagName("META");
if(title.search('videos') > 0){
window.open('https://www.google.com');
}
else{
for(i = 0;i<metatags.length;i++){
var meta_content = metatags[i].content;
if(meta_content.search('videos')>0){
window.open('https://www.google.com');
break;
}
}
}
manifest.json
`
{
"manifest_version": 2,
"name": "videos",
"version":"1.0",
"description":"An extension that goes to google chrome if it comes across the word videos in head or meta tag",
"background": {
"scripts": ["background.js"],
"persistent": false
}
}

Chrome Extension Content Script - Inject Javascript before page code

I am trying to make a Chrome extension with a content script to inject a script into a webpage before all other scripts in the page. (I am using the xhook library to intercept XHR requests, which overwrites the XHR class. I need to do this because it is currently impossible to modify responses using Chrome extension APIs.) The "document_start" event is executed before any of the DOM is written, so I manually create the body element with the content script. However, this creates 2 body tags in the HTML, which appears to make variables defined within the injected script tag inaccessible to the code in the main page.
How should I do this?
I have simplified version of my code below:
manifest.json
{
// Required
"manifest_version": 2,
"name": "My Extension",
"version": "0.1",
"description": "My Description",
"author": "Me",
"permissions": ["https://example.com/*"],
"content_scripts": [{
"matches": ["https://example.com/*"],
"js": ["xhook.js"],
"run_at": "document_start",
"all_frames": true
}
]
}
xhook.js
var script_tag = document.createElement('script');
script_tag.type = 'text/javascript';
holder = document.createTextNode(`
//Xhook library code
// XHook - v1.4.9 - https://github.com/jpillora/xhook
//...
//Now to use the library
console.log('loading extension');
xhook.after(function (request, response) {
//console.log(request.url);
if (request.url.startsWith("https://example.com/")) {
var urlParams = new URLSearchParams(window.location.search);
fetch('https://example.com/robots.txt')
.then(
function (apiresponse) {
if (apiresponse.status == 200) {
response.text = apiresponse.text();
return;
};
if (apiresponse.status !== 200) {
console.log('File not found. Status Code: ' +
apiresponse.status);
return;
};
});
};
});
xhook.enable();`);
script_tag.appendChild(holder);
document.body = document.createElement("body");
document.head.appendChild(script_tag);
Thanks!
If the extension is loaded at document_start, document.head = null. Hence, to overcome this, do - document.lastChild.appendChild(script_tag);. This creates a script tag in your <html> hierarchy. Hope this helps.
Also, Could you please tell why are you doing the following statement
document.body = document.createElement("body"); I believe this is not required.

How can I change document elements by webExtension when user click on extension icon in toolbar?

I want to create a webExtension and I want to have icon in toolbar for this extension.
In my manifest.json file I put this code:
{
"manifest_version": 2,
"name": "test",
"version": "1.0",
"description": "test",
"icons": {
"48": "icons/icon48.png",
"96": "icons/icon96.png"
},
"background": {
"scripts": ["background.js"]
},
"permissions": [
"activeTab",
"contextMenus"
],
"browser_action": {
"default_icon": {
"19": "button/btn19.png",
"38": "button/btn38.png"
},
"default_title": "test"
}
}
When user click on this extension icon in toolbar, I want to get elements of current page and add < a > tag in document where I want. I put this java script code in background.js file. But these code doesn't execute.
How can I fix this?
background.js :
function change() {
var elems = document.body.getElementsByTagName("*");
var re = new RegExp(/abba\b/g);
for (var i = 0; i < elems.length; i++) {
var str = elems[i].innerHTML;
if (!str.match(/<[a-zA-Z0-9\s:./\"\'=\\;()-_]*>/) && re.test(str)) {
var aTag = document.createElement("a");
aTag.setAttribute('href', "test.php?t=" + str.match(/abba\b/)[0]);
aTag.setAttribute('target', "_blank");
aTag.innerHTML = " --**CHANGES**-- ";
elems[i].appendChild(aTag);
}
}
}
browser.browserAction.onClicked.addListener(change);
Background pages do not have access to the contents of the web page.
You need to use content scripts. Content scripts are injected into the page after page load on idle
Get more information from the documentation
to add a content script to your extension you can add this to manifest.json
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["contentscript.js"]
}]
and then rename background.js to contentscript.js. This way the code is always executed on each page.
Or alternatively just create contentscript.js and move the contents change() function into it
contentscript.js:
var elems = document.body.getElementsByTagName("*");
var re = new RegExp(/abba\b/g);
for (var i = 0; i < elems.length; i++) {
var str = elems[i].innerHTML;
if (!str.match(/<[a-zA-Z0-9\s:./\"\'=\\;()-_]*>/) && re.test(str)) {
var aTag = document.createElement("a");
aTag.setAttribute('href', "test.php?t=" + str.match(/abba\b/)[0]);
aTag.setAttribute('target', "_blank");
aTag.innerHTML = " --**CHANGES**-- ";
elems[i].appendChild(aTag);
}
}
then background.js will call tabs.executeScript() when browser action clicked. This way it is only called when necessary
background.js:
browser.browserAction.onClicked.addListener(function(){
browser.tabs.executeScript({file: "/contentscript.js"})
});

Chrome Extension Oddity with Tab API

I'm writing a Chrome Extension and am having some difficulty getting more than 5 tabs open. here is the source code.
manifset.json
{
"manifest_version": 2,
"name": "Test",
"description": "testing this",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"bookmarks"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>Testing</title>
<style>
body {
min-width: 357px;
overflow-x: hidden;
}
</style>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function () {
chrome.bookmarks.getTree(function (stuff){
traverseBookmarks(stuff[0].children[0].children);
});
});
function traverseBookmarks(bookmarkTreeNodes) {
for(var i=0;i<bookmarkTreeNodes.length;i++) {
var bookmark = document.createElement('a');
if(bookmarkTreeNodes[i].url){
bookmark.href = bookmarkTreeNodes[i].url;
bookmark.target = "_blank";
}
else{
(function(num) {
bookmark.addEventListener("click", function() {
addChildren(bookmarkTreeNodes[num].children, false );
})})(i);
document.body.appendChild(document.createElement("br"));
}
bookmark.innerHTML = bookmarkTreeNodes[i].title;
document.body.appendChild(bookmark);
document.body.appendChild(document.createElement("br"));
if(bookmarkTreeNodes[i].children) {
traverseBookmarks(bookmarkTreeNodes[i].children);
}
}
}
function addChildren(children) {
for(var i = 0; i < children.length; i++){
// will open each link in the current window
chrome.tabs.create({
url: children[i].url
});
}
}
The goal is to be able to click the folder(now just a link symbolizing the folder) and open all links inside that folder. Currently what happens in I click on the link to the folder and it opens the first 5. For the sake of getting some form of logging I added:
var bookmark = document.createElement('a');
bookmark.innerHTML = children[i].title;
document.body.appendChild(bookmark);
document.body.appendChild(document.createElement("br"));
to the addChildren() function. It prints out every child. The issue I'm running into is that when I click on the folder it only opens up the first 5 tabs then I'm guessing the focus leaves the popup so it doesn't finish. I can't really find anything else online to help
Any help is appreciated. Let me know if I need to clarify anything.
I suspect the problem is just as you said, when you create a new tab it is active by default so the popup loses focus and unloads. You could fix this in one of two ways. You can send the list of url's to a background page and have that open them all. This will work because the background page stays loaded when opening tabs.
Another, probably better, way to fix it would be to create the tabs with the active property set to false and then maybe switch to the first tab in the group after they are all open. Code:
function addChildren(children) {
for(var i = 0; i < children.length; i++){
chrome.tabs.create({
url: children[i].url,
active: false
});
}
// switch focus to first opened tab
chrome.tabs.query({url:children[0].url},function(tabs){
chrome.tabs.update(tabs[tabs.length-1].id,{active:true});
});
}

Categories