IP.Chat Ignore

Allows you to ignore chat messages from specific users.

目前为 2014-05-13 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name IP.Chat Ignore
  3. // @namespace Makaze
  4. // @include *
  5. // @grant none
  6. // @version 1.1.7
  7. // @description Allows you to ignore chat messages from specific users.
  8. // ==/UserScript==
  9.  
  10. var MakazeScriptStyles,
  11. IPChatMenuItems,
  12. reference,
  13. ignoredUsersMenu,
  14. menuButton,
  15. styleElem,
  16. leaveImgSrc,
  17. i = 0;
  18.  
  19. // Classes constructor
  20.  
  21. function ClassHandler() {
  22. var self = this;
  23.  
  24. this.classList = function(elem) {
  25. return elem.className.trim().split(/[\b\s]/);
  26. };
  27.  
  28. this.hasClass = function(elem, className) {
  29. var classes = self.classList(elem),
  30. has = false,
  31. i = 0;
  32.  
  33. for (i = 0; i < classes.length; i++) {
  34. if (classes[i] === className) {
  35. has = true;
  36. break;
  37. }
  38. }
  39.  
  40. return (has);
  41. };
  42.  
  43. this.addClass = function(elem, className) {
  44. var classes;
  45.  
  46. if (!self.hasClass(elem, className)) {
  47. classes = self.classList(elem);
  48. classes.push(className);
  49. elem.className = classes.join(' ').trim();
  50. }
  51.  
  52. return self;
  53. };
  54.  
  55. this.removeClass = function(elem, className) {
  56. var classes = self.classList(elem),
  57. i = 0;
  58.  
  59. for (i = 0; i < classes.length; i++) {
  60. if (classes[i] === className) {
  61. classes.splice(i, 1);
  62. }
  63. }
  64.  
  65. elem.className = classes.join(' ').trim();
  66.  
  67. return self;
  68. };
  69.  
  70. this.toggleClass = function(elem, className) {
  71. var classes;
  72.  
  73. if (self.hasClass(elem, className)) {
  74. self.removeClass(elem, className);
  75. } else {
  76. classes = self.classList(elem);
  77. classes.push(className);
  78. elem.className = classes.join(' ').trim();
  79. }
  80.  
  81. return self;
  82. };
  83. }
  84.  
  85. // Initialize
  86.  
  87. var Classes = new ClassHandler();
  88.  
  89. // End Classes constructor
  90.  
  91. function empty(elem) {
  92. while (elem.hasChildNodes()) {
  93. elem.removeChild(elem.lastChild);
  94. }
  95. }
  96.  
  97. function createElement(type, callback) {
  98. var element = document.createElement(type);
  99.  
  100. callback(element);
  101.  
  102. return element;
  103. }
  104.  
  105. function fade(elem, type, speed) {
  106. var defaultOpacity,
  107. currentDisplay = elem.style.display || window.getComputedStyle(elem).display;
  108.  
  109. elem.style.opacity = '';
  110. defaultOpacity = window.getComputedStyle(elem).opacity;
  111. elem.style.opacity = 0;
  112.  
  113. // Default values:
  114.  
  115. switch (arguments.length) {
  116. case 1:
  117. type = 'toggle';
  118. case 2:
  119. speed = 300;
  120. break;
  121. }
  122.  
  123. switch (type) {
  124. case 'in':
  125. elem.style.display = '';
  126. setTimeout(function() {
  127. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  128. elem.style.opacity = defaultOpacity;
  129. setTimeout(function() {
  130. elem.style.transition = '';
  131. elem.style.opacity = '';
  132. }, speed + 10);
  133. }, 1);
  134. break;
  135. case 'out':
  136. elem.style.transition = '';
  137. elem.style.opacity = defaultOpacity;
  138. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  139. elem.style.opacity = 0;
  140. setTimeout(function() {
  141. elem.style.display = 'none';
  142. elem.style.transition = '';
  143. elem.style.opacity = '';
  144. }, speed + 10);
  145. break;
  146. case 'toggle':
  147. default:
  148. if (currentDisplay === 'none') {
  149. elem.style.display = '';
  150. setTimeout(function() {
  151. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  152. elem.style.opacity = defaultOpacity;
  153. setTimeout(function() {
  154. elem.style.transition = '';
  155. elem.style.opacity = '';
  156. }, speed + 10);
  157. }, 1);
  158. } else {
  159. elem.style.transition = '';
  160. elem.style.opacity = defaultOpacity;
  161. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  162. elem.style.opacity = 0;
  163. setTimeout(function() {
  164. elem.style.display = 'none';
  165. elem.style.transition = '';
  166. elem.style.opacity = '';
  167. }, speed + 10);
  168. }
  169. }
  170. }
  171.  
  172. function toggleIgnoreStatus(userID, elem) {
  173. var currRef,
  174. ignoreLink,
  175. isIgnored = false,
  176. name,
  177. opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {},
  178. ignoreList = (opts.hasOwnProperty('ipc_ignores')) ? opts.ipc_ignores : [],
  179. i = 0,
  180. j = 0;
  181.  
  182. for (i = 0; i < ignoreList.length; i++) {
  183. if (ignoreList[i].user === userID) {
  184. isIgnored = true;
  185. break;
  186. }
  187. }
  188.  
  189. ignoreLink = document.getElementById('block_all_' + userID);
  190.  
  191. if (ignoreLink != null) {
  192. if (arguments.length > 1) {
  193. currRef = elem;
  194. } else {
  195. currRef = document.getElementById(ignoreLink.parentNode.parentNode.id.split('_menucontent')[0]);
  196. }
  197.  
  198. if (isIgnored) {
  199. currRef.style.textDecoration = '';
  200. currRef.style.fontStyle = '';
  201. ignoreLink.childNodes[1].nodeValue = ' Ignore All Chats';
  202. } else {
  203. currRef.style.textDecoration = 'line-through';
  204. currRef.style.fontStyle = 'oblique';
  205. ignoreLink.childNodes[1].nodeValue = ' Stop Ignoring All Chats';
  206. }
  207. }
  208.  
  209. if (isIgnored) {
  210. for (j = 0; j < document.getElementsByClassName('ignoredUser' + userID).length; j++) {
  211. document.getElementsByClassName('ignoredUser' + userID)[j].style.display = '';
  212. Classes.removeClass(document.getElementsByClassName('ignoredUser' + userID)[j], 'ignoredUser' + userID);
  213. }
  214.  
  215. opts.ipc_ignores.splice(i, 1);
  216.  
  217. localStorage.setItem('MakazeScriptOptions', JSON.stringify(opts));
  218. } else {
  219. if (arguments.length > 1) {
  220. currRef = elem;
  221. } else {
  222. currRef = document.getElementById(ignoreLink.parentNode.parentNode.id.split('_menucontent')[0]);
  223. }
  224.  
  225. name = currRef.getElementsByTagName('span')[0].textContent.trim();
  226.  
  227. opts.ipc_ignores.push({ 'user': userID, 'name': name });
  228.  
  229. localStorage.setItem('MakazeScriptOptions', JSON.stringify(opts));
  230. }
  231. getIgnoredUsers();
  232. }
  233.  
  234. function createIgnoreLink(reference) {
  235. if (document.getElementById(reference.id + '_menucontent').getElementsByTagName('a')[0] == null) {
  236. return false;
  237. }
  238.  
  239. var userID = reference.parentNode.parentNode.getElementsByTagName('a')[0].id.split('link_')[1],
  240. opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {},
  241. ignoreList = (opts.hasOwnProperty('ipc_ignores')) ? opts.ipc_ignores : [],
  242. blockCloneSrc = document.getElementById(reference.id + '_menucontent').getElementsByClassName('block_user')[0] || document.getElementById(reference.id + '_menucontent').getElementsByClassName('unblock_user')[0],
  243. blockClone = blockCloneSrc.parentNode.cloneNode(true),
  244. blockCloneParent = blockCloneSrc.parentNode.parentNode,
  245. ignoreLink = blockClone.getElementsByTagName('a')[0],
  246. name = reference.getElementsByTagName('span')[0].textContent.trim(),
  247. isIgnored = false,
  248. i = 0;
  249.  
  250. ignoreLink.onclick = null;
  251. ignoreLink.href = 'javascript:void(0)';
  252. ignoreLink.className = 'block_all_user';
  253. ignoreLink.id = 'block_all_' + userID;
  254. ignoreLink.title = 'Ignore All Chats';
  255.  
  256. for (i = 0; i < ignoreList.length; i++) {
  257. if (ignoreList[i].user === userID) {
  258. isIgnored = true;
  259. reference.style.textDecoration = 'line-through';
  260. reference.style.fontStyle = 'oblique';
  261. if (ignoreList.name !== name) {
  262. opts.ipc_ignores[i].name = name;
  263. localStorage.setItem('MakazeScriptOptions', JSON.stringify(opts));
  264. }
  265. break;
  266. }
  267. }
  268.  
  269. ignoreLink.childNodes[1].nodeValue = (isIgnored) ? ' Stop Ignoring All Chats' : ' Ignore All Chats';
  270.  
  271. ignoreLink.onclick = function() {
  272. var user = this.id.split('block_all_')[1];
  273. toggleIgnoreStatus(user, reference);
  274. };
  275.  
  276. blockCloneParent.appendChild(blockClone);
  277. }
  278.  
  279. function getIgnoredUsers() {
  280. var container = document.getElementById('ignoredUsers').getElementsByClassName('scrollableContent')[0],
  281. opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {},
  282. ignoreList = (opts.hasOwnProperty('ipc_ignores')) ? opts.ipc_ignores : [],
  283. ignoredUsrID,
  284. ignoredUsrName,
  285. i = 0;
  286.  
  287. empty(container);
  288.  
  289. function createUnignore(id, name) {
  290. return createElement('a', function(link) {
  291. link.setAttribute('data-userid', id);
  292. link.href = 'javascript:void(0)';
  293. link.title = 'Unignore this user';
  294.  
  295. link.appendChild(createElement('img', function(img) {
  296. img.src = leaveImgSrc;
  297. }));
  298.  
  299. link.appendChild(document.createTextNode(' ' + name));
  300.  
  301. link.onclick = function() {
  302. toggleIgnoreStatus(id);
  303. fade(this, 'out');
  304. };
  305. });
  306. }
  307.  
  308. for (i = 0; i < ignoreList.length; i++) {
  309. ignoredUsrID = ignoreList[i].user;
  310. ignoredUsrName = ignoreList[i].name;
  311.  
  312. container.appendChild(createUnignore(ignoredUsrID, ignoredUsrName));
  313. }
  314. }
  315.  
  316. if (document.body.id === 'ipboard_body' && document.getElementById('storage_chatroom') != null) {
  317. // Styling
  318.  
  319. if (document.getElementById('MakazeScriptStyles') == null) {
  320. MakazeScriptStyles = createElement('style', function(style) {
  321. style.id = 'MakazeScriptStyles';
  322. style.type = 'text/css';
  323. });
  324. document.head.appendChild(MakazeScriptStyles);
  325. }
  326.  
  327. styleElem = document.getElementById('MakazeScriptStyles');
  328.  
  329. if (styleElem.hasChildNodes()) {
  330. styleElem.childNodes[0].nodeValue += '\n\n';
  331. } else {
  332. styleElem.appendChild(document.createTextNode(''));
  333. }
  334.  
  335. if (!styleElem.childNodes[0].nodeValue.match('.MakazeScriptMenu')) {
  336. styleElem.childNodes[0].nodeValue += '.MakazeScriptMenu { position: fixed; z-index: 99999; top: 50%; left: 50%; padding: 10px; background-color: rgba(255, 255, 255, .85); box-shadow: 0px 0px 3px #888; border-radius: 5px; } .MakazeScriptMenu th { font-weight: bolder; } .MakazeScriptMenu th, .MakazeScriptMenu td { padding: 3px; } .MakazeScriptMenu .menu-save { text-align: center; margin-top: 6px; } .MakazeScriptMenu .menu-save > a { padding: 2px 10px; border: 1px solid #ccc; border-radius: 3px; font-weight: bolder; cursor: pointer; } .MakazeScriptMenu .menuTitle { margin-bottom: 10px; font-weight: bolder; } .MakazeScriptMenu .scrollableContent { width: 312px; height: 150px; overflow: auto; padding: 2px; } .MakazeScriptMenu textarea, .MakazeScriptMenu input[type=text], .MakazeScriptMenu input[type=number] { font-family: Consolas, Ubuntu Mono, sans-serif; font-size: 10px; color: #333; padding: 3px; box-sizing: border-box; }\n\n';
  337. }
  338.  
  339. styleElem.childNodes[0].nodeValue +=
  340. '#ignoredUsers {\n' +
  341. 'margin-left: -168px;\n' +
  342. 'margin-top: -110px;\n' +
  343. '}\n\n' +
  344.  
  345. '#ignoredUsers .scrollableContent > a {\n' +
  346. 'display: inline-block;\n' +
  347. 'background-color: #eee;\n' +
  348. 'box-shadow: 0px 0px 3px #aaa;\n' +
  349. 'border: 2px solid #fff;\n' +
  350. 'padding: 1px 4px;\n' +
  351. 'border-radius: 2px;\n' +
  352. 'margin-right: 10px;\n' +
  353. 'margin-bottom: 10px;\n' +
  354. 'font-size: 10px;\n' +
  355. '}\n\n' +
  356.  
  357. '#ignoredUsers .scrollableContent > a > img {\n' +
  358. 'height: 12px;\n' +
  359. '}';
  360.  
  361. // Menu creation
  362.  
  363. ignoredUsersMenu = createElement('div', function(menu) {
  364. menu.id = 'ignoredUsers';
  365. menu.className = 'MakazeScriptMenu';
  366. menu.style.display = 'none';
  367.  
  368. menu.appendChild(createElement('div', function(title) {
  369. title.className = 'menuTitle';
  370. title.appendChild(document.createTextNode('Ignored Users'));
  371. }));
  372.  
  373. menu.appendChild(createElement('div', function(scroll) {
  374. scroll.className = 'scrollableContent';
  375. }));
  376.  
  377. menu.appendChild(createElement('div', function(save) {
  378. save.className = 'menu-save';
  379.  
  380. save.appendChild(createElement('a', function(link) {
  381. link.href = 'javascript:void(0)';
  382. link.id = 'ignoredUsers_close';
  383. link.appendChild(document.createTextNode('Close'));
  384. link.onclick = function() {
  385. fade(this.parentNode.parentNode, 'out');
  386. };
  387. }));
  388. }));
  389. });
  390.  
  391. document.body.appendChild(ignoredUsersMenu);
  392.  
  393. getIgnoredUsers();
  394.  
  395. // Button creation
  396.  
  397. if (document.getElementById('IPChatMenuItems') == null) {
  398. IPChatMenuItems = createElement('div', function(menu) {
  399. menu.id = 'IPChatMenuItems';
  400. menu.style.textAlign = 'right';
  401. });
  402. document.getElementById('chatters-online-wrap').nextSibling.nextSibling.getElementsByTagName('ul')[0].appendChild(IPChatMenuItems);
  403. }
  404.  
  405. if (document.getElementById('IPChatMenuItems').innerHTML.length) {
  406. document.getElementById('IPChatMenuItems').appendChild(document.createElement('br'));
  407. }
  408.  
  409. menuButton = createElement('a', function(button) {
  410. button.id = 'gnoredUsersMenuButton';
  411. button.className = 'ipsButton_secondary';
  412. button.href = 'javascript:void(0)';
  413. button.style.marginTop = '10px';
  414. button.appendChild(document.createTextNode('Manage Ignored Users'));
  415.  
  416. button.onclick = function() {
  417. var menu = document.getElementById('ignoredUsers');
  418. if (menu.style.display === 'none') {
  419. getIgnoredUsers();
  420. }
  421. fade(menu);
  422. };
  423. });
  424. document.getElementById('IPChatMenuItems').appendChild(menuButton);
  425.  
  426. // Get leaving image source
  427.  
  428. leaveImgSrc = document.getElementById('leave_room').getElementsByTagName('img')[0].src;
  429.  
  430. // Add ignore links
  431.  
  432. if (document.getElementById('chatters-online-wrap') != null) {
  433. for (i = 0; i < document.getElementById('chatters-online-wrap').getElementsByClassName('chatmodmenu').length; i++) {
  434. reference = document.getElementById('chatters-online-wrap').getElementsByClassName('chatmodmenu')[i];
  435. createIgnoreLink(reference);
  436. }
  437. }
  438.  
  439. document.addEventListener('DOMNodeInserted', function(event) {
  440. // Add ignore link to new users
  441.  
  442. if (event.target.nodeType === 1 && Classes.hasClass(event.target, 'kickmenu')) {
  443. var checkForPartner = setInterval(function() {
  444. var link = document.getElementById(event.target.id.split('_menucontent')[0]);
  445. if (link != null) {
  446. createIgnoreLink(link);
  447. clearTimeout(checkForPartner);
  448. }
  449. }, 1);
  450. return false;
  451. }
  452.  
  453. // Ignore messages in chat
  454.  
  455. if (event.target.nodeType !== 1 || event.target.id !== 'storage_chatroom') {
  456. return false;
  457. }
  458.  
  459. var nick,
  460. curr,
  461. opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {},
  462. ignoreList = (opts.hasOwnProperty('ipc_ignores')) ? opts.ipc_ignores : [],
  463. latestMessage,
  464. i = 0;
  465.  
  466. if (!ignoreList.length) {
  467. return false;
  468. }
  469.  
  470. latestMessage = event.target.parentNode.getElementsByTagName('div')[event.target.parentNode.getElementsByTagName('div').length - 1];
  471.  
  472. if (!Classes.hasClass(latestMessage.parentNode, 'post')) {
  473. return false;
  474. }
  475.  
  476. if (Classes.hasClass(latestMessage.parentNode, 'chat-moderator')) {
  477. return false;
  478. }
  479.  
  480. nick = null;
  481.  
  482. curr = latestMessage.parentNode;
  483.  
  484. while (nick === null) {
  485. if (curr.getElementsByTagName('label').length) {
  486. nick = curr.getElementsByTagName('label')[0].textContent;
  487. } else {
  488. curr = curr.previousSibling;
  489. }
  490. }
  491.  
  492. for (i = 0; i < ignoreList.length; i++) {
  493. if (ignoreList[i].name === nick) {
  494. latestMessage.parentNode.style.display = 'none';
  495. Classes.addClass(latestMessage.parentNode, 'ignoredUser' + ignoreList[i].user);
  496. break;
  497. }
  498. }
  499. });
  500. }