Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+299
@@ -0,0 +1,299 @@
|
||||
/**@license
|
||||
*
|
||||
* favloader v. 0.4.4
|
||||
*
|
||||
* Vanilla JavaScript library for loading animation in favicon
|
||||
*
|
||||
* Copyright (c) 2018-2019 Jakub T. Jankiewicz <https://jcubic.pl/me>
|
||||
* Released under the MIT license
|
||||
*
|
||||
* Build: Sat, 22 May 2021 11:37:31 +0000
|
||||
*/
|
||||
/* global define, module, global, Worker, Blob, BlobBuilder, setTimeout, parseGIF */
|
||||
(function(factory) {
|
||||
var root = typeof window !== 'undefined' ? window : global;
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
// istanbul ignore next
|
||||
define([], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
// Node/CommonJS
|
||||
module.exports = factory();
|
||||
} else {
|
||||
// Browser
|
||||
// istanbul ignore next
|
||||
root.favloader = factory();
|
||||
}
|
||||
})(function(undefined) {
|
||||
// we use web worker to trigger interval since browser main thread is limited
|
||||
// when tab is not active
|
||||
function fworker(fn) {
|
||||
// ref: https://stackoverflow.com/a/10372280/387194
|
||||
var str = '(' + fn.toString() + ')()';
|
||||
var URL = window.URL || window.webkitURL;
|
||||
var blob;
|
||||
try {
|
||||
blob = new Blob([str], {type: 'application/javascript'});
|
||||
} catch (e) { // Backwards-compatibility
|
||||
window.BlobBuilder = window.BlobBuilder ||
|
||||
window.WebKitBlobBuilder ||
|
||||
window.MozBlobBuilder;
|
||||
blob = new BlobBuilder();
|
||||
blob.append(str);
|
||||
blob = blob.getBlob();
|
||||
}
|
||||
return new Worker(URL.createObjectURL(blob));
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
var interval = (function() {
|
||||
var worker = fworker(function() {
|
||||
// rAF polyfil without setTimeout, ref: https://gist.github.com/paulirish/1579671
|
||||
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
||||
for(var x = 0; x < vendors.length && !self.requestAnimationFrame; ++x) {
|
||||
self.requestAnimationFrame = self[vendors[x]+'RequestAnimationFrame'];
|
||||
self.cancelAnimationFrame = self[vendors[x]+'CancelAnimationFrame']
|
||||
|| self[vendors[x]+'CancelRequestAnimationFrame'];
|
||||
}
|
||||
var raf = {};
|
||||
self.addEventListener('message', function(response) {
|
||||
var data = response.data;
|
||||
var id = data.id;
|
||||
if (data.type !== 'RPC' || id === null) {
|
||||
return;
|
||||
}
|
||||
if (data.method == 'setInterval') {
|
||||
var interval_id = data.params[0];
|
||||
if (typeof interval_id === 'number') {
|
||||
raf[interval_id] = self.setInterval(function() {
|
||||
self.postMessage({ type: 'interval', id: interval_id });
|
||||
}, data.params[1]);
|
||||
self.postMessage({ type: 'RPC', id: id, result: interval_id });
|
||||
} else {
|
||||
self.postMessage({
|
||||
type: 'RPC',
|
||||
id: id,
|
||||
result: null,
|
||||
error: 'Invalid Argument, expected number'
|
||||
});
|
||||
}
|
||||
} else if (data.method == 'clearInterval') {
|
||||
self.clearInterval(raf[data.params[0]]);
|
||||
delete raf[data.params[0]];
|
||||
}
|
||||
});
|
||||
});
|
||||
var callbacks = {};
|
||||
var rpc = (function() {
|
||||
var id = 0;
|
||||
return function rpc(method, params) {
|
||||
var _id = ++id;
|
||||
return new Promise(function(resolve, reject) {
|
||||
worker.addEventListener('message', function handler(response) {
|
||||
var data = response.data;
|
||||
if (data && data.type === 'RPC' && data.id === _id) {
|
||||
if (data.error) {
|
||||
reject(data.error);
|
||||
} else {
|
||||
resolve(data.result);
|
||||
}
|
||||
worker.removeEventListener('message', handler);
|
||||
}
|
||||
});
|
||||
worker.postMessage({ type: 'RPC', method: method, id: _id, params: params });
|
||||
});
|
||||
};
|
||||
})();
|
||||
worker.addEventListener('message', function(response) {
|
||||
var data = response.data;
|
||||
if (data && data.type === 'interval' && callbacks[data.id]) {
|
||||
callbacks[data.id]();
|
||||
}
|
||||
});
|
||||
return {
|
||||
set: function(fn, interval) {
|
||||
var interval_id = Date.now();
|
||||
callbacks[interval_id] = fn;
|
||||
rpc('setInterval', [interval_id, interval]);
|
||||
return interval_id;
|
||||
},
|
||||
clear: function(id) {
|
||||
delete callbacks[id];
|
||||
return rpc('clearInterval', [id]);
|
||||
}
|
||||
};
|
||||
})();
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
var hidden, visibilityChange;
|
||||
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
|
||||
hidden = "hidden";
|
||||
visibilityChange = "visibilitychange";
|
||||
} else if (typeof document.msHidden !== "undefined") {
|
||||
hidden = "msHidden";
|
||||
visibilityChange = "msvisibilitychange";
|
||||
} else if (typeof document.webkitHidden !== "undefined") {
|
||||
hidden = "webkitHidden";
|
||||
visibilityChange = "webkitvisibilitychange";
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function warn(message) {
|
||||
if (console && console.warn) {
|
||||
console.warn(message);
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
throw new Error(message);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
var ctx,
|
||||
c,
|
||||
link,
|
||||
icon,
|
||||
id,
|
||||
progress = 0,
|
||||
duration,
|
||||
initialized,
|
||||
settings,
|
||||
gif,
|
||||
type,
|
||||
initial_turns = -.25,
|
||||
interval_id,
|
||||
step;
|
||||
// ----------------------------------------------------------------------------------
|
||||
function init(options) {
|
||||
if (document.readyState !== "complete") {
|
||||
setTimeout(init.bind(this, options), 100);
|
||||
return;
|
||||
}
|
||||
settings = Object.assign({
|
||||
size: 16,
|
||||
radius: 6,
|
||||
thickness: 2,
|
||||
color: '#0F60A8',
|
||||
duration: 5000
|
||||
}, options);
|
||||
|
||||
if (!link) {
|
||||
link = document.querySelector('link[rel*="icon"]');
|
||||
if (!link) {
|
||||
link = document.createElement('link');
|
||||
link.setAttribute('rel', 'icon');
|
||||
document.head.appendChild(link);
|
||||
warn("No default icon found, restore state will not work");
|
||||
} else {
|
||||
icon = link.getAttribute('href');
|
||||
type = link.getAttribute('type');
|
||||
}
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
if (settings.gif) {
|
||||
if (typeof parseGIF === 'undefined') {
|
||||
throw new Error('parseGIF not defined, please include parseGIF.js file');
|
||||
}
|
||||
parseGIF(settings.gif).then(function(data) {
|
||||
gif = data;
|
||||
});
|
||||
} else {
|
||||
if (!c) {
|
||||
c = document.createElement('canvas');
|
||||
}
|
||||
c.width = c.height = settings.size;
|
||||
ctx = c.getContext('2d');
|
||||
|
||||
ctx.lineCap = "round";
|
||||
ctx.lineWidth = settings.thickness;
|
||||
ctx.strokeStyle = settings.color;
|
||||
duration = settings.duration;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function clear() {
|
||||
if (interval_id) {
|
||||
interval.clear(interval_id);
|
||||
interval_id = null;
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function restore() {
|
||||
if (icon) {
|
||||
link.setAttribute('href', icon + '?' + Date.now());
|
||||
link.setAttribute('type', type);
|
||||
} else if (link) {
|
||||
link.parentNode.removeChild(link);
|
||||
}
|
||||
clear();
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function animate() {
|
||||
if (!initialized) {
|
||||
setTimeout(animate, 100);
|
||||
return;
|
||||
}
|
||||
if (interval_id) {
|
||||
return;
|
||||
}
|
||||
progress = 0;
|
||||
if (settings.gif && parseGIF) {
|
||||
if (!gif) {
|
||||
setTimeout(animate, 100);
|
||||
return;
|
||||
}
|
||||
interval_id = interval.set(animateGIF, 300);
|
||||
} else {
|
||||
interval_id = interval.set(draw, 300);
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function turn(x) {
|
||||
return (x + initial_turns) * 2 * Math.PI;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function animateGIF() {
|
||||
progress++;
|
||||
if (progress >= gif.uris.length) {
|
||||
progress = 0;
|
||||
}
|
||||
update(gif.uris[progress]);
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function arcStart(pos) {
|
||||
return turn(pos + initial_turns) + turn(Math.max(0, pos * 2 - 1));
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function arcEnd(pos) {
|
||||
return turn(pos + initial_turns) + turn(Math.min(1, pos * 2));
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function update(dataURI) {
|
||||
var newIcon, icon = document.querySelector('link[rel*="icon"]');
|
||||
(newIcon = icon.cloneNode(true)).setAttribute('href', dataURI);
|
||||
icon.parentNode.replaceChild(newIcon, icon);
|
||||
link = newIcon;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
function draw() {
|
||||
ctx.clearRect(0, 0, settings.size, settings.size);
|
||||
if (typeof settings.frame === 'function') {
|
||||
settings.frame(ctx);
|
||||
} else {
|
||||
var position = progress % duration / duration;
|
||||
ctx.beginPath();
|
||||
var center = Math.round(settings.size / 2);
|
||||
ctx.arc(center, center, settings.radius, arcStart(position), arcEnd(position));
|
||||
ctx.stroke();
|
||||
}
|
||||
update(ctx.canvas.toDataURL());
|
||||
progress += duration / 100;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
return {
|
||||
init: init,
|
||||
start: animate,
|
||||
stop: restore,
|
||||
version: '0.4.4'
|
||||
};
|
||||
});
|
||||
Reference in new issue
Block a user