Misunderstanding concept of localStorage - javascript

I'm using this code published by Sasi Varunan here
<script type="text/javascript">
// Broad cast that your're opening a page.
localStorage.openpages = Date.now();
var onLocalStorageEvent = function(e){
if(e.key == "openpages"){
// Listen if anybody else opening the same page!
localStorage.page_available = Date.now();
}
if(e.key == "page_available"){
alert("One more page already open");
}
};
window.addEventListener('storage', onLocalStorageEvent, false);
</script>
Code is working like charm - doing exactly what I want - detect if an application it's already open in another tab browser or even in another browser window.
From my understanding:
The very first time when the application is started the followings thinks happen:
App set openpages key with Date.now() value.
Because of 1. storage event listener start onLocalStorageEvent event.
Because the openpages key exists, is setting page_available key with Date.now ()
When the followings apps are started they find page_available key in storage (the second if) the alert is triggered and I can redirect them to an error page.
QUESTION:
If I close all the browser windows and restart the app in a new winwdow everything still works fine.
This is what I don't understand because the page_available key is persistent is still there in the storage (no one deleted) the app should go on the second if and that the alert ... but this is not happening.

The very first time when the application is started the followings thinks happen:
App set openpages key with Date.now() value.
Because of 1. storage event listener start onLocalStorageEvent event.
Because the openpages key exists, is setting page_available key with Date.now ()
When the followings apps are started they find page_available key in storage (the second if) the alert is triggered and I can redirect them to an error page.
The entire idea here is to communicate between the tabs using the storage event that is being triggered every time you access localStorage.
So when the page loads it first access the openpages key to trigger the storage event with e.key == "openpages".
Only after that it registers the event listener. So 2 only happens when you load the page on a second tab. On the second tab the event is triggered and the event listener is registered. Because the storage event is triggered for all the tabs, the event listener of the first tab (which is already registered) is being executed.
Tab 1 is triggered by the storage event with e.key == "openpages" and gets into the first if. There it triggers the storage event by accessing page_available key.
At this point tab 2 event listener reacts to the storage event but this time with e.key == "page_available" and gets into the second if where it shows the alert.
Note that if you don't close the tabs and open more tabs, tab 3 will trigger the storage event for all other tabs and you will have multiple tabs with alerts.
Just for reference:
If you want to trigger the alert on the first tab and not the second one you can achieve it with this code:
// Broadcast that you're opening the page.
localStorage.openpage = Date.now();
var onLocalStorageEvent = function(e) {
if (e.key == "openpage") {
alert("One more page already open");
}
};
window.addEventListener('storage', onLocalStorageEvent);
Read more about localStorage here.
Read more about addEventListener here.

After a restart of the browser window everything still works fine, and
I don't understand why because the page_available key is still there
in the storage
This is because localStorage has no expiration date which is opposite of sessionStorage. sessionStorage gets cleared once the browser is closed, but localStorage still remains.
You can still clear the localStorage by clearing the browser cache & cookies
Also this snippet localStorage.openpages = Date.now(); seems to be incorrect.
If you want to set a value in localStorage, do like this
localStorage.setItem('openpages',Date.now());

Related

How to determine whether the user closes browser tab or refreshes the page

