Greasy Fork is available in English.

Freenode Web IRC 刷屏插件

在 Freenode Web IRC 聊天室中创造瀑布

  1. // ==UserScript==
  2. // @name Freenode Web IRC 刷屏插件
  3. // @namespace xuyiming.open@outlook.com
  4. // @description 在 Freenode Web IRC 聊天室中创造瀑布
  5. // @author 依然独特
  6. // @version 1.0.0
  7. // @grant none
  8. // @run-at document-end
  9. // @include http://webchat.freenode.net/*
  10. // @match http://webchat.freenode.net/*
  11. // @license Public Domain
  12. // @homepageURL https://gist.github.com/xymopen/e10ecd98485f97b7372b
  13. // ==/UserScript==
  14.  
  15. "use strict";
  16.  
  17. ( function() {
  18. var POST_INTERVAL = 250;
  19.  
  20. function main() {
  21. var intervalID, post, e = document.querySelector( "div.dynamicpanel.qwebirc-qui.bottomboundpanel.widepanel.input" );
  22.  
  23. intervalID = setInterval( function() {
  24. if ( e.style.display !== "none" ) {
  25. load();
  26. clearInterval( intervalID );
  27. }
  28. }, 1000 );
  29.  
  30. post = ( function() {
  31. var queue = [ ],
  32. form = document.querySelector( "form.input" ),
  33. input = form.querySelector( "input.keyboard-input" );
  34.  
  35. function next() {
  36. if ( queue.length > 0 ) {
  37. input.value = queue.shift();
  38. submit( form );
  39. }
  40. };
  41.  
  42. function submit( form ) {
  43. var event = document.createEvent( "HTMLEvents" );
  44. event.initEvent( "submit", true, true );
  45. form.dispatchEvent( event );
  46. };
  47.  
  48. form.addEventListener( "submit", function () {
  49. setTimeout( next, POST_INTERVAL );
  50. }, false );
  51.  
  52. return function( message ) {
  53. queue = queue.concat( message.replace( /\t/g, " " ).split( "\n" ).filter( function( line ) {
  54. // 去掉空行
  55. return !/^\s+$/.test( line );
  56. } ) );
  57. next();
  58. };
  59. } )();
  60.  
  61. function load() {
  62. var textarea = document.createElement( "textarea" ),
  63. position = {
  64. self: { x: 0, y: 0 }, //元素相对基准点的位置
  65. viewport: { x: 0, y: 0 }, //基准点在页面中的位置
  66. cursor: { x: 0, y: 0 } //光标相对元素的位置
  67. };
  68.  
  69. function onkeydown( event ) {
  70. var value, selectionStart, selectionEnd, beforeSelected, selected, afterSelected;
  71.  
  72. // Tab 添加缩进而不是切换焦点
  73. if ( event.keyCode === 9 ) {
  74. event.preventDefault();
  75.  
  76. value = textarea.value;
  77.  
  78. selectionStart = textarea.selectionStart;
  79. selectionEnd = textarea.selectionEnd;
  80.  
  81. beforeSelected = value.slice( 0, selectionStart );
  82. selected = value.slice( selectionStart, selectionEnd );
  83. afterSelected = value.slice( selectionEnd );
  84.  
  85. selected = selected.split( "\n" ).map( function( line ) {
  86. return "\t" + line;
  87. } ).join( "\n" );
  88.  
  89. textarea.value = beforeSelected + selected + afterSelected;
  90.  
  91. // 如果没有选定内容,则将光标移至制表符后
  92. if ( selectionStart === selectionEnd ) {
  93. textarea.selectionStart = textarea.selectionEnd = selectionEnd + 1;
  94. // 否则,选定制表符和原有选定内容
  95. } else {
  96. textarea.selectionStart = selectionStart;
  97. textarea.selectionEnd = selectionStart + selected.length;
  98. }
  99. // Ctrl + Enter 发送消息
  100. } else if ( event.ctrlKey && event.keyCode === 13 && textarea.value.replace( /\s/g, "" ) ) {
  101. event.preventDefault();
  102. post( textarea.value.trim() );
  103. textarea.value = "";
  104. }
  105. };
  106.  
  107. function onmousedown( event ) {
  108. var x, y, style, rect;
  109.  
  110. // 按住 Ctrl 和鼠标可以移动 <textarea>
  111. if ( event.ctrlKey ) {
  112. event.preventDefault();
  113.  
  114. style = getComputedStyle( textarea );
  115. rect = ( textarea.offsetParent && textarea.offsetParent.getBoundingClientRect() ) || { top: 0, left: 0 };
  116.  
  117. /*
  118. switch( style.position ) {
  119. case "absolute":
  120. case "fixed":
  121. position.self.x = textarea.offsetLeft - parseInt( style.marginLeft );
  122. position.self.y = textarea.offsetTop - parseInt( style.marginTop );
  123. break;
  124. case "relative":
  125. x = textarea.offsetLeft,
  126. y = textarea.offsetTop;
  127. textarea.style.top = "0px";
  128. textarea.style.left = "0px";
  129. position.self.x = x - textarea.offsetLeft;
  130. position.self.y = y - textarea.offsetTop;
  131. break;
  132. default:
  133. // static 定位元素无法拖动
  134. return;
  135. }
  136. */
  137.  
  138. /* */
  139. position.self.x = textarea.offsetLeft - parseInt( style.marginLeft, 10 );
  140. position.self.y = textarea.offsetTop - parseInt( style.marginTop, 10 );
  141. /* */
  142.  
  143. position.viewport.x = rect.left;
  144. position.viewport.y = rect.top;
  145. position.cursor.x = event.pageX - position.viewport.x - position.self.x;
  146. position.cursor.y = event.pageY - position.viewport.y - position.self.y;
  147.  
  148. textarea.style.top = position.self.y + "px";
  149. textarea.style.left = position.self.x + "px";
  150. textarea.style.bottom = "auto";
  151. textarea.style.right = "auto";
  152.  
  153. document.addEventListener( "mousemove", onmousemove, false );
  154. document.addEventListener( "mouseup", onmouseup, false );
  155. }
  156. };
  157.  
  158. function onmousemove( event ) {
  159. event.preventDefault();
  160. textarea.style.top = event.pageY - position.viewport.y - position.cursor.y + "px";
  161. textarea.style.left = event.pageX - position.viewport.x - position.cursor.x + "px";
  162. };
  163.  
  164. function onmouseup( event ) {
  165. event.preventDefault();
  166. position = {
  167. self: { x: 0, y: 0 },
  168. viewport: { x: 0, y: 0 },
  169. cursor: { x: 0, y: 0 }
  170. };
  171. document.removeEventListener( "mousemove", onmousemove, false );
  172. document.removeEventListener( "mouseup", onmouseup, false );
  173. };
  174.  
  175. textarea.style.border = "1px solid rgb( 195, 210, 224 )";
  176. textarea.style.width = "150px";
  177. textarea.style.height = "75px";
  178. textarea.style.top = "45px";
  179. textarea.style.right = "150px";
  180. textarea.style.position = "fixed";
  181.  
  182. textarea.addEventListener( "keydown", onkeydown, false );
  183. textarea.addEventListener( "mousedown", onmousedown, false );
  184.  
  185. document.body.appendChild( textarea );
  186. };
  187. };
  188.  
  189. if ( document.readyState === "complete" ) {
  190. main();
  191. } else {
  192. // 因为需要等待样式表
  193. window.addEventListener( "load", main.bind( this ), false );
  194. }
  195. } )();