Struggling with local storage for a Chrome Extension - javascript

I'm struggling with trying to develop a simple Chrome Extension for my "portfolio".
What I want to do is really simple. I think I can do it in two different ways!
First way:
I have an input field into my popup.html. What I want to do is get the text prompted into this input field and save it into the storage. After that, into my contentScript, I want to read the text/field saved into the storage and use it for some JS logic.
So, basically this is the input from popup.html:
<input class="custom-input-script-length" type="text" name="custom" id="values-input"/>
This is a function that get as parameter the value from the input. It's declared/called inside my popup.js:
function saveValue(value) {
if(value !== '') {
chrome.storage.local.set({'valuesInput': value}, function() {
console.log("Values saved!");
})
}
}
Now, I've tried many ways to read the value directly from the chrome tab (not from the extension, I've tried into the contentScript) but it never works, it will always return an "undefined".
How should I read that value?
What my extension must do it's just grab the entire responseHeader and search for a specific value from the toString (for example: cache-control). If it will find it it will just show the value into a new div added into the DOM, that's all.
Another solution could be send/read the entire responseHeader from the chrome tab from inside the popup but even in this way it never works. All I get is "undefined" or the responseHeader of the extension context...
Do you have any advice?
I'm usind the Manifest V3 and I already have the storage permissions added into it.
Thanks for everyone who will answer!

This is a response to OP's question which is too long for a comment.
The only way I could reproduce the problem was by trying to set the popup input value before the page had completed loading. The Chrome storage method calls worked as expected. To avoid problems, initialization code should be loaded at the end of the page or else wrapped in a DOMContentLoaded event.
OP also asks how to pass the stored value between popup and content pages. And in this case the content page can read the value directly from storage, which is shared between the pages. The content page may also receive notifications when the value changes by using the chrome.storage.onChanged event.
The relevant parts of the Chrome extension are shown below:
popup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Popup</title>
</head>
<body>
<input class="custom-input-script-length" type="text" name="custom" id="values-input"/>
<!-- script must load last -->
<script src="scripts/popup.js"></script>
</body>
</html>
popup.js
let valuesInput = document.getElementById("values-input");
valuesInput.addEventListener("change", (event) => {
chrome.storage.local.set({valuesInput: valuesInput.value});
})
chrome.storage.local.get('valuesInput', function(obj) {
if(obj.valuesInput !== undefined && obj.valuesInput !== '') {
valuesInput.value = obj.valuesInput;
}else {
console.log("input field can't be empty.");
}
});
content.js
let valuesInput = null;
chrome.storage.local.get('valuesInput', (result) => {
console.log('storage.get', result);
valuesInput = result.valuesInput;
})

Related

How do I allow my window to open and there be the text the user inputs?

I want the user to be able to open the website and there will be a prompt that will ask the user to tell them about themselves and the text they input display in a new window?
<html>
<head>
<script>
var text = prompt("Tell us something about yourself ");
function newWindow() {
var OpenWindow = window.open("", "slayyyter", "height=300 , width=300");
}
function showText() {
OpenWindow.document.write(text);
}
</script>
</head>
<body>
<button onclick="showText()">A</button>
</body>
</html>
The code has three errors in it. Open the web console (typically by pressing F12) to see messages for some of them.
The prompt string
"Tell us something about
yourself"
has a line feed in it that needs to be removed,
The variable OpenWindow declared in newWindow is not in scope of the code inside showText. If declaring OpenWindow globally, remove var before the variable name inside newWindow to prevent the global variable being shadowed by a local declaration.
newWindow needs to be called
Here's an example that returns the window object instead of saving it in a global variable:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>Test</title>
<head>
<script>
"use strict";
var text = prompt("Tell us something about yourself");
function newWindow() {
return window.open("", "slayyyter",
"height=300 , width=300");
}
function showText() {
var openWindow = newWindow();
newWindow().document.write(text);
newWindow.close();
}
</script>
</head>
<body>
<button onclick="showText()"> A </button>
</body>
</html>
Note
document.write is useful for learning exercises in JavaScript, but call document.close to finalize a document after writing to it - it stops the window loading indicator in opened windows.
Seach on "HTML5 document type declaration", "Declaring the character set in HTML" and "when to use strict mode in JavaScript" for more information.
You'll want to use your browser's tools and JavaScript console, which on button click says that OpenWindow is not defined. This is because of scope. OpenWindow only exists where you define it - inside function newWindow. To access it in other functions declare it outside (right under var text will do). You can leave it defined but blank, then assign it later. So under the declaration of "text" just put var OpenWindow;. Then inside newWindow delete "var" from in front of OpenWindow. You may have other issues as I have not tested the code, but that's the main one.
Hints:
read up on scope
read up on browser debug tools, especially JS console
do your tutorials in http://jsfiddle.net or something similar, and you can share examples here when you ask for help.
I'm afraid what you want to achieve isn't doable that easily because there is no direct way to tell the new browser window what you have written in the first window.
You can do it like this however.
Prompt to enter some text
Save the entered text into the browser's localstorage.
Open the same html page using window.open() but append a query string to the url e.g. ?id=new
Make a distinction via code if the site was called with or without a query string. If there's no query string show the prompt dialog, if there is a query string get the text from the localStorage and write it to the browser window.
Use this snippet and save it as test.html
<html>
<head>
<script type="text/javascript">
var urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('id') == null) {
var text = prompt("Tell us something about yourself");
localStorage.setItem('myText', text);
window.open("test.html?id=new", "slayyyter");
} else {
document.write("You have written: " + localStorage.getItem('myText'));
}
</script>
</head>
</html>
As a side note - window.open() accepts an url as the first parameter. You can't simply enter some text or pass a string containing text - it must be a valid resource e.h. an image, a html file, php,...