I am building a two person game app using vue.js. The app uses vuex for state management and Firestore as the backend server.
If the user leaves the app by either closing the browser tab or navigating away, the games Firestore files need to be deleted. However, if the user refreshes the page, the Firestore files need to remain so that the reload process can repopulate the game.
So I need to determine if the user has refreshed the page as opposed to closing the browser or navigating away.
As shown below, in vue's created lifecycle I setup a "beforeunload" event Listener and also start my Firestore listeners
created() {
// This window event listener fires when the user
// navigates away from or closes the browser window
window.addEventListener("beforeunload", (event) => {
const isByRefresh = getUnloadInitiator();
if (!isByRefresh) {
this.stopFirestoreListeners("beforeunload");
}
// Cancel the event. This allows the user to cancel via popup. (for debug purposes)
event.preventDefault();
event.returnValue = "";
// the absence of a returnValue property on the event
// guarantees the browser unload happens
// delete event["returnValue"];
});
this.startFirestoreListeners("created");
},
The getUnloadInitiator function is shown below. This is where I need help. Right now all this function does is console.log various performance values.
function getUnloadInitiator() {
// check for feature support before continuing
if (performance.mark === undefined) {
console.log("performance.mark NOT supported");
return false;
}
console.log("===============================");
// Yes I know that performance.navigation is depreciated.
const nav = performance.navigation;
console.log("nav=", nav);
console.log("===============================");
// Use getEntriesByType() to just get the "navigation" events
var perfEntries = performance.getEntriesByType("navigation");
for (var i = 0; i < perfEntries.length; i++) {
var p = perfEntries[i];
console.log("= Navigation entry[" + i + "]=", p);
// other properties
console.log("type = " + p.type);
}
console.log("===============================");
performance.mark("beginLoop");
const entries = performance.getEntries({
name: "beginLoop",
entryType: "mark",
});
const firstEntry = entries[0];
console.log("firstEntry.type=", firstEntry.type);
console.log("===============================");
//TODO: Determine how unload was initiated
return true;
}
Below is the output from my console.logs. They are the same for refreshing the page, closing the browser tab, or navigating away. All show "reload" as the navigation type.
===============================
nav= PerformanceNavigation {type: 1, redirectCount: 0}
===============================
= Navigation entry[0]= PerformanceNavigationTiming {unloadEventStart: 25.399999976158142, unloadEventEnd: 25.69999998807907, domInteractive: 633, domContentLoadedEventStart: 633, domContentLoadedEventEnd: 633, …}
type = reload
===============================
firstEntry.type= reload
===============================
Any help on how to differentiate between refreshing the page, closing the browser tab, or navigating away would be appreciated. There must be away, because the native cancel browser popup I'm using for debug purposes differentiates between fresh and browser tab close.
Thanks
You can use a source of authority as persistence, be it firestore, local storage, or cookies. you are able to get the browser's tab ID with tab.id and compare it to an existing one should one exist.
browser.pageAction.show(tab.id);
Source: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Working_with_the_Tabs_API

Are there any window events triggered if user "pulls the plug" and shuts down their computer?

I have a website, and I only want the client to be able to have 1 WebSocket connection at a time (when they open another tab while there is already another connection display, I display an error to them).
I'm working on a client-side solution where I update a flag in local storage to true when the connection is requested (It won't request if the flag is already true) then I listen for the beforeunload event and set the local storage flag to false if that tab had an open connection.
This seems to be working great except for the edge case of when a user shuts down their computer abruptly and thus beforeunload never fires, so when they turn their computer back on the local storage flag is stuck at true and they are stuck not being able to connect in any tabs.
Is there an event that will be called before the shutdown where I can set my local storage flag to false?
If not is there another solution for the client to keep track that it has only 1 WebSocket connection across all tabs so it can block a connection if there is already one?
window.addEventListener('beforeunload', this.setFlagToFalse);
As correctly stated in Jaromanda's comment, a computer without power can not emit an Event to the browser (which doesn't even exist anymore...).
However, one solution to your root problem is to listen to the storage event.
This event will fire across all the Windows that do share the same Storage area, when an other Window will make any modification to this Storage.
So we can use it as a mean to communicate between Windows from the same domain, in almost real time. This means that you don't have to keep your flag up to date, you can now know directly if an other Window is already active.
Here is a basic implementation. I'll let you the joy of making it more suited to your needs.
let alone = true; // a flag to know if we are alone
onstorage = e => { // listen to the storage event
if(e.key === 'am_I_alone') {
if(e.newValue === 'just checking') { // someone else is asking for permission
localStorage.am_I_alone = 'false'; // refuse
}
else if(e.newValue === 'false') { // we've been refused access
alone = false;
}
}
};
localStorage.am_I_alone = 'just checking'; // trigger the event on the other Windows
setTimeout(()=>{ // let them a little time to answer
if(alone) { // no response, we're good to go
// so the next one can trigger the event
localStorage.am_I_alone = "true";
startWebSocket();
}
else { // we've been rejected...
error();
}
}, 500);
Live Plnkr

