change the button of a firefox-webextension into a textString
Asked Answered
N

1

1

Currently I am building a webextension on firefox 47.

When you click a webextension button, a drop-down menu appears, from there I can navigate to other websites.

The button that is appearing is the icon I specified in manifest.json. I wonder if there is any way to change the icon of the extension to a text-string containing the URL I am currently visiting, and changes every time I visit a new URL.

Namangan answered 26/1, 2017 at 8:34 Comment(4)
Are you asking about the actual browser/page action icon, or the something in the drop-down menu (i.e. within the HTML you have supplied)?Incorrect
Why are you using Firefox 47 (current is 50.1.0)? The WebExtensions API is still in development. What is working improves with each version of Firefox. There were significant improvements in Firefox 48, and later versions. I suggest using Firefox Developer Edition, or Firefox Nightly. You should also make careful note of what version of Firefox is required for the functionality you desire to use. This information is contained in the "Browser compatibility" section of the MDN documentation pages.Incorrect
Mayken: the browser action icon. In reply to your question of the Firefox version, I might make a horrible mistake but... As I am completely new to developing in Firefox (sysadmin). I found it much easier install the webextension in V47. (just zip the directory to a .xpi and install it) whereas in the newer version I was asked to let the extension be signed by Mozilla. I did not have time for that.Namangan
I can certainly understand that. I would suggest that you consider installing the WebExtensions you are developing as Temporary Extensions (not required to be signed). If you want to install them as normal extensions, then you can use Developer Edition. The Getting started with firefox-addon topic in documentation has some information on installing add-ons, which is focused on doing so for development (i.e. without it being signed).Incorrect
I
4

No, you can not directly change a browser action or page action icon into some long string of text. You can:

  • Browser Actions:
    • Change the icon using browserAction.setIcon(). This changes the image which is displayed. It will always be the same normal icon size. You could include a very limited amount of text in the icon image. However, it would be complex to do this dynamically, but switching between a limited set might not be that bad.
    • Change the badge text using browserAction.setBadgeText(). The amount of text is limited to about four characters.
    • Change the background color of the badge text using browserAction.setBadgeBackgroundColor()
    • Change the icon's title using browserAction.setTitle(). This is displayed as a tooltip. The text is not inherently restricted in length. However, there are reasonable limitations on what will actually be displayed to the user.
    • Change from sending an event to your background page, for which you can listen with a browserAction.onClicked listener, to displaying an HTML popup by supplying the popup's URL with browserAction.setPopup(). You can change back to the click event by specifying '' as the URL for the popup.
    • Enable or disable the button with browserAction.enable() and browserAction.disable().
  • Page Actions:
    • Change the icon using pageAction.setIcon(). This changes the image which is displayed. It will always be the same normal icon size. You could include a very limited amount of text in the icon image. However, it would be complex to do this dynamically, but switching between a limited set might not be that bad.
    • Change the icon's title using pageAction.setTitle(). This is displayed as a tooltip. The text is not inherently restricted in length. However, there are reasonable limitations on what will actually be displayed to the user.
    • Change from sending an event to your background page, for which you can listen with a pageAction.onClicked listener, to displaying an HTML popup by supplying the popup's URL with pageAction.setPopup(). You can change back to the click event by specifying '' as the URL for the popup.
    • Show or hide the button with pageAction.show() and pageAction.hide().

Example of changing the icon badge and badge color:

Example of changing the icon badge and badge color

The code used to create the on/off states for the button is:

background.js

//The browserButtonStates Object describes the states the button can be in and the
//  'action' function to be called when the button is clicked when in that state.
//  In this case, we have two states 'on' and 'off'.
//  You could expand this to as many states as you desire.
//icon is a string, or details Object for browserAction.setIcon()
//title must be unique for each state. It is used to track the state.
//  It indicates to the user what will happen when the button is clicked.
//  In other words, it reflects what the _next_ state is, from the user's
//  perspective.
//action is the function to call when the button is clicked in this state.
var browserButtonStates = {
    defaultState: 'off',
    on: {
        //icon         : '/ui/is-on.png'
        badgeText  : 'On',
        badgeColor : 'green',
        title        : 'Turn Off',
        action       : function(tab) {
                           chrome.webNavigation.onCommitted.removeListener(onTabLoad);
                       },
        nextState    : 'off'
    },
    off: {
        //icon         : '/ui/is-off.png'
        badgeText  : 'Off',
        badgeColor : 'red',
        title        : 'Turn On',
        action       : function(tab) {
                           chrome.webNavigation.onCommitted.addListener(onTabLoad);
                       },
        nextState    : 'on'
    }
}

