Options for a chrome extension: tab notifier 1.1

The version 1.1.0 of tab notifier for chrome has been released. It now stores persistently the list of ignored sites and allows to manage it by means of a option page. Let’s see how it’s done.
To store the options now the extension uses the localStorage attribute of the window object.
This is the simplest part. As we saw in the previous post everytime there is a click on the menu item “Ignore this site” we change the object mutedDomains. Now we also stringify it to store it in localStorage:

var menuItemId=chrome.contextMenus.create({type:"checkbox",
	title:"Ignore this site",
	checked:true,
	contexts:["all"],
	documentUrlPatterns:["http://*/*", "https://*/*"],
	onclick:function(info,tab){
		var hostname = getHostname(tab.url);
		if (hostname) {
			if(info.checked) {
				mutedDomains[hostname]=true;
			} else {
				delete mutedDomains[hostname];
			}
			window.localStorage.ignoredSites = JSON.stringify(mutedDomains);
		}
	}
});

Please note that we don’t need to put the attributes of localStorage inside a namespace (hence ignoredSites is totally arbitrary) because they will be unique for every extension in the way they are unique for each subdomain when they are used in the scope of a web page.

To restore the object we use the following code:

var updateOptions=function() {
	var s=window.localStorage.ignoredSites;
	if (s) try {
		mutedDomains=JSON.parse(s);
	} catch(e){console.log(e);};
};
updateOptions();
window["updateOptions"]=updateOptions;

The function “updateOptions” is attached to the window object to be accessible to the option page as we’ll see pretty soon.
Since now the list of ignored sites won’t be reset at the beginning of every session, it becomes more important to allow the users to manage that list. We can achieve that with an option page. Let’s add a row to the manifest.json file:

{
   "background_page": "background.html",
   "content_scripts": [ {
      "js": [ "tabnot.js" ],
      "matches": [ "http://*/*", "https://*/*" ]
   } ],
   "description": "Notifies when the title of a tab changes",
   "icons": {
	"16": "icon16.png",
	"48": "icon.png"
   },
   "name": "Tab notifier",
   "permissions": [ "tabs", "notifications", "contextMenus" ],
   "options_page": "options.html",
   "homepage_url": "http://unusoft.it/blog/index.php/tab-notifier/",
   "update_url": "http://unusoft.it/extensions/updates.xml",
   "version": "1.1.0"
}

Then we add two new files to the extensions: options.html and options.js. The first contains the interface of the configuration, here’s the core of it:

<select id="ignoredSitesSl" multiple="multiple" size="16">
</select>
<div class="buttons">
<div class="left">
	<button id="removeBt">Remove selected</button>
	<button id="selectAllBt">Select all</button>
</div>
<div class="right">
	<button id="saveBt">Save</button>
	<button id="resetBt">Reset</button>
</div>
</div>
<script type="text/javascript">initOptionsPage();</script>

ignoredSitesSl will be programmatically filled when initOptionsPage (contained in options.js) is invoked. To see the full code follow the instructions in the previous post.
Beside the initialization of the interface options.js contains the javascript code bound to the click event of every button in the page:

(function() {
    var ignoredSites,ignoredSitesSl,removeBt,selectAllBt,saveBt,ResetBt
    ,load=function() {
		var s=window.localStorage.ignoredSites;
		ignoredSites={};
		if (s) try {
			ignoredSites=JSON.parse(s);
		} catch(e){console.log(e);};

		for (i in ignoredSites) {
			var o = document.createElement("option");
			o.innerHTML=i;
			ignoredSitesSl.appendChild(o);
		}
		disButts(true);
    }
	,disButts=function(a) {
		resetBt.disabled = a;
        saveBt.disabled = a;
	}
	
    window.initOptionsPage = function() {
        removeBt = document.getElementById("removeBt");
		selectAllBt = document.getElementById("selectAllBt");
		saveBt = document.getElementById("saveBt");
		resetBt = document.getElementById("resetBt");
		ignoredSitesSl = document.getElementById("ignoredSitesSl");
		load();
        removeBt.addEventListener("click",function(){
		var d=false;
			for(var c=0;c<ignoredSitesSl.options.length;c++) {
				var o=ignoredSitesSl.options;
				if(o.selected) {
					delete ignoredSites[o.innerHTML];
					ignoredSitesSl.removeChild(o);
					c--;d=true;
				}
			}
			if (d)disButts(false);
		},false);
        selectAllBt.addEventListener("click",function(){
			var l=ignoredSitesSl.options.length;
			for(var c=0;c<l;c++) {
				ignoredSitesSl.options.selected=true;
			}
		},false);
        saveBt.addEventListener("click",function(){
			window.localStorage.ignoredSites = JSON.stringify(ignoredSites);
			chrome.extension.getBackgroundPage()["updateOptions"]();
			disButts(true);
		},false);
        resetBt.addEventListener("click",function(){
			while (ignoredSitesSl.options.length> 0) ignoredSitesSl.options.remove(0);
			load();
		},false);
    };
})();

As you can see from the rows 48 and 49, when the button “Save” is pressed two actions are performed: the list of ignored sites is stored and the updateOptions function in the background page is called. In this way the background page always uses the most recent version of the list.

Tab notifier for Firefox

Tab notifier for Firefox has been released.
This extension shows a desktop notification when the title of a tab changes while the tab is not focused.
Here’s some features of this extension that are not yet available in the chrome version:

  • You can manage the list of web sites to block. Update (21/12/2011): added this feature to tab notifier for chrome as well
  • You can block a web site just with one click when the first notification appears.

You can install it from the Mozilla Add-ons web site.