Google Chrome Extension - Tabbed Bin

    Prologue


    Good day, dear visitor of HabraHabr!
    On this next day of knowledge in our life (which, however, I spent exclusively on work, not school), under the influence of this article, I am writing a story about my experience in creating an extension for Google Chrome - TabBasket (I don’t know how you, but I’m nonsense on the names). The article is designed in a mixed style - the elements of the lesson overlap, as well as explanations of the code and a description of key points.
    Before going directly to the main point, I note that my CSS knowledge is a bit messy, there was very little experience, so some of my decision may seem a little strange.

    What we have


    To write the extension, we practically do not need any tools, all the work can be done even in notepad or gedit. We choose the editor to your taste (personally, in such cases I use either Notepad ++ or NetBeans; the first is easier, the second is more functional, the choice is always yours).

    Get to the point


    First things first source .

    It is assumed that the reader is already familiar with the basics of creating extensions (again from the article mentioned above), so let's start off with a manifesto:

    {
    "name" : "TabBasket ",
    "version" : "1.5",
    "permissions" : [
    "tabs", "http://*/*"
    ],
    "background_page" : "back.html",
    "browser_action" : {
       "default_title": "Closed tabs",
       "default_icon": "icon.png",
       "popup": "popup.html"
    }
    }

    * This source code was highlighted with Source Code Highlighter.

    The two elements back.html and popup.html will be gradually examined (created, written) further. There is nothing unexpected in the manifest, everything is quite transparent. For a better understanding of the process, I will briefly outline the idea. A wonderful back.html page works in the shadow, has no appearance, its code starts immediately after installing the extension or launching the browser if the extension has already been installed. Its role is to set handlers for the events of creating, deleting, or updating tabs. Popup.html directly forms a list of closed tabs, allows you to restore any of them.

    We move on. We parse the back.html file:

    /* Tab constructor function. */
    function AnyTab()
    {
    this.id = 0
    this.url = ""
    this.name = ""
    this.favicon = ""
    }

    * This source code was highlighted with Source Code Highlighter.

    A constructor function for an object that stores tab information. The language allows you to create an object initialized by default with different methods, I chose this one. The id of the tab is stored (issued by the browser itself), url (what is o_O?), Name (the name of the site) and favicon (the site icon, with it a separate whistle). Further on the code

    var active = []
    var closedTabs = []
    var maxTabCount = 15

    * This source code was highlighted with Source Code Highlighter.

    We need two arrays - active (open) tabs and closed. The maximum number of tabs I have chosen (in my opinion) is optimal. We hang event handlers

    chrome.tabs.onUpdated.addListener(onTabUpdated)
    chrome.tabs.onRemoved.addListener(onTabRemoved)
    chrome.tabs.onCreated.addListener(onTabCreated)

    * This source code was highlighted with Source Code Highlighter.

    In this case, onTabUpdated, onTabRemoved, and onTabCreated are the names of the function handlers. Now we will slightly open the veil of secrecy - when the tab is created, you need to remember the characteristics we need (link, name, etc.). This is done because only the id of the closed tab comes to the onTabRemoved function, and there is already no mention of it. Therefore, when closing a tab, it is searched for by its id in the active array (by the way, it may not be there - if the extension was installed at the time when the program already had the tab open), the data is copied to the closedTabs array and, accordingly, deleted from the active array . Now we have full information about the closed tab and can easily restore it! An attentive reader, however, will draw attention to the fact that I did not mention the onTabUpdated function. She has a special role caused by the following feature (read the problem) - all the information about the tab does not immediately come to the onTabCreated function. With the naked eye you can see how the title changes at the newly made tab, the icon is loaded. This data later flows into the onTabUpdated function.

    The role of the workhorse is played by the updateTab function. If you pass -1 as the first parameter, then simply a new tab will be created. In another case, the id of the tab whose information has been updated is passed there.

    function updateTab(index, tab) {
        /* Add new tab. index = -1 passed in onTabCreated */
        if (index === -1) {
          var newTab = new AnyTab()
          newTab.id = tab.id
          newTab.url = tab.url
          newTab.name = tab.title
          newTab.favicon = tab.favIconUrl
          active.push(newTab)
        }
        /* Or update tab. Find index first. */
        else {
          var j, tbCt = active.length

          for ( j = 0; j < tbCt; j++ ) {
            if ( index == active[j].id )
              break
          }
          
          if ( j == tbCt ) {
            console.log("updateTab not found ID "+index)
            return
          }
          
          active[j].id = tab.id
          active[j].url = tab.url
          active[j].name = tab.title
          active[j].favicon = tab.favIconUrl || "icon.png" 
        }
      }

    * This source code was highlighted with Source Code Highlighter.

    The hardest part is behind, now a little about the look and popup.html?
    The interface of this extension is a pop-up window with a list of sites, an icon on the left for more intuitive use. Also on top there is a div of the toolArea class - this is the tool area, while there is only one button honorably flaunted there - cleaning the list.

    The JavaScript filling of this page is quite typical and transparent, the key point here is access to back.html, that is, to all functions and variables declared there by calling the chrome.extension.getBackgroundPage () method.

    The script is voluminous, but if you break it into logical parts, it turns out very simply:
    • List creation
    • Defining mouseover and mouseout handlers
    • Implementation of the functions of clicking on the list item, as well as cursor

    This is already pure, simple JavaScript, with a little admixture of the techniques we have already used.
    Creature:

    var back = chrome.extension.getBackgroundPage()
      for ( var k = back.closedTabs.length - 1; k >= 0; k--) {  
        document.write ("
    ")
        document.write ("")
        var txtName = back.closedTabs[k].name
        if (txtName.length > 40)
            txtName = txtName.substr(0, 35) + "..."
        document.write ("" + txtName + "")
        document.write ("
    ")
      }

    * This source code was highlighted with Source Code Highlighter.

    Handlers:

    var divs = document.getElementsByTagName("div");
      for (var i = 0; i < divs.length; i++)
      {
        if (divs[i].id === "toolDiv") {
          divs[i].onclick = cleanToolClick
        } else {
          divs[i].onmouseover = mouseOverEvent
          divs[i].onmouseout = mouseOutEvent
        }
      }

    * This source code was highlighted with Source Code Highlighter.

    At a certain point in the development, I caught myself thinking that when creating a new tab in divClick using the chrome.tabs.create function (which, by the way, takes an object of arguments that are easier to peek in the documentation than remembering from the article), the tab automatically gets into onTabCreated , so no need to worry about adding tabs created programmatically to the array of active!

    Todo


    Write suggestions for improvement! So far, it seems only obvious to make the options page with the choice of the maximum number of tabs, but because of one such fad, the page does not want to (read lazy) create!

    Epilogue


    As a result of the work done, we get a fairly useful extension in the household and everyday life that implements the much-needed functionality, like a browser basket. The article describes the basic techniques for working with tabs, the principles of close interaction of structural elements of the Google Chrome extension. Creating extensions is a very interesting and exciting activity! A basic requirement is basic knowledge of html, css and JavaScript, but not mandatory - nothing will stand in front of a lively interest!
    And I accept comments on the code, as I consider myself a newcomer to JS!
    Good luck in your endeavors, go for it, experiment, create!

    Also popular now: