Add button for Smooth Scroll to the top / bottom

为页面添加按钮,平滑的滚动到顶部/底部

  1. // ==UserScript==
  2. // @name Add button for Smooth Scroll to the top / bottom
  3. // @author burningall
  4. // @description 为页面添加按钮,平滑的滚动到顶部/底部
  5. // @version 2015.7.14
  6. // @include *
  7. // @grant GM_addStyle
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @grant GM_listValues
  11. // @grant GM_deleteValue
  12. // @run-at document-start
  13. // @compatible chrome 完美支持
  14. // @compatible firefox 完美支持
  15. // @license The MIT License (MIT); http://opensource.org/licenses/MIT
  16. // @supportURL http://www.burningall.com
  17. // @contributionURL troy450409405@gmail.com|alipay.com
  18. // @namespace https://greasyfork.org/zh-CN/users/3400-axetroy
  19. // ==/UserScript==
  20.  
  21.  
  22. //========快捷键列表=======
  23. //【Ctrl+F2】>>>>>调出控制面板
  24. //【Ctrl+Alt】>>>>呼出按钮
  25. //【alt+1】>>>>>>>向上滚动
  26. //【alt+2】>>>>>>>向下滚动
  27. //【Esc】>>>>>>>>>退出控制面板
  28.  
  29. function checkList() {
  30. if (GM_getValue(window.top.location.host, '不在黑名单中') == window.top.location.host) { //如果该页面在黑名单中,则不执行
  31. return true;
  32. };
  33. };
  34. //================公共函数区============
  35.  
  36. function addEvent(obj, event, fn) {
  37. return obj.addEventListener ? obj.addEventListener(event, fn, false) : obj.attachEventListener("on" + event, fn);
  38. };
  39.  
  40. function getSize(obj) {
  41. return document.documentElement[obj] != 0 ? document.documentElement[obj] : document.body[obj];
  42. }
  43.  
  44. function hasScroll() {
  45. return getSize('scrollHeight') > getSize('clientHeight') ? true : false;
  46. };
  47.  
  48. function getStyle(obj, attr) {
  49. return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr];
  50. }
  51.  
  52. function $(id) {
  53. return document.getElementById(id);
  54. }
  55.  
  56. function doMove(obj, attr, dir, target, endFn) {
  57. dir = parseInt(getStyle(obj, attr)) < target ? dir : -dir;
  58. clearInterval(obj.timer);
  59. obj.timer = setInterval(function() {
  60. var speed = parseInt(getStyle(obj, attr)) + dir;
  61. if (speed > target && dir > 0 || speed < target && dir < 0) {
  62. speed = target;
  63. };
  64. obj.style[attr] = speed + "px";
  65. if (speed == target) {
  66. clearInterval(obj.timer);
  67. endFn && endFn();
  68. };
  69. },
  70. 30);
  71. };
  72. //================样式区============
  73. var cssText = '\
  74. #scrollMars-troy{\
  75. position:fixed !important;\
  76. right:30px;\
  77. z-index:9999999 !important;\
  78. }\
  79. \
  80. .sroll-btn-troy{\
  81. width:50px !important;\
  82. height:50px !important;\
  83. text-align:center !important;\
  84. background:#303030 !important;\
  85. color:#fff !important;\
  86. display:block !important;\
  87. opacity:0.8 !important;\
  88. fitter:alpha(opacity:80) !important;\
  89. cursor:pointer !important;\
  90. border-radius:50% !important;\
  91. box-shadow:2px 2px 40px 2px #303030 !important;\
  92. line-height:50px !important;\
  93. font-size:35px !important;\
  94. font-style:inherit !important;\
  95. font-weight:bold !important;\
  96. font-family:"宋体" !important;\
  97. }\
  98. #scrollMars-troy>div>div:hover{\
  99. background:#FF0000 !important;\
  100. }\
  101. #mars-point{\
  102. width:100px !important;\
  103. height:100px !important;\
  104. position:absolute !important;\
  105. top:0 !important;\
  106. left:-40px !important;\
  107. }\
  108. #setting-troy{\
  109. width: 300px !important;\
  110. height: auto !important;\
  111. border: 2px solid #303030 !important;\
  112. position: fixed !important;\
  113. top: 200px !important;\
  114. left: 33% !important;\
  115. color: #fff !important;\
  116. background: #303030 !important;\
  117. z-index:9999999999 !important;\
  118. }\
  119. #setting-troy>div{\
  120. margin: 20px !important;\
  121. }\
  122. #setting-troy>div input{\
  123. color:#fff !important;\
  124. background:#303030 !important;\
  125. padding:5px !important;\
  126. margin:5px !important;\
  127. }\
  128. #percent{\
  129. position:absolute !important;\
  130. top:42px !important;\
  131. left:-20px;\
  132. color:#147474 !important;\
  133. font-family:"微软雅黑" !important;\
  134. font-size:16px !important;\
  135. line-height:16px !important;\
  136. }\
  137. '
  138. GM_addStyle(cssText);
  139. //================主要代码区============
  140. GM_getValue("turn") ? GM_setValue("turn", true) : GM_setValue("turn", GM_getValue("turn"));
  141.  
  142. function readmode(speed, inteval, endFn) {
  143. if (!$('percent') || GM_getValue("turn") == false || createBtn() == false) {
  144. return;
  145. }
  146. clearInterval(document.readMode);
  147. document.readMode = setInterval(function() {
  148. var position = getSize('scrollTop') + speed;
  149. document.body.scrollTop = document.documentElement.scrollTop = position;
  150. clearTimeout(document.showPercent);
  151. var precent = parseInt(getSize('scrollTop') / (getSize('scrollHeight') - getSize('clientHeight')) * 100);
  152. $('percent').style.display = "block";
  153. $('percent').innerHTML = precent + '%';
  154. if (position + getSize('clientHeight') >= getSize('scrollHeight')) { //如果滚到底部
  155. clearInterval(document.readMode);
  156. $('percent').style.display = "none";
  157. }
  158. }, inteval)
  159. GM_setValue("turn", true);
  160. }
  161.  
  162. function moveMars(obj, index) {
  163. if (index == 'mouseout') {
  164. clearTimeout(obj.timerHover);
  165. obj.timerHover = setTimeout(function() {
  166. doMove(obj, "right", 5, -30);
  167. },
  168. 3000); //鼠标离开后,3s隐藏到边栏
  169. } else if (index == 'mouseover') {
  170. clearTimeout(obj.timerHover);
  171. doMove(obj, "right", 5, 30);
  172. }
  173. }
  174.  
  175. function scroll(obj, dir) { //obj随意,dir>0往上滚,dir<0往下滚
  176. clearInterval(obj.timerScroll);
  177. clearInterval(document.readMode);
  178. obj.timerScroll = setInterval(function() {
  179. var position;
  180. if (dir > 0) { //往上滚动
  181. var speed = (getSize('scrollTop') / 10) + 10;
  182. position = getSize('scrollTop') - speed;
  183. if (position <= 0) { //如果滚到顶部
  184. document.body.scrollTop = document.documentElement.scrollTop = 0;
  185. clearInterval(obj.timerScroll);
  186. }
  187. } else { //往下滚动
  188. var speed = ((getSize('scrollHeight') - getSize('scrollTop')) / 20) + 10;
  189. position = getSize('scrollTop') + speed;
  190. if (position + getSize('clientHeight') >= getSize('scrollHeight')) { //如果滚到底部
  191. document.body.scrollTop = document.documentElement.scrollTop = getSize('scrollHeight');
  192. clearInterval(obj.timerScroll);
  193. }
  194. }
  195. document.body.scrollTop = document.documentElement.scrollTop = position;
  196. }, 20)
  197. }
  198.  
  199. function createBtn() {
  200. if (checkList() == true) {
  201. return false;
  202. }
  203. var jugg = $("scrollMars-troy");
  204. if (jugg && hasScroll() == true) { //如果有滚动条,并且存在滚动按钮
  205. $('scrollMars-troy').style.top = (getSize('clientHeight') / 3) + 'px'; //调整按钮位置
  206. } else if (jugg && hasScroll() == false) { //如果没有滚动条,但是有按钮
  207. jugg.remove(jugg); //删除按钮
  208. };
  209. if (hasScroll() == false && !jugg) { //如果没有滚动条,并且没有按钮
  210. return false;
  211. } else if (hasScroll() == true && !jugg) { //如果有滚动条,并且没有按钮
  212. var mars = document.createElement('div');
  213. mars.id = "scrollMars-troy";
  214. window.top.document.documentElement.appendChild(mars);
  215. mars.innerHTML = "\
  216. <div id='percent'></div>\
  217. <div id='mars-point'></div>\
  218. <div>\
  219. <div id='goTop-troy' title='返回顶部' class='sroll-btn-troy'></div>\
  220. <div id='goBtn-troy' title='去到底部' class='sroll-btn-troy'></div>\
  221. </div>\
  222. ";
  223. $('scrollMars-troy').style.top = (getSize('clientHeight') / 3) + 'px';
  224. $("goTop-troy").innerHTML = "↑";
  225. $("goBtn-troy").innerHTML = "↓";
  226. addEvent($("goTop-troy"), "click", function() {
  227. scroll(mars, 1)
  228. });
  229. addEvent($("goBtn-troy"), "click", function() {
  230. scroll(mars, -1)
  231. });
  232. addEvent($("mars-point"), "mouseover", function(e) {
  233. moveMars(mars, "mouseover");
  234. });
  235. addEvent($("mars-point"), "mouseout", function(e) {
  236. moveMars(mars, "mouseout");
  237. });
  238. addEvent(mars, "mouseover", function() {
  239. moveMars(mars, "mouseover")
  240. });
  241. addEvent(window, "resize", function() {
  242. $('scrollMars-troy').style.top = (getSize('clientHeight') / 3) + 'px';
  243. });
  244. moveMars(mars, "mouseout"); //页面加载完成,默认3s后隐藏到边栏
  245. return true;
  246. };
  247. };
  248. //================执行区============
  249. addEvent(window, 'mousewheel', function() { //滚动则停止,兼容chrome/ie/opera
  250. createBtn() && clearInterval($('scrollMars-troy').timerScroll);
  251. })
  252.  
  253. addEvent(window, 'DOMMouseScroll', function() { //滚动则停止,兼容firefox
  254. createBtn() && clearInterval($('scrollMars-troy').timerScroll);
  255. })
  256.  
  257. addEvent(document, 'dblclick', function(event) { //双击进入阅读模式
  258. var type = /input|form|textarea|img|a|li|object|video|audio/ig;
  259. event = event || window.event;
  260. var macType = type.test(event.target.nodeName);
  261. if (macType) {
  262. return;
  263. };
  264. readmode(1, 20);
  265. })
  266.  
  267. addEvent(document, 'click', function() { //单击退出阅读模式
  268. if ($('percent')) {
  269. clearInterval(document.readMode);
  270. $('percent').style.display = "none";
  271. }
  272. })
  273.  
  274. addEvent(window.top, "resize", function() { //页面大小改变,初始化按钮
  275. createBtn();
  276. });
  277. addEvent(document, 'DOMContentLoaded', function() {
  278. createBtn();
  279. })
  280. //================快捷键区============
  281. addEvent(window, 'keydown', function(event) {
  282. event = event || window.event;
  283. if (event.altKey && event.keyCode == 49) { //alt+1,向上滚动
  284. scroll($('scrollMars-troy'), 1)
  285. } else if (event.altKey && event.keyCode == 50) { //alt+2,向下滚动
  286. scroll($('scrollMars-troy'), -1)
  287. } else if (event.ctrlKey && event.altKey) { //ctrl+alt,调出按钮
  288. moveMars($('scrollMars-troy'), "mouseover");
  289. setTimeout(function() {
  290. moveMars($('scrollMars-troy'), "mouseout");
  291. }, 3000);
  292. } else if (event.keyCode == 27) { //Esc退出控制面板
  293. var setting = $('setting-troy');
  294. setting  &&  setting.remove(setting);
  295. } else if (event.ctrlKey && event.keyCode == 113) { //ctrl+F2,调处控制面板
  296. $('setting-troy') &&  setting.remove(setting);
  297. var setting = document.createElement('div');
  298. setting.id = 'setting-troy';
  299. var inner = "\
  300. <div id='setting-pan-troy'>\
  301. <div>\
  302. 控制面板:Ctrl+F2<br />\
  303. 添加黑名单域名:<input type='text' id='blackList' placeholder='www.baidu.com' /><br />\
  304. <input type='button' value='添加黑名单' id='saveSetting' />\
  305. <input type='button' id='quiet' value='退出面板(Esc)' /><br/><hr />\
  306. <input type='button' id='clear' value='移除黑名单'>\
  307. <input type='button' id='showlist' value='显示黑名单'>\
  308. <input type='button' id='clearall' value='清空黑名单'>\
  309. <input type='button' id='readmodebtn' value='双击滚动开关'>\
  310. </div>\
  311. </div>\
  312. "
  313. window.top.document.documentElement.appendChild(setting);
  314. setting.innerHTML = inner;
  315. //var domian=/^[0-9-a-z]{0,}\.{0,1}[0-9-a-z]+\.{0,1}[a-z]{0,}\.{1}[a-z]+$/ig;//用于验证域名是否符合规范
  316. var domian = /^[0-9a-zA-Z]+[0-9a-zA-Z\.-]*\.[a-zA-Z]{2,4}$/;
  317. var host = window.top.location.host;
  318. $('blackList').value = host;
  319. //GM_setValue("turn",true);//第一次安装脚本,默认开启双击滚动
  320. addEvent($('quiet'), 'click', function() { //退出
  321. setting.remove(setting);
  322. });
  323. addEvent($('clear'), 'click', function() { //移出黑名单
  324. alert(GM_getValue($('blackList').value, '未获取') + ":移除成功");
  325. GM_deleteValue($('blackList').value);
  326. });
  327. addEvent($('clearall'), 'click', function() { //清空黑名单
  328. for (var i = 0; i < GM_listValues().length; i++) {
  329. if (domian.test(GM_listValues()[i]) == true) {
  330. console.log('黑名单:' + GM_listValues()[i] + '被删除');
  331. GM_deleteValue(GM_listValues()[i]);
  332. }
  333. }; //for
  334. alert('清空完毕,\nBug:可能需要多点几次,才能清空');
  335. })
  336. addEvent($('showlist'), 'click', function() { //显示黑名单
  337. if (GM_listValues().length <= 1) {
  338. alert('空的黑名单');
  339. return;
  340. } else {
  341. for (var i = 0; i < GM_listValues().length; i++) {
  342. if (domian.test(GM_listValues()[i]) == true) {
  343. var list = document.createElement('li');
  344. list.innerHTML = GM_listValues()[i];
  345. document.querySelector('#setting-pan-troy>div').appendChild(list);
  346. }
  347. } //for
  348. }
  349. });
  350. addEvent($('readmodebtn'), 'click', function() { //禁用双击滚动
  351. console.log("当前状态:" + GM_getValue("turn"), "空的变量");
  352. if (GM_getValue("turn") == true) {
  353. GM_setValue("turn", false);
  354. alert('开关状态:' + GM_getValue("turn") + ',禁用成功');
  355. return;
  356. } else if (GM_getValue("turn") == false) {
  357. GM_setValue("turn", true);
  358. alert('开关状态:' + GM_getValue("turn") + ',开启成功');
  359. return;
  360. }
  361. })
  362. addEvent($('saveSetting'), 'click', function() { //保存
  363. if (domian.test($('blackList').value) == false) { //检查输入的域名是否符合规范
  364. alert($('blackList').value + '域名格式不正确' + '\n比如:tieba.baidu.com或www.baidu.com')
  365. return;
  366. } else if ($('blackList').value != '') { //如果有填入黑名单列表
  367. if (GM_getValue($('blackList').value, '不存在这个黑名单') != $('blackList').value) { //不在黑名单中
  368. GM_setValue($('blackList').value, $('blackList').value);
  369. alert('禁用:' + $('blackList').value + '成功');
  370. } else {
  371. alert('该域名已在黑名单中');
  372. }
  373. } else { //没有填入黑名单
  374. alert('请输入域名');
  375. return;
  376. }
  377. })
  378. }
  379. }) //监听keydown,快捷键