-1

How can I set the badge number on a specific tab only? So far I have a code that sets the badge number on all the tabs.. I've been reading around A LOT, but there doesn't seem to be a whole lot of information about this, so perhaps I will find a solution for this here.

I would like something like Adblock Plus, which sets the badge number for a specific tab. This is pretty easy in Chrome etc, but doesn't seem to be the case in Safari.

enter image description here

Does anyone know how extensions like Adblock plus shows the badge number on a specific tab?

So far I only have this code, but as mentioned, it sets the badge on all the tabs, which is not the result I want.

safari.extension.toolbarItems[0].badge = 2;

Edit:

I have been looking at the source code of Adblock plus, and a few other extensions that had this function. And it seems it is using some prototype.

Adblock plus background snippet:

BrowserAction.prototype = {
_set: function(name, value)
{
  var toolbarItem = getToolbarItemForWindow(this._page._tab.browserWindow);
  if (!toolbarItem)
  {
    return;
  }
  var property = toolbarItemProperties[name];
  if (!property)
  {
    property = toolbarItemProperties[name] = {
      pages: new ext.PageMap(),
      global: toolbarItem[name]
    };
  }
  property.pages.set(this._page, value);
  if (isPageActive(this._page))
  {
    toolbarItem[name] = value;
  }
},
setIcon: function(path)
{
  this._set("image", safari.extension.baseURI + path.replace("$size", "16"));
},
setBadge: function(badge)
{
  if (!badge)
  {
    this._set("badge", 0);
  }
  else if ("number" in badge)
  {
    this._set("badge", badge.number);
  }
}
};

Content script (adblockplus.js)

FilterNotifier.on("filter.hitCount", function(filter, newValue, oldValue, page)
{
if (!(filter instanceof BlockingFilter) || !page)
{
  return;
}
Prefs.blocked_total++;
var blocked = blockedPerPage.get(page) || 0;
blockedPerPage.set(page, ++blocked);
if (Prefs.show_statsinicon)
{
  page.browserAction.setBadge(
  {
    color: badgeColor,
    number: blocked
  });
}
});

It seems this is how Adblock plus does it, but so far I haven't been able to replicate it. Still trying though..

Anders
  • 513
  • 2
  • 10
  • 32

1 Answers1

0

Okay, so I finally found a solution for this, and thought I would share what I did, in case somebody else is in the same situation.

This morning I got the idea of storing the data in an array, when the user visits one of the websites I want to display the badge number on (doesn't store all websites the user visits), only if it matched one of the websites I wanted to target. I stored the following data in the array: root domain (example.com) and the badgeNumber.

For this to work, you need to make an array of the root domain of the websites you want to target, and then only execute the following when it matches, otherwise the array would fill up very quickly, and we don't want too much data in it.

In the global page, start by making an empty array to store the data

var badgeUpdateArray = [];

You then need to set up message handling in your global page as well.

safari.application.addEventListener('message', handleMessage, false);

function handleMessage(event) {
if(event.name === "setBadgeText"){

    var id = badgeUpdateArray.length + 1;
    var isFound = 0;
    var found = badgeUpdateArray.some(function (el) {
        if(el.identifier === event.message.identifier){
            // Was found
            isFound = 1;
        }
    });
    if (isFound == 0) {
        // Not found, add to the array
        badgeUpdateArray.push({identifier:event.message.identifier,badgeNumber:event.message.badgeNumber});
    }

    // Set the badge number
    safari.extension.toolbarItems[0].badge = event.message.badgeNumber;
}
}

Now we need to send the message from the content script to the global page. You need to get the root domain (example.com), I'm not getting into that here, as it's pretty easy. You will also need the badgeNumber value, this can be gathered from wherever (GET request, or elsewhere..)

Remember, only execute this code if the website matches your target domains.

var message = {
        identifier: domain,
        badgeNumber: rows.length
    }
    safari.self.tab.dispatchMessage("setBadgeText", message);

This will send the message, and store the data in the array, it will also set the badge number.

Now, for this to be working on different tabs, you will need to make an event handler for "activate" on the global page, this will run whenever a tab is active.

safari.application.addEventListener("activate", updateBadge, true);

function updateBadge(){

var cDomain = safari.application.activeBrowserWindow.activeTab.url;
cDomain = cDomain.replace("www3.","");
cDomain = cDomain.replace("www2.","");
cDomain = cDomain.replace("www1.","");
cDomain = cDomain.replace("www.","");
cDomain = new URL(cDomain);
cDomain = cDomain.hostname;

var id = badgeUpdateArray.length + 1;
var isFound = 0;
var badgeNumber = 0;
var found = badgeUpdateArray.some(function (el) {
    badgeNumber = el.badgeNumber;
    if(el.identifier === cDomain){
        // Was found, set the badge number
        isFound = 1;
        safari.extension.toolbarItems[0].badge = el.badgeNumber;
    }
});
if (isFound == 0) {
    // Was not found
    safari.extension.toolbarItems[0].badge = 0;
}

}

Hopefully I've got it all in here, and at least something that works, though I have to say that I would prefer an easier way of storing it.. like Chrome etc does it, with the tab API.

Anders
  • 513
  • 2
  • 10
  • 32