This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greasyfork.org/scripts/453212/1105873/FaviconBadger.js
// ==UserScript==
// @name FaviconBadger
// @description Add a counter badge on the favicon
// @version 1.0
// @author ??
// ==/UserScript==
/**
* Create new FaviconBadger instance
* @param {Object} [Options]
* @param {Object} [Options.size=0.6] - Badge's size
* @param {Object} [Options.position='ne'] - Badge's position ['n' 's' 'e' 'w' 'nw' 'ne' 'sw' 'se']
* @param {Object} [Options.radius=8] - Badge's border radius
* @param {Object} [Options.backgroundColor='#f00'] - Badge's background color
* @param {Object} [Options.color='#fff'] - Badge's text color
* @return {Object} FaviconBadger object
* @example
* const faviconBadger = new FaviconBadger({
* size : 0.6,
* position : 'ne',
* radius : 8,
* backgroundColor : '#f00',
* color : '#fff'
* });
* faviconBadger.value = 1;
* faviconBadger.update();
*/
const FaviconBadger = (function () {
function FaviconBadger(options) {
const _this = this;
this.backgroundColor = options.backgroundColor || '#f00';
this.color = options.color || '#fff';
this.size = options.size || 0.6;
this.position = options.position || 'ne';
this.radius = options.radius || 8;
// this.src = options.src || '';
this.canvas = document.createElement('canvas');
var _a;
this.src = (_a = document.querySelector('link[rel$=icon]')) === null || _a === void 0 ? void 0 : _a.href;
this.ctx = this.canvas.getContext('2d');
this.faviconSize = 0;
this.offset = { x: 0, y: 0 };
this.badgeSize = 0;
this.value = 0;
this.img = new Image();
this.img.addEventListener('load', function () {
_this.faviconSize = _this.img.naturalWidth;
_this.badgeSize = _this.faviconSize * _this.size;
_this.canvas.width = _this.faviconSize;
_this.canvas.height = _this.faviconSize;
const sd = _this.faviconSize - _this.badgeSize;
const sd2 = sd / 2;
_this.offset = {
n: { x: sd2, y: 0 },
e: { x: sd, y: sd2 },
s: { x: sd2, y: sd },
w: { x: 0, y: sd2 },
nw: { x: 0, y: 0 },
ne: { x: sd, y: 0 },
sw: { x: 0, y: sd },
se: { x: sd, y: sd }
}[_this.position] || { x: 0, y: 0 };
_this._draw();
});
this.img.crossOrigin = 'Anonymous';
this.img.src = this.src;
}
FaviconBadger.prototype._drawIcon = function () {
this.ctx.clearRect(0, 0, this.faviconSize, this.faviconSize);
if (this.value)
this.ctx.drawImage(this.img, 0, 0 + this.faviconSize * 0.2, this.faviconSize * 0.8, this.faviconSize * 0.8);
else
this.ctx.drawImage(this.img, 0, 0, this.faviconSize, this.faviconSize);
};
FaviconBadger.prototype._drawShape = function () {
const r = this.radius;
const xa = this.offset.x;
const ya = this.offset.y;
const xb = this.offset.x + this.badgeSize;
const yb = this.offset.y + this.badgeSize;
this.ctx.beginPath();
this.ctx.moveTo(xb - r, ya);
this.ctx.quadraticCurveTo(xb, ya, xb, ya + r);
this.ctx.lineTo(xb, yb - r);
this.ctx.quadraticCurveTo(xb, yb, xb - r, yb);
this.ctx.lineTo(xa + r, yb);
this.ctx.quadraticCurveTo(xa, yb, xa, yb - r);
this.ctx.lineTo(xa, ya + r);
this.ctx.quadraticCurveTo(xa, ya, xa + r, ya);
this.ctx.fillStyle = this.backgroundColor;
this.ctx.fill();
this.ctx.closePath();
const margin = (this.badgeSize * 0.18) / 2;
this.ctx.beginPath();
this.ctx.textBaseline = 'middle';
this.ctx.textAlign = 'center';
this.ctx.font = 'bold '.concat(this.badgeSize * 0.9, 'px Arial');
this.ctx.fillStyle = this.color;
this.ctx.fillText(this.value.toString(), this.badgeSize / 2 + this.offset.x, this.badgeSize / 2 + this.offset.y + margin);
this.ctx.closePath();
};
FaviconBadger.prototype._drawFavicon = function () {
document.querySelectorAll('link[rel*=\'icon\']').forEach(elm => {
elm.parentElement.removeChild(elm);
});
const link = document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = this.canvas.toDataURL();
document.querySelector('head').appendChild(link);
};
FaviconBadger.prototype._draw = function () {
this._drawIcon();
if (this.value)
this._drawShape();
this._drawFavicon();
};
FaviconBadger.prototype.update = function () {
this.value = Math.min(99, parseInt(this.value.toString(), 10));
this._draw();
};
return FaviconBadger;
}());