Showing posts with label firefox. Show all posts
Showing posts with label firefox. Show all posts

Thursday, July 8, 2010

View Tab : The Implementation - Part 3

So far, I've discussed how the page to be displayed in the preview thumbnail (PT) is scaled down, snipped and drawn on a canvas, which, indeed, was the trickiest part of the implementation. Well, it seems straightforward once you know what is to be done, but less than six weeks ago, we hardly knew the A,B,C of Javascript, and this seemed quite an impossible task. We learnt about the canvas element almost by chance. I'd noticed, during my initial, failed attempts, that attempting to drag a tab in Firefox creates a tiny thumbnail showing the contents of that tab (you can try that right now, if you've never noticed it). So, I decided to look into the browser's main javascript file : chrome://browser/content/browser.js, which is where I came across the canvas element for the first time. It was only after that, that we could actually start working on View Tab.

As I said at the end of the last post, we are done with creating a preview canvas, and all that's left to do is make sure it shows up at the right place. For this, first we create a popup element.

//Create a Tooltip to show the canvas
    prevTooltip = document.createElement("popup");
    prevTooltip.id="viewTabTooltip";
    prevTooltip.position="after_pointer";
    prevTooltip.appendChild(prevCanvas);
    prevTooltip.setAttribute("style","margin:21px 0px;
        -moz-box-shadow:10px 10px 2px black;
        text-rendering:geometricPrecision !important;");

The popup element is, as the name suggests, a popup, which is not shown in the document, and has to be attached to another element in one of three ways, to cause it to show on clicking, right-clicking and hovering the mouse over the element. More on popups here.

The popup, called prevTooltip, is given the id "viewTabTooltip" and its position is set to "after_pointer", which ensures it shows up below the mouse pointer, when it is invoked. Then, the canvas, containing the preview is appended to prevTooltip, and the popup is styled.

Finally, the popup is appended to the browser's mainPopupSet, and attached to aTab using it's tooltip attribute.

//Attach the tooltip to aTab
    document.getElementById("mainPopupSet")
            .appendChild(prevTooltip);
    aTab.setAttribute("tooltip","viewTabTooltip");
    }
}

With this the function viewTab.createPreview() is complete, and will do the job of showing the PT if called when the mouse pointer is moved over a tab.

Next, the function to remove the popup is defined.

/* Function to End Preview */
viewTab.endPreview = function(aTab,firsttab){
    if(firsttab) aTab=gBrowser.tabContainer.
       getElementsByClassName("tabbrowser-tab")[0];

The first line of code in the function, again, as I mentioned in the first post, is included to avoid a specific error.

if(document.getElementById("viewTabTooltip")){
   document.getElementById("mainPopupSet").
     removeChild(document.getElementById
                          ("viewTabTooltip"));
   aTab.removeAttribute("tooltip");
}}

If the document contains an element with the id "viewTabTooltip", which is the popup that contains the preview canvas, then it is removed, and the tooltip attribute of aTab is also removed. This completes viewTab.endPreview().

Next, a function to set the onmouseover and onmouseout attributes of tabs, so that the functions defined earlier are invoked when they are needed, is defined.

