Title: threadstats.js Author: Anonymous Pastebin link: http://pastebin.com/XRrpNu60 First Edit: Saturday 1st of September 2012 05:38:41 AM CDT Last Edit: Saturday 1st of September 2012 05:38:41 AM CDT // ==UserScript== // @name        4chan thread statistics // @version     3.0 // @namespace   anon.4chan.org // @description Adds thread statistics. // @include     http://boards.4chan.org/*/res/* // @include     https://boards.4chan.org/*/res/* // @run-at      document-start // ==/UserScript==   (function() {         "use strict";                 function formatNumber(num)         {                 return String(num).replace(/\B(?=(?:\d{3})+(?!\d))/g, " ");         }                 function formatTime(time)         {                 var days = Math.floor(time / 86400000),                         daysS = days == 1 ? "" : "s";                                 var hours = Math.floor((time -= days * 86400000) / 3600000),                         hoursS = hours == 1 ? "" : "s";                                 var minutes = Math.floor((time -= hours * 3600000) / 60000),                         minutesS = minutes == 1 ? "" : "s";                                 var seconds = Math.floor((time -= minutes * 60000) / 1000),                         secondsS = seconds == 1 ? "" : "s";                                 if (days)                         return days + " day" + daysS + ", " + hours + " hour" + hoursS + ", " + minutes + " minute" + minutesS + " and " + seconds + " second" + secondsS;                 else if (hours)                         return hours + " hour" + hoursS + ", " + minutes + " minute" + minutesS + " and " + seconds + " second" + secondsS;                 else if (minutes)                         return minutes + " minute" + minutesS + " and " + seconds + " second" + secondsS;                 else                         return seconds + " second" + secondsS;         }                 var posts = [],                 postsSparse = [],                 op, last, last10,                 appended = false,                 board = document.location.href.match(/^https?:\/\/boards.4chan.org(\/[^\/]+\/)/)[1];                 var statistics = document.createElement("div");         statistics.className = "threadstatisticstext";         statistics.style.textAlign = "center";         statistics.style.fontSize = "xx-small";         statistics.style.paddingBottom = "4px";                 function makeLabel(title)         {                 var b = document.createElement("b");                 var text = document.createTextNode("");                 b.appendChild(document.createTextNode(" " + title + ": "));                 statistics.appendChild(b);                 statistics.appendChild(text);                                 return text;         }                 var threadAge = makeLabel("Thread age");         statistics.appendChild(document.createElement("br"));                 var boardPosts = makeLabel("Posts in " + board),                 boardPosts10 = makeLabel("last 10 mins");         statistics.appendChild(document.createElement("br"));                 var threadPosts = makeLabel("Posts in thread"),                 threadPosts10 = makeLabel("last 10 mins");         statistics.appendChild(document.createElement("br"));                 var boardPPM = makeLabel(board + " posts per min"),                 boardPPM10 = makeLabel("last 10 mins");         statistics.appendChild(document.createElement("br"));                 var threadPPM = makeLabel("Thread posts per min"),                 threadPPM10 = makeLabel("last 10 mins");         statistics.appendChild(document.createElement("br"));                 var csv = document.createElement("a"),                 csvData = "data:text/plain,ID,Date";         csv.setAttribute("href", csvData);         csv.setAttribute("target", "_blank");         csv.appendChild(document.createTextNode("csv"));         statistics.appendChild(csv);                 function updatePosts(target)         {                 var newPosts = false;                                 if (!target.querySelectorAll)                         return;                                 for (var i = 0, query = target.querySelectorAll("div.thread > div.postContainer > div.post > div.postInfo[id^=pi] > span.dateTime[data-utc]"),                         length = query.length, elem; i < length && (elem = query[i]); i ++)                 {                         var id = Number(elem.parentNode.getAttribute("id").substr(2)),                                 time = Number(elem.getAttribute("data-utc")) * 1000;                                                 if (id && time && !postsSparse[id])                         {                                 newPosts = true;                                                                 posts.push(postsSparse[id] = {                                         id: id,                                         time: time,                                         seq: posts.length,                                 });                                                                 csvData += "%0d%0a" + id + "," + time;                         }                 }                                 if (newPosts)                 {                         csv.setAttribute("href", csvData);                                                 op = posts[0];                         last = posts[posts.length - 1];                                                 if (last == op)                         {                                 threadPosts.data = "1 (?%)";                                 boardPosts.data = "?";                                 threadPPM.data = "?";                                 boardPPM.data = "?";                         }                         else                         {                                 var dTime = last.time - op.time;                                 var dId = last.id - op.id;                                                                 threadPosts.data = formatNumber(posts.length) + " (" + (posts.length / dId * 100).toFixed(2) + "%)";                                 boardPosts.data = formatNumber(dId);                                 boardPPM.data = (dId / (dTime / 60000)).toFixed(2);                         }                                                 updateLast10();                                                 if (!appended && document.querySelector("div#bottom"))                         {                                 appended = true;                                                                 var bottom = document.querySelector("div#bottom");                                 bottom.parentNode.insertBefore(statistics, bottom);                                                                 updateThreadAge();                                 setInterval(updateThreadAge, 1000);                                 setInterval(updateLast10, 10000);                         }                 }         }                 function updateThreadAge()         {                 var dTime = Math.max(Date.now() - op.time, 0);                                 threadAge.data = formatTime(dTime);                                 if (last != op)                         threadPPM.data = (posts.length / (dTime / 60000)).toFixed(2);                                 if (last10)                         threadPPM10.data = ((posts.length - last10.seq) / Math.min(dTime / 60000, 10)).toFixed(2);         }                 function updateLast10()         {                 var now = Math.max(Date.now(), last ? last.time : 0);                 last10 = null;                                 for (var i = 0, max = posts.length; i < max; i ++)                         if (now - posts[i].time <= 600000)                         {                                 last10 = posts[i];                                 break;                         }                                 if (!last10)                 {                         threadPosts10.data = "0 (0%)";                         boardPosts10.data = "?";                         threadPPM10.data = "0";                         boardPPM10.data = "?";                 }                 else if (last10 == last == op)                 {                         threadPosts10.data = "1 (?%)";                         boardPosts10.data = "?";                         threadPPM10.data = "?";                         boardPPM10.data = "?";                                                 last10 = null;                 }                 else if (last10 == last)                 {                         threadPosts10.data = "1 (?%)";                         boardPosts10.data = "?";                         threadPPM10.data = "0.10";                         boardPPM10.data = "?";                                                 last10 = null;                 }                 else                 {                         var dTime = last.time - last10.time;                         var dId = last.id - last10.id;                         var dSeq = posts.length - last10.seq;                                                 threadPosts10.data = formatNumber(dSeq) + " (" + (dSeq / dId * 100).toFixed(2) + "%)";                         boardPosts10.data = formatNumber(dId);                         boardPPM10.data = (dId / (dTime / 60000)).toFixed(2);                 }         }                 document.addEventListener("DOMContentLoaded", updatePosts.bind(this, document));         document.addEventListener("DOMNodeInserted", function(e) {                 updatePosts(e.target);         });                 updatePosts(document); })();