Greasemonkey Mouse Gestures

Just a Mouse Gestures

À partir de 2017-02-27. Voir la dernière version.

  1. // ==UserScript==
  2. // @name Greasemonkey Mouse Gestures
  3. // @name:zh-CN 鼠标手势
  4. // @name:zh-TW 滑鼠手勢
  5. // @namespace hoothin
  6. // @version 0.63
  7. // @description Just a Mouse Gestures
  8. // @description:zh-CN 就是个鼠标手势
  9. // @description:zh-TW 就是個滑鼠手勢
  10. // @author hoothin
  11. // @include *
  12. // @grant GM_openInTab
  13. // @grant GM_setValue
  14. // @grant GM_getValue
  15. // @grant GM_registerMenuCommand
  16. // @grant unsafeWindow
  17. // @license MIT License
  18. // @compatible chrome
  19. // @compatible firefox
  20. // ==/UserScript==
  21.  
  22. var lastX,lastY,lastSign,afterGestures,gesturesWords,gesturesContent,gestures,signs;
  23. const defaultFun={
  24. close:"unsafeWindow.opener=null;unsafeWindow.open('', '_self', '');unsafeWindow.close();",
  25. openNew:"GM_openInTab('about:newtab', false)",
  26. scrollToTop:"unsafeWindow.scrollTo(0, 0)",
  27. scrollToBottom:"unsafeWindow.scrollTo(0, 1073741824)",
  28. back:"unsafeWindow.history.back()",
  29. forward:"unsafeWindow.history.forward()",
  30. reload:"unsafeWindow.location.reload()"
  31. };
  32. function initEventListener(start,move,end,tracer,clientX,clientY,startBool){
  33. var isMouse=start=="mousedown";
  34. var moveFun=function(e){
  35. tracer(eval(clientX),eval(clientY),isMouse);
  36. gesturesWords.innerHTML=signs;
  37. var gesturesWidth=signs.length*51+40;
  38. gesturesContent.style.width=gesturesWidth+"px";
  39. gesturesContent.style.marginLeft=-gesturesWidth/2+"px";
  40. };
  41. document.addEventListener(start, function(e) {
  42. if(!startBool || eval(startBool)){
  43. lastX=eval(clientX);
  44. lastY=eval(clientY);
  45. lastSign=signs="";
  46. document.addEventListener(move, moveFun, false);
  47. }
  48. }, false);
  49. document.addEventListener(end, function(e) {
  50. document.removeEventListener(move, moveFun, false);
  51. setTimeout(function(){if(gesturesContent.parentNode)gesturesContent.parentNode.removeChild(gesturesContent);},500);
  52. if(afterGestures)afterGestures();
  53. for(var g of gestures){
  54. var gSign=g.gesture;
  55. if(signs==gSign){
  56. if(!isMouse)document.body.appendChild(gesturesContent);
  57. var fun=defaultFun[g.fun];
  58. if(fun===undefined || !fun){
  59. eval(g.fun);
  60. }else eval(fun);
  61. e.stopPropagation();
  62. e.preventDefault();
  63. break;
  64. }
  65. }
  66. }, false);
  67. }
  68. (function() {
  69. 'use strict';
  70. var i18n;
  71. var lang = navigator.appName=="Netscape"?navigator.language:navigator.userLanguage;
  72. const minLength=256,tg=0.5;
  73. switch (lang){
  74. case "zh-CN":
  75. i18n={
  76. close:"关闭页面",
  77. openNew:"新建标签页",
  78. scrollToTop:"滚动至最上",
  79. scrollToBottom:"滚动至最下",
  80. back:"后退",
  81. forward:"前进",
  82. reload:"刷新",
  83. addListener:"点击监听鼠标手势",
  84. listening:"正在监听鼠标手势",
  85. bind:"绑定功能",
  86. custom:"自定义代码",
  87. ok:"确定",
  88. del:"删除",
  89. saved:"已设定的手势",
  90. alert1:"请先监听手势",
  91. alert2:"还没有绑定功能",
  92. alert3:"请输入自定义代码",
  93. configure:"鼠标手势设置"
  94. };
  95. break;
  96. default:
  97. i18n={
  98. close:"Close tab",
  99. openNew:"Open new tab",
  100. scrollToTop:"Scroll to top",
  101. scrollToBottom:"Scroll to bottom",
  102. back:"Back",
  103. forward:"Forward",
  104. reload:"Reload",
  105. addListener:"Click to add gesture listener",
  106. listening:"Listening",
  107. bind:"Bind function",
  108. custom:"Custom code",
  109. ok:"Ok",
  110. del:"Delete",
  111. saved:"Saved gestures",
  112. alert1:"Please add gesture first",
  113. alert2:"Nothing bind",
  114. alert3:"Input custom code please",
  115. configure:"Mouse Gestures - Configure"
  116. };
  117. break;
  118. }
  119. gestures=GM_getValue("gestures");
  120. if(!gestures){
  121. gestures=[{gesture:"↓→",fun:"close"},
  122. {gesture:"→↑",fun:"openNew"},
  123. {gesture:"←↑",fun:"scrollToTop"},
  124. {gesture:"←↓",fun:"scrollToBottom"},
  125. {gesture:"→↑←",fun:"back"},
  126. {gesture:"←↑→",fun:"forward"},
  127. {gesture:"↑↓",fun:"reload"},
  128. {gesture:"↓↑↓",fun:"var t=((unsafeWindow.getSelection&&unsafeWindow.getSelection())||(document.getSelection&&document.getSelection())||(document.selection&&document.selection.createRange&&document.selection.createRange().text));var e=(document.charset||document.characterSet);if(t!=''){GM_openInTab('http://translate.google.cn/?text='+t+'&hl=zh-CN&langpair=auto|zh-CN&tbb=1&ie='+e,false);}else{GM_openInTab('http://translate.google.cn/translate?u='+encodeURIComponent(location.href)+'&hl=zh-CN&langpair=auto|zh-CN&tbb=1&ie='+e,false);}"},
  129. {gesture:"↓↑↓←",fun:'var d=document,b=d.body;with(b.onselectstart=b.oncopy=b.onpaste=b.onkeydown=b.oncontextmenu=b.onmousemove=b.ondragstart=d.oncopy=d.onpaste=null,d.onselectstart=d.oncontextmenu=d.onmousedown=d.onkeydown=function(){return!0},d.wrappedJSObject||d)onmouseup=null,onmousedown=null,oncontextmenu=null;for(var a=d.getElementsByTagName("*"),i=a.length-1;i>=0;i--){var o=a[i];with(o.wrappedJSObject||o)onmouseup=null,onmousedown=null}var h=d.getElementsByTagName("head")[0];if(h){var s=d.createElement("style");s.innerHTML="html,*{-webkit-user-select:text!important;-moz-user-select:text!important;}",h.appendChild(s)}unsafeWindow.Event.prototype.preventDefault=function(){};'},
  130. {gesture:"↓↑↓↑",fun:"var d = document, e = d.getElementById('wappalyzer-container') ; if ( e !== null ) { d.body.removeChild(e); } var u = 'https://wappalyzer.com/bookmarklet/', t = new Date().getTime(), c = d.createElement('div'), p = d.createElement('div'), l = d.createElement('link'), s = d.createElement('script') ; c.setAttribute('id', 'wappalyzer-container'); l.setAttribute('rel', 'stylesheet'); l.setAttribute('href', u + 'css/wappalyzer.css'); d.head.appendChild(l); p.setAttribute('id', 'wappalyzer-pending'); p.setAttribute('style', 'background-image: url(' + u + 'images/pending.gif) !important'); c.appendChild(p); s.setAttribute('src', u + 'js/wappalyzer.js?' + t); s.onload = function() { s = d.createElement('script'); s.setAttribute('src', u + 'js/apps.js?' + t); s.onload = function() { s = d.createElement('script'); s.setAttribute('src', u + 'js/driver.js?' + t); c.appendChild(s); }; c.appendChild(s); }; c.appendChild(s); d.body.appendChild(c);"},
  131. {gesture:"↓↑↓→",fun:"GM_openInTab('http://just998.com/xiu/photo'+unsafeWindow.location.search,false)"}
  132. ];
  133. GM_setValue("gestures",gestures);
  134. }
  135. function tracer(curX,curY,showSign) {
  136. let distanceX=curX-lastX,distanceY=curY-lastY;
  137. let distance=distanceX*distanceX+distanceY*distanceY;
  138. if (distance>minLength) {
  139. lastX=curX;
  140. lastY=curY;
  141. let direction="";
  142. let slope=Math.abs(distanceY/distanceX);
  143. if(slope>tg){
  144. if(distanceY>0) {
  145. direction="↓";
  146. }else{
  147. direction="↑";
  148. }
  149. }else if(slope<=1/tg) {
  150. if(distanceX>0) {
  151. direction="→";
  152. }else{
  153. direction="←";
  154. }
  155. }
  156. if(lastSign!=direction) {
  157. signs+=direction;
  158. lastSign=direction;
  159. if(showSign)document.body.appendChild(gesturesContent);
  160. }
  161. }
  162. }
  163. gesturesContent=document.createElement("div");
  164. gesturesContent.id="gesturesContent";
  165. gesturesContent.style.cssText="width:300px;height:70px;position:fixed;left:50%;top:50%;margin-top:-25px;margin-left:-150px;z-index:999999999;background-color:#000;border:1px solid;border-radius:10px;opacity:0.65;filter:alpha(opacity=65);box-shadow:5px 5px 20px 0px #000;";
  166. gesturesContent.innerHTML='<div id="gesturesWords" style="position:absolute;left:20px;top:5px;font:bold 50px \'黑体\';color:#ffffff"></div>';
  167. gesturesWords=gesturesContent.querySelector("#gesturesWords");
  168. initEventListener("touchstart","touchmove","touchend",tracer,"e.changedTouches[0].clientX","e.changedTouches[0].clientY");
  169. initEventListener("mousedown","mousemove","contextmenu",tracer,"e.clientX","e.clientY","e.which === 3");
  170. if(location.href=="https://github.com/hoothin/UserScripts/tree/master/Mouse%20Gestures"){
  171. var entryContent=document.querySelector("article.entry-content"),mobile=false;
  172. if(!entryContent){
  173. mobile=true;
  174. entryContent=document.querySelector(".files-list");
  175. }
  176. var configBody=document.createElement("div");
  177. configBody.id="configBody";
  178. configBody.style.cssText="opacity:0.65;filter:alpha(opacity=65);box-shadow:5px 5px 20px 0px #000;height:160px";
  179. configBody.innerHTML='<div id="configContent" style="position:relative;left:20px;top:5px;"></div>';
  180. var configContent=configBody.querySelector("#configContent");
  181. var newOrEdit=document.createElement("div");
  182. configContent.appendChild(newOrEdit);
  183. var newOrEditSign=document.createElement("div");
  184. newOrEditSign.innerHTML="";
  185. newOrEditSign.style.float="left";
  186. newOrEdit.appendChild(newOrEditSign);
  187. var newOrEditBtn=document.createElement("input");
  188. newOrEditBtn.type="button";
  189. newOrEditBtn.value=i18n.addListener;
  190. newOrEdit.appendChild(newOrEditBtn);
  191. var functionArea=document.createElement("p");
  192. newOrEdit.appendChild(functionArea);
  193. var functionSelect=document.createElement("select");
  194. functionSelect.innerHTML="<option>"+i18n.bind+"</option><option value='custom'>"+i18n.custom+"</option>";
  195. for(var key in defaultFun){
  196. var optionStr="<option value='"+key+"'>"+i18n[key]+"</option>";
  197. functionSelect.innerHTML+=optionStr;
  198. }
  199. functionArea.appendChild(functionSelect);
  200. var newOrEditEval=document.createElement("input");
  201. newOrEditEval.style.width=(mobile?"230":"750")+"px";
  202. newOrEditEval.style.display="none";
  203. functionArea.appendChild(newOrEditEval);
  204. var newOrEditOkBtn=document.createElement("input");
  205. newOrEditOkBtn.type="button";
  206. newOrEditOkBtn.value=i18n.ok;
  207. newOrEdit.appendChild(newOrEditOkBtn);
  208. var gesturesHas=document.createElement("p");
  209. newOrEdit.appendChild(gesturesHas);
  210. var gesturesSelect=document.createElement("select");
  211. var refreshGestures=function(){
  212. gesturesSelect.innerHTML="<option>"+i18n.saved+"</option>";
  213. gestures.forEach(function(item){
  214. var optionStr="<option value='"+item.gesture+"'>"+item.gesture+"</option>";
  215. gesturesSelect.innerHTML+=optionStr;
  216. });
  217. };
  218. refreshGestures();
  219. gesturesHas.appendChild(gesturesSelect);
  220. var newOrEditDelBtn=document.createElement("input");
  221. newOrEditDelBtn.type="button";
  222. newOrEditDelBtn.value=i18n.del;
  223. gesturesHas.appendChild(newOrEditDelBtn);
  224. entryContent.insertBefore(configBody,entryContent.firstChild);
  225. functionSelect.onchange=function(){
  226. if(functionSelect.options.selectedIndex===0)return;
  227. var value=functionSelect.options[functionSelect.options.selectedIndex].value;
  228. newOrEditEval.style.display=(value=="custom"?"initial":"none");
  229. };
  230. gesturesSelect.onchange=function(){
  231. if(gesturesSelect.options.selectedIndex===0)return;
  232. var value=gesturesSelect.options[gesturesSelect.options.selectedIndex].value;
  233. newOrEditSign.innerHTML=value;
  234. gestures.every(function(item){
  235. if(item.gesture==value){
  236. functionSelect.options[1].selected = true;
  237. for (var i=2;i<functionSelect.options.length;i++) {
  238. if (functionSelect.options[i].value == item.fun) {
  239. functionSelect.options[i].selected = true;
  240. break;
  241. }
  242. }
  243. functionSelect.onchange();
  244. newOrEditEval.value=item.fun;
  245. return false;
  246. }
  247. return true;
  248. });
  249. };
  250. newOrEditBtn.onclick=function(e){
  251. newOrEditBtn.value=i18n.listening;
  252. newOrEditBtn.setAttribute("disabled","disabled");
  253. afterGestures=function(){
  254. newOrEditBtn.removeAttribute("disabled");
  255. afterGestures=null;
  256. newOrEditSign.innerHTML=signs;
  257. newOrEditBtn.value=i18n.addListener;
  258. };
  259. };
  260. newOrEditOkBtn.onclick=function(e){
  261. if(!newOrEditSign.innerHTML){
  262. alert(i18n.alert1);
  263. }else if(functionSelect.options.selectedIndex===0){
  264. alert(i18n.alert2);
  265. }else {
  266. var op=functionSelect.options;
  267. var selIndex=op.selectedIndex;
  268. if(selIndex===1 && !newOrEditEval.value){
  269. alert(i18n.alert3);
  270. }else{
  271. var code=op[selIndex].value;
  272. if(selIndex===1){
  273. code=newOrEditEval.value;
  274. }
  275. for(var index in gestures){
  276. if(gestures[index].gesture==newOrEditSign.innerHTML){
  277. gestures.splice(index,1);
  278. break;
  279. }
  280. }
  281. gestures.push({gesture:newOrEditSign.innerHTML,fun:code});
  282. GM_setValue("gestures",gestures);
  283. refreshGestures();
  284. }
  285. }
  286. };
  287. newOrEditDelBtn.onclick=function(e){
  288. var value=gesturesSelect.options[gesturesSelect.options.selectedIndex].value;
  289. for(var index in gestures){
  290. if(gestures[index].gesture==value){
  291. gestures.splice(index,1);
  292. break;
  293. }
  294. }
  295. refreshGestures();
  296. };
  297. }
  298. function goSetting(){
  299. location.href="https://github.com/hoothin/UserScripts/tree/master/Mouse%20Gestures";
  300. }
  301. GM_registerMenuCommand(i18n.configure, goSetting);
  302. })();