/* Function to set the onmouseover property of the tabs*/
viewTab.init = function (){
  tabs = gBrowser.tabContainer.
getElementsByClassName("tabbrowser-tab");
for(var i=0;i
    if (i!=0){
    tabs[i].setAttribute("onmouseover",
        "viewTab.createPreview(tabs["+i+"]);");
    tabs[i].setAttribute("onmouseout",
        "viewTab.endPreview(tabs["+i+"]);");
    }
    else
    {
        tabs[0].setAttribute("onmouseover",
        "if(tabs[0] !=gBrowser.selectedTab) 
         viewTab.createPreview(tabs[0],true);");
    tabs[0].setAttribute("onmouseout",
        "viewTab.endPreview(tabs[0],true);");
    }
}
}
The function is pretty straightforward, an array of tabs is created and their respective onmouseover and onmouseout attributes are set to invoke viewTab.createPreview() and viewTab.endPreview(). The portion under else is required because, as mentioned earlier, the first tab causes some trouble, and needs to be dealt with separately.

Finally, event handlers are added to the gBrowser, the primary tabbrowser element, to invoke viewTab.init() whenever any change is made to the tabs.

//Add the event handlers to listen for new tabs
gBrowser.addEventListener
         ("load",viewTab.init,false);
gBrowser.addEventListener
         ("TabSelect",viewTab.init,false);
gBrowser.addEventListener
         ("TabClose",viewTab.init,false);
gBrowser.addEventListener
         ("TabMove",viewTab.init,false);

I'd initially assumed it would be enough to listen just for the "TabOpen" event (which I ultimately removed!), which is supposedly fired whenever a new tab is opened. But apparently it wasn't enough, so I tried listening for just the "load" event, (which is fired in more places than "TabOpen"), but it wasn't enough either,and so, after a experimenting for a while with possible ways of manipulating tabs, I was finally able to come up with this almost exhaustive list of events to listen for, so that the PT's always show up. Including "TabSelect" has an added advantage: even if something's gone wrong and PT's aren't showing up, selecting a different tab invokes viewTab.init and that puts things back in place.

With that, the implementation of View Tab is complete! Hope it was useful.

Friday, July 2, 2010

All About about:config

Most people already know about about:config but I thought I'd mention it anyway, just as a token of appreciation to the the fact that Firefox lets customize it to do things exactly the way you want them to be done, which makes it all the more a wonderful application to use.
All you have to do is type in the words about:config into the URL bar and hit Enter. You might receive a warning that looks something like:


That warning isn't there for no reason, and most people will advise you not to mess with things that don't make obvious sense, so better be careful. However, once you do click on the button, you will see a screen that looks like:


This page is basically a list of preferences (a huge list at that, but, it's not complete, there are lots of other preferences not shown in this list). There's a column for the preference name, which apart from uniquely identifying the preference, also gives you an idea about what it's for (in most cases). If you paln on designing an add-on which depends on one of these preferences, the preference name is what you should be using. More on handling preferences here.

Next, there's column showing the status, whether a preference currently bears it default value, or one set by the user. Preferences set by the user are shown in bold. The term user set doesn't really mean the preference has been set by the user herself, it could have been done by an extension, or a theme, or an external application. So you might want to think twice before you decide to restore defaults.

Then there's a column showing the preference type:string, integer or boolean. The next column shows the value currently held by the preference. You can change the value of a preference by double-clicking on it. If the preference is a boolean, it is toggled automatically, otherwise you are prompted to enter a new value (in case of integers and strings). You can also add new preferences by right-clicking, and selecting New.

There's also a search box(at the top of the page, in case you didn't notice) that allows you to filter preferences that contain the string you enter in the box. This, plus the fact the preferences are extremely well-named, make this page extremely easy to use. For example, you can simply type in tab to see and modify almost all the preferences related to tabs.

If there's something you feel can be done differently, without changing the structure of firefox itself, then you will, in most cases, find a preference that lets you do that. I, for example don't like the downloads window popping up when I start a new download. If you type in download in the filter box, you will find a series of preferences beginning with browser.download.manager that let you control certain properties of downloads window. In my case, all I had to do was double-click on the preference browser.download.manager.showWhenStarting which is a boolean set to true by default, and is responsible for opening the downloads window when a new download starts. You might find some interesting preferences under the keywords: mouse, history, bookmark, extension, url, cache etc.

One must, of course, be extremely careful while changing preferences, for, as the warning indicates, changing them can be harmful to the stability, security, and performance of Firefox. Do so, only if you are sure of what you are doing. It is a good idea to verify what you plan to do, before actually doing it.

Monday, May 24, 2010

Hi! This blog's being written to record the progress of the project my friend Ravi and I have taken up under WNCC-IITB for the summer. We are working on the following extensions for Mozilla Firefox 3.0 and above :
1. ViewTab : A no-nonsense extension that shows a preview of the contents of a tab when the mouse pointer is moved over the corresponding tab-head.
2. Multi-Tab Search : Allows the user to search for a string in all or some of the currently open tabs.
3.Source Viewer-Modifier : Installs a button on the toolbar which, when clicked, divides the content window into two parts, one showing the page and the other showing the page source. The user can modify the code, and preview the page with the modified code.