📜 ⬆️ ⬇️

Google Chrome Extension - Tabs Cart

Prologue


Good day, dear visitor HabraHabra!
In this knowledge day, which is another day in our life (which I, however, spent exclusively at work and not at 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 don't care for names). The article is framed in a mixed style - the elements of the lesson, as well as explanations on the code and description of the key points echo each other.
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 decisions may seem a bit strange.

What we have


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

Closer to the point


First of all, the source code .
')
It is assumed that the reader is already familiar with the basics of creating extensions (again from the article mentioned above), so we will begin with a lively 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 reviewed (created, written) further. There is no unexpected in the manifesto, everything is quite transparent. For a greater understanding of the process, briefly state the idea. A wonderful page back.html works in the shadows, does not have an 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 creating, deleting, or updating tabs events. Popup.html directly generates a list of closed tabs, allows you to restore any of them.

Moving on. 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 information about a tab. The language allows you to create an object initialized with default values ​​by different methods, I chose this one. Tab id is stored (issued by the browser itself), url (what is o_O?), Name (site name) and favicon (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 will need two arrays - active (open) tabs and closed. I chose the maximum number of tabs (in my opinion) 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 handler functions. Now let's slightly open the veil of secrecy - when the tab is created, you need to remember the characteristics we need (link, title, etc.). This is done because only the id of the closed tab comes to the onTabRemoved function, and there is no mention of it itself. Therefore, when closing a tab, it is searched by its id in the active array (by the way, it may not be there - if the extension was installed at the moment when the tab was opened in the program), the data is copied to the closedTabs array and, accordingly, removed from the active array . Now we have complete information about the closed tab and can easily restore it! The attentive reader, however, will draw attention to the fact that I did not mention the onTabUpdated function. It 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 of the new tab changes, the icon is loaded. This data later flows into the onTabUpdated function.

The role of the workhorse is played by the updateTab function. If the first parameter is -1, then a new tab will simply be created. In another case, the tab id is sent there, the information about which was updated.

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 most difficult part behind, now is a little about appearance 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. There is also a toolArea class div on top - this is the tool pane, while there is only one button honoring it there - clearing the list.

The JavaScript content of this page is fairly typical and transparent, the key point here is access to back.html, that is, all the 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:

This is already clean, simple JavaScript, with a few admixtures 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 ( "<div id='" + back.closedTabs[k].id + "' onclick='divClick(this)' class='divClass'>" )
document .write ( "<img src=" + back.closedTabs[k].favicon + " class='imgClass'>" )
var txtName = back.closedTabs[k].name
if (txtName.length > 40)
txtName = txtName.substr(0, 35) + "..."
document .write ( "<span class='labelClass'>" + txtName + "</span>" )
document .write ( "</div>" )
}


* 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 moment of development, I caught myself thinking that when creating a new tab in divClick using the chrome.tabs.create function (which, by the way, accepts an object of arguments that are easier to peek in the documentation than memorizing from the article), the tab automatically falls into onTabCreated so you don’t need to worry about adding program-generated active tabs to the array!

ToDo


Write suggestions for improvement! So far it only seems obvious to make an options page with the choice of the maximum number of tabs, but because of one such fad, I don’t feel like creating a page (read).

Epilogue


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

Source: https://habr.com/ru/post/127676/


All Articles