Tinycon

A small library for manipulating the Favicon

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/36273/236489/Tinycon.js

  1. /*!
  2. * Tinycon - A small library for manipulating the Favicon
  3. * Tom Moor, http://tommoor.com
  4. * Copyright (c) 2015 Tom Moor
  5. * @license MIT Licensed
  6. + @special modifed for lorify-ng extension by OpenA
  7. */
  8.  
  9. (function(){
  10.  
  11. var Tinycon = {};
  12. var currentFavicon = null;
  13. var originalFavicon = null;
  14. var faviconImage = null;
  15. var canvas = null;
  16. var options = {};
  17. // Chrome browsers with nonstandard zoom report fractional devicePixelRatio.
  18. var r = Math.ceil(window.devicePixelRatio) || 1;
  19. var size = 16 * r;
  20. var options = {
  21. width: 7,
  22. height: 9,
  23. font: 10 * r + 'px arial',
  24. color: '#ffffff',
  25. background: '#F03D25',
  26. fallback: true,
  27. crossOrigin: true,
  28. abbreviate: true
  29. };
  30.  
  31. var ua = (function () {
  32. var agent = navigator.userAgent.toLowerCase();
  33. // New function has access to 'agent' via closure
  34. return function (browser) {
  35. return agent.indexOf(browser) !== -1;
  36. };
  37. }());
  38.  
  39. var browser = {
  40. ie: ua('trident'),
  41. chrome: ua('chrome'),
  42. webkit: ua('chrome') || ua('safari'),
  43. safari: ua('safari') && !ua('chrome'),
  44. mozilla: ua('mozilla') && !ua('chrome') && !ua('safari')
  45. };
  46.  
  47. // private methods
  48. var getFaviconTag = function(){
  49.  
  50. var links = document.getElementsByTagName('link');
  51.  
  52. for(var i=0, len=links.length; i < len; i++) {
  53. if ((links[i].getAttribute('rel') || '').match(/\bicon\b/i)) {
  54. return links[i];
  55. }
  56. }
  57.  
  58. return false;
  59. };
  60.  
  61. var removeFaviconTag = function(){
  62.  
  63. var links = document.getElementsByTagName('link');
  64.  
  65. for(var i=0, len=links.length; i < len; i++) {
  66. var exists = (typeof(links[i]) !== 'undefined');
  67. if (exists && (links[i].getAttribute('rel') || '').match(/\bicon\b/i)) {
  68. links[i].parentNode.removeChild(links[i]);
  69. }
  70. }
  71. };
  72.  
  73. var getCurrentFavicon = function(){
  74.  
  75. if (!originalFavicon || !currentFavicon) {
  76. var tag = getFaviconTag();
  77. currentFavicon = tag ? tag.getAttribute('href') : '/favicon.ico';
  78. if (!originalFavicon) {
  79. originalFavicon = currentFavicon;
  80. }
  81. }
  82.  
  83. return currentFavicon;
  84. };
  85.  
  86. var getCanvas = function (){
  87.  
  88. if (!canvas) {
  89. canvas = document.createElement("canvas");
  90. canvas.width = size;
  91. canvas.height = size;
  92. }
  93.  
  94. return canvas;
  95. };
  96.  
  97. var setFaviconTag = function(url){
  98. if(url){
  99. removeFaviconTag();
  100.  
  101. var link = document.createElement('link');
  102. link.type = 'image/x-icon';
  103. link.rel = 'icon';
  104. link.href = url;
  105. document.getElementsByTagName('head')[0].appendChild(link);
  106. }
  107. };
  108.  
  109. var log = function(message){
  110. if (window.console) window.console.log(message);
  111. };
  112.  
  113. var drawFavicon = function(label, color) {
  114.  
  115. // fallback to updating the browser title if unsupported
  116. if (!getCanvas().getContext || browser.ie || browser.safari || options.fallback === 'force') {
  117. return updateTitle(label);
  118. }
  119.  
  120. var context = getCanvas().getContext("2d");
  121. var color = color || '#000000';
  122. var src = getCurrentFavicon();
  123.  
  124. faviconImage = document.createElement('img');
  125. faviconImage.onload = function() {
  126.  
  127. // clear canvas
  128. context.clearRect(0, 0, size, size);
  129.  
  130. // draw the favicon
  131. context.drawImage(faviconImage, 0, 0, faviconImage.width, faviconImage.height, 0, 0, size, size);
  132.  
  133. // draw bubble over the top
  134. if ((label + '').length > 0) drawBubble(context, label, color);
  135.  
  136. // refresh tag in page
  137. refreshFavicon();
  138. };
  139.  
  140. // allow cross origin resource requests if the image is not a data:uri
  141. // as detailed here: https://github.com/mrdoob/three.js/issues/1305
  142. if (!src.match(/^data/) && options.crossOrigin) {
  143. faviconImage.crossOrigin = 'anonymous';
  144. }
  145.  
  146. faviconImage.src = src;
  147. };
  148.  
  149. var updateTitle = function(label) {
  150.  
  151. if (options.fallback) {
  152. // Grab the current title that we can prefix with the label
  153. var originalTitle = document.title;
  154.  
  155. // Strip out the old label if there is one
  156. if (originalTitle[0] === '(') {
  157. originalTitle = originalTitle.slice(originalTitle.indexOf(' '));
  158. }
  159.  
  160. if ((label + '').length > 0) {
  161. document.title = '(' + label + ') ' + originalTitle;
  162. } else {
  163. document.title = originalTitle;
  164. }
  165. }
  166. };
  167.  
  168. var drawBubble = function(context, label, color) {
  169.  
  170. // automatic abbreviation for long (>2 digits) numbers
  171. if (typeof label == 'number' && label > 99 && options.abbreviate) {
  172. label = abbreviateNumber(label);
  173. }
  174.  
  175. var radius = canvas.width / 100 * 38,
  176. centerX = canvas.width - radius,
  177. centerY = radius,
  178. fontPix = radius * 1.5;
  179. // webkit seems to render fonts lighter than firefox
  180. context.font = 'bold '+ fontPix +'px arial';
  181. context.fillStyle = '#48de3d';
  182. context.strokeStyle = 'rgba(0,0,0,0.2)';
  183. // bubble
  184. context.beginPath();
  185. context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
  186. context.fill();
  187. context.stroke();
  188. // label
  189. context.fillStyle = '#fff';
  190. context.textAlign = "center";
  191. context.fillText(label, centerX, fontPix);
  192. };
  193.  
  194. var refreshFavicon = function(){
  195. // check support
  196. if (!getCanvas().getContext) return;
  197.  
  198. setFaviconTag(getCanvas().toDataURL());
  199. };
  200.  
  201. var abbreviateNumber = function(label) {
  202. var metricPrefixes = [
  203. ['G', 1000000000],
  204. ['M', 1000000],
  205. ['k', 1000]
  206. ];
  207.  
  208. for(var i = 0; i < metricPrefixes.length; ++i) {
  209. if (label >= metricPrefixes[i][1]) {
  210. label = round(label / metricPrefixes[i][1]) + metricPrefixes[i][0];
  211. break;
  212. }
  213. }
  214.  
  215. return label;
  216. };
  217.  
  218. var round = function (value, precision) {
  219. var number = new Number(value);
  220. return number.toFixed(precision);
  221. };
  222.  
  223. Tinycon.setImage = function(url){
  224. currentFavicon = url;
  225. refreshFavicon();
  226. return this;
  227. };
  228.  
  229. Tinycon.setBubble = function(label, color) {
  230. label = label || '';
  231. drawFavicon(label, color);
  232. return this;
  233. };
  234.  
  235. Tinycon.reset = function(){
  236. currentFavicon = originalFavicon;
  237. setFaviconTag(originalFavicon);
  238. };
  239.  
  240. if(typeof define === 'function' && define.amd) {
  241. define(Tinycon);
  242. } else if (typeof module !== 'undefined') {
  243. module.exports = Tinycon;
  244. } else {
  245. window.Tinycon = Tinycon;
  246. }
  247.  
  248. })();