//This moves the Browser Action button between states and executes the action
//  when the button is clicked. With two states, this toggles between them.
chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.browserAction.getTitle({tabId:tab.id},function(title){
        //After checking for errors, the title is used to determine
        //  if this is going to turn On, or Off.
        if(chrome.runtime.lastError){
            console.log('browserAction:getTitle: Encountered an error: ' 
                + chrome.runtime.lastError);
            return;
        }
        //Check to see if the current button title matches a button state
        let newState = browserButtonStates.defaultState;
        Object.keys(browserButtonStates).some(key=> {
            if(key === 'defaultState') {
                return false;
            }
            let state = browserButtonStates[key];
            if(title === state.title) {
                newState = state.nextState;
                setBrowserActionButton(browserButtonStates[newState]);
                if(typeof state.action === 'function') {
                    //Do the action of the matching state
                    state.action(tab);
                }
                //Stop looking
                return true;
            }
        });
        setBrowserActionButton(browserButtonStates[newState]);
    });
});

function setBrowserActionButton(tabId,details){
    if(typeof tabId === 'object' && tabId !== null){
        //If the tabId parameter is an object, then no tabId was passed.
        details = tabId;
        tabId       = null;
    }
    let icon   = details.icon;
    let title  = details.title;
    let text   = details.badgeText;
    let color  = details.badgeColor;

    //Supplying a tabId is optional. If not provided, changes are to all tabs.
    let tabIdObject = {};
    if(tabId !== null && typeof tabId !== 'undefined'){
        tabIdObject.tabId = tabId;
    }
    if(typeof icon === 'string'){
        //Assume a string is the path to a file
        //  If not a string, then it needs to be a full Object as is to be passed to
        //  setIcon().
        icon = {path:icon};
    }
    if(icon) {
        Object.assign(icon,tabIdObject);
        chrome.browserAction.setIcon(icon);
    }
    if(title) {
        let detailsObject = {title};
        Object.assign(detailsObject,tabIdObject);
        chrome.browserAction.setTitle(detailsObject);
    }
    if(text) {
        let detailsObject = {text};
        Object.assign(detailsObject,tabIdObject);
        chrome.browserAction.setBadgeText(detailsObject);
    }
    if(color) {
        let detailsObject = {color};
        Object.assign(detailsObject,tabIdObject);
        chrome.browserAction.setBadgeBackgroundColor(detailsObject);
    }
}

//Set the starting button state to the default state
setBrowserActionButton(browserButtonStates[browserButtonStates.defaultState]);

manifest.json:

{
    "description": "Demo Button toggle",
    "manifest_version": 2,
    "name": "Demo Button toggle",
    "version": "0.1",

    "background": {
        "scripts": [
            "background.js"
        ]
    },

    "browser_action": {
        "default_icon": {
            "32": "myIcon.png"
        },
        "default_title": "Turn On",
        "browser_style": true
    }
}

The code in this answer was originally posted in my answer to In a Firefox WebExtension, how I can make a button that looks and acts like a toggle.

Incorrect answered 26/1, 2017 at 17:55 Comment(3)
Thank you for this answer, it might just help me. As for the button size is concerned: I managed to make it the size I wanted with some adaption in userchrome.css and the DOM-inspector. The way I see my two options are: making textlabels and convert them to images, which will be a lot of work (). Or I include a little bit of text in the icon as you say, but this is something I cant find as a functionality in the documentation...Namangan
@NICKvr, If you are using userChrome.css it sounds like it is for personal use. At least for the next year, you could use an Add-on SDK based extension which has a much wider range of API supported options, and the ability to insert arbitrary content, should you desire.Incorrect
Actually, I want to use it to install the ext. on all our client systems. They use the FF-browser, of which all the buttons are hidden, and they only have a "home button" and a dropdown-list (kind of kiosk mode). currently we use an add-on with SDK. However , upgrading to a new OS (MINT 17) also made me do an upgrade of FF (=malfunction add-on ). As I was first thinking about updating the original SDK add-on, I noticed the old method is deprecating. This and the advantage of compatibility with future Firefox versions, let me to the idea of starting from scratch using a webextension...Namangan

© 2022 - 2024 — McMap. All rights reserved.