Search code examples
javascriptjqueryfaviconuserscripts

Dynamically changing favicon back and forth multiple times


I am running a userscript (using tampermonkey) on a site, and I have a function which is called each time something else on the page changes.

I have a value stored in something called Available. If this is 0, then I want to use the standard favicon for the site. Otherwise, I want a red box added to the favicon with text displaying the value of Available.

This works initially, however after Available goes > 0, then == 0, then > 0 again, it stops adding the red box with white text on top.

The code is definitely reaching the key point each time, as my console log shows the value for Available is being triggered.

Here's what I have:

if(Available > 0){
    var canvas = document.createElement('canvas');
    canvas.width = 16;canvas.height = 16;
    var ctx = canvas.getContext('2d');

    var img = new Image();
    img.src = '/favicon.ico';
    img.onload = function() {
        ctx.drawImage(img, 0, 0);
        ctx.fillStyle = "#F00";
        ctx.fillRect(10, 7, 6, 8);
        ctx.fillStyle = '#FFFFFF';
        ctx.font = 'bold 10px sans-serif';
        ctx.fillText(Available, 10, 14);

        var link = document.createElement('link');
        link.type = 'image/x-icon';
        link.rel = 'shortcut icon';
        link.href = canvas.toDataURL("image/x-icon");
        document.getElementsByTagName('head')[0].appendChild(link);
    };
}
else {
    var canvas2 = document.createElement('canvas');
    canvas2.width = 16;
    canvas2.height = 16;
    var ctx2 = canvas2.getContext('2d');

    var img2 = new Image();
    img2.src = '/favicon.ico';
    img2.onload = function() {
        ctx2.drawImage(img2, 0, 0);

        var link2 = document.createElement('link');
        link2.type = 'image/x-icon';
        link2.rel = 'shortcut icon';
        link2.href = canvas2.toDataURL("image/x-icon");
        document.getElementsByTagName('head')[0].appendChild(link2);
    };
}

Solution

  • You most likely need to remove the previously-added icon links, so the browser doesn't just keep using the first one you added:

    var oldLinks = document.querySelectorAll('link[rel*="icon"]');
    
    for (var i = oldLinks.length - 1; i >= 0; --i) {
      var ln = oldLinks[i],
          pn = ln.parentNode;
    
      pn.removeChild(ln);
    }
    
    if (Available > 0) {
      // as before
    }