JavaScript - How to know if web-page load for the first time, or after a refresh?

I would like to execute a JavaScript function after a web-page was refreshed (any way: F5 key, browser's refresh key, user re-enter same URL or any other method).
This method should be execute only after refresh, not after 1st page-load.
Something like:
window.onrefresh = function() { ... }; // of curse, onrefresh isn't real event
I find some solutions in the web, but none meat my needs:
Dirty Flag
This method is simple, on load check flag - if flag not exist this is first load, else set the flag:
Save flag in local-storage/cookie. The flag can be current Date/Time.
If on-load flag not exist create it - this is first load. Else if flag exist compare it to current Date/Time - after refresh.
Save the flag in the site URL. The flag will be '#' sign ('#' - will not change the site Navigation). Same as before on-load test if '#' exist at the end of the URL this is "refresh" load, else this is a first load - we need to add a '#' at the end of the URL.
performance.navigation
The window object has this property: window.performance.navigation.type which can have 3 values:
0 - Page loaded due to link
1 - Page Reloaded
2 - Page loaded due to Back button
However this not working as expected. This value is always "1", on both first load and after refresh.
You can use the Navigation Timing API to gather performance data on the client side which you can then transmit to a server using XMLHttpRequest or other techniques. A Performance object offers access to the performance and timing-related information from the browser.
We can do so by using Navigation Timing API. The main interface of Navigation Timing API for your requirement is performance.navigation.type which checks the URL loaded in browser for the first time or it is loaded. Here is the sample.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script>
if (window.performance) {
alert("Browser Supports");
}
if (performance.navigation.type == 1) {
alert("Reloaded");
} else {
alert("Not Reloaded");
}
</script>
</head>
<body>
<h2>testing</h2>
</body>
</html>
Hope it helps you

Is there any way to count number of tabs are opened in chrome?

I am trying to find a way to count a number of tabs that are currently open in Chrome by javascript.
I have searched and found chrome.tabs.query(). But when I opened my console and tried it I got an undefined message.
Is it not supported anymore by Chrome, or can it only be used in extension development?
As wscourge has implied, chrome.tabs.query() is a Chrome extension API, which is only available to extensions, not web page JavaScript. In fact, it is only available in the background context of an extension (i.e. not content scripts).
To find the number of tabs that are open, you could do something like:
chrome.tabs.query({windowType:'normal'}, function(tabs) {
console.log('Number of open tabs in all normal browser windows:',tabs.length);
});
If you want to run this from a console, you will need to have an extension loaded that has a background page. You will then need to open the console for the background page. From that console, you can execute the above code.
I found the answer to this question here: https://superuser.com/questions/967064/how-to-get-tab-count-in-chrome-desktop-without-app-extension
Go to chrome://inspect/#pages
Run the following line of code in the javascript console:
document.getElementById("pages-list").childElementCount
The tabs count will be printed to the console.
Local and Session storage
In case when we want count only tabs witch our website - first on page load (open tab) event we generate tab hash and we save it in sessionStorage (not shared between tabs) and as key in TabsOpen object in localStorage (which is shared between tabs). Then in event page unload (close tab) we remove current tab hash (saved in sesionStorage) from TabsOpen in localStorage.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My project</title>
...
<script>
function tabLoadEventHandler() {
let hash = 'tab_' + +new Date();
sessionStorage.setItem('TabHash',hash);
let tabs = JSON.parse(localStorage.getItem('TabsOpen')||'{}');
tabs[hash]=true;
localStorage.setItem('TabsOpen',JSON.stringify(tabs));
}
function tabUnloadEventHandler() {
let hash= sessionStorage.getItem('TabHash');
let tabs = JSON.parse(localStorage.getItem('TabsOpen')||'{}');
delete tabs[hash];
localStorage.setItem('TabsOpen',JSON.stringify(tabs));
}
</script>
...
</head>
<body onunload="tabUnloadEventHandler()" onload="tabLoadEventHandler()">
...
</body>
</html>
Thanks to this in TabsOpen object in localStorage we have information about current open tabs which can be read by
let tabsCount = Object.keys( JSON.parse(localStorage.getItem('TabsOpen')||'{}') ).length
It can only be used in extension development.
You are not able to access that information from document level.
This is not a solution using javascript, but maybe it can help double-check the count against another solution. It is by far the easiest (one-click) solution that works for me:
If you have chrome sync enabled, simply navigate to chrome.google.com/sync
It should give you the count of open tabs, among other counts (e.g. bookmarks, extensions, etc)

Chrome extension to store the keys users press

I am building a chrome extension which will store all the keys pressed by the user and will store those keys into a text file inside the directory.
I want to keep track of user key pressed whatever he searches or types i want to store it into a text file ..
For now I've made it store the keywords in an array and alert it when needed. The array isn't getting alerted.
Here is my JavaScript file:
var your_array = [];
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
document.onkeydown = function(e) {
var keyPress;
if (typeof event !== 'undefined') {
keyPress = event.keyCode;
} else if (e) {
keyPress = e.which;
}
your_array.push(String.fromCharCode(keyPress));
return false; // Prevents the default action
};
checkPageButton.addEventListener('click', function() {
alert(your_array);
die;
}, false);
}, false);
...and this is what my HTML file looks like:
<!doctype html>
<html>
<head>
<title>Storing Keyword</title>
<link rel='stylesheet' href='popup.css' />
<script src="popup.js"></script>
</head>
<body>
<h3>I can store your keywords</h3>
<button id="checkPage">Really Show Me !</button>
</body>
</html>
This is my JSON manifest file:
{
"manifest_version": 2,
"name": "Keyword store",
"description": "This extension will analyze a page using GTmetrix",
"version": "1.0",
"browser_action": {
"default_icon": "avator/icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
The issue is that the alert appears but it gets closed automatically within few milliseconds.
If anyone has any idea how to store keys in a text file please let me know about that too...
Thank you.
The issue is that the alert appears but it gets closed automatically within few milliseconds.
Chrome popups do not survive focus loss.
Your alert() cause the dialog box to appear, which loses focus and the page closed/destroyed.
Use console.log and inspect the popup for debugging instead.
If anyone has any idea how to store keys in a text file please let me know about that too
There was a recent question where I answered rather extensively about options to do it. If you need persistent storage, use chrome.storage API. If you need to specifically output a file, you can't get R/W access from an extension, though you can offer a file for "download".
I want to keep track of user key pressed whatever he searches or types
That's not going to be possible; your extension as it is now will only get notified about keystrokes within your popup. There isn't an extension API to globally intercept keypresses. At most, you can inject similar scripts in all tabs, but again this will not get you stuff typed in the address/search bar.

Unable to access URL property of an <object> element (Javascript\jQuery)

I have a problem of being unable to access data contained in the object corresponding to an <object>-html element which is used to display another website. The use-case scenario is that I want to display external website within my page and I want to know on which links users click (within this integrated external website)
Specifically, I am interested in the URL or in the name of the document. When I try to get this data (which I can see when I browse through the object using firebug) I am unable to do it. Somehow access is restricted or I do something wrong.
Here is exactly what I am doing.
1) I define an object with a wikipedia article as a data source
<object id='wikiframe' data='http://en.wikipedia.org/wiki/thing' width='100%' height='700px'> Error: Embedded data could not be displayed. </object>
2) I define a click event for the document in order to know when user clicks
$(function() {
document.onclick = myClickHandler;
function myClickHandler() {
// Please help to assign a string with the wikipedia article name or with the string of url of the link which was clicked to the variable articleName;
var articleName;
var wikiObject = $("#wikiframe");
alert('The name of the currenttly opened wiki article is: ' + articleName);
}
});
Now here are the problems:
1) If I click within the article, click event does not fire.
2) I cannot access the data contained in the object corresponding to this element. But there is information I need in it as you see on the screenshot.
On the screenshot you see a wikipedia article which was opened by clicking on a link within the article which was first displayed. Firebug displays the information I need (in this case the URL to the article "Noumenon"
Link to image displaying the properties I want to access http://img856.imageshack.us/img856/3217/informationcontainedino.png
Can you please help by telling me what I need to add in order to assign articleName a string with the url of the clicked link.
The whole code is here:
<!doctype html>
<html lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
If you click anywhere except the object click event fires. If you click on object it does not. I want the click event firing on clicking within wiki article and showing either a) the name of currently opened article OR b) the url of the clicked link
<object id='wikiframe' data='http://en.wikipedia.org/wiki/thing' width='100%' height='700px'> Error: Embedded data could not be displayed. </object>
</body>
<script>
$(function() {
document.onclick = myClickHandler;
function myClickHandler() {
// Please help to assign a string with the wikipedia article name to the variable articleName;
var articleName;
var wikiObject = $("#wikiframe");
alert('The name of the currenttly opened wiki article is: ' + articleName);
}
});
</script>
</html>

Categories