Greasy Fork is available in English.

DONE - Visual Sign Of A Loaded Page

Shows a big DONE sign when the page is fully loaded

  1. // ==UserScript==
  2. // @name DONE - Visual Sign Of A Loaded Page
  3. // @namespace http://userscripts.org/users/23652
  4. // @description Shows a big DONE sign when the page is fully loaded
  5. // @include http://*.*/*
  6. // @include https://*.*/*
  7. // @copyright JoeSimmons
  8. // @version 1.0.3
  9. // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. +function () {
  14. 'use strict';
  15.  
  16. // temporary fade function until I implement one in JSL
  17. function fade(dir, element) {
  18. var interval = 0.05,
  19. fps = Math.floor(1000 / 60),
  20. count, intv;
  21.  
  22. function anim() {
  23. var curOpacity = parseFloat(element.style.opacity);
  24.  
  25. if (dir === 'in') {
  26. if (curOpacity >= 1) {
  27. count = 1;
  28. element.style.opacity = '1';
  29. window.clearInterval(intv);
  30. } else {
  31. element.style.opacity = (count += interval);
  32. }
  33. } else if (dir === 'out') {
  34. if (curOpacity <= 0) {
  35. count = 0;
  36. element.style.opacity = '0';
  37. element.style.display = 'none';
  38. window.clearInterval(intv);
  39. } else {
  40. element.style.opacity = (count -= interval);
  41. }
  42. }
  43. }
  44.  
  45. if (typeof element === 'string') {
  46. element = document.getElementById(element);
  47. }
  48.  
  49. if (dir === 'in') {
  50. element.style.opacity = '0';
  51. count = 0;
  52.  
  53. if (element.style.display === 'none') {
  54. element.style.display = '';
  55. }
  56. } else if (dir === 'out') {
  57. element.style.opacity = '1';
  58. count = 1;
  59. } else {
  60. return;
  61. }
  62.  
  63. intv = window.setInterval(anim, fps);
  64. }
  65.  
  66. // runAfterPageIdle by JoeSimmons
  67. // supply it a function and it will run when the page stops mutating
  68. function runAfterPageIdle(fn) {
  69. var time = Date.now(),
  70. set = window.setInterval.bind(window),
  71. clear = window.clearInterval.bind(window),
  72. idleTime = 499, // adjustable -- the user's function runs after this idle length; in ms
  73. freezeCalled = false,
  74. listenIntv;
  75.  
  76. function listen(a) {
  77. var now = Date.now(); // why call Date.now() twice? :)
  78.  
  79. if (typeof a === 'undefined' && (now - time) > idleTime) {
  80. // clear if it's been idle for the set length of time
  81. checkFreezing();
  82. } else if (typeof a === 'object') {
  83. // reset if it hasn't been idle for the set length of time
  84. time = now;
  85. }
  86. }
  87.  
  88. function checkFreezing() {
  89. var firstTime = Date.now(),
  90. lastTime = firstTime,
  91. endOnShortInterval = false,
  92. freezingIntv;
  93.  
  94. // this script has the possibility of checking for freezing twice,
  95. // but we only want it to run once, regardless of which function calls it first
  96. if (freezeCalled === true) { return; }
  97. freezeCalled = true;
  98.  
  99. function monitor() {
  100. var now = Date.now(),
  101. diff = now - lastTime;
  102.  
  103. if (diff < 41 && endOnShortInterval === true || (now - firstTime) > 499) {
  104. clear(freezingIntv);
  105. done();
  106. } else if (diff > 299) {
  107. endOnShortInterval = true;
  108. }
  109. }
  110.  
  111. freezingIntv = set(monitor, 20);
  112. }
  113.  
  114. function done() {
  115. // clear the interval
  116. clear(listenIntv);
  117.  
  118. // remove listeners
  119. document.removeEventListener('DOMSubtreeModified', listen, false);
  120. document.removeEventListener('DOMNodeInserted', listen, false);
  121. document.removeEventListener('DOMNodeRemoved', listen, false);
  122.  
  123. // run user at next event loop slot
  124. window.setTimeout(fn, 0);
  125. }
  126.  
  127. if (typeof JSL !== 'undefined' && typeof JSL.setInterval === 'function' && typeof JSL.clearInterval === 'function') {
  128. set = JSL.setInterval.bind(JSL);
  129. clear = JSL.clearInterval.bind(JSL);
  130. }
  131.  
  132. if (typeof fn === 'function') {
  133. listenIntv = set(listen, 125); // check 8 times per second
  134.  
  135. // set listeners
  136. document.addEventListener('DOMSubtreeModified', listen, false);
  137. document.addEventListener('DOMNodeInserted', listen, false);
  138. document.addEventListener('DOMNodeRemoved', listen, false);
  139.  
  140. window.addEventListener('load', function () {
  141. window.setTimeout(checkFreezing, 0);
  142. }, false);
  143. }
  144. }
  145.  
  146. function main() {
  147. var box = document.createElement('div'),
  148. boxWidth = Math.floor(window.innerWidth * 0.95),
  149. oldTitle;
  150.  
  151. GM_addStyle('' +
  152. '#load_sign { ' +
  153. 'background: #D7FFD7; ' +
  154. 'border: 3px ridge #008000; ' +
  155. 'color: #00C400; ' +
  156. 'display: block; ' +
  157. 'font-style: Arial; ' +
  158. 'font-size: 24pt; ' +
  159. 'height: 42px; ' +
  160. 'left: ' + (window.innerWidth / 2 - boxWidth / 2) + 'px; ' + // division comes first here so it works
  161. 'margin: 0 auto; ' +
  162. 'min-height: 42px; ' +
  163. 'padding: 4px 0; ' +
  164. 'position: fixed; ' +
  165. 'text-align: center; ' +
  166. 'text-shadow: 2px 2px 4px #C7C7C7; ' +
  167. 'top: 0; ' +
  168. 'width: ' + boxWidth + 'px; ' +
  169. 'z-index: 2100100100; ' +
  170. '}' +
  171. '');
  172.  
  173. box.id = 'load_sign';
  174. box.appendChild( document.createTextNode('DONE') );
  175. document.body.appendChild(box);
  176.  
  177. // add done to the title
  178. oldTitle = document.title;
  179. document.title = '[DONE] ' + oldTitle;
  180.  
  181. window.setTimeout(function () {
  182. fade('out', 'load_sign');
  183. document.title = oldTitle;
  184. }, 750);
  185. }
  186.  
  187. // make sure the page is not in a frame
  188. if (window.frameElement || window !== window.top) { return; }
  189.  
  190. runAfterPageIdle(main);
  191. }();