HTML5 history disabling forward button

I am writing a single page javascript application using the HTML5 History API. The application loads content via Ajax and internally maintains state information on the foreground screen using a screen stack.
I want to enable navigation with the back button, but I never want to the forward button to be enabled.
A couple quick bits of information:
The user should only ever be able to go back, never forward
Pressing browser back button closes the current page screen user is on and reloads the previous one
Project is targeted towards the latest version of Chrome only, so other browsers implementations are not important
I am using native JavaScript and jQuery only, I would like to do this without History.js
When I load a new screen I run the following line:
history.pushState(screenData, window.document.title, "#");
I bind to the popstate event via jQuery:
$(window).bind("popstate", function(event) {
if (event.originalEvent.state != null) {
// Logic that loads the previous screen using my screen stack
}
});
My application's history management is working, however when I go back the forward button is enabled. I need to figure out how to remove data from history on the popstate event.
Can I do this with replaceState? I'm not sure how to go about doing this...
The accepted answer solves the problem to disable the forward button, but creates a new annoying issue "the page navigated back to" is inserted in duplicate into the history (as indicated in the answers comments).
Here is how solve the question "diabled forward button" and to avoid the "duplicate" back-button-issue.
//setup the popstate EventListener that reacts to browser history events
window.addEventListener("popstate",function(event){
// In order to remove any "forward"-history (i.e. disable forward
// button), this popstate's event history state (having been navigated
// back to) must be insert _again_ as a new history state, thereby
// making it the new most forwad history state.
// This leaves the problem that to have this popstate event's history
// state to become the new top, it would now be multiple in the history
//
// Effectively history would be:
// * [states before..] ->
// * [popstate's event.state] ->
// * [*newly pushed _duplicate_ of popstate's event.state ]
//
// To remove the annoyance/confusion for the user to have duplicate
// history states, meaning it has to be clicked at least twice to go
// back, we pursue the strategy of marking the current history state
// as "obsolete", as it has been inserted _again_ as to be the most
// forward history entry.
//
// the popstate EventListener will hence have to distinguish 2 cases:
//
// case A) "popstate event is _not_ an obsolete duplicate"...
if( typeof event.state == "object"
&& event.state.obsolete !== true)
{
//...so we _firstly_ mark this state as to from now on "obsolete",
// which can be done using the history API's replaceState method
history.replaceState({"obsolete":true},"");
// and _secondly_ push this state _one_more_time_ to the history
// which will solve the OP's desired "disable forward button" issue
history.pushState(event.state,"");
}
// case B: there is the other case that the user clicked "back" and
// encounters one of the duplicate history event entries that are
// "obsolete" now.
if( typeof event.state == "object"
&& event.state.obsolete === true)
{
//...in which case we simply go "back" once more
history.back()
// by this resolving the issue/problem that the user would
// be counter-intuively needing to click back multiple times.
// > we skip over the obsolete duplicates, that have been the
// the result of necessarily pushing a history state to "disable
// forward navigation"
}
},false);
Bad Part
To really disable the forward button, you would have to be able to delete browser history, which is not allowed by all javascript implementations because it would allow sites to delete the entire history, which would never be in the interest of the user.
Good Part
This is a bit tricky, but I guess it could work if you want to do custom history. You could just use pushState in the popstate event to make your actual page the topmost history entry. I assume the way you handle your history, your window will never unload. This allows you to keep track of the user history yourself:
var customHistory = [];
Push every page you load with history.pushState(screenData, window.document.title, "#");, like you did before. Only you add the state to your custom history, too:
history.pushState(screenData, window.document.title, "#");
customHistory.push({data: screenData, title: window.document.title, location: '#'});
now if you have a popstate event, you just pop you custom history and push it to the topmost entry:
window.onpopstate = function(e) {
var lastEntry = customHistory.pop();
history.pushState(lastEntry.data, lastEntry.title, lastEntry.location);
// load the last entry
}
Or in jQuery
$(window).on('popstate', function(e) {
var lastEntry = customHistory.pop();
history.pushState(lastEntry.data, lastEntry.title, lastEntry.location);
// load the last entry
});
Just use following jquery to disable forward button:
$( document ).ready( function(){
history.pushState(null, document.title, location.href);
});
NOTE:
This code was tested and worked fine without showing any problems, however
I would incentivize developers to test it more before going to production with the code.
If HTML5 history.replaceState() is used anywhere in your application,
the code below might now work.
I created a custom function in order to disable the forward button.
Here is the code (it doesn't work with the hash routing strategy):
<script>
(function() {
// function called after the DOM has loaded
disableForwardButton();
})();
function disableForwardButton() {
var flag, loop = false;
window.addEventListener('popstate', function(event) {
if (flag) {
if (history.state && history.state.hasOwnProperty('page')) {
loop = true;
history.go(-1);
} else {
loop = false;
history.go(-1);
}
} else {
history.pushState({
page: true
},
null,
null
);
}
flag = loop ? true : !flag;
});
window.onclick = function(event) {
flag = false;
};
}
</script>
As Redrif pointed out in the comments of the accepted answer, the problem is that you have to double click the back button in order to navigate back to the page which is tedious and impractical.
Code explanation: each time you click the back button you need to create an additional history element so that the the current page which you are located on
points to the newly created history page. In that way there is no page to go forward to since the pushState is the last state (picture it as the last element in the array) therefore your forward button will always be disabled.
The reason why it was mandatory to introduce the loop variable is because you can have a scenario where you go back to a certain page and the pushState code occurs which creates the last history element and instead going back again you choose to click on some link again and again go back the previous page which now creates an additional history element. In other words, you have something like this:
[page1, page2, page2, page2]
now, once on page2 (index 3 element) and you click the back button again you will get to the page2 again index 1 element and you do not want that. Remember that you can have an array of x page2 elements hence the loop false variable was introduced to resolve that particular case, with it you jump all the way from page2 to page 1 no matter how many page2 elements are their in the array.

How to delete a localStorage item when the browser window/tab is closed?

My Case: localStorage with key + value that should be deleted when browser is closed and not single tab.
Please see my code if its proper and what can be improved:
//create localStorage key + value if not exist
if (localStorage) {
localStorage.myPageDataArr = {
"name" => "Dan",
"lastname" => "Bonny"
};
}
//when browser closed - psedocode
$(window).unload(function() {
localStorage.myPageDataArr = undefined;
});
should be done like that and not with delete operator:
localStorage.removeItem(key);
Use with window global keyword:-
window.localStorage.removeItem('keyName');
You should use the sessionStorage instead if you want the key to be deleted when the browser close.
You can make use of the beforeunload event in JavaScript.
Using vanilla JavaScript you could do something like:
window.onbeforeunload = function() {
localStorage.removeItem(key);
return '';
};
That will delete the key before the browser window/tab is closed and prompts you to confirm the close window/tab action. I hope that solves your problem.
NOTE: The onbeforeunload method should return a string.
localStorage.removeItem(key); //item
localStorage.clear(); //all items
There is a very specific use case in which any suggestion to use sessionStorage instead of localStorage does not really help.
The use-case would be something as simple as having something stored while you have at least one tab opened, but invalidate it if you close the last tab remaining.
If you need your values to be saved cross-tab and window, sessionStorage does not help you unless you complicate your life with listeners, like I have tried.
In the meantime localStorage would be perfect for this, but it does the job 'too well', since your data will be waiting there even after a restart of the browser.
I ended up using a custom code and logic that takes advantage of both.
I'd rather explain then give code. First store what you need to in localStorage, then also in localStorage create a counter that will contain the number of tabs that you have opened.
This will be increased every time the page loads and decreased every time the page unloads. You can have your pick here of the events to use, I'd suggest 'load' and 'unload'.
At the time you unload, you need to do the cleanup tasks that you'd like to when the counter reaches 0, meaning you're closing the last tab.
Here comes the tricky part: I haven't found a reliable and generic way to tell the difference between a page reload or navigation inside the page and the closing of the tab.
So If the data you store is not something that you can rebuild on load after checking that this is your first tab, then you cannot remove it at every refresh.
Instead you need to store a flag in sessionStorage at every load before increasing the tab counter.
Before storing this value, you can make a check to see if it already has a value and if it doesn't,
this means you're loading into this session for the first time, meaning that you can do the cleanup at load if this value is not set and the counter is 0.
use sessionStorage
The sessionStorage object is equal to the localStorage object, except that it stores the data for only one session. The data is deleted when the user closes the browser window.
The following example counts the number of times a user has clicked a button, in the current session:
Example
if (sessionStorage.clickcount) {
sessionStorage.clickcount = Number(sessionStorage.clickcount) + 1;
} else {
sessionStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "You have clicked the button " +
sessionStorage.clickcount + " time(s) in this session.";
Try using
$(window).unload(function(){
localStorage.clear();
});
Hope this works for you
There are five methods to choose from:
setItem(): Add key and value to localStorage
getItem(): Retrieve a value by the key from localStorage
removeItem(): Remove an item by key from localStorage
clear(): Clear all localStorage
key(): Passed a number to retrieve nth key of a localStorage
You can use clear(), this method when invoked clears the entire storage of all records for that domain. It does not receive any parameters.
window.localStorage.clear();
for (let i = 0; i < localStorage.length; i++) {
if (localStorage.key(i).indexOf('the-name-to-delete') > -1) {
arr.push(localStorage.key(i));
}
}
for (let i = 0; i < arr.length; i++) {
localStorage.removeItem(arr[i]);
}
8.5 years in and the original question was never actually answered.
when browser is closed and not single tab.
This basic code snippet will give you the best of both worlds. Storage that persists only as long as the browser session (like sessionStorage), but is also shareable between tabs (localStorage).
It does this purely through localStorage.
function cleanup(){
// place whatever cleanup logic you want here, for example:
// window.localStorage.removeItem('my-item')
}
function tabOpened(){
const tabs = JSON.parse(window.localStorage.getItem('tabs'))
if (tabs === null) {
window.localStorage.setItem('tabs', 1)
} else {
window.localStorage.setItem('tabs', ++tabs)
}
}
function tabClosed(){
const tabs = JSON.parse(window.localStorage.getItem('tabs'))
if (tabs === 1) {
// last tab closed, perform cleanup.
window.localStorage.removeItem('tabs')
cleanup()
} else {
window.localStorage.setItem('tabs', --tabs)
}
}
window.onload = function () {
tabOpened();
}
window.onbeforeunload = function () {
tabClosed();
}
why not used sessionStorage?
"The sessionStorage object is equal to the localStorage object, except that it stores the data for only one session. The data is deleted when the user closes the browser window."
http://www.w3schools.com/html/html5_webstorage.asp
Although, some users already answered this question already, I am giving an example of application settings to solve this problem.
I had the same issue. I am using https://github.com/grevory/angular-local-storage module in my angularjs application. If you configure your app as follows, it will save variable in session storage instead of local storage. Therefore, if you close the browser or close the tab, session storage will be removed automatically. You do not need to do anything.
app.config(function (localStorageServiceProvider) {
localStorageServiceProvider
.setPrefix('myApp')
.setStorageType('sessionStorage')
});
Hope it will help.
Here's a simple test to see if you have browser support when working with local storage:
if(typeof(Storage)!=="undefined") {
console.log("localStorage and sessionStorage support!");
console.log("About to save:");
console.log(localStorage);
localStorage["somekey"] = 'hello';
console.log("Key saved:");
console.log(localStorage);
localStorage.removeItem("somekey"); //<--- key deleted here
console.log("key deleted:");
console.log(localStorage);
console.log("DONE ===");
} else {
console.log("Sorry! No web storage support..");
}
It worked for me as expected (I use Google Chrome).
Adapted from: http://www.w3schools.com/html/html5_webstorage.asp.
I don't think the solution presented here is 100% correct because window.onbeforeunload event is called not only when browser/Tab is closed(WHICH IS REQUIRED), but also on all other several events. (WHICH MIGHT NOT BE REQUIRED)
See this link for more information on list of events that can fire window.onbeforeunload:-
http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
After looking at this question 6 years after it was asked, I found that there still is no sufficient answer to this question; which should achieve all of the following:
Clear Local Storage after closing the browser (or all tabs of the domain)
Preserve Local Storage across tabs, if at least one tab remains active
Preserve Local Storage when reloading a single tab
Execute this piece of javascript at the start of each page load in order to achieve the above:
((nm,tm) => {
const
l = localStorage,
s = sessionStorage,
tabid = s.getItem(tm) || (newid => s.setItem(tm, newid) || newid)((Math.random() * 1e8).toFixed()),
update = set => {
let cur = JSON.parse(l.getItem(nm) || '{}');
if (set && typeof cur[tabid] == 'undefined' && !Object.values(cur).reduce((a, b) => a + b, 0)) {
l.clear();
cur = {};
}
cur[tabid] = set;
l.setItem(nm, JSON.stringify(cur));
};
update(1);
window.onbeforeunload = () => update(0);
})('tabs','tabid');
Edit: The basic idea here is the following:
When starting from scratch, the session storage is assigned a random id in a key called tabid
The local storage is then set with a key called tabs containing a object those key tabid is set to 1.
When the tab is unloaded, the local storage's tabs is updated to an object containing tabid set to 0.
If the tab is reloaded, it's first unloaded, and resumed. Since the session storage's key tabid exists, and so does the local storage tabs key with a sub-key of tabid the local storage is not cleared.
When the browser is unloaded, all session storage will be cleared. When resuming the session storage tabid won't exists anymore and a new tabid will be generated. Since the local storage does not have a sub-key for this tabid, nor any other tabid (all session were closed), it's cleared.
Upon a new created tab, a new tabid is generated in session storage, but since at least one tabs[tabid] exists, the local storage is not cleared
This will do the trick for objects.
localStorage.removeItem('key');
Or
localStorage.setItem('key', 0 );
You can simply use sessionStorage. Because sessionStorage allow to clear all key value when browser window will be closed .
See there : SessionStorage- MDN
This is an old question, but it seems none of the answer above are perfect.
In the case you want to store authentication or any sensitive information that are destructed only when the browser is closed, you can rely on sessionStorage and localStorage for cross-tab message passing.
Basically, the idea is:
You bootstrap from no previous tab opened, thus both your localStorage and sessionStorage are empty (if not, you can clear the localStorage). You'll have to register a message event listener on the localStorage.
The user authenticate/create a sensitive info on this tab (or any other tab opened on your domain).
You update the sessionStorage to store the sensitive information, and use the localStorage to store this information, then delete it (you don't care about timing here, since the event was queued when the data changed). Any other tab opened at that time will be called back on the message event, and will update their sessionStorage with the sensitive information.
If the user open a new tab on your domain, its sessionStorage will be empty. The code will have to set a key in the localStorage (for exemple: req). Any(all) other tab will be called back in the message event, see that key, and can answer with the sensitive information from their sessionStorage (like in 3), if they have such.
Please notice that this scheme does not depend on window.onbeforeunload event which is fragile (since the browser can be closed/crashed without these events being fired). Also, the time the sensitive information is stored on the localStorage is very small (since you rely on transcients change detection for cross tab message event) so it's unlikely that such sensitive information leaks on the user's hard drive.
Here's a demo of this concept: http://jsfiddle.net/oypdwxz7/2/
There are no such the way to detect browser close so probably you can't delete localStorage on browser close but there are another way to handle the things you can uses sessionCookies as it will destroy after browser close.This is I implemented in my project.
if(localStorage.getItem("visit") === null) {
localStorage.setItem('visit', window.location.hostname);
console.log(localStorage.getItem('visit'));
}
else if(localStorage.getItem('visit') == 'localhost'){
console.log(localStorage.getItem('visit'));
}
else {
console.log(localStorage.getItem('visit'));
}
$(document).ready(function(){
$("#clickme").click(function(){
localStorage.setItem('visit', '0');
});
});
window.localStorage.removeItem('visit');
window.addEventListener('beforeunload', (event) => {
localStorage.setItem("new_qus_id", $('.responseId').attr('id'));
var new_qus_no = localStorage.getItem('new_qus_id');
console.log(new_qus_no);
});
if (localStorage.getItem('new_qus_id') != '') {
var question_id = localStorage.getItem('new_qus_id');
} else {
var question_id = "<?php echo $question_id ; ?>";
}
you can try following code to delete local storage:
delete localStorage.myPageDataArr;

Accessing every document that a user currently views from an extension

I'm writing an extension that checks every document a user views on certain data structures, does some back-end server calls and displays the results as a dialog.The problem is starting and continuing the sequence properly with event listeners. My actual idea is:
Load: function()
{
var Listener = function(){ Fabogore.Start();};
var ListenerTab = window.gBrowser.selectedTab;
ListenerTab.addEventListener("load",Listener,true);
}
(...)
ListenerTab.removeEventListener("load", Listener, true);
Fabogore.Load();
The Fabogore.Load function is first initialized when the browser gets opened. It works only once I get these data structures, but not afterwards. But theoretically the script should initialize a new listener, so maybe it's the selectedTab. I also tried listening to focus events.
If someone has got an alternative solution how to access a page a user is currently viewing I would feel comfortable as well.
The common approach is using a progress listener. If I understand correctly, you want to get a notification whenever a browser tab finished loading. So the important method in your progress listener would be onStateChange (it needs to have all the other methods as well however):
onStateChange: function(aWebProgress, aRequest, aFlag, aStatus)
{
if ((aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP) &&
(aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW) &&
aWebProgress.DOMWindow == aWebProgress.DOMWindow.top)
{
// A window finished loading and it is the top-level frame in its tab
Fabogore.Start(aWebProgress.DOMWindow);
}
},
Ok, I found a way which works from the MDN documentation, and achieves that every document a user opens can be accessed by your extension. Accessing every document a user focuses is too much, I want the code to be executed only once. So I start with initializing the Exentsion, and Listen to DOMcontentloaded Event
window.addEventListener("load", function() { Fabogore.init(); }, false);
var Fabogore = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", Fabogore.onPageLoad, true);
},
This executes the code every Time a page is loaded. Now what's important is, that you execute your code with the new loaded page, and not with the old one. You can acces this one with the variable aEvent:
onPageLoad: function(aEvent)
{
var doc = aEvent.originalTarget;//Document which initiated the event
With the variable "doc" you can check data structures using XPCNativeWrapper etc. Thanks Wladimir for bringing me in the right direction, I suppose if you need a more sophisticated event listening choose his way with the progress listeners.

Categories

Resources