ball4phone

一个用于手机浏览器<自定义函数>的悬浮球。💚点击:选择并运行自定义js函数。💙拖拽:forward前进。💜长按:选中页面dom并进行处理后回显

  1. // jshint esversion: 6
  2. // eslint-disable-next-line
  3. // ==UserScript==
  4. // @name ball4phone
  5. // @namespace https://dniness.github.io/
  6. // @name:zh-CN 红裤衩の悬浮球
  7. // @version 2.30
  8. // @description 一个用于手机浏览器<自定义函数>的悬浮球。💚点击:选择并运行自定义js函数。💙拖拽:forward前进。💜长按:选中页面dom并进行处理后回显
  9. // @author Dniness
  10. // @match *://*/*
  11. // @icon data:image/svg+xml,<svg width='64' height='64' fill='none' xmlns='http://www.w3.org/2000/svg'><circle cx='32' cy='32' r='32' fill='darkslateblue'/></svg>
  12. // @grant none
  13. // @run-at document-body
  14. // @license MPL2.0
  15. // @noframes
  16. // ==/UserScript==
  17.  
  18. 'use strict';
  19. (function($ball={
  20. // Your code here...
  21. Enter(){return this&&this.textContent},
  22. a(){alert('a')},
  23. A(){alert('a+shift')},
  24. $(){this.x$test.error},
  25. z(){this&&this.appendChild(this.firstElementChild)},
  26. w(x){return (x.pop().background='pink')&&'<a href="//Dniness.github.io/customization">a link test</a>'},
  27. ' '(){return `blank space
  28.  
  29. // OR,you could set Dniness.ball while document-start`},
  30. //your code here end
  31. ready(){
  32. location.origin.startsWith('https://m.')&&
  33. (document.body.style.zoom=2.25)},
  34. }) {
  35. customElements.define(this, class extends HTMLElement {
  36. constructor() {
  37. super();
  38. let pwd = document.createElement("div")
  39. Object.assign(pwd.$ball=$ball,(window.Dniness||'').ball);
  40. let shadow = this.attachShadow({mode: 'closed'});
  41. window.addEventListener("popstate",pwd.$p=$=>{
  42. $=$&&document.elementFromPoint(8,8);
  43. ($||'').Dniness$ball&&$.Run(null);
  44. },pwd.Dniness$ball=true);
  45. !(pwd.Run={
  46. _($,$_){
  47. this.style = this.defaultStyle;
  48. //this.style.opacity=1;
  49. try{
  50. $=($||0).nextSibling==this?null:$==this?this:
  51. ($&&this.$ball[$]||this.$p).call(this.active,$_=[this.style]);
  52. }catch(e){
  53. $='[ERROR]:\r\r'+(e.message||e);
  54. this.style.color=$_="darkred";
  55. }
  56. this.active = undefined;
  57. this.textContent="\n";
  58. (this.previousSibling||this).style.display=
  59. this.style.display='block';
  60. $_=($_||0).length?"innerText":"innerHTML";
  61. if($===undefined){
  62. this.focus();
  63. this.style.display='none';
  64. }else if($===null){
  65. this.style.opacity=1/11;
  66. }else if($===this){
  67. this.style.opacity=0.2;
  68. this.previousSibling.style.display='none';
  69. }else{
  70. this[$_]+="don't use back key:\n\n"+
  71. $.toString().replace(/[\r\n]+/g,"\n");
  72. ($_=this.style).opacity=$_.opacity<0.3?0.3:$_.opacity;
  73. }
  74. },
  75. on:e=>{pwd['on'+e[0]]=new Function((e.pop()+'').slice(4,-1).replace(/\$/g,'this'))},
  76. $:e=>e[0].replace('$','-')+':'+e[1],
  77. })._.call(pwd,'ready');
  78. pwd.onmouseup = function(e){
  79. if(this.style.opacity==0.2){
  80. this.Run(this);
  81. this.style.display='none';
  82. e=document.elementFromPoint(e.clientX,e.clientY);
  83. if(e.tagName=='IFRAME'&&e.src){
  84. this.Run(null);
  85. location.replace(e.src);
  86. }else{
  87. this.Run(this.previousSibling);
  88. while(!'BODY.DIV.CODE'.includes(e.tagName)||!e.childElementCount){
  89. e=e.parentElement;
  90. }
  91. this.active=e;
  92. this.previousSibling.focus();
  93. }
  94. }else this.Run(null);
  95. };
  96. pwd.defaultStyle=Object.entries({
  97. top:0,
  98. left:0,
  99. width:'100%',
  100. height:'100%',
  101. position:'fixed',
  102. font$weight:'bold',
  103. font$size:'4vw',
  104. line$height:'4vw',
  105. white$space:'pre-wrap',
  106. word$wrap:'break-word',
  107. overflow:'auto',
  108. border:'none',
  109. text$align:'left',
  110. background:'darkslateblue',
  111. color:'white',
  112. caret$color:'transparent',
  113. position:'Fixed',
  114. z$index:9<<9,
  115. opacity:1
  116. }).map(pwd.Run.$).join(';');
  117.  
  118. //main ball
  119. pwd = [shadow.appendChild(document.createElement("input")),shadow.appendChild(pwd)];
  120. pwd[0].Run = pwd.pop().Run;
  121. (pwd = pwd.pop()).style=
  122. Object.entries({
  123. bottom:'5%',
  124. right:'2%',
  125. width:'6vh',
  126. height:'6vh',
  127. border$radius:'50%',
  128. border:'none',
  129. text$align:'center',
  130. background:'darkslateblue',
  131. color:'white',
  132. caret$color:'transparent',
  133. position:'Fixed',
  134. z$index:(9<<9)+9,
  135. opacity:1/4,
  136. font:'bold 3vh SANS-SERIF'
  137. }).map(pwd.Run.$).join(';');
  138.  
  139. Object.entries({
  140. focus:$=>{$.type='password';$.value=~8},
  141. blur:$=>{$.type='text';$.value='Ctrl'},
  142. keyup:$=>{$.Run($)($);$.blur()},
  143. keydown:$=>{$.value=1-$.value},
  144. mousedown:$=>{clearTimeout($.rto);$.asyncRun($.rto=0,$);},
  145. touchend:$=>{$.rto=$.rto||setTimeout($.forward,500,$)},
  146. contextmenu:$=>{$.asyncRun($,$.nextSibling);return false}
  147. }).forEach(pwd.Run.on);
  148. pwd.nextSibling.Run=pwd.Run._;
  149. pwd.Run=c=>c[c.value[1]?'asyncRun':'jumpTop'];//jumpTop = key(back)
  150. pwd.jumpTop=a=>{(a=a.style).bottom=(8+a.bottom).slice(~3-~a.bottom[1])};
  151. pwd.asyncRun=(e,x)=>(e||x).nextSibling.Run(x||e.value[2]||'Enter');
  152. pwd.forward=o=>{o.blur();history.forward();o.rto=0};
  153. shadow=pwd=$ball=!pwd.onblur();
  154. }
  155. });
  156. document.body.appendChild(document.createElement(this))
  157. }).call('dniness-ball');