Greasemonkey Mouse Gestures

Just a Mouse Gestures script

2018-01-10 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

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