Guest User

Untitled

a guest
Nov 24th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.96 KB | None | 0 0
  1.  
  2.  
  3. /*
  4. * q.js v2018.3-2
  5. * http://anonsw.github.io/8chjs/
  6. */
  7.  
  8. // Settings
  9. var qflair = ''; // Examples: REAL, →
  10. var qcolor = '#ffc';
  11. var youcolor = '#fcc';
  12. var scrollcolor = 'rgba(153, 153, 153, 0.6)';
  13. var scrollbackcolor = '#333';
  14. var scrolltime = 400; // ms
  15. var updateDelay = 200; // ms
  16. var sidenavWidth = 20; // px
  17.  
  18. var floodEnabled = true;
  19. var floodThreshold = 15; // min # posts before beginning fade
  20. var floodVanish = 25; // max # posts before completed fade/hide
  21. var floodBehavior = 'fade'; // hide, fade
  22.  
  23. var rateHistoryLen = 50; // Data points on chart
  24. var rateAvgLen = 10; // Number of data points to average for instantaneous rate
  25.  
  26. /* House keeping variables */
  27. var qposts = [];
  28. var allqposts = [];
  29. var currq = -1;
  30. var youposts = [];
  31. var curryou = -1;
  32. var qnavposts = [];
  33. var younavposts = [];
  34. var ctx;
  35. var borderSz;
  36. var scrollWd;
  37. var minheight;
  38. var ratehistory = [];
  39.  
  40. // Suggestions from 589388.html#590283
  41. // ...shill detection features, such as
  42. // easily knowing the proportion of posts from a user that don't link.
  43. // I'd want to know any ID that was posting > 1/3 posts targetting noone.
  44.  
  45. // TODO: Behavior for post hover should be to show original post visual before all q.js mods
  46. // TODO: Add flags to turn on/off features
  47. // TODO: Auto-filter/shade? Custom-regexes?
  48. // Ex. If post has Q's trip code as name, auto-filter/shade post and responses
  49. // TODO: Custom-regex -> post color/fade (auto-filter by selecting text and choosing new menu item?)
  50. // Examples: daily reminder, guys, check this out, shill, get out, filtered, tell us more, archive everything
  51. // TODO: Manual shade
  52. // TODO: remove Q trip codes from post content?
  53. // TODO: remove Q from end of post content if not a Q post?
  54. // TODO: recognize all of known Q trip codes? (make to sure to exclude known comps)
  55. // TODO: Links to reset on current Q/(you) post
  56. // TODO: Link to go to latest post (end key doesn't always work, but try capturing that as well?)
  57. // TODO: Keyboard shortcuts for navigation
  58. // TODO: Current/Total overall post navigation
  59. // TODO: Remap end key to always go to end of page
  60. // TODO: Check box for each post to mark as "read", "spam", ?
  61. // TODO: Autocorrect all-caps posts (50% threshold)?
  62. // TODO: Correct broken links but remove referral when clicked?
  63. // TODO: Make flood post fading non-linear to give leniency to posters just passing flood threshold
  64. // TODO: Penalize reposts in flood detection (if id's different, merge?) ?
  65. // TODO: Scorecard of posters orderd by post count (post rate, reply count, ...)?
  66. // TODO: Color/shade posts where there are no references and no question marks
  67. // TODO: If Q or trip used in name field, strike them out or replace with Anonymous?
  68. // TODO: embedded posts in Q posts don't have background-color and inherit Q color, fix?
  69.  
  70. /* Case insensitive contains selector for finding yous. SO #8746882 */
  71. jQuery.expr[":"].icontains = jQuery.expr.createPseudo(function (arg) {
  72. return function (elem) {
  73. return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
  74. };
  75. });
  76.  
  77. /* Display a replies counter overlay in the top right corner */
  78. $(function(){
  79. $('head').append('<style>#thread_stats_posts_ovl { '+
  80. 'position:fixed;top:35px;right:35px;'+
  81. 'font:38px sans-serif;opacity:0.5;color:#f60;}</style>');
  82. $('body').append('<div id="thread_stats_posts_ovl"/>');
  83. function copyStats() { $('#thread_stats_posts_ovl').
  84. text($('#thread_stats_posts').text());}
  85. $(document).on('new_post',copyStats); copyStats();});
  86.  
  87. /* On scroll stop. SO #9144560 */
  88. (function ($) {
  89. var on = $.fn.on, timer;
  90. $.fn.on = function () {
  91. var args = Array.apply(null, arguments);
  92. var last = args[args.length - 1];
  93.  
  94. if (isNaN(last) || (last === 1 && args.pop())) return on.apply(this, args);
  95.  
  96. var delay = args.pop();
  97. var fn = args.pop();
  98.  
  99. args.push(function () {
  100. var self = this, params = arguments;
  101. clearTimeout(timer);
  102. timer = setTimeout(function () {
  103. fn.apply(self, params);
  104. }, delay);
  105. });
  106.  
  107. return on.apply(this, args);
  108. };
  109. }(this.jQuery || this.Zepto));
  110.  
  111. /* Scroll to element */
  112. function myScrollTo(el) {
  113. $('html, body').animate({
  114. scrollTop: $(el).offset().top - $('div.boardlist').height()
  115. }, scrolltime);
  116. }
  117.  
  118. /* Highlight you references */
  119. function highlightYouRefs() {
  120. $('div.body:icontains("(You)")').each(function() {
  121. $(this).parents('div.post').first().css('background-color',youcolor);
  122. });
  123. return $.Deferred().resolve();
  124. }
  125.  
  126. // Set which posts are (you) posts
  127. function setYouPosts() {
  128. youposts = $.map($('div.post:not(.post-hover) > p.intro > label span.name > span.own_post, div.post:not(.post-hover) > div.body > p.body-line > small:icontains("(You)")'), function(el) {
  129. return $(el).closest('div.post');
  130. });
  131. return $.Deferred().resolve();
  132. }
  133.  
  134.  
  135. /* Remove invalid (you)'s */
  136. function removeInvalidYous() {
  137. $('div.body:icontains("(You)")').each(function() {
  138. $(this).find(':not(small)').contents().filter(function() { return this.nodeType == 3 }).each(function() {
  139. this.textContent = this.textContent.replace(/\(+ *You *\)+/ig, "you");
  140. });
  141. });
  142. return $.Deferred().resolve();
  143. }
  144.  
  145. /* Highlight Q posts */
  146. function highlightQ() {
  147. $(allqposts).each(function(idx,val) {
  148. var div = $(val).parents('div.post').first();
  149. if($(div).css('background-color') !== qcolor) {
  150. if(qflair !== "") {
  151. $(val).prepend(qflair + " ");
  152. }
  153. $(div).css('background-color', qcolor);
  154. }
  155. });
  156. return $.Deferred().resolve();
  157. }
  158.  
  159. /* Scroll to next Q */
  160. function nextq() {
  161. if(qposts.length > 0) {
  162. if(currq < qposts.length-1) {
  163. currq++;
  164. }
  165. myScrollTo($(qposts).get(currq));
  166. }
  167. }
  168.  
  169. /* Scroll to last Q */
  170. function lastq() {
  171. if(qposts.length > 0) {
  172. currq = qposts.length - 1;
  173. myScrollTo($(qposts).get(currq));
  174. }
  175. }
  176.  
  177. /* Scroll to previous Q */
  178. function prevq() {
  179. if(qposts.length > 0) {
  180. if(currq > 0) {
  181. currq--;
  182. }
  183. myScrollTo($(qposts).get(currq));
  184. }
  185. }
  186.  
  187. /* Scroll to first Q */
  188. function firstq() {
  189. if(qposts.length > 0) {
  190. currq = 0;
  191. myScrollTo($(qposts).get(currq));
  192. }
  193. }
  194.  
  195. /* Scroll to next (You) */
  196. function nextyou() {
  197. if(youposts.length > 0) {
  198. if(curryou < youposts.length-1) {
  199. curryou++;
  200. }
  201. myScrollTo($(youposts).get(curryou));
  202. }
  203. }
  204.  
  205. /* Scroll to last (You) */
  206. function lastyou() {
  207. if(youposts.length > 0) {
  208. curryou = youposts.length - 1;
  209. myScrollTo($(youposts).get(curryou));
  210. }
  211. }
  212.  
  213. /* Scroll to previous (You) */
  214. function prevyou() {
  215. if(youposts.length > 0) {
  216. if(curryou > 0) {
  217. curryou--;
  218. }
  219. myScrollTo($(youposts).get(curryou));
  220. }
  221. }
  222.  
  223. /* Scroll to first (You) */
  224. function firstyou() {
  225. if(youposts.length > 0) {
  226. curryou = 0;
  227. myScrollTo($(youposts).get(curryou));
  228. }
  229. }
  230.  
  231. /* Inserts Q navigation links */
  232. function qnav() {
  233. $('div.boardlist').append('<span>[ <a href="javascript:firstq();"><i class="fa fa-step-backward"></i></a> <a href="javascript:prevq();"><i class="fa fa-backward"></i></a> <span style="filter:brightness(70%);">Q</span> <span class="qcount">(?:?)</span> <a href="javascript:nextq();"><i class="fa fa-forward"></i></a> <a href="javascript:lastq();"><i class="fa fa-step-forward"></i></a> ]</span>');
  234. }
  235.  
  236. /* Inserts (You) navigation links */
  237. function younav() {
  238. $('div.boardlist').append('<span>[ <a href="javascript:firstyou();"><i class="fa fa-step-backward"></i></a> <a href="javascript:prevyou();"><i class="fa fa-backward"></i></a> <span style="filter:brightness(70%);">(You)</span> <span class="youcount">(?:?)</span> </span><a href="javascript:nextyou();"><i class="fa fa-forward"></i></a> <a href="javascript:lastyou();"><i class="fa fa-step-forward"></i></a> ]</span>');
  239. }
  240.  
  241. /* Inserts feature toggle links */
  242. function togglenav() {
  243. $('div.boardlist').append('<span>[ <a href="javascript:toggleFlood();">Turn Post Fading <span class="toggleFloodState">Off</span></a> ]</span>')
  244. }
  245.  
  246. function postratenav() {
  247. var height = $('div.boardlist').height() - 1;
  248. $('div.boardlist').append('<span>[ Post Rate: <span class="postRate">0</span> posts/min <canvas class="postRateChart"></canvas>]</span>')
  249. $('.postRate').css('color', $('div.boardlist a').css('color'));
  250. var charts = $('.postRateChart');
  251. $(charts).each(function() {
  252. $(this).css('width', '100px');
  253. $(this).css('height', height);
  254. $(this).css('vertical-align', 'middle');
  255. //$(this).css('border', '1px solid');
  256. //$(this).css('border-color', $('div.boardlist').css('color'));
  257. var gctx = $(this).get(0).getContext('2d');
  258. gctx.canvas.height = 20;
  259. gctx.canvas.width = 100;
  260. });
  261. }
  262.  
  263. /* Inserts side navigation */
  264. function sidenav() {
  265. $('body').append('<canvas id="sidenav"></canvas>');
  266. var nav = $('#sidenav');
  267. $(nav).css('position', 'fixed');
  268. $(nav).css('top', $('div.boardlist').height());
  269. $(nav).css('right', 0);
  270. $(nav).css('width', sidenavWidth);
  271. $(nav).css('height', $(window).height() - $('div.boardlist').height());
  272. $(nav).css('background-color', scrollbackcolor);
  273. $('body').css('margin-right', sidenavWidth);
  274. ctx = $('#sidenav').get(0).getContext('2d');
  275. //ctx.canvas.height = $(document).height() - $('div.boardlist').height();
  276. ctx.canvas.height = 2048;
  277. ctx.canvas.width = sidenavWidth;
  278. borderSz = 1;
  279. scrollWd = ctx.canvas.width / 2;
  280. }
  281.  
  282. /* Update navigation counts */
  283. function updateNavCounts() {
  284. var fontSize = -1;
  285. var lineHeight;
  286.  
  287. if(currq > qposts.length) { currq = qposts.length; }
  288. if(curryou > youposts.length) { curryou = youposts.length; }
  289.  
  290. for(i=0; i<qposts.length; i++) {
  291. var el = $(qposts).get(i);
  292. if(fontSize == -1) {
  293. fontSize = $(el).css('font-size');
  294. lineHeight = Math.floor(parseInt(fontSize.replace('px', '')) * 1.5);
  295. }
  296. if(($(el).offset().top + $(el).height() - 2.25*lineHeight) > $(window).scrollTop()) {
  297. currq = i;
  298. break;
  299. }
  300. }
  301.  
  302. for(i=0; i<youposts.length; i++) {
  303. var el = $(youposts).get(i);
  304. if(fontSize == -1) {
  305. fontSize = $(el).css('font-size');
  306. lineHeight = Math.floor(parseInt(fontSize.replace('px', '')) * 1.5);
  307. }
  308. if(($(el).offset().top + $(el).height() - 2.25*lineHeight) > $(window).scrollTop()) {
  309. curryou = i;
  310. break;
  311. }
  312. }
  313.  
  314. // TODO: check for duplicates and remove from counts
  315. $('.qcount').text("(" + (currq+1) + ":" + qposts.length + ")");
  316. $('.youcount').text("(" + (curryou+1) + ":" + youposts.length + ")");
  317. }
  318.  
  319. /* Update navigation graphics */
  320. function updateNavGraphics() {
  321. var sidenav = $('#sidenav');
  322. if(sidenav.length) {
  323. $(sidenav).css('height', $(window).height() - $('div.boardlist').height());
  324. minheight = ctx.canvas.height / ($(window).height() - $('div.boardlist').height()); // 1px
  325. ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  326.  
  327. // Draw nav q posts
  328. qnavposts = [];
  329. ctx.fillStyle = qcolor;
  330. for (i = 0; i < qposts.length; i++) {
  331. // TODO: check if we have already added post, don't draw it again
  332. var el = $(qposts).get(i);
  333. var height = $(el).height() / $(document).height() * ctx.canvas.height;
  334. if(height < minheight) height = minheight;
  335. qnavposts[i] = {
  336. x : borderSz,
  337. y : $(el).offset().top / $(document).height() * ctx.canvas.height,
  338. width : ctx.canvas.width - borderSz*2,
  339. height : height
  340. };
  341. ctx.fillRect(qnavposts[i].x, qnavposts[i].y, qnavposts[i].width, qnavposts[i].height);
  342. }
  343.  
  344. // Draw nav you posts
  345. younavposts = [];
  346. ctx.fillStyle = youcolor;
  347. for (i = 0; i < youposts.length; i++) {
  348. // TODO: check if we have already added post, don't add it again
  349. var el = $(youposts).get(i);
  350. var height = $(el).height() / $(document).height() * ctx.canvas.height;
  351. if(height < minheight) height = minheight;
  352. younavposts[i] = {
  353. x : borderSz,
  354. y : $(el).offset().top / $(document).height() * ctx.canvas.height,
  355. width : ctx.canvas.width - borderSz*2,
  356. height : height
  357. };
  358. ctx.fillRect(younavposts[i].x, younavposts[i].y, younavposts[i].width, younavposts[i].height);
  359. }
  360.  
  361. // Update nav window
  362. ctx.fillStyle = scrollcolor;
  363. ctx.fillRect(
  364. scrollWd / 2,
  365. $(window).scrollTop() / $(document).height() * ctx.canvas.height,
  366. scrollWd,
  367. $(window).height() / $(document).height() * ctx.canvas.height
  368. );
  369.  
  370. // Add red marker at bottom of >750 posts
  371. if($('#thread_stats_posts').text() > 750) {
  372. var barHeight = (4 * 2048) / ($(window).height() - $('div.boardlist').height());
  373. ctx.fillStyle = '#f66';
  374. ctx.fillRect(
  375. 0,
  376. ctx.canvas.height - barHeight,
  377. ctx.canvas.width,
  378. barHeight
  379. );
  380. }
  381. }
  382. }
  383.  
  384. function updateNavPostRate() {
  385. var posts = $('div.post').not('.post-hover');
  386. var startPost = posts.length - (rateHistoryLen + rateAvgLen) + 1;
  387. if(startPost < 1) startPost = 1;
  388. var start = $($($(posts).get(0)).find('.intro time').get(0)).attr('unixtime'); //$('div.post:first .intro time').attr('unixtime');
  389. ratehistory = [];
  390. timehistory = [];
  391. for(var i=startPost; i<posts.length; i++) {
  392. // TODO: check if we have already added post, don't add it again
  393. var step = $($($(posts).get(i)).find('.intro time').get(0)).attr('unixtime'); //$($('div.post .intro time').get(i)).attr('unixtime');
  394. timehistory[timehistory.length] = step;
  395. if(timehistory.length - rateAvgLen - 1 >= 0) {
  396. var avgend = timehistory[timehistory.length - 1];
  397. var avgstart = timehistory[timehistory.length - rateAvgLen - 1];
  398. ratehistory[ratehistory.length] = rateAvgLen / ((avgend - avgstart) / 60);
  399. } else {
  400. ratehistory[ratehistory.length] = 0;
  401. }
  402. }
  403. //console.log(ratehistory);
  404.  
  405. $('.postRate').text(ratehistory[ratehistory.length-1].toFixed(1));
  406.  
  407. if(ratehistory.length > rateAvgLen) {
  408. var maxRate = Math.max.apply(null, ratehistory);
  409. var minRate = Math.min.apply(null, ratehistory);
  410. //console.log("Max: " + maxRate);
  411. //console.log("Min: " + minRate);
  412. if(minRate > (maxRate - 0.5)) {
  413. minRate = maxRate - 0.5;
  414. maxRate = maxRate + 0.5;
  415. }
  416. if(minRate < 0) {
  417. minRate = 0;
  418. }
  419. var maxTime = timehistory[timehistory.length-1];
  420. var minTime = timehistory[rateAvgLen];
  421. $('.postRateChart').each(function() {
  422. var gctx = $(this).get(0).getContext('2d');
  423. gctx.clearRect(0, 0, gctx.canvas.width, gctx.canvas.height);
  424. gctx.strokeStyle = $('div.boardlist a').css('color');
  425. gctx.beginPath();
  426. var x = 0;
  427. var y = gctx.canvas.height - (ratehistory[rateAvgLen] - minRate)/(maxRate - minRate) * gctx.canvas.height;
  428. gctx.moveTo(x, y);
  429. for(var i=rateAvgLen+1; i<ratehistory.length; i++) {
  430. x = (timehistory[i] - minTime)/(maxTime - minTime) * gctx.canvas.width;
  431. y = gctx.canvas.height - (ratehistory[i] - minRate)/(maxRate - minRate) * gctx.canvas.height;
  432. gctx.lineTo(x, y);
  433. }
  434. gctx.stroke();
  435. gctx.closePath();
  436. });
  437. }
  438. }
  439.  
  440. /* Update navigation */
  441. function updateNav() {
  442. updateNavCounts();
  443. updateNavGraphics();
  444. updateNavPostRate();
  445. }
  446.  
  447. // Update nav when scrolling stops
  448. $(window).on('scroll', function(e) {
  449. updateNavCounts();
  450. updateNavGraphics();
  451. }, updateDelay);
  452.  
  453. // Update nav when resize stops
  454. $(window).on('resize', function(e) {
  455. updateNav();
  456. }, updateDelay);
  457.  
  458. /* Set which posts are Q posts */
  459. function setQPosts() {
  460. qposts = $.map($('div.post span.trip:contains("!!mG7VJxZNCI"):visible').not('.post-hover'), function(el) {
  461. return $(el).parents('div.post').first();
  462. });
  463. allqposts = $('span.trip:contains("!!mG7VJxZNCI")');
  464. return $.Deferred().resolve();
  465. }
  466.  
  467. /* Set which posts are you posts */
  468. function setYouPosts() {
  469. youposts = $.map($('div.post span.own_post,div.body:icontains("(You)")').not('.post-hover'), function(el) {
  470. return $(el).parents('div.post').first();
  471. });
  472. return $.Deferred().resolve();
  473. }
  474.  
  475. function setFloodPosts() {
  476. if(floodEnabled) {
  477. var stats = {};
  478. var firstId = null;
  479. $('span.poster_id').each(function () {
  480. var id = $(this).text();
  481. if (!(id in stats)) {
  482. stats[id] = {count: 0};
  483. }
  484. stats[id].count++;
  485. if (firstId == null) {
  486. firstId = id;
  487. }
  488. });
  489. $.each(stats, function (key, value) {
  490. if (key != firstId) {
  491. if (value.count > floodThreshold) {
  492. if (floodBehavior === 'fade') {
  493. var intensity = value.count;
  494. if (intensity > floodVanish) {
  495. intensity = floodVanish;
  496. }
  497. intensity = ((floodVanish - floodThreshold) - (intensity - floodThreshold)) / (floodVanish - floodThreshold);
  498. if (intensity < 0.1) {
  499. intensity = 0.1;
  500. }
  501. $('span.poster_id:contains("' + key + '")').each(function () {
  502. $(this).parents('div.post').first().css('opacity', intensity);
  503. $(this).parents('div.post').first().hover(function () {
  504. $(this).animate({opacity: 1.0}, updateDelay);
  505. }, function () {
  506. $(this).animate({opacity: intensity}, updateDelay);
  507. });
  508. });
  509. } else if (floodBehavior === 'hide') {
  510. if (value.count >= floodVanish) {
  511. $('span.poster_id:contains("' + key + '")').each(function () {
  512. $(this).parents('div.post').first().hide();
  513. });
  514. }
  515. }
  516. }
  517. }
  518. });
  519. }
  520. return $.Deferred().resolve();
  521. }
  522.  
  523. function toggleFlood() {
  524. if(floodEnabled) {
  525. floodEnabled = false;
  526. $('.toggleFloodState').text('On');
  527. if(floodBehavior === 'fade') {
  528. $('span.poster_id').each(function () {
  529. $(this).parents('div.post').first().css('opacity', 1);
  530. $(this).parents('div.post').first().off('mouseenter mouseleave');
  531. });
  532. } else if(floodBehavior === 'hide') {
  533. $(this).parents('div.post').first().show();
  534. }
  535. } else {
  536. floodEnabled = true;
  537. $('.toggleFloodState').text('Off');
  538. runq()
  539. }
  540. }
  541.  
  542. /* Helper to run snippets in the right order */
  543. function runq() {
  544. setQPosts()
  545. .done(highlightQ)
  546. .done(removeInvalidYous)
  547. .done(highlightYouRefs)
  548. .done(setYouPosts)
  549. .done(setFloodPosts)
  550. .done(updateNav);
  551. }
  552.  
  553. /* Attach snippets to ready/change events */
  554. $(document).ready(function() {
  555. qnav();
  556. younav();
  557. togglenav();
  558. postratenav();
  559. sidenav();
  560. runq();
  561.  
  562. // Select the node that will be observed for mutations
  563. var targetNode = $('div.thread')[0];
  564.  
  565. // Options for the observer (which mutations to observe)
  566. var config = { childList: true };
  567.  
  568. // Callback function to execute when mutations are observed
  569. var callback = function(mutationsList) {
  570. for(var mutation of mutationsList) {
  571. if (mutation.type == 'childList') {
  572. runq();
  573. break;
  574. }
  575. }
  576. };
  577.  
  578. // Create an observer instance linked to the callback function
  579. var observer = new MutationObserver(callback);
  580.  
  581. // Start observing the target node for configured mutations
  582. observer.observe(targetNode, config);
  583. });
  584.  
  585.  
  586. //================================================================
  587. //
  588. // Toastmaster 2.5.2
  589. // Finds the bread so you don't have to.
  590. //
  591. // Always look through the code to find shifty stuff.
  592. //
  593. //
  594. //================================================================
  595. //2345678901234567890123456789012345678901234567890123456789012345
  596. /*
  597. these files can be extracted and saved as text and they should
  598. still be loadable
  599. */
  600. var container;
  601. /* this is literally just a picture of toast */
  602.  
  603. var toast = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAA"
  604. + "AAbCAMAAAC6CgRnAAAARVBMVEWZMwAAAABmMwBmMzNmZjOZZgCZ"
  605. + "ZjOZZmbMZgDMZjPMZmaZmTOZmWbMmTPMmWbMmZn/mWbMzGbMzJn"
  606. + "/zGb/zJn/zMz//8zDFCa2AAAAAXRSTlMAQObYZgAAAAlwSFlzAA"
  607. + "ALEwAACxMBAJqcGAAAAAd0SU1FB+IIBAI4ECHmtE4AAAFKSURBV"
  608. + "CjPVVIBcsMwCKubQuZb0J2xu/8/dRJJt5ZzcnGEhAy+3V7R3uL2"
  609. + "FtrfffN927a7P+7tDYEDuRiZ4II/LrQ5EQwQKVAp8HZCBu6Jrpm"
  610. + "5JpiST+ytBGFBovIrB5iDX3RECCKKh+SDSoxEYaYtWVEkhkdgCl"
  611. + "uBTmIO2kHwr015m6mCqROMkMwsOcjOurwERYbcpBDrgfyBsPpDM"
  612. + "VHLiVTYifJ5sEiWKs6FoLtRPo+ijXI4aazzvGEvrHJXnAcgyi9b"
  613. + "wiyrm8mKKUCS5IJnaPFfpXrHWt27xyqsV8Fuhu5yadHDIcy+7eK"
  614. + "xWVaaqKyz15IHaWFfTjkhvTQpEp1pxmWdc+aL7D/M1F1a57l6KI"
  615. + "GwNPuCrOZ5tlVvCsU4edX6+he8E+xY5bWaA0eX6+BgBq/SwfGz/"
  616. + "2EahAbLGgd8Z/92v0JD+rjQH/ELBU8elOTZkAQAAAAASUVORK5C"
  617. + "YII=";
  618.  
  619. /* this is an MP3 file. you should inspect it yourself */
  620. var frog = "data:audio/wav;base64,UklGRjkKAABXQVZFZm10IBAAAAABA"
  621. + "AEAQB8AAEAfAAABAAgAZGF0YRUKAAB9fn1+gIGDhIOAf4B/gH+B"
  622. + "goGCgYKBf4CAf4B/gIGDgoGCf4B+foGCgYKBfnx9f3+AgoGCgoK"
  623. + "Af35/gYB/f4B/foKDhIOEg398fYB+fH6BgoGCgX9+foGCgYKCgH"
  624. + "17e3yAhISCgYOEg4GAfHuAg4SDgH+BgoGBg4aEf31/f3x8foB9e"
  625. + "XuAgoCAg4aFgoF+e3p8f4B8foOBf4GEgn6Ag4N+f4SDe3d+gn1+"
  626. + "h4h8e4aLh4GDhoB4eoB+eX6HhXx8g4R8fIODgX+Cgnp3foF8fYS"
  627. + "Ggn+BgHp4en6Af4CBf4GEgoCCh4V+en2CgX6DiYh+eH6BfICMjo"
  628. + "J4eXl4gIuLhIGDfnV7hYeDhYh9b3F9gn+Bh4Z7dX+Ef3+Lint0f"
  629. + "YN8e4SFeniDiYB5g4d/foaEdnqJjH58iId4eIaGeHqIhXR1hYh6"
  630. + "dn+Ce3qFiod9d4CGgnp+hYF5e4WHgYGHhHd2goiDg4uNf3iBhHt"
  631. + "7iZCDdnl8dneGjYF3fHtzdIKKhH+Afnd0eoOFfXd+iIN7hY2Acn"
  632. + "aEiImPjn1rboCTlo+Gdm5veIuYmY59Z11shJaenIVnX2NqgZ2fi"
  633. + "315bGV4kIp2f457aH2UgmyDnodqe5WCaIKkjGVymIxjcaCdbWSN"
  634. + "l25gi6aFYXWUelx8p5RocJiKXWidqHdghp1zWIKumWlumJNiYJe"
  635. + "vfll9m3FTga2NWG+ce1F5sp5kaZiDV3avr3lohXVQZp6ynYmBal"
  636. + "xxhYSOoZRwbY6KYGiXlm1/r5RbZY95V4i+oF9hinJMe7mra2KFa"
  637. + "Ul6urBwZIpyTXu1omVxpIhYdq2RV26upGJjoJ1bWZ61d1SKqW1M"
  638. + "jsSVUG2jdUN8w6FQXpx7RXnAolhtoHRMgbyfZXqZZEByqJFniKl"
  639. + "+W3mcmXxodIeAfpmfeWJ6kIZ/lJl5a4WTeWuEknZmgZN6aIKPaF"
  640. + "WApI1uhplwW3ySfH6qsYBda3VoeKi1hmJ0fVxinrKCapScbGuil"
  641. + "1RUj5ZkdLqsWkR9lWhzvrlrVH99T2u2uHNeh4VXZaOhZWWel1xi"
  642. + "oZtWXa29dWChqVpSqs6DSoKlWDWLxoVIeJhOO5rYnFaDqGIzcLe"
  643. + "mboGwj19xloRedqKMYnmSX0WJwphnkK9sNXC+o15ynntdfpaLf3"
  644. + "yAhIF/gIOCfnt+gH9/gYKBgoF+e32BgX+Af4GCgYKBgoGBgoGCg"
  645. + "YKAf4B/gH+BgX+Af4CBg4SGhIKBgoF/gYKCgH1/gYKBgoGCfnuA"
  646. + "goB/gYJ+f3+BgoKEgoF/gH+AgoGCgoB/fX6Af4CCgn99f4B/gIG"
  647. + "CgX+BgoGAf4GCgYKBgoF/gYKDgYCDg397fYB/f4GFhoSBfnx7fX"
  648. + "+AgYODhIKBf4B/e32AgoF/gH97foGAgH+BgX+AgYKBgoSDgYKBg"
  649. + "oGAgoKAgYKAf4CDhYOCf319foCBgX1+gYF/gISGg4GBgn19gYB/"
  650. + "gIJ/e36BgYB+f35+gICCgoGAgYJ/e36CgH5/g4J/gYKEgn+Bg4O"
  651. + "AgIOEgX+BgoGCgYOBfH+CgHt9g4WBfICDg35/gYB/foGEg4B9e3"
  652. + "p9goGAhIiFe3d7gIOEg4GAf4GBfX+CgX9+gYF8foWGgHt/gn58g"
  653. + "IOBf4GBfH2DhYJ/gYSBe32AfnyChIKEhoN/gYKBf4KGgnp7fXp8"
  654. + "hYeBgIJ/en2Fgnl4g4eCg4R+eHh+goGCgoWBeHl/gHx/h4J3eIG"
  655. + "DgIOGgX6EiH58h42Een2CgHp4gIaAf4ySgW51h4h+goqDdnuJgW"
  656. + "1zjI97eIyPeXB6f3l5hox/dHuEfXeBh4J9gH55fYKDhIN9eoKDf"
  657. + "ICIgXd8iIZ6f4yOgnyChX17h4qCeYCGfnuChH13eX+Dg4F+f4B9"
  658. + "fYB8e4GGfnmAg3x4e3p0d4aHfnyCgXuAiIR4eoJ7dX+PlI6Ig3l"
  659. + "ydYGHhoyVi3dvdHZ3g5GUi4WFgXpyamx+j42CiJOEbGlxb3CKoJ"
  660. + "V9eXxpW22LkomPn5NxY292bG+Rr6qNfIJ8XU1qlaWXhpGcgllSc"
  661. + "4uIiZGIdXqAbnKQlXlrhZiBaniQh3J6jo57doGIgHZ7g4F6f4uM"
  662. + "gHJ5g4J8g4p8bnaGgXmEjHlqeox+b36RhG58kol0f5eLcHaPjnp"
  663. + "/lIxsYnWBfYuhoIFoZmVqg6GkkIB2ZGCAnY9xd5F+X3Gbl2xpjI"
  664. + "llcJ+gc2KEh2Jon7CBXX6WbVmJr4lfgKaAV3upiVd2rZpgZ6CUV"
  665. + "2GjomNblZFUY6mxb16YjlRprrR2aJKFVWCUooN6lIdfZYeNd3eP"
  666. + "jGtmiZd2ZIOYd1+GsZhgYpCOW2Kit4NagJ9zUYK2mmB1qYtQaKe"
  667. + "TTlylrWhPjaVfSpHBi054pW1Hg76kZnadd0xroqZ/fJmEX2mIjo"
  668. + "iHgXl3eXl6hIyFeHV7d293hod6eIWGeHSFjoJ2foiBfIeQhnl7h"
  669. + "IJ/hIiGgn1ya3qTlYd/gHVibJCei3qHimhRbZOThJKihF1jgoBo"
  670. + "d5+fc2OIl2xUf6KAX4q4k1tnkn9VdLKscWeXkVRZmqtzYJ6saE+"
  671. + "JnFxNlb2FUH+naD+AxLFnb6J6QFibr4FslpZmYoWXj4J7gIZ8bG"
  672. + "t8ioiFjZF5YW2Ff2p6m49nbpqVYFiFmHNporqEVW+PaVSUx6Bjd"
  673. + "aB4RW+xnF1yt6VXUpWcTkSYxotKeahkK2nDznpYlY9KRYSwlXOK"
  674. + "lnBgfZOPiIN7dneBioiCg4aAc292g4N4dYGIgHl9hH1ydIOLgny"
  675. + "GiXpzgY2BdoOZmYBvfI6MeHOEhWhbe52YhIOPfVlTb4WGjqGhe1"
  676. + "Zcen9zi66heHaQf1JVh5V2fq+yeFRjbFNjqsmgcoCDUE2QuI9sn"
  677. + "bp7RGCUdUBuv712Xo2HOz+e2KhfgqVhMWaxqXJ4n4BVbJGVhoKH"
  678. + "hHp3fIGEhoJ+fHx2cHJ2dnV+i46GhIuJd2pxfoCBjJiRgXx+end"
  679. + "9io+Dd4CSlIh5cnBjW26MlpGTloRhUWeHg3qXtJtpYHmAamqLm4"
  680. + "qEmJBlV298am2dwKZwZnprTWyzwpWBnpNSPXSbcFWb2adTUYVoJ"
  681. + "FzS8ZlVgY5AJXS7pG6Do31cdZeUhn55e4OLioODiYd9dXd7f4KF"
  682. + "hYSBenNxdnh3eH+Ki4WBgn54en6AgomSkIiDhIJ7dnd8f4KKlJe"
  683. + "Qf29pYVtke5ajnIRtYF9sgY2Up7amhG5tbGNpjq2lj4N1VzY9a4"
  684. + "yZtNzPgUtMUD5QpOXSloeFUjBelH1zvNOAQnKaPQV/9+GCf8Z7A"
  685. + "BOo5oNkoqVTRIejkn94e4aLiYSFjIt+cm5wdHV6hIaCg4iLgnV3"
  686. + "gn98jJuWhH+CfGtkeI+NfX2RnZJ7bWtjYX6aknqAmpd6Y2h2fYi"
  687. + "ZopN/eoB6aWiAjoiLnqGDZGZza197q7WYhox9T0F6rJh7nruGRF"
  688. + "mafCZM1emXa621OgBB39mPi6eeXE1vioV/gYGAf4CAgoF/gH+Bg"
  689. + "oB/";
  690.  
  691. function _i(o) {
  692. return (o) ? document.getElementById(o) : null;
  693. }
  694. function _n(o) {
  695. return (o) ? document.getElementsByName(o) : [];
  696. }
  697. function _t(o) {
  698. return (o) ? document.getElementsByTagName(o) : [];
  699. }
  700. function _$(o) {
  701. return (o) ? document.getElementsByClassName(o): [];
  702. }
  703.  
  704. function _c(ob,id) {
  705. switch(ob) {
  706. case 'DIV':
  707. case 'SPAN':
  708. case 'INPUT':
  709. var ob = document.createElement(ob);
  710. ob.id = id;
  711. break;
  712. case 'LABEL':
  713. var ob = document.createElement(ob);
  714. ob.setAttribute('for', id);
  715. break;
  716. default:
  717. ob.appendChild(document.createTextNode(id));
  718. }
  719. return ob;
  720. }
  721.  
  722. function css(s, j) {
  723. for(var k in j) {
  724. s.style[k] = j[k];
  725. }
  726. }
  727.  
  728. function filter_by_id() {
  729. var id = _i('search_input').value;
  730. var list = _$('poster_id');
  731. var node;
  732. var valid;
  733. for(var i = 0; i < list.length; i++) {
  734. node = (list[i].parentNode.parentNode);
  735. valid = (-1 == node.innerText.indexOf(id));
  736. node.style.display=(valid)?'none':'inline-block';
  737. if (node.nextSibling) {
  738. node.nextSibling.style.display=(valid)?'none':'inline';
  739. }
  740. }
  741. }
  742.  
  743. function get_bread_number(text) {
  744. if ( (text.toLowerCase().indexOf('ebake') != -1)
  745. || (text.toLowerCase().indexOf('q research general') != -1)) {
  746. var rx = /[^0-9]*([0-9]+)[^0-9]*/g;
  747. var arr = rx.exec(text);
  748.  
  749. return arr && arr.length > 1 ? arr[1] : false;
  750. }
  751.  
  752. return false;
  753. }
  754. window.colored = 0;
  755. window.all_breads = {};
  756.  
  757. function make_toast(url, time) {
  758.  
  759. var response;
  760. var x = new XMLHttpRequest();
  761. x.open('GET', url, true);
  762.  
  763. if (typeof window.all_breads[url] == 'undefined') {
  764. window.all_breads[url] = 0;
  765. }
  766. if (window.all_breads[url] > 751 || window.all_breads[url] == -1) {
  767. return;
  768. }
  769. if (url == '#') {
  770. var opt = _c('SPAN', "ribbit");
  771.  
  772. var container = _i('dythreads');
  773.  
  774. var colors = ["#fefefe", "green", "red"];
  775.  
  776.  
  777. css(opt,{
  778. font : 'normal normal bold 8px/15px '
  779. + '"Courier New", Courier, Monospace',
  780. float : 'right',
  781. color : colors[1],
  782. cursor : 'pointer',
  783. width : '49px',
  784. height : '13px',
  785. margin : '1px',
  786. border : '1px solid #b0b0b0',
  787. display : 'inline-block',
  788. filter : 'brightness(100%)',
  789. textAlign : 'left',
  790. textIndent : '9px',
  791. borderRadius : '3px',
  792. verticalAlign : 'top',
  793. backgroundSize : '13px'
  794. });
  795.  
  796. opt.innerHTML = "RIBBIT!"
  797. + " <span style='font-weight:bold;color:"
  798. + colors[2]
  799. + ";'>"
  800. + "</span>";
  801.  
  802.  
  803. container.appendChild(opt);
  804.  
  805. opt.onclick = function () {
  806. var snd = new Audio(frog);
  807. snd.play();
  808. };
  809. return;
  810. }
  811. else x.onreadystatechange = function() {
  812. var that = url;
  813.  
  814. if(x.readyState === 4 && x.status == 200) {
  815.  
  816. response = JSON.parse(x.responseText);
  817.  
  818. var container = _i('dythreads');
  819.  
  820. var bread = response.posts[0];
  821. var posts = response.posts.length;
  822. var txt = bread.sub;
  823. window.all_breads[url] = posts;
  824. if (typeof txt == 'undefined') {
  825. txt = bread.com;
  826. if (txt.length > 40) {
  827. txt = txt.substring(0,39) + '...';
  828. }
  829. }
  830. var num = get_bread_number(txt);
  831.  
  832. // skip this bread forever
  833. if (false == num) {
  834. window.all_breads[that] = -1;
  835. return;
  836. }
  837.  
  838. var thread = _n('thread');
  839.  
  840. var hrefs = _t('A');
  841. for(var i = window.colored; i < hrefs.length; i++) {
  842.  
  843. if (-1 == hrefs[i].href.indexOf("res/" + thread[0].value+".html") &&
  844. -1 != hrefs[i].href.indexOf("qresearch")) {
  845. hrefs[i].style.color='#0077aa';
  846. window.colored = i; // don't color it twice.
  847. }
  848. }
  849.  
  850. if (thread[0].value == bread.no) {
  851. var pfi = _i('post-form-inner');
  852.  
  853. if (pfi && (posts > 750)) {
  854. css(pfi,{
  855. border :'3px solid red',
  856. padding :'3px',
  857. opacity : '0.7',
  858. background : 'url(data:image/png;base64,iVB'
  859. + 'ORw0KGgoAAAANSUhEUgAAAAQAAAAE'
  860. + 'CAYAAACp8Z5+AAAAGklEQVQIW2NkY'
  861. + 'GD4D8SMQAwGcAY2AbBKDBUAVuYCBQ'
  862. + 'Pd34sAAAAASUVORK5CYII=) repeat',
  863. borderRadius : '10px',
  864. });
  865. }
  866. }
  867.  
  868. var opts = _n('toast');
  869. var colors = ((thread[0].value == bread.no)
  870. ? ((posts < 750)
  871. ? ["#04ae04", "white", "black"]
  872. : ["#ae0404", "white", "black"])
  873. : ["#fefefe", "green", "red"]);
  874. for(var i = 0; i < opts.length; i++) {
  875. if (opts[i].getAttribute('no') == bread.no) {
  876. opts[i].innerHTML = num
  877. + " <span style='font-weight:bold;color:"
  878. + colors[2]
  879. + "'>"
  880. + posts
  881. +"</span>";
  882.  
  883. opts[i].style.background = colors[0]
  884. + " url("
  885. + toast
  886. + ") 0px 0px/25px 25px no-repeat";
  887.  
  888. opts[i].style.backgroundSize = "13px";
  889.  
  890. return;
  891. }
  892.  
  893. }
  894.  
  895. var opt = _c('SPAN', "" + bread.no);
  896.  
  897. opt.setAttribute('no',bread.no);
  898.  
  899. opt.addEventListener('mouseout',function() {
  900. css(opt,{
  901. cursor : 'pointer',
  902. filter : 'brightness(100%)'
  903. })
  904. });
  905.  
  906. opt.addEventListener('mouseover',function() {
  907. css(opt,{
  908. cursor : 'auto',
  909. filter : 'brightness(80%)'
  910. })
  911. });
  912.  
  913. css(opt,{
  914. font : 'normal normal bold 8px/15px '
  915. + '"Courier New", Courier, Monospace',
  916. float : 'right',
  917. color : colors[1],
  918. width : '59px',
  919. height : '13px',
  920. margin : '1px',
  921. border : '1px solid #b0b0b0',
  922. display : 'inline-block',
  923. filter : 'brightness(100%)',
  924. textAlign : 'left',
  925. textIndent : '18px',
  926. background : colors[0] + ' url(' + toast
  927. + ') 0px 0px/25px 25px no-repeat',
  928.  
  929. borderRadius : '3px',
  930. verticalAlign : 'top',
  931. backgroundSize : '13px'
  932. });
  933.  
  934. opt.innerHTML = num
  935. + " <span style='font-weight:bold;color:"
  936. + colors[2]
  937. + ";'>"
  938. + posts
  939. + "</span>";
  940.  
  941. opt.id = "" + bread.no;
  942.  
  943. container.appendChild(opt);
  944.  
  945. opt.setAttribute('name','toast');
  946.  
  947. opt.onclick = function () {
  948. var no = bread.no;
  949. if(typeof url != 'undefined') {
  950. window.location.href =
  951. '/qresearch/res/' + no + '.html';
  952. }
  953. };
  954.  
  955. opt.setAttribute('old',false);
  956. }
  957. };
  958. x.send();
  959.  
  960. }
  961.  
  962. // every 60 seconds we reload from threads.json
  963.  
  964. function refresh() {
  965. // prune expired breads and append new ones.
  966. var opts = _n('toast');
  967.  
  968. for(var i = 0; i < opts.length; i++) {
  969. if (opts[i].getAttribute('old') == true) {
  970. container.removeChild(opts[i]);
  971.  
  972. }
  973. else {
  974. opts[i].setAttribute('old',true);
  975. }
  976. }
  977.  
  978. var x = new XMLHttpRequest();
  979. x.open('GET', "/qresearch/threads.json", true);
  980. x.onreadystatechange = function() {
  981. if(x.readyState === 4 && x.status == 200) {
  982.  
  983. var response = JSON.parse(x.responseText);
  984. find_recent_bread(response);
  985. }
  986. };
  987. x.send();
  988. trips();
  989.  
  990.  
  991. }
  992. // Count instances of Q with trips, mark untripped Q's as fakes
  993. function trips() {
  994. var m = _i('notify');
  995. var t = 0;
  996. var k, r;
  997. var list = _$('trip');
  998. for(var i = 0; i < list.length; i++) {
  999. r = list[i].innerText.trim();
  1000. if (list[i].parentNode.parentNode.className !='intro') continue;
  1001. if (! r.length || r == 'FAKE') {
  1002. continue;
  1003. }
  1004. k = list[i].previousSibling.innerText.trim();
  1005. if (k == 'Q' || k == 'Q+') {
  1006. t++;
  1007.  
  1008. }
  1009. }
  1010. if (t) {
  1011. m.innerHTML = "Q Posts (" + t + ")";
  1012. }
  1013. if ((t != window.t) && t) {
  1014. m.animate([
  1015. { color: 'red' },
  1016. { color: 'white' },
  1017. { color: 'blue' }
  1018. ], {
  1019. duration: 500,
  1020. iterations: 17
  1021. });
  1022. window.t = t;
  1023. }
  1024. var list = _$('name');
  1025. for(var i = 0; i < list.length; i++) {
  1026. r = list[i].innerText.trim();
  1027. k = list[i].nextSibling;
  1028.  
  1029. if (k && k.className!='trip') {
  1030. if (r == 'Q' || r == 'Q+') {
  1031. list[i].innerHTML = r
  1032. + " <span style='color:red'>[FAKE]</span>";
  1033. }
  1034. }
  1035. }
  1036.  
  1037. }
  1038.  
  1039. function find_recent_bread(board) {
  1040. var now = ~~((new Date).getTime() / 1000);
  1041. var thread;
  1042. for(var i = 0; i < board.length; i++) {
  1043. for(var j = 0; j < board[i].threads.length; j++) {
  1044. thread = board[i].threads[j];
  1045. // only show threads modified within the last 2 hours
  1046.  
  1047. if (now - thread.last_modified < 7200) {
  1048. make_toast('/qresearch/res/'+thread.no + '.json',
  1049. thread.last_modified);
  1050. }
  1051. }
  1052. }
  1053.  
  1054. }
  1055.  
  1056. // Post controls is loaded and we're already in a thread
  1057. // append the controls at the top, but only once.
  1058. var toast_init = function() {
  1059. container = (_n('postcontrols'))[0];
  1060. var dythreads = _i('dythreads');
  1061.  
  1062. if (! dythreads) {
  1063. var box = _c('DIV', 'notify');
  1064. var bar = _c('DIV', 'dythreads');
  1065. var label = _c('LABEL', 'search_input');
  1066. var text = _c(label, 'Search:');
  1067. var search = _c('INPUT', 'search_input');
  1068.  
  1069. container.appendChild(bar);
  1070. bar.appendChild(label);
  1071. bar.appendChild(search);
  1072. bar.appendChild(box);
  1073.  
  1074. css(bar,{
  1075. top : '15px',
  1076. width : 'calc(100% - 8px)',
  1077. height : '16px',
  1078. margin : '0 0 0 -16px',
  1079. zIndex : '100',
  1080. display : 'block',
  1081. padding : '0 8px 0 16px',
  1082. position : 'fixed',
  1083. textAlign : 'left',
  1084. background : '#eef2ff url(/stylesheets/img/fade-blue.png)'
  1085. + ' repeat-x 50% 0%',
  1086. borderBottom : '1px solid #b0b0b0'
  1087. });
  1088.  
  1089. css(search,{
  1090. font : 'normal normal bold 8px/13px "Courier New", '
  1091. + 'Courier, Monospace',
  1092. float :'left',
  1093. height :'9px',
  1094. border :'none',
  1095. marginTop :'2px'
  1096. });
  1097.  
  1098. css(label,{
  1099. font : 'normal normal bold 8px/15px "Courier New", '
  1100. + 'Courier, Monospace',
  1101. float :'left',
  1102. height : '13px',
  1103. });
  1104.  
  1105. css(box,{
  1106. font : 'normal normal bold 8px/13px "Courier New", '
  1107. + 'Courier, Monospace',
  1108. color : 'red',
  1109. width : '105px',
  1110. float : 'left',
  1111. height : '15px',
  1112. margin : '2px 0 0 5px'
  1113. });
  1114.  
  1115.  
  1116.  
  1117. setInterval("refresh();", 5000);
  1118. search.onkeyup =
  1119. search.oninput =
  1120. search.onchange =
  1121. search.onkeydown = function(e) {
  1122. var c;
  1123. e = e || event;
  1124. c = (e.keyCode || e.which || e.charCode || 0)
  1125. if (c == 13) e.stopPropagation();
  1126. if (window.to) clearTimeout(window.to);
  1127. window.to = setTimeout(function() {
  1128. filter_by_id();
  1129. }, 1000);
  1130.  
  1131. return c !== 13;
  1132. };
  1133. var auto = _i('auto_update_status');
  1134. if (auto) {
  1135.  
  1136. auto.setAttribute('checked',true);
  1137. //auto.setPropertyuchecked = true;
  1138. }
  1139. refresh();
  1140. make_toast('#',0);
  1141. }
  1142. }
  1143. $(document).ready(toast_init);
Add Comment
Please, Sign In to add comment