Habr Percentage Ring

Percentage Rings around numbers which show grades (for with userstyles)

当前为 2014-12-16 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @id HabrPercentageRing
  3. // @name Habr Percentage Ring
  4. // @version 11.2014.11.11
  5. // @namespace github.com/spmbt
  6. // @author spmbt0
  7. // @contributor KOLANICH
  8. // @description Percentage Rings around numbers which show grades (for with userstyles)
  9. // @icon http://habrahabr.ru/favicon.ico
  10. // @update 0.81 bug + подгонка эллипсов
  11. // @include /^https?://(m\.|webcache\.googleusercontent\.com\/search\?q=cache(:|%3A|%3a)(http(:|%3A|%3a)(\/|%2F|%2f)(\/|%2F|%2f))?)?(habrahabr|geektimes).ru(?!\/special|\/api)/
  12. // @include http://habrahabr.ru*
  13. // @exclude http://habrahabr.ru/api*
  14. // @radius 14
  15. // @magic_offsets [46, 99, 26, 56, 14, 18, 9, 12, 17, 43, 11, 4]
  16. // @delay 2999
  17. // @pos_vote_color #1b1
  18. // @neg_vote_color #a24
  19. // ==/UserScript==
  20. // работает автономно или как модуль для HabrAjax
  21. "use strict";
  22. const mo=new Int8Array(JSON.parse(GM_getMetadata("magic_offsets")[0]));
  23. const r2=GM_getMetadata("radius")[0];
  24. const baseOpacity=0.25;
  25. const pvc=GM_getMetadata("pos_vote_color")[0];
  26. const nvc=GM_getMetadata("neg_vote_color")[0];
  27.  
  28. function writePercRound(aP, aM) {
  29. var aPM = Number(aP) + Number(aM);
  30. if (aPM == 0)
  31. return document.createElement('div');
  32. var c = document.createElement('canvas'), ell = 1 - 1 / 3.6;
  33. c.width = c.height = r2 * 2;
  34. c.style.backgroundColor = 'transparent';
  35. c.style.position = 'absolute';
  36. c.style.left = (-r2 + mo[7]) + 'px';
  37. c.style.top = (-r2 + 1 + 8) + 'px';
  38. var q = c.getContext("2d"),
  39. log = Math.log(aPM) / 1.6 + 1;
  40. c.style.opacity = baseOpacity + log * 0.1;
  41. c.style.zIndex = 1;
  42. q.lineWidth = log;
  43. q.strokeStyle = pvc;
  44. var perc = (0.5 - aM / aPM) * Math.PI, perc2 = (0.5 + aM / aPM) * Math.PI;
  45. q.beginPath();
  46. q.scale(1, ell);
  47. q.arc(r2, r2 / ell, r2 - 1, perc, perc2 + 2 * (perc == perc2 && aP != 0) * Math.PI, aP == 0 || aM != 0);
  48. q.stroke();
  49. q.beginPath();
  50. q.strokeStyle = nvc;
  51. q.arc(r2, r2 / ell, r2 - 1, perc, perc2 + 2 * (perc == perc2 && aM != 0) * Math.PI, !1);
  52. q.stroke();
  53. return c;
  54. }
  55.  
  56. function setUpdateHandlers (oP,oPM, oPP) {
  57. var ff = function () {
  58. setTimeout(function () {
  59. habrPercentageRing(oP)
  60. }, GM_getMetadata("delay")[0])
  61. };
  62. oPM && oPM.addEventListener('click', ff, !1);
  63. oPP && oPP.addEventListener('click', ff, !1);
  64. };
  65. function getPositionCenter(obj) { //
  66. var x = 0,
  67. y = 0,
  68. w2 = Math.floor(obj.offsetWidth / 2),
  69. h2 = Math.floor(obj.offsetHeight / 2);
  70. while (obj) {
  71. x += obj.offsetLeft;
  72. y += obj.offsetTop;
  73. obj = obj.offsetParent;
  74. }
  75. return {x : x, y : y, w2 : w2, h2 : h2};
  76. };
  77.  
  78.  
  79. function habrPercentageRing(blck) {
  80. var marks = blck && blck.childNodes && blck.querySelectorAll('.mark'),
  81. isC2 = blck && / c2/.test(blck.className),
  82. isQa = /\/qa\//.test(location.href);
  83. function $q(q, f) {
  84. return (f || document).querySelector(q)
  85. };
  86. if (!marks)
  87. return;
  88. for (var i in marks) {
  89. var o = marks[i],
  90. oP = o.parentNode;
  91. if (!o || !o.attributes)
  92. continue;
  93. o.style.position = 'relative';
  94. if (/\/users\//.test(location.href)) {
  95. oP.style.marginRight = mo[4]+'px';
  96. oP.style.marginTop = '2px';
  97. }
  98. var oXS = $q('span', o);
  99. if (oXS && oXS.getAttribute('title')) {
  100. let oXSt = oXS.getAttribute('title').match(/[\d\.]+/g),
  101. oC = $q('canvas', o);
  102. if (oC)
  103. oC.parentNode.removeChild(oC);
  104. if (oXSt && oXSt.length && !$q('canvas', o)) {
  105. var aP = oXSt[1], aM = oXSt[2];
  106. let c = writePercRound(aP, aM);
  107. //getPositionCenter(o);
  108. var oPM = $q('.minus', oP), oPP = $q('.plus', oP), oPPI = /infopanel/.test(oP.parentNode.className);
  109. if (oPM && (-aP - aM))
  110. oPM.style.left = (oPPI ? mo[0] : mo[2] + 6 * (Math.abs(aP - aM) > mo[6])) + 'px';
  111. oXS.style.left = '-1px';
  112. if (oPPI) { //new layout
  113. c.style.left = (Math.abs(aP - aM) > mo[1] ? -r2 + mo[8] : (aP == aM ? -r2 + 3 : -r2 + mo[10] - mo[11] * (Math.abs(aP - aM) <= mo[6]))) + 'px';
  114. c.style.top = '-5px';
  115. } else if (oP.parentNode.parentNode.className == 'entry-info vote_holder') { //old layout
  116. c.style.left = (Math.abs(aP - aM) > mo[1] ? -r2 + mo[3] : (aP == aM ? -r2 + mo[9] : -r2 + mo[0] + mo[11] * (Math.abs(aP - aM) > mo[6]))) + 'px';
  117. c.style.top = isC2 ? '-6px' : '-4px';
  118. } else { //comments
  119. c.style.left = (Math.abs(aP - aM) > mo[1] ? -r2 + mo[5] : (aP == aM ? -r2 + 8 : -r2 + mo[6] + mo[11] * (Math.abs(aP - aM) > mo[6]))) - (isC2 && !isQa ? 3 : 0) + 'px';
  120. oXS.style.top = 0;
  121. oXS.style.left = (aP == aM ? 7 : -1) + 'px';
  122. c.style.top = isC2 ? '-8px' : '-6px';
  123. }
  124. oXS.style.position = 'relative';
  125. o.insertBefore(c, oXS);
  126. if (oPPI && Math.abs(aP - aM) > mo[1])
  127. o.style.left = (-mo[6])+'px';
  128. oXS.style.zIndex = 2;
  129. setUpdateHandlers(oP,oPM, oPP);
  130. }
  131. }
  132. }
  133. };
  134. habrPercentageRing(document);
  135.  
  136. window.addEventListener('chgDom', function (ev) { //проверить блок по событию от модулей (Fx6+, Chrome,Safari)
  137. habrPercentageRing(ev.detail);
  138. }, !1);