mirror of
https://github.com/lipka/piecon.git
synced 2026-01-14 07:57:59 -05:00
If there are multiple link elements and favicon is not last, first setProgress would cause "Cannot read property 'getAttribute' of undefined" links is now Array instead of HTMLCollection, so that it does't change while for loop iterates through it. Closes #17 Closes #13 Closes #11
190 lines
5.5 KiB
JavaScript
190 lines
5.5 KiB
JavaScript
//
|
|
// piecon.js
|
|
//
|
|
// https://github.com/lipka/piecon
|
|
//
|
|
// Copyright (c) 2015 Lukas Lipka <lukaslipka@gmail.com>. All rights reserved.
|
|
//
|
|
|
|
(function(){
|
|
var Piecon = {};
|
|
|
|
var currentFavicon = null;
|
|
var originalFavicon = null;
|
|
var originalTitle = null;
|
|
var canvas = null;
|
|
var options = {};
|
|
var defaults = {
|
|
color: '#ff0084',
|
|
background: '#bbb',
|
|
shadow: '#fff',
|
|
fallback: false
|
|
};
|
|
|
|
var isRetina = window.devicePixelRatio > 1;
|
|
|
|
var ua = (function () {
|
|
var agent = navigator.userAgent.toLowerCase();
|
|
return function (browser) {
|
|
return agent.indexOf(browser) !== -1;
|
|
};
|
|
}());
|
|
|
|
var browser = {
|
|
ie: ua('msie'),
|
|
chrome: ua('chrome'),
|
|
webkit: ua('chrome') || ua('safari'),
|
|
safari: ua('safari') && !ua('chrome'),
|
|
mozilla: ua('mozilla') && !ua('chrome') && !ua('safari')
|
|
};
|
|
|
|
var getFaviconTag = function() {
|
|
var links = document.getElementsByTagName('link');
|
|
|
|
for (var i = 0, l = links.length; i < l; i++) {
|
|
if (links[i].getAttribute('rel') === 'icon' || links[i].getAttribute('rel') === 'shortcut icon') {
|
|
return links[i];
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
var removeFaviconTag = function() {
|
|
var links = Array.prototype.slice.call(document.getElementsByTagName('link'), 0);
|
|
var head = document.getElementsByTagName('head')[0];
|
|
|
|
for (var i = 0, l = links.length; i < l; i++) {
|
|
if (links[i].getAttribute('rel') === 'icon' || links[i].getAttribute('rel') === 'shortcut icon') {
|
|
head.removeChild(links[i]);
|
|
}
|
|
}
|
|
};
|
|
|
|
var setFaviconTag = function(url) {
|
|
removeFaviconTag();
|
|
|
|
var link = document.createElement('link');
|
|
link.type = 'image/x-icon';
|
|
link.rel = 'icon';
|
|
link.href = url;
|
|
|
|
document.getElementsByTagName('head')[0].appendChild(link);
|
|
};
|
|
|
|
var getCanvas = function () {
|
|
if (!canvas) {
|
|
canvas = document.createElement("canvas");
|
|
if (isRetina) {
|
|
canvas.width = 32;
|
|
canvas.height = 32;
|
|
} else {
|
|
canvas.width = 16;
|
|
canvas.height = 16;
|
|
}
|
|
}
|
|
|
|
return canvas;
|
|
};
|
|
|
|
var drawFavicon = function(percentage) {
|
|
var canvas = getCanvas();
|
|
var context = canvas.getContext("2d");
|
|
|
|
percentage = percentage || 0;
|
|
|
|
if (context) {
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Draw shadow
|
|
context.beginPath();
|
|
context.moveTo(canvas.width / 2, canvas.height / 2);
|
|
context.arc(canvas.width / 2, canvas.height / 2, Math.min(canvas.width / 2, canvas.height / 2), 0, Math.PI * 2, false);
|
|
context.fillStyle = options.shadow;
|
|
context.fill();
|
|
|
|
// Draw background
|
|
context.beginPath();
|
|
context.moveTo(canvas.width / 2, canvas.height / 2);
|
|
context.arc(canvas.width / 2, canvas.height / 2, Math.min(canvas.width / 2, canvas.height / 2) - 2, 0, Math.PI * 2, false);
|
|
context.fillStyle = options.background;
|
|
context.fill();
|
|
|
|
// Draw pie
|
|
if (percentage > 0) {
|
|
context.beginPath();
|
|
context.moveTo(canvas.width / 2, canvas.height / 2);
|
|
context.arc(canvas.width / 2, canvas.height / 2, Math.min(canvas.width / 2, canvas.height / 2) - 2, (-0.5) * Math.PI, (-0.5 + 2 * percentage / 100) * Math.PI, false);
|
|
context.lineTo(canvas.width / 2, canvas.height / 2);
|
|
context.fillStyle = options.color;
|
|
context.fill();
|
|
}
|
|
|
|
setFaviconTag(canvas.toDataURL());
|
|
}
|
|
};
|
|
|
|
var updateTitle = function(percentage) {
|
|
if (percentage > 0) {
|
|
document.title = '(' + percentage + '%) ' + originalTitle;
|
|
} else {
|
|
document.title = originalTitle;
|
|
}
|
|
};
|
|
|
|
Piecon.setOptions = function(custom) {
|
|
options = {};
|
|
|
|
for (var key in defaults){
|
|
options[key] = custom.hasOwnProperty(key) ? custom[key] : defaults[key];
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
Piecon.setProgress = function(percentage) {
|
|
if (!originalTitle) {
|
|
originalTitle = document.title;
|
|
}
|
|
|
|
if (!originalFavicon || !currentFavicon) {
|
|
var tag = getFaviconTag();
|
|
originalFavicon = currentFavicon = tag ? tag.getAttribute('href') : '/favicon.ico';
|
|
}
|
|
|
|
if (!isNaN(parseFloat(percentage)) && isFinite(percentage)) {
|
|
if (!getCanvas().getContext || browser.ie || browser.safari || options.fallback === true) {
|
|
// Fallback to updating the browser title if unsupported
|
|
return updateTitle(percentage);
|
|
} else if (options.fallback === 'force') {
|
|
updateTitle(percentage);
|
|
}
|
|
|
|
return drawFavicon(percentage);
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
Piecon.reset = function() {
|
|
if (originalTitle) {
|
|
document.title = originalTitle;
|
|
}
|
|
|
|
if (originalFavicon) {
|
|
currentFavicon = originalFavicon;
|
|
setFaviconTag(currentFavicon);
|
|
}
|
|
};
|
|
|
|
Piecon.setOptions(defaults);
|
|
|
|
if(typeof define === 'function' && define.amd) {
|
|
define(Piecon);
|
|
} else if (typeof module !== 'undefined') {
|
|
module.exports = Piecon;
|
|
} else {
|
|
window.Piecon = Piecon;
|
|
}
|
|
})();
|