Advertisement
Guest User

For skitty

a guest
Mar 27th, 2015
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.14 KB | None | 0 0
  1. // ==UserScript==
  2. // @name 8chan Filter
  3. // @version 0.2.0
  4. // @namespace nokosage
  5. // @description Regular expression, point-and-click filtering on 8chan.
  6. // @author nokosage
  7. // @include *://*8chan.co/*/*.html*
  8. // @run-at document-start
  9. // @grant none
  10. // @updateURL https://raw.githubusercontent.com/nokosage/8chan-Filter/master/8chanFilter.meta.js
  11. // @downloadURL https://raw.githubusercontent.com/nokosage/8chan-Filter/master/8chanFilter.user.js
  12. // @icon
  13. // ==/UserScript==
  14.  
  15. /*
  16. 8chan Filter v0.2.0
  17. https://github.com/nokosage/8chan-Filter/
  18.  
  19. Developers:
  20. nokosage
  21.  
  22. Contributers:
  23. https://github.com/nokosage/8chan-Filter/graphs/contributors
  24.  
  25. This script contains code from 4chan Filter (aeosynth) (http://userscripts-mirror.org/scripts/show/109922.html)
  26. @license: GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  27. */
  28.  
  29. (function(){
  30. var d, on, off, main, ready;
  31.  
  32. main = function() {
  33. //x-browser
  34. if (typeof GM_deleteValue == 'undefined') {
  35. GM_addStyle = function(css) {
  36. var style = document.createElement('style');
  37. style.textContent = css;
  38. document.getElementsByTagName('head')[0].appendChild(style);
  39. }
  40.  
  41. GM_deleteValue = function(name) {
  42. localStorage.removeItem(name);
  43. }
  44.  
  45. GM_getValue = function(name, defaultValue) {
  46. var value = localStorage.getItem(name);
  47. if (!value)
  48. return defaultValue;
  49. var type = value[0];
  50. value = value.substring(1);
  51. switch (type) {
  52. case 'b':
  53. return value == 'true';
  54. case 'n':
  55. return Number(value);
  56. default:
  57. return value;
  58. }
  59. }
  60.  
  61. GM_log = function(message) {
  62. console.log(message);
  63. }
  64.  
  65. GM_registerMenuCommand = function(name, funk) {
  66. //todo
  67. }
  68.  
  69. GM_setValue = function(name, value) {
  70. value = (typeof value)[0] + value;
  71. localStorage.setItem(name, value);
  72. }
  73. }
  74.  
  75. //define
  76. function $(selector, root) {
  77. if (!root) root = document.body;
  78. return root.querySelector(selector);
  79. }
  80.  
  81. function $$(selector, root) {
  82. if (!root) root = document.body;
  83. var result = root.querySelectorAll(selector);
  84. var a = [];
  85. for (var i = 0, l = result.length; i < l; i++)
  86. a.push(result[i]);
  87. return a;
  88. }
  89.  
  90. function x(xpath, root) {
  91. if (!root) root = document.body;
  92. return document.evaluate(xpath, root, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  93. }
  94.  
  95. function X(xpath, root) {
  96. if (!root) root = document.body;
  97. var result = document.evaluate(xpath, root, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
  98. var a = [], item;
  99. while (item = result.iterateNext())
  100. a.push(item);
  101. return a;
  102. }
  103.  
  104. //main
  105. if (!$('[name="board"]')) return;
  106.  
  107. if (!String.trim)//lol opera
  108. String.prototype.trim = function() {
  109. return this.replace(/^\s+|\s+$/g,"");
  110. }
  111.  
  112. GM_addStyle("\
  113. #thread_filter { color: inherit; text-align: right; font-size:16px; z-index:1; }\
  114. #thread_filter > div:first-child { cursor: move; }\
  115. #thread_filter > div:not(:first-child) > span,\
  116. #thread_filter label,\
  117. #thread_filter a\
  118. { cursor: pointer }\
  119. #thread_filter .autohide { display: none }\
  120. #thread_filter:hover .autohide,\
  121. #thread_filter:active .autohide\
  122. { display: block }\
  123. #thread_filter > div,\
  124. #thread_filter.reply.autohide:not(:hover) > div\
  125. { padding: 0 5px 0 0; }\
  126. #thread_filter.reply > div:first-child { padding: 10px 10px 0 10px }\
  127. #thread_filter.reply > div:last-child { padding: 0 10px 10px 10px }\
  128. #thread_filter.reply > div:not(:first-child):not(:last-child) { padding: 0 10px 0 10px }\
  129. #thread_filter.reply:not(.autohide),\
  130. #thread_filter.reply.autohide:hover\
  131. { border: 2px ridge; }\
  132. #thread_filter.autohide:not(:hover)\
  133. { background: transparent; }\
  134. ")
  135.  
  136. var dialog = document.createElement('div');
  137. dialog.innerHTML = '\
  138. <div>\
  139. <span></span><br>\
  140. <span></span>\
  141. </div>\
  142. <div>\
  143. <select></select> <label>Fappe Tyme<input type="checkbox"></label><br>\
  144. <span>Name</span> <input><br>\
  145. <span>Tripcode</span> <input><br>\
  146. <span>Email</span> <input><br>\
  147. <span>Subject</span> <input><br>\
  148. <span>Comment</span> <input><br>\
  149. <span>File</span> <input><br>\
  150. </div>\
  151. <div style="display: none;">\
  152. <label>Min Width <input maxlength="4" size="2"></label><br>\
  153. <label>Min Height <input maxlength="4" size="2"></label><br>\
  154. <label>Manual Filtering<input type="checkbox"></label><br>\
  155. <label>Global Default<input type="checkbox"></label><br>\
  156. <label>Show Stubs<input type="checkbox"></label><br>\
  157. <label>Auto Tyme<input type="checkbox"></label><br>\
  158. <label>Alternate Skin<input type="checkbox"></label><br>\
  159. <label>Sticky<input type="checkbox"></label><br>\
  160. </div>\
  161. <div>\
  162. <a title="The characters .*+?^${}()|[]/\\ are RegEx operators. Prefix them with a backslash to make them behave normally (? -> \\?).">hide</a> \
  163. <a title="Show filtered posts">show</a> \
  164. <a title="Switch between main/advanced controls">adv</a> \
  165. <a title="Auto-hide dialog box">auto</a>\
  166. </div>';
  167. dialog.id = 'thread_filter';
  168. dialog.style.position = GM_getValue('Sticky', true) ? 'fixed' : 'absolute';
  169. if (GM_getValue('right', true))
  170. dialog.style.right = GM_getValue('right', 0);
  171. else
  172. dialog.style.left = GM_getValue('left');
  173. if (GM_getValue('top', true))
  174. dialog.style.top = GM_getValue('top', 0);
  175. else
  176. dialog.style.bottom = GM_getValue('bottom');
  177.  
  178. const reply = /res|read|archive\/|thread/.test(window.location.pathname);//imageboard|textboard|suptgarchive|4chanarchive+easymodo
  179. try{const site = window.location.hostname.match(/\.(\w+)/)[1]} catch(e){};// using try/catch because my saved test pages don't have url formatted filneames
  180. const server = location.hostname.match(/(\w+)?/)[0];
  181. const tripx =
  182. site == 'easymodo' ? ".//span[@class='trip']" :
  183. server == 'dis' ? './/span[@class="trip"]' :
  184. "./span[@class='trip']|./a/span[@class='trip']";
  185. //we can't just use the dis xpath because on the imageboards,
  186. // replies are children of the OP, and we don't want to filter
  187. // the entire thread just because of one reply.
  188. const filex = site == 'easymodo' ? "./span" : "./div[@class='files']";
  189. const imagex = site == 'easymodo' ? ".//img[@class='post-image']" : ".//img[@class='post-image']|//span[@class='tn_reply' or @class='tn_thread']";
  190. switch (site) {
  191. case 'thisisnotatrueending':
  192. var board = '\/tg\/';
  193. break;
  194. case 'easymodo':
  195. board = window.location.pathname.match(/\.pl(\/\w+)/)[1] + '/';
  196. break;
  197. default:// use .+? for i18n.
  198. board = window.location.pathname.match(/(\/read)?(\/.+?\/)/)[2];
  199. }
  200. const manual = GM_getValue('Manual Filtering', true);
  201. const stubs = GM_getValue('Show Stubs');
  202. var replies = X('//div[@class="post reply"]');
  203. //console.log(replies);
  204. var imageCount = X(imagex).length;
  205. var threads = X("./form/div/div[@id!='footer'][not(contains(@id,'hidden'))]"); //MOD
  206. var posts = $$('.post');//Text Boards
  207. var disSubjects = $$('span.replies + a');
  208. var hideCount = 0;
  209. var listBoard = board;
  210. var replyHidden = JSON.parse(GM_getValue(board + 'manual', '[]'));
  211. var now = new Date().getTime();
  212. var cutoff = now - (7 * 24 * 60 * 60 * 1000);//prune after seven days
  213. while (replyHidden.length && replyHidden[0].timestamp < cutoff)
  214. replyHidden.shift();
  215. GM_setValue(board + 'manual', JSON.stringify(replyHidden));
  216.  
  217. var postCount = (posts.length || threads.length) ? replies.length : $$('blockquote').length;
  218.  
  219. $('div:first-child', dialog).addEventListener('mousedown', startMove, true);
  220. $('div:first-child > span:first-child', dialog).textContent = 'Images: ' + imageCount + ' Posts: ' + postCount;
  221.  
  222. var list = $('select', dialog);
  223. list.addEventListener('mouseup', loadValues, true);//the 'change' event is kinda weird.
  224. list.addEventListener('keyup', loadValues, true);
  225.  
  226. var option = document.createElement('option');
  227. option.textContent = 'global';
  228. list.appendChild(option);
  229. option = document.createElement('option');
  230. option.textContent = board;
  231. list.appendChild(option);
  232. if (!GM_getValue('Global Default'))
  233. option.selected = true;
  234.  
  235. var remainingBoards = GM_getValue('boardList', '').replace(board, '').match(/\/\w+\//g);
  236. for (var i in remainingBoards) {
  237. var option = document.createElement('option');
  238. option.textContent = remainingBoards[i];
  239. list.appendChild(option);
  240. }
  241.  
  242. var filters = $$('div:nth-child(2) input:not([type])', dialog);
  243. for (var i = 0, l = filters.length; i < l; i++) {
  244. var span = filters[i].previousElementSibling;
  245. span.addEventListener('click', expandInput, true);
  246. var name = span.textContent;
  247. filters[i].value = GM_getValue(list.value + name, '');
  248. filters[i].addEventListener('keypress', function(event) { if (event.keyCode == 13) applyF() }, true);
  249. }
  250.  
  251. var boxes = $$('input[type="checkbox"]', dialog);
  252. var hideText = boxes[0];// Expand Images can get added
  253. if (GM_getValue('Auto Tyme'))
  254. hideText.checked = GM_getValue('Fappe Tyme');
  255. hideText.addEventListener('click', switcher, true);
  256. for (var i = 1, l = boxes.length; i < l; i++) {
  257. var text = boxes[i].previousSibling.nodeValue;
  258. var defaultValue = false;
  259. switch (text) {
  260. case 'Manual Filtering':
  261. defaultValue = true;
  262. break;
  263. case 'Sticky':
  264. defaultValue = true;
  265. break;
  266. }
  267. boxes[i].checked = GM_getValue(text, defaultValue);
  268. boxes[i].addEventListener('click', switcher, true);
  269. }
  270.  
  271. var dimensions = $$('input[size]', dialog);
  272. for (var i = 0, l = dimensions.length; i < l; i++) {
  273. dimensions[i].value = GM_getValue(dimensions[i].previousSibling.nodeValue.trim(), 0);
  274. }
  275.  
  276. var anchors = $$('a', dialog);
  277. anchors[0].addEventListener('click', applyF, true);
  278. anchors[1].addEventListener('click', reset, true);
  279. anchors[2].addEventListener('click', advF, true);
  280. anchors[3].addEventListener('click', autoHideF, true);
  281.  
  282. var omitted = $$('.omittedposts');
  283. for (var i = 0, l = omitted.length; i < l; i++) {//getPosts on thread collapse. Does this work w/ 4chan x?
  284. omitted[i].addEventListener('DOMCharacterDataModified', function() { if (/^\d/.test(this.textContent)) getPosts() }, true);//4chan extension
  285. var button = omitted[i].previousSiblingElement;
  286. if (button)
  287. button.addEventListener('DOMAttrModified', function() { if (this.textContent=='+') getPosts() }, true);
  288. }
  289.  
  290. if (manual)
  291. addReplyHiding(document.body);
  292. //document.body.addEventListener('DOMNodeInserted', function(e){if(e.target.nodeName=='TABLE') getPosts($('.reply', e.target))}, true);
  293. window.$(document).on('new_post', function(e, post) {
  294. getPosts();
  295. applyF();
  296. });
  297. autoHideF();
  298. document.body.appendChild(dialog);
  299. applyF();
  300.  
  301. //functions
  302.  
  303. function addReplyHiding(root) {
  304. var spans = $$('[id^=norep]', root);
  305. for (var i = 0, el; el = spans[i]; i++) {
  306. var toggle = document.createElement('a');
  307. toggle.style.cursor = 'pointer';
  308. toggle.className = 'pointer';
  309. toggle.addEventListener('click', handleReply, true);
  310. toggle.textContent = 'Hide';
  311. el.parentNode.insertBefore(toggle, el.nextSibling);
  312. el.parentNode.insertBefore(document.createTextNode(' '), toggle);
  313. }
  314. }
  315.  
  316. function hideReply(toggle, bq, click) {
  317. if (stubs) {
  318. var stb, txt;
  319. bq.style.display = 'none';
  320. bq.nextSibling.style.display = 'none';
  321. if (!$('.filter_stub', bq.previousSibling)) {
  322. stb = document.createElement("div");
  323. lbl = $('label', $('.intro', bq));
  324. no = $('[class="post_no"]', $('.intro', bq));
  325. stb.innerHTML = '<a class="filter_stub" style="text-decoration: none; margin-left: 4px; cursor: pointer;">'+
  326. ' [ - ] - ' + lbl.textContent + ' ' + no.textContent + no.nextSibling.textContent+
  327. '</a>';
  328. $('[class="post_anchor"]').parentNode.insertBefore(stb, bq);
  329. //stb.addEventListener('click', showReply($('.delete', stb.nextSibling), stb.nextSibling, false), false);
  330. }
  331. } else {
  332. //toggle.parentNode.parentNode.style.display = 'none';
  333. //toggle.parentNode.parentNode.nextSibling.style.display = 'none';
  334. //bq.style.display = 'none';
  335. //bq.previousSibling.style.display = 'none';
  336. }
  337. if (click) {
  338. replyHidden.push({
  339. id: bq.parentNode.id,
  340. timestamp: new Date().getTime()
  341. });
  342. GM_setValue(board + 'manual', JSON.stringify(replyHidden));
  343. }
  344. }
  345.  
  346. function showReply(toggle, bq, click) {
  347. bq.style.display = '';
  348. bq.nextSibling.style.display = '';
  349. //toggle.textContent = 'Hide';
  350. //bq.previousSibling.style.display = '';
  351. /* if ($('.filter_stub', bq.previousSibling)) {
  352. $('[class="post_anchor"]').removeChild(bq.previousSibling);
  353. }*/
  354. if ($('.filter_stub', bq.previousSibling)) {
  355. var _ref = $('.filter_stub', bq.previousSibling);
  356. var node = _ref.parentNode;
  357. node.parentNode.removeChild(node);
  358. }
  359. if (click) {
  360. var id = bq.parentNode.id;
  361. for (var i in replyHidden) {
  362. if (replyHidden[i].id == id)
  363. replyHidden.splice(i, 1);
  364. }
  365. GM_setValue(board + 'manual', JSON.stringify(replyHidden));
  366. }
  367. }
  368.  
  369. function handleReply() {
  370. var bq = this;//x(".body", this);
  371. if (this.textContent == 'Show')
  372. showReply(this, bq, true);
  373. else
  374. hideReply(this, bq, true);
  375. }
  376.  
  377. function getPosts(el) {
  378. if (el) {
  379. if (manual)
  380. addReplyHiding(el);
  381. var tempImage = x(".//img[@class='post-image']|.//span[@class='tn_reply']", el);
  382. if (tempImage)
  383. imageCount++;
  384. if (hideText.checked && !tempImage) {
  385. el.style.display = 'none';
  386. hideCount++;
  387. } else if (spam(el)) {
  388. el.style.display = 'none';
  389. hideCount++;
  390. }
  391. replies.push(el);
  392. var hideSpan = $('div:first-child span:last-child', dialog);
  393. hideSpan.textContent = 'Hidden Posts: ' + hideCount;
  394. } else {
  395. imageCount = X(imagex).length;
  396. replies = X('//div[@class="post reply"]');
  397. hideCountF();
  398. }
  399. var postCount = reply ? replies.length + 1 : threads.length ? threads.length + replies.length : $$('blockquote').length;
  400. $('div:first-child > span:first-child', dialog).textContent = 'Images: ' + imageCount + ' Posts: ' + postCount;
  401. }
  402.  
  403. function reset() {
  404. if (!reply)
  405. for (var i = 0; i < threads.length; i++) {
  406. var prev = threads[i].previousSibling;
  407. if (!prev || prev.nodeName == 'HR' || /^?/.test(prev.textContent)) {
  408. threads[i].parentNode.style.display = ''; //MOD
  409. threads[i].parentNode.nextSibling.style.display = ''; //MOD
  410. }
  411. }
  412. if (manual && stubs)
  413. for (var i in replies)
  414. showReply($('.delete', replies[i]), replies[i]);
  415. else
  416. for (var i in replies) {
  417. replies[i].parentNode.style.display = '';
  418. replies[i].previousSibling.style.display = '';
  419. }
  420. for (var i = 0; i < posts.length; i++) {
  421. posts[i].parentNode.parentNode.style.display = '';
  422. posts[i].style.display = '';
  423. }
  424. if (hideText.checked)
  425. hideTextF(true);
  426. else if (this.nodeName)//Don't call hideCountF() in the middle of applyF()
  427. hideCountF();
  428. }
  429.  
  430. function switcher() {
  431. var name = this.previousSibling.nodeValue;
  432. var checked = this.checked;
  433. GM_setValue(name, checked);
  434. switch(name) {
  435. case 'Alternate Skin':
  436. skinF(checked);
  437. break;
  438. case 'Fappe Tyme':
  439. hideTextF(checked);
  440. break;
  441. case 'Sticky':
  442. dialog.style.position = checked ? 'fixed' : 'absolute';
  443. break;
  444. }
  445. }
  446.  
  447. function hideTextF(checked) {
  448. if (checked) {
  449. const minWidth = GM_getValue('Min Width');
  450. const minHeight = GM_getValue('Min Height');
  451. for (var i in replies) {
  452. if (!x(filex, replies[i]))
  453. replies[i].parentNode.style.display = 'none';
  454. else if (site != 'easymodo') {
  455. var type = x("./span[@class='filesize']/a", replies[i]);
  456. if (type.textContent.match(/[a-z]+/) == 'gif')
  457. continue;
  458. var size = x("./span[@class='filesize']/text()[2]", replies[i]);
  459. size = size.textContent.match(/(\d+)x(\d+)/);
  460. if (Number(size[1]) < minWidth)
  461. replies[i].parentNode.style.display = 'none';
  462. else if (Number(size[2]) < minHeight)
  463. replies[i].parentNode.style.display = 'none';
  464. }
  465. }
  466. hideCountF();
  467. } else {
  468. if (manual && stubs)
  469. for (var i in replies)
  470. replies[i].parentNode.style.display = '';
  471. else
  472. applyF();
  473. }
  474. }
  475.  
  476. var specialCom;
  477. var specialTag;
  478. var names;
  479. var tripcodes;
  480. var emails;
  481. var subjects;
  482. var comments;
  483. var files;
  484. function applyF() {
  485. var prefix = list.value;
  486. for (var i = 0, l = filters.length; i < l; i++)
  487. GM_setValue(prefix + filters[i].previousElementSibling.textContent, filters[i].value);
  488. for (var i = 0, l = dimensions.length; i < l; i++) {
  489. if (!dimensions[i].value.length || isNaN(dimensions[i].value) || dimensions[i].value < 0)
  490. dimensions[i].value = 0;
  491. GM_setValue(dimensions[i].previousSibling.nodeValue.trim(), dimensions[i].value);
  492. }
  493.  
  494. specialTag = [];
  495. specialCom = [];
  496. names = fetch('Name');
  497. tripcodes = fetch('Tripcode');
  498. emails = fetch('Email');
  499. subjects = fetch('Subject');
  500. comments = fetch('Comment');
  501. files = fetch('File');
  502. var nonEmpty;
  503.  
  504. function fetch(el) {
  505. var temp = GM_getValue(board + el);
  506. if (temp)
  507. nonEmpty = true;
  508. else
  509. GM_deleteValue(board + el);
  510. temp += ';' + GM_getValue('global' + el, '');
  511. var rawMatches = temp.match(/[^\s;][^;]*/g);
  512. var filterList = new Array;
  513. if (rawMatches) {
  514. if (el == 'Comment')
  515. for (var i = 0, l = rawMatches.length; i < l; i++) {
  516. var raw = rawMatches[i];
  517. var tempArray = raw.match(/(?: -([fhi]{1,3}))?( ?#.*)?$/);
  518. var match = tempArray[0],
  519. tags = tempArray[1];
  520. s = raw.substr(0, raw.length - match.length);
  521. if (tags) {
  522. var filter = new RegExp(s, /i/.test(tags) ? '' : 'i');
  523. tags = tags.replace(/i/, '');
  524. if (tags.length) {
  525. specialTag.push(tags);
  526. specialCom.push(filter);
  527. } else
  528. filterList.push(filter);
  529. } else
  530. filterList.push(new RegExp(s, 'i'));
  531. }
  532. else
  533. for (var i = 0, l = rawMatches.length; i < l; i++) {
  534. raw = rawMatches[i];
  535. tempArray = raw.match(/(?: -(i))?( ?#.*)?$/);
  536. match = tempArray[0],
  537. tags = tempArray[1];
  538. s = raw.substr(0, raw.length - match.length);
  539. filterList.push(new RegExp(s, tags ? '' : 'i'));
  540. }
  541. }
  542. return filterList;
  543. }
  544. var boardList = GM_getValue('boardList', '');
  545. if (nonEmpty && prefix != 'global' && boardList.indexOf(prefix) == -1)
  546. GM_setValue('boardList', boardList + prefix);
  547. else if (!nonEmpty)
  548. GM_setValue('boardList', boardList.replace(prefix, ''));
  549. reset();
  550. if (!reply) {
  551. for (var i in threads) {
  552. if (spam(threads[i])) {
  553. threads[i].parentNode.style.display = 'none'; //MOD
  554. threads[i].parentNode.nextSibling.style.display = 'none'; //MOD
  555. }
  556. }
  557. }
  558. if (manual && stubs) {
  559. for (var i in replies) {
  560. //console.log($('.delete', replies[i]) +' - '+ $('.body', replies[i]));
  561. if (spam(replies[i]))
  562. hideReply($('.delete', replies[i]), replies[i]);
  563. }
  564. } else {
  565. for (var i in replies)
  566. if (spam(replies[i])) {
  567. replies[i].style.display = 'none';
  568. replies[i].previousSibling.style.display = 'none';
  569. }
  570. }/*
  571. posts.forEach(function (post) {
  572. if (spam(post)) {
  573. if ($('.postnum', post).textContent == 1 && !reply)//OP
  574. post.parentNode.parentNode.style.display = 'none';
  575. else
  576. post.style.display = 'none';
  577. }
  578. });*/
  579. if (subjects) {//this is kind of ugly
  580. disSubjects.forEach(function (sub) {
  581. for (j in subjects)
  582. if (subjects[j].test(sub.textContent))
  583. sub.parentNode.parentNode.parentNode.parentNode.style.display = 'none';
  584. });
  585. }
  586.  
  587. hideCountF();
  588. }
  589.  
  590. function spam(el) {
  591. var temp = el.id;
  592. for (var i in replyHidden) {
  593. if (temp == replyHidden[i].id)
  594. return true;
  595. }
  596. var bq = $('.body', el);
  597. if (!bq) return false; //MOD
  598. bqTC = bq.textContent;
  599. bqIH = bq.innerHTML;
  600. for (var i in comments)
  601. if (comments[i].test(bqTC))
  602. return true;
  603. if (specialCom)
  604. for (var i in specialCom) {
  605. if (/f/.test(specialTag[i]) && x(filex, el))
  606. continue;
  607. temp = /h/.test(specialTag[i]) ? bqIH : bqTC;
  608. if (specialCom[i].test(temp))
  609. return true;
  610. }
  611. var n = x(".//span[@class='name' or @class='name']", el);
  612. var t = $('.trip', el);
  613. for (var i in names)
  614. if (names[i].test(n.textContent))
  615. return true;
  616. if (t)
  617. for (var i in tripcodes)
  618. if (tripcodes[i].test(t.textContent))
  619. return true;
  620. if (files) {
  621. temp = x(filex, el);
  622. if (temp)
  623. for (j in files)
  624. if (files[j].test(temp.textContent))
  625. return true;
  626. } if (tripcodes) {
  627. //temp = x(tripx, el);
  628. //if (_t)
  629. // for (var i in tripcodes)
  630. // if (tripcodes[i].test(_t.textContent))
  631. // return true;
  632. } if (emails) {
  633. temp = $('a', n);
  634. if (temp)
  635. for (j in emails)
  636. if (emails[j].test(decodeURIComponent(temp.href.slice(7))))//slice off mailto:
  637. return true;
  638. } if (subjects) {
  639. temp = el.nodeName == "DIV" ? $('.filetitle', el) : $('.replytitle', el);
  640. if (temp)
  641. for (j in subjects)
  642. if (subjects[j].test(temp.textContent))
  643. return true;
  644. }
  645. return false;
  646. }
  647.  
  648. //GUI
  649. var height;
  650. var initial_mouseX;
  651. var initial_mouseY;
  652. var initial_boxX;
  653. var initial_boxY;
  654. function startMove(event) {
  655. height = Math.min(document.documentElement.clientHeight, document.body.clientHeight);
  656. initial_mouseX = event.clientX;
  657. initial_mouseY = event.clientY;
  658. if (dialog.style.right)
  659. initial_boxX = parseInt(dialog.style.right);
  660. else
  661. initial_boxX = document.body.clientWidth - dialog.offsetWidth - parseInt(dialog.style.left);
  662. if (dialog.style.top)
  663. initial_boxY = parseInt(dialog.style.top);
  664. else
  665. initial_boxY = height - dialog.offsetHeight - parseInt(dialog.style.bottom);
  666. document.addEventListener('mousemove', move, true);
  667. document.addEventListener('mouseup', endMove, true);
  668. }
  669.  
  670. function move(event) {
  671. var right = initial_boxX + initial_mouseX - event.clientX;
  672. var left = document.body.clientWidth - dialog.offsetWidth - right;
  673. dialog.style.left = '';
  674. if (left < right) {
  675. dialog.style.right = '';
  676. dialog.style.left = left + 'px';
  677. if (left < 25)
  678. dialog.style.left = 0;
  679. } else if (right < 25)
  680. dialog.style.right = 0;
  681. else
  682. dialog.style.right = right + 'px';
  683.  
  684. var top = initial_boxY - initial_mouseY + event.clientY;
  685. var bottom = height - dialog.offsetHeight - top;
  686. dialog.style.bottom = '';
  687. if (bottom < top) {
  688. dialog.style.top = '';
  689. dialog.style.bottom = bottom + 'px';
  690. if (bottom < 25)
  691. dialog.style.bottom = 0;
  692. } else if (top < 25)
  693. dialog.style.top = 0;
  694. else
  695. dialog.style.top = top + 'px';
  696. }
  697.  
  698. function endMove() {
  699. document.removeEventListener('mousemove', move, true);
  700. document.removeEventListener('mouseup', endMove, true);
  701. GM_setValue('right', dialog.style.right);
  702. GM_setValue('left', dialog.style.left);
  703. GM_setValue('top', dialog.style.top);
  704. GM_setValue('bottom', dialog.style.bottom);
  705. }
  706.  
  707. function expandInput() {
  708. var input = this.nextElementSibling;
  709. if (input.style.display != 'none') {
  710. input.style.display = 'none';
  711. var textArea = document.createElement('textarea');
  712. textArea.cols = 23;
  713. textArea.rows = 5;
  714. textArea.value = input.value;
  715. textArea.addEventListener('change', function() { this.previousElementSibling.value = this.value }, true);
  716. this.parentNode.insertBefore(textArea, input.nextSibling);
  717. this.appendChild(document.createElement('br'));
  718. textArea.focus();
  719. } else {
  720. this.removeChild(this.lastChild);//remove <br>
  721. this.parentNode.removeChild(input.nextSibling);//remove textArea
  722. input.style.display = '';
  723. input.focus();
  724. }
  725. }
  726.  
  727. function autoHideF() {
  728. var autoHide = $('a:nth-of-type(4)', dialog);
  729. var adv = $('a:nth-of-type(3)', dialog);
  730. var hideSpan = $('div:first-child span:last-child', dialog);
  731. var mainDiv = $('div:nth-child(2)', dialog);
  732. var advDiv = $('div:nth-child(3)', dialog);
  733. var buttonsDiv = $('div:last-child', dialog);
  734. var skin = GM_getValue('Alternate Skin');
  735. if (this.nodeName)
  736. GM_setValue('autohide', !GM_getValue('autohide'));
  737. if (GM_getValue('autohide')) {
  738. autoHide.innerHTML = '<b>auto</b>';
  739. hideSpan.className = 'autohide';
  740. adv.textContent == 'adv' ? mainDiv.className = 'autohide' : advDiv.className = 'autohide';
  741. buttonsDiv.className = 'autohide';
  742. dialog.className = skin ? 'autohide' : 'reply autohide';
  743. } else {
  744. autoHide.innerHTML = 'auto';
  745. hideSpan.className = '';
  746. mainDiv.className = '';
  747. advDiv.className = '';
  748. buttonsDiv.className = '';
  749. dialog.className = skin ? '' : 'reply';
  750. }
  751. }
  752.  
  753. function advF() {
  754. var mainDiv = $('div:nth-child(2)', dialog);
  755. var advDiv = $('div:nth-child(3)', dialog);
  756. if (this.textContent == 'adv') {
  757. this.textContent = 'main';
  758. mainDiv.style.display = 'none';
  759. advDiv.style.display = '';
  760. if (GM_getValue('autohide')) {
  761. mainDiv.className = '';
  762. advDiv.className = 'autohide';
  763. }
  764. } else {
  765. this.textContent = 'adv';
  766. mainDiv.style.display = '';
  767. advDiv.style.display = 'none';
  768. if (GM_getValue('autohide')) {
  769. mainDiv.className = 'autohide';
  770. advDiv.className = '';
  771. }
  772. }
  773. }
  774.  
  775. function skinF(useClear) {
  776. if (GM_getValue('autohide'))
  777. dialog.className = useClear ? 'autohide' : 'reply autohide';
  778. else
  779. dialog.className = useClear ? '' : 'reply';
  780. }
  781.  
  782. function loadValues() {
  783. for (var i = 0, l = filters.length; i < l; i++)
  784. GM_setValue(listBoard + filters[i].previousElementSibling.textContent, filters[i].value);
  785. listBoard = list.value;
  786. for (var i = 0, l = filters.length; i < l; i++)
  787. filters[i].value = GM_getValue(listBoard + filters[i].previousElementSibling.textContent, '');
  788. var textArea = $$('textarea', dialog);
  789. for (var i = 0, l = textArea.length; i < l; i++)
  790. textArea[i].value = textArea[i].previousSibling.value;
  791. }
  792.  
  793. function hideCountF() {
  794. hideCount = 0;/*
  795. for (var i = 0; i < threads.length; i++)
  796. if (threads[i].style.display)
  797. hideCount++;*/
  798. if (manual && stubs) {
  799. for (var i in replies)
  800. if ($('.body', replies[i]).style.display)
  801. hideCount++;
  802. } else
  803. for (var i in replies)
  804. if (replies[i].style.display)
  805. hideCount++;/*
  806. for (var i = 0; i < posts.length; i++)
  807. if (posts[i].style.display)
  808. hideCount++;
  809. */
  810. $('span:last-child', dialog).textContent = 'Hidden Posts: ' + hideCount;
  811. }
  812. };
  813.  
  814. d = document;
  815.  
  816. on = function (el, type, handler) {
  817. return el.addEventListener(type, handler, false);
  818. };
  819.  
  820. off = function (el, type, handler) {
  821. return el.removeEventListener(type, handler, false);
  822. };
  823.  
  824. ready = function(fc) {
  825. var cb;
  826. if (d.readyState !== 'loading') {
  827. fc();
  828. return ;
  829. }
  830. cb = function () {
  831. off(d, 'DOMContentLoaded', cb);
  832. return fc();
  833. };
  834. return on(d, 'DOMContentLoaded', cb);
  835. };
  836.  
  837. ready(main);
  838.  
  839. }).call(this);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement