TorViet Shoutbox Enhancer

A small script to tweak the shoutbox

目前为 2015-06-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name TorViet Shoutbox Enhancer
  3. // @namespace http://torviet.com/userdetails.php?id=1662
  4. // @version 0.7.2
  5. // @license http://www.wtfpl.net/txt/copying/
  6. // @homepageURL https://github.com/S-a-l-a-d/TorViet-Shoutbox-Enhancer
  7. // @supportURL https://github.com/S-a-l-a-d/TorViet-Shoutbox-Enhancer/issues
  8. // @icon http://torviet.com/pic/salad.png
  9. // @description A small script to tweak the shoutbox
  10. // @author Salad
  11. // @match http://torviet.com/qa.php*
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @grant GM_deleteValue
  15. // @grant GM_addStyle
  16. // ==/UserScript==
  17.  
  18. (function() {
  19. // First let's get the elements which we will work on.
  20. var boxHead = document.getElementById('boxHead'),
  21. marquee = document.getElementsByClassName('marquee')[0],
  22. sltTheme = document.getElementById('sltTheme'),
  23. clock = document.getElementById('clock'),
  24. inputSection = document.getElementsByClassName('input-section')[0],
  25. idQuestion = document.getElementById('idQuestion'),
  26. navigationPage = document.getElementsByClassName('navigation_page')[0],
  27. emoGroup = document.getElementById('emogroup'),
  28. emoGroupDetail = document.getElementsByClassName('emo-group-detail')[0];
  29.  
  30. // Also create a namespace.
  31. var EMOTICON = (function() {
  32. var emoList = GM_getValue('emoList'),
  33. emoHtml = '';
  34.  
  35. var promptForEmoList = function(action, list) {
  36. var message = 'Chọn bộ emoticon bạn muốn' + ' ' + action + ':\n',
  37. answer;
  38.  
  39. for (var i = 0, len = list.length; i < len; i++) {
  40. message += i + 1 + '. ' + list[i] + '\n';
  41. }
  42.  
  43. message += 'Điền tên bộ emoticon, ngăn cách bằng dấu phẩy, phân biệt hoa/thường.' + ' ' +
  44. 'Có thể điền emoticon đơn bằng cách điền tên tập tin emoticon đó.\nVí dụ: Voz,707,Rage';
  45.  
  46. do {
  47. answer = prompt(message);
  48. }
  49. while (!answer || answer.trim() === '');
  50.  
  51. return answer.replace(/\s+/g, '').split(',');
  52. };
  53. var initemoList = function() {
  54. var emoListAvailable = [];
  55. for (var i = 0, options = emoGroup.options, len = options.length; i < len; i++) {
  56. emoListAvailable.push(options[i].text);
  57. }
  58.  
  59. emoList = promptForEmoList('sử dụng', emoListAvailable);
  60. GM_setValue('emoList', emoList);
  61. };
  62. var requestEmoticons = function(groupName) {
  63. var request = new XMLHttpRequest();
  64. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  65. * Using synchronous request here is the simplest implementation to make it work. *
  66. * This process is fast enough so the user will hardly notice the unresponsive moment *
  67. * while the browser is sending the request and receiving the response. *
  68. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  69. request.open('POST', 'qa_smiley_ajax.php', false);
  70. request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  71. request.onreadystatechange = function() {
  72. request.readyState == 4 && request.status == 200 &&
  73. (emoHtml = JSON.parse(request.responseText).str);
  74. };
  75. request.send('group=' + groupName);
  76. };
  77. var makeEmoticonHtml = function(emoName) {
  78. emoHtml = '<div style="height:43px;width:43px;float:left;display:inline-block;margin:1px;">' +
  79. '<a style="margin: 0;" class="btuEmotion" alt="[em' + emoName +
  80. ']"><img style="max-width: 43px; max-height: 43px" src="/pic/smilies/' + emoName +
  81. '.gif" alt=""></a></div>';
  82. };
  83.  
  84. return {
  85. checkemoList: function() {
  86. !emoList && initemoList();
  87. },
  88. add: function() {
  89. var emoListAvailable = [];
  90. for (var i = 0, options = emoGroup.options, len = options.length; i < len; i++) {
  91. (emoList.indexOf(options[i].text) === -1) &&
  92. emoListAvailable.push(options[i].text);
  93. }
  94.  
  95. var emoListToAdd = promptForEmoList('thêm', emoListAvailable);
  96. for (var i = 0, len = emoListToAdd.length; i < len; i++) {
  97. (emoList.indexOf(emoListToAdd[i]) === -1) &&
  98. emoList.push(emoListToAdd[i]);
  99. }
  100.  
  101. GM_setValue('emoList', emoList);
  102. location.href = 'qa.php';
  103. },
  104. remove: function() {
  105. var emoListToRemove = promptForEmoList('xóa', emoList);
  106. for (var i = 0, len = emoListToRemove.length; i < len; i++) {
  107. var index = emoList.indexOf(emoListToRemove[i]);
  108. (index > -1) && emoList.splice(index, 1);
  109. }
  110.  
  111. GM_setValue('emoList', emoList);
  112. location.href = 'qa.php';
  113. },
  114. clear: function() {
  115. GM_deleteValue('emoList');
  116. location.href = 'qa.php';
  117. },
  118. getEmoticons: function(groupName) {
  119. requestEmoticons(groupName);
  120. return emoHtml;
  121. },
  122. generateEmoticons: function(emoName) {
  123. makeEmoticonHtml(emoName);
  124. return emoHtml;
  125. },
  126. addEmosToEmoGroup: function() {
  127. emoGroupDetail.innerHTML = '';
  128. for (var i = 0, len = emoList.length; i < len; i++) {
  129. emoGroupDetail.innerHTML += isNaN(emoList[i]) ?
  130. this.getEmoticons(emoList[i]) :
  131. this.generateEmoticons(emoList[i]);
  132. }
  133. },
  134. addEmoGroupEvent: function() {
  135. // Let's add click events for the newly added emoticons.
  136. for (var i = 0, emos = emoGroupDetail.childNodes, len = emos.length; i < len; i++)
  137. emos[i].firstChild.addEventListener('click', function(e) {
  138. idQuestion.value += e.target.parentNode.getAttribute('alt');
  139. idQuestion.focus();
  140. });
  141. }
  142. };
  143. })();
  144.  
  145. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  146. * Now remove the unnecessary elements including the box containing new torrents *
  147. * and football news, the warning, the theme drop-down list and the clock. *
  148. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  149. boxHead.parentNode.removeChild(boxHead);
  150. marquee.parentNode.removeChild(marquee);
  151. sltTheme.parentNode.removeChild(sltTheme);
  152. clock.innerHTML = '';
  153.  
  154. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  155. * Here we get the window height of the current window size and the height *
  156. * without the input section and the div holding the navigation. *
  157. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  158. var windowHeight = window.innerHeight,
  159. remainingHeight = inputSection.parentNode.offsetHeight + navigationPage.offsetHeight - 100;
  160.  
  161. // And polish things with our custom CSS.
  162. GM_addStyle(
  163. '.all-wrapper {' +
  164. ' background-image: none !important;' +
  165. ' height : ' + windowHeight + 'px;' +
  166. ' margin : auto;' +
  167. '}' +
  168. '.all-wrapper > :nth-child(2) {' +
  169. ' padding: 0 !important;' +
  170. '}' +
  171. '.navigation_page {' +
  172. ' width: auto;' +
  173. '}' +
  174. '#boxQuestion {' +
  175. ' height: ' + (windowHeight - remainingHeight) + 'px;' +
  176. '}' +
  177. '.q-head {' +
  178. ' border-radius: 0;' +
  179. '}' +
  180. '#clock {' +
  181. ' height : 72px;' +
  182. ' text-align: center;' +
  183. '}' +
  184. '#emo-section, .slimScrollDiv, .emo-group-detail {' +
  185. ' height : ' + (windowHeight - remainingHeight - 72 - 6) + 'px !important;' +
  186. ' padding: 0 !important;' +
  187. '}'
  188. );
  189.  
  190. var toBeAppendedToClock = document.createDocumentFragment(),
  191. someText = document.createElement('span'),
  192. btnAdd = document.createElement('input'),
  193. btnRemove = document.createElement('input'),
  194. btnClear = document.createElement('input');
  195.  
  196. someText.innerHTML = 'For custom emoticon group<br />';
  197.  
  198. btnAdd.type = 'button';
  199. btnAdd.value = 'Add';
  200. btnAdd.addEventListener('click', EMOTICON.add);
  201.  
  202. btnRemove.type = 'button';
  203. btnRemove.value = 'Remove';
  204. btnRemove.addEventListener('click', EMOTICON.remove);
  205.  
  206. btnClear.type = 'button';
  207. btnClear.value = 'Clear';
  208. btnClear.addEventListener('click', EMOTICON.clear);
  209.  
  210. toBeAppendedToClock.appendChild(emoGroup.parentNode);
  211. toBeAppendedToClock.appendChild(someText);
  212. toBeAppendedToClock.appendChild(btnAdd);
  213. toBeAppendedToClock.appendChild(btnRemove);
  214. toBeAppendedToClock.appendChild(btnClear);
  215. clock.appendChild(toBeAppendedToClock);
  216.  
  217. // Here comes our own functions.
  218. function changeEmoGroup() {
  219. emoGroupDetail.innerHTML = EMOTICON.getEmoticons(emoGroup.value);
  220. EMOTICON.addEmoGroupEvent();
  221. }
  222.  
  223. function keyEvent(e) {
  224. switch (e.keyCode) {
  225. // Down arrow.
  226. case 40:
  227. emoGroup !== document.activeElement &&
  228. emoGroup.selectedIndex !== emoGroup.length - 1 &&
  229. emoGroup.selectedIndex++;
  230. changeEmoGroup();
  231. break;
  232. // Up arrow.
  233. case 38:
  234. emoGroup !== document.activeElement &&
  235. emoGroup.selectedIndex !== 0 &&
  236. emoGroup.selectedIndex--;
  237. changeEmoGroup();
  238. break;
  239. // Enter.
  240. case 13:
  241. var inputText = idQuestion.value;
  242. inputText = inputText.replace(/(:\^\))|(\/:\))/g, '[em528]');
  243. inputText = inputText.replace(/:\)/g, '[em564]');
  244. inputText = inputText.replace(/:\({2}/g, '[em7]');
  245. inputText = inputText.replace(/:\(/g, '[em561]');
  246. inputText = inputText.replace(/:x/g, '[em535]');
  247. inputText = inputText.replace(/:"\>/g, '[em23]');
  248. inputText = inputText.replace(/:\-?\*/g, '[em570]');
  249. inputText = inputText.replace(/=\(\(/g, '[em572]');
  250. inputText = inputText.replace(/:\-?[oO]/g, '[em222]');
  251. inputText = inputText.replace(/[xX]\-?\(/g, '[em541]');
  252. inputText = inputText.replace(/[bB]\-\)/g, '[em555]');
  253. inputText = inputText.replace(/\>:\)/g, '[em552]');
  254. inputText = inputText.replace(/:\|/g, '[em206]');
  255. inputText = inputText.replace(/:\-&/g, '[em37]');
  256. inputText = inputText.replace(/\(:\|/g, '[em571]');
  257. inputText = inputText.replace(/:\-?\?/g, '[em223]');
  258. inputText = inputText.replace(/=\)\)/g, '[em707]');
  259. inputText = inputText.replace(/:\-?[dD]/g, '[em536]');
  260. inputText = inputText.replace(/;;\)/g, '[em524]');
  261. inputText = inputText.replace(/:\-?\>/g, '[em537]');
  262. inputText = inputText.replace(/:\-[sS]/g, '[em558]');
  263. inputText = inputText.replace(/\[\-\(/g, '[em200]');
  264. inputText = inputText.replace(/=[pP]~/g, '[em566]');
  265. inputText = inputText.replace(/;\)\)/g, '[em18]');
  266. inputText = inputText.replace(/[tT]_[tT]/g, '[em544]');
  267. inputText = inputText.replace(/\-_\-/g, '[em136]');
  268. idQuestion.value = inputText;
  269. break;
  270. default:
  271. }
  272. }
  273.  
  274. // The following should run at startup.
  275. document.addEventListener('keydown', keyEvent);
  276. EMOTICON.checkemoList();
  277. EMOTICON.addEmosToEmoGroup();
  278. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  279. * Let's see if the user is using Firefox. *
  280. * This method is taken from http://stackoverflow.com/questions/9847580/ *
  281. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  282. typeof InstallTrigger === 'undefined' && EMOTICON.addEmoGroupEvent();
  283. idQuestion.focus();
  284. })();