Add button for Smooth Scroll to the top / bottom

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

As of 2015-06-09. See the latest version.

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