g -> Main

This commit is contained in:
James Campos 2012-03-15 23:14:51 -07:00
parent 8cb14a9af2
commit 0189630901
2 changed files with 205 additions and 208 deletions

View File

@ -73,7 +73,7 @@
*/ */
(function() { (function() {
var $, $$, Anonymize, AutoGif, Conf, Config, DAY, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, GetTitle, HOUR, ImageExpand, ImageHover, Keybinds, MINUTE, Main, NAMESPACE, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, ReplyHiding, ReportButton, RevealSpoilers, SECOND, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Threading, Time, TitlePost, Unread, Updater, VERSION, Watcher, d, engine, flatten, g, log, ui, _base; var $, $$, Anonymize, AutoGif, Conf, Config, DAY, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, GetTitle, HOUR, ImageExpand, ImageHover, Keybinds, MINUTE, Main, NAMESPACE, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, ReplyHiding, ReportButton, RevealSpoilers, SECOND, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Threading, Time, TitlePost, Unread, Updater, VERSION, Watcher, d, engine, flatten, log, ui, _base;
Config = { Config = {
main: { main: {
@ -226,10 +226,6 @@
d = document; d = document;
g = {
callbacks: []
};
ui = { ui = {
dialog: function(id, position, html) { dialog: function(id, position, html) {
var el, saved; var el, saved;
@ -553,7 +549,7 @@
if (!(regexp = filter.match(/\/(.+)\/(\w*)/))) continue; if (!(regexp = filter.match(/\/(.+)\/(\w*)/))) continue;
filter = filter.replace(regexp[0], ''); filter = filter.replace(regexp[0], '');
boards = ((_ref2 = filter.match(/boards:([^;]+)/)) != null ? _ref2[1].toLowerCase() : void 0) || 'global'; boards = ((_ref2 = filter.match(/boards:([^;]+)/)) != null ? _ref2[1].toLowerCase() : void 0) || 'global';
if (boards !== 'global' && boards.split(',').indexOf(g.BOARD) === -1) { if (boards !== 'global' && boards.split(',').indexOf(Main.BOARD) === -1) {
continue; continue;
} }
try { try {
@ -576,7 +572,7 @@
} }
if (!this.filters[key].length) delete this.filters[key]; if (!this.filters[key].length) delete this.filters[key];
} }
if (Object.keys(this.filters).length) return g.callbacks.push(this.node); if (Object.keys(this.filters).length) return Main.callbacks.push(this.node);
}, },
createFilter: function(regexp, op, hl, top) { createFilter: function(regexp, op, hl, top) {
var test; var test;
@ -605,7 +601,7 @@
if (!(result = filter(value, isOP))) continue; if (!(result = filter(value, isOP))) continue;
if (result === true) { if (result === true) {
if (isOP) { if (isOP) {
if (!g.REPLY) { if (!Main.REPLY) {
ThreadHiding.hide(post.el.parentNode); ThreadHiding.hide(post.el.parentNode);
} else { } else {
continue; continue;
@ -620,7 +616,7 @@
} else { } else {
$.addClass(el.parentNode, result[0]); $.addClass(el.parentNode, result[0]);
} }
if (isOP && result[1] && !g.REPLY) { if (isOP && result[1] && !Main.REPLY) {
thisThread = el.parentNode; thisThread = el.parentNode;
if (firstThread = $('div[class=op]')) { if (firstThread = $('div[class=op]')) {
$.before(firstThread.parentNode, [thisThread, thisThread.nextElementSibling]); $.before(firstThread.parentNode, [thisThread, thisThread.nextElementSibling]);
@ -700,7 +696,7 @@
StrikethroughQuotes = { StrikethroughQuotes = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var el, quote, _i, _len, _ref; var el, quote, _i, _len, _ref;
@ -750,7 +746,7 @@
for (_i = 0, _len = quotes.length; _i < _len; _i++) { for (_i = 0, _len = quotes.length; _i < _len; _i++) {
quote = quotes[_i]; quote = quotes[_i];
if (quote.hash === quote.getAttribute('href')) { if (quote.hash === quote.getAttribute('href')) {
quote.pathname = "/" + g.BOARD + "/res/" + threadID; quote.pathname = "/" + Main.BOARD + "/res/" + threadID;
} }
} }
post = { post = {
@ -795,7 +791,7 @@
toggle: function(thread) { toggle: function(thread) {
var a, backlink, num, pathname, prev, table, threadID, _i, _len, _ref, _ref2, _results; var a, backlink, num, pathname, prev, table, threadID, _i, _len, _ref, _ref2, _results;
threadID = thread.firstChild.id; threadID = thread.firstChild.id;
pathname = "/" + g.BOARD + "/res/" + threadID; pathname = "/" + Main.BOARD + "/res/" + threadID;
a = $('.omittedposts', thread); a = $('.omittedposts', thread);
switch (a.textContent[0]) { switch (a.textContent[0]) {
case '+': case '+':
@ -810,7 +806,7 @@
case '-': case '-':
a.textContent = a.textContent.replace('-', '+'); a.textContent = a.textContent.replace('-', '+');
num = (function() { num = (function() {
switch (g.BOARD) { switch (Main.BOARD) {
case 'b': case 'b':
case 'vg': case 'vg':
return 3; return 3;
@ -880,7 +876,7 @@
className: 'replyhider', className: 'replyhider',
innerHTML: '<a href="javascript:;">[ - ]</a>' innerHTML: '<a href="javascript:;">[ - ]</a>'
}); });
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var td; var td;
@ -888,7 +884,7 @@
td = ReplyHiding.td.cloneNode(true); td = ReplyHiding.td.cloneNode(true);
$.on(td.firstChild, 'click', ReplyHiding.toggle); $.on(td.firstChild, 'click', ReplyHiding.toggle);
$.replace(post.el.previousSibling, td); $.replace(post.el.previousSibling, td);
if (post.id in g.hiddenReplies) return ReplyHiding.hide(post.root); if (post.id in Main.hiddenReplies) return ReplyHiding.hide(post.root);
}, },
toggle: function() { toggle: function() {
var id, parent, quote, table, _i, _j, _len, _len2, _ref, _ref2; var id, parent, quote, table, _i, _j, _len, _len2, _ref, _ref2;
@ -901,7 +897,7 @@
quote = _ref[_i]; quote = _ref[_i];
$.addClass(quote, 'filtered'); $.addClass(quote, 'filtered');
} }
g.hiddenReplies[id] = Date.now(); Main.hiddenReplies[id] = Date.now();
} else { } else {
table = parent.nextSibling; table = parent.nextSibling;
table.hidden = false; table.hidden = false;
@ -912,9 +908,9 @@
quote = _ref2[_j]; quote = _ref2[_j];
$.removeClass(quote, 'filtered'); $.removeClass(quote, 'filtered');
} }
delete g.hiddenReplies[id]; delete Main.hiddenReplies[id];
} }
return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); return $.set("hiddenReplies/" + Main.BOARD + "/", Main.hiddenReplies);
}, },
hide: function(table) { hide: function(table) {
var div, name, trip, uid, _ref, _ref2; var div, name, trip, uid, _ref, _ref2;
@ -996,7 +992,7 @@
Keybinds.img(thread, true); Keybinds.img(thread, true);
break; break;
case Conf.zero: case Conf.zero:
window.location = "/" + g.BOARD + "/0#0"; window.location = "/" + Main.BOARD + "/0#0";
break; break;
case Conf.nextPage: case Conf.nextPage:
if ((_ref = $('input[value=Next]')) != null) _ref.click(); if ((_ref = $('input[value=Next]')) != null) _ref.click();
@ -1005,11 +1001,11 @@
if ((_ref2 = $('input[value=Previous]')) != null) _ref2.click(); if ((_ref2 = $('input[value=Previous]')) != null) _ref2.click();
break; break;
case Conf.nextThread: case Conf.nextThread:
if (g.REPLY) return; if (Main.REPLY) return;
Nav.scroll(+1); Nav.scroll(+1);
break; break;
case Conf.previousThread: case Conf.previousThread:
if (g.REPLY) return; if (Main.REPLY) return;
Nav.scroll(-1); Nav.scroll(-1);
break; break;
case Conf.expandThread: case Conf.expandThread:
@ -1124,7 +1120,7 @@
open: function(thread, tab) { open: function(thread, tab) {
var id, url; var id, url;
id = thread.firstChild.id; id = thread.firstChild.id;
url = "//boards.4chan.org/" + g.BOARD + "/res/" + id; url = "//boards.4chan.org/" + Main.BOARD + "/res/" + id;
if (tab) { if (tab) {
return $.open(url); return $.open(url);
} else { } else {
@ -1145,7 +1141,7 @@
td.focus(); td.focus();
return; return;
} }
if (!(g.REPLY || $.x('ancestor::div[@class="thread"]', next) === thread)) { if (!(Main.REPLY || $.x('ancestor::div[@class="thread"]', next) === thread)) {
return; return;
} }
rect = next.getBoundingClientRect(); rect = next.getBoundingClientRect();
@ -1193,14 +1189,14 @@
return $.add(d.body, span); return $.add(d.body, span);
}, },
prev: function() { prev: function() {
if (g.REPLY) { if (Main.REPLY) {
return window.scrollTo(0, 0); return window.scrollTo(0, 0);
} else { } else {
return Nav.scroll(-1); return Nav.scroll(-1);
} }
}, },
next: function() { next: function() {
if (g.REPLY) { if (Main.REPLY) {
return window.scrollTo(0, d.body.scrollHeight); return window.scrollTo(0, d.body.scrollHeight);
} else { } else {
return Nav.scroll(+1); return Nav.scroll(+1);
@ -1236,18 +1232,18 @@
QR = { QR = {
init: function() { init: function() {
if (!$.id('recaptcha_challenge_field_holder')) return; if (!$.id('recaptcha_challenge_field_holder')) return;
g.callbacks.push(this.node); Main.callbacks.push(this.node);
return setTimeout(this.asyncInit); return setTimeout(this.asyncInit);
}, },
asyncInit: function() { asyncInit: function() {
var form, iframe, link, loadChecking, script; var form, iframe, link, loadChecking, script;
if (Conf['Hide Original Post Form']) { if (Conf['Hide Original Post Form']) {
link = $.el('h1', { link = $.el('h1', {
innerHTML: "<a href=javascript:;>" + (g.REPLY ? 'Quick Reply' : 'New Thread') + "</a>" innerHTML: "<a href=javascript:;>" + (Main.REPLY ? 'Quick Reply' : 'New Thread') + "</a>"
}); });
$.on($('a', link), 'click', function() { $.on($('a', link), 'click', function() {
QR.open(); QR.open();
if (!g.REPLY) $('select', QR.el).value = 'new'; if (!Main.REPLY) $('select', QR.el).value = 'new';
return $('textarea', QR.el).focus(); return $('textarea', QR.el).focus();
}); });
form = d.forms[0]; form = d.forms[0];
@ -1362,7 +1358,7 @@
value = 'Loading'; value = 'Loading';
disabled = true; disabled = true;
} }
if (g.dead) { if (Main.dead) {
value = 404; value = 404;
disabled = true; disabled = true;
QR.cooldown.auto = false; QR.cooldown.auto = false;
@ -1380,8 +1376,8 @@
cooldown: { cooldown: {
init: function() { init: function() {
if (!Conf['Cooldown']) return; if (!Conf['Cooldown']) return;
QR.cooldown.start($.get("/" + g.BOARD + "/cooldown", 0)); QR.cooldown.start($.get("/" + Main.BOARD + "/cooldown", 0));
return $.sync("/" + g.BOARD + "/cooldown", QR.cooldown.start); return $.sync("/" + Main.BOARD + "/cooldown", QR.cooldown.start);
}, },
start: function(timeout) { start: function(timeout) {
var seconds; var seconds;
@ -1391,14 +1387,14 @@
set: function(seconds) { set: function(seconds) {
if (!Conf['Cooldown']) return; if (!Conf['Cooldown']) return;
QR.cooldown.count(seconds); QR.cooldown.count(seconds);
return $.set("/" + g.BOARD + "/cooldown", Date.now() + seconds * SECOND); return $.set("/" + Main.BOARD + "/cooldown", Date.now() + seconds * SECOND);
}, },
count: function(seconds) { count: function(seconds) {
if (!((0 <= seconds && seconds <= 60))) return; if (!((0 <= seconds && seconds <= 60))) return;
setTimeout(QR.cooldown.count, 1000, seconds - 1); setTimeout(QR.cooldown.count, 1000, seconds - 1);
QR.cooldown.seconds = seconds; QR.cooldown.seconds = seconds;
if (seconds === 0) { if (seconds === 0) {
$["delete"]("/" + g.BOARD + "/cooldown"); $["delete"]("/" + Main.BOARD + "/cooldown");
if (QR.cooldown.auto) QR.submit(); if (QR.cooldown.auto) QR.submit();
} }
return QR.status(); return QR.status();
@ -1408,7 +1404,7 @@
var caretPos, id, range, s, sel, ta, text, _ref; var caretPos, id, range, s, sel, ta, text, _ref;
if (e != null) e.preventDefault(); if (e != null) e.preventDefault();
QR.open(); QR.open();
if (!g.REPLY) { if (!Main.REPLY) {
$('select', QR.el).value = $.x('ancestor::div[@class="thread"]', this).firstChild.id; $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', this).firstChild.id;
} }
id = this.previousElementSibling.hash.slice(1); id = this.previousElementSibling.hash.slice(1);
@ -1770,7 +1766,7 @@
QR.spoiler = !!$('#com_submit + label'); QR.spoiler = !!$('#com_submit + label');
spoiler = $('#spoilerLabel', QR.el); spoiler = $('#spoilerLabel', QR.el);
spoiler.hidden = !QR.spoiler; spoiler.hidden = !QR.spoiler;
if (!g.REPLY) { if (!Main.REPLY) {
threads = '<option value=new>New thread</option>'; threads = '<option value=new>New thread</option>';
_ref = $$('.op'); _ref = $$('.op');
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -1878,7 +1874,7 @@
return; return;
} }
QR.cleanError(); QR.cleanError();
threadID = g.THREAD_ID || $('select', QR.el).value; threadID = Main.THREAD_ID || $('select', QR.el).value;
QR.cooldown.auto = QR.replies.length > 1; QR.cooldown.auto = QR.replies.length > 1;
if (Conf['Auto Hide QR'] && !QR.cooldown.auto) QR.hide(); if (Conf['Auto Hide QR'] && !QR.cooldown.auto) QR.hide();
if (Conf['Thread Watcher'] && Conf['Auto Watch Reply'] && threadID !== 'new') { if (Conf['Thread Watcher'] && Conf['Auto Watch Reply'] && threadID !== 'new') {
@ -1965,12 +1961,12 @@
if (Conf['Thread Watcher'] && Conf['Auto Watch']) { if (Conf['Thread Watcher'] && Conf['Auto Watch']) {
$.set('autoWatch', postNumber); $.set('autoWatch', postNumber);
} }
location.pathname = "/" + g.BOARD + "/res/" + postNumber; location.pathname = "/" + Main.BOARD + "/res/" + postNumber;
} else { } else {
QR.cooldown.auto = QR.replies.length > 1; QR.cooldown.auto = QR.replies.length > 1;
QR.cooldown.set(/sage/i.test(reply.email) ? 60 : 30); QR.cooldown.set(/sage/i.test(reply.email) ? 60 : 30);
if (Conf['Open Reply in New Tab'] && !g.REPLY && !QR.cooldown.auto) { if (Conf['Open Reply in New Tab'] && !Main.REPLY && !QR.cooldown.auto) {
$.open("//boards.4chan.org/" + g.BOARD + "/res/" + thread + "#" + postNumber); $.open("//boards.4chan.org/" + Main.BOARD + "/res/" + thread + "#" + postNumber);
} }
} }
if (Conf['Persistent QR'] || QR.cooldown.auto) { if (Conf['Persistent QR'] || QR.cooldown.auto) {
@ -1978,10 +1974,10 @@
} else { } else {
QR.close(); QR.close();
} }
if (g.REPLY && (Conf['Unread Count'] || Conf['Unread Favicon'])) { if (Main.REPLY && (Conf['Unread Count'] || Conf['Unread Favicon'])) {
Unread.foresee.push(postNumber); Unread.foresee.push(postNumber);
} }
if (g.REPLY && Conf['Thread Updater'] && Conf['Auto Update This']) { if (Main.REPLY && Conf['Thread Updater'] && Conf['Auto Update This']) {
Updater.update(); Updater.update();
} }
QR.status(); QR.status();
@ -2265,8 +2261,8 @@
} }
$.add($('#main_tab + div', dialog), ul); $.add($('#main_tab + div', dialog), ul);
} }
hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); hiddenThreads = $.get("hiddenThreads/" + Main.BOARD + "/", {});
hiddenNum = Object.keys(g.hiddenReplies).length + Object.keys(hiddenThreads).length; hiddenNum = Object.keys(Main.hiddenReplies).length + Object.keys(hiddenThreads).length;
li = $.el('li', { li = $.el('li', {
innerHTML: "<button>hidden: " + hiddenNum + "</button> <span class=description>: Forget all hidden posts. Useful if you accidentally hide a post and have \"Show Stubs\" disabled." innerHTML: "<button>hidden: " + hiddenNum + "</button> <span class=description>: Forget all hidden posts. Useful if you accidentally hide a post and have \"Show Stubs\" disabled."
}); });
@ -2337,10 +2333,10 @@
return d.body.style.removeProperty('overflow'); return d.body.style.removeProperty('overflow');
}, },
clearHidden: function() { clearHidden: function() {
$["delete"]("hiddenReplies/" + g.BOARD + "/"); $["delete"]("hiddenReplies/" + Main.BOARD + "/");
$["delete"]("hiddenThreads/" + g.BOARD + "/"); $["delete"]("hiddenThreads/" + Main.BOARD + "/");
this.textContent = "hidden: 0"; this.textContent = "hidden: 0";
return g.hiddenReplies = {}; return Main.hiddenReplies = {};
}, },
keybind: function(e) { keybind: function(e) {
var key; var key;
@ -2401,7 +2397,7 @@
thread: function(node) { thread: function(node) {
var div, nodes; var div, nodes;
node = Threading.op(node); node = Threading.op(node);
if (g.REPLY) return; if (Main.REPLY) return;
nodes = []; nodes = [];
while (node.nodeName !== 'HR') { while (node.nodeName !== 'HR') {
nodes.push(node); nodes.push(node);
@ -2422,7 +2418,7 @@
ThreadHiding = { ThreadHiding = {
init: function() { init: function() {
var a, hiddenThreads, op, thread, _i, _len, _ref; var a, hiddenThreads, op, thread, _i, _len, _ref;
hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); hiddenThreads = $.get("hiddenThreads/" + Main.BOARD + "/", {});
_ref = $$('.thread'); _ref = $$('.thread');
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
thread = _ref[_i]; thread = _ref[_i];
@ -2441,7 +2437,7 @@
}, },
toggle: function(thread) { toggle: function(thread) {
var hiddenThreads, id; var hiddenThreads, id;
hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); hiddenThreads = $.get("hiddenThreads/" + Main.BOARD + "/", {});
id = $('.op', thread).id; id = $('.op', thread).id;
if (thread.hidden || thread.firstChild.className === 'block') { if (thread.hidden || thread.firstChild.className === 'block') {
ThreadHiding.show(thread); ThreadHiding.show(thread);
@ -2450,7 +2446,7 @@
ThreadHiding.hide(thread); ThreadHiding.hide(thread);
hiddenThreads[id] = Date.now(); hiddenThreads[id] = Date.now();
} }
return $.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); return $.set("hiddenThreads/" + Main.BOARD + "/", hiddenThreads);
}, },
hide: function(thread) { hide: function(thread) {
var a, div, name, num, op, span, text, trip, uid, _ref, _ref2; var a, div, name, num, op, span, text, trip, uid, _ref, _ref2;
@ -2568,7 +2564,7 @@
Updater.count.textContent = 404; Updater.count.textContent = 404;
Updater.count.className = 'warning'; Updater.count.className = 'warning';
clearTimeout(Updater.timeoutID); clearTimeout(Updater.timeoutID);
g.dead = true; Main.dead = true;
if (Conf['Unread Count']) { if (Conf['Unread Count']) {
Unread.title = Unread.title.match(/^.+-/)[0] + ' 404'; Unread.title = Unread.title.match(/^.+-/)[0] + ' 404';
} else { } else {
@ -2665,8 +2661,8 @@
$.on(favicon, 'click', this.cb.toggle); $.on(favicon, 'click', this.cb.toggle);
$.before(input, favicon); $.before(input, favicon);
} }
if (g.THREAD_ID === $.get('autoWatch', 0)) { if (Main.THREAD_ID === $.get('autoWatch', 0)) {
this.watch(g.THREAD_ID); this.watch(Main.THREAD_ID);
$["delete"]('autoWatch'); $["delete"]('autoWatch');
} else { } else {
this.refresh(); this.refresh();
@ -2699,7 +2695,7 @@
$.rm(div); $.rm(div);
} }
$.add(Watcher.dialog, nodes); $.add(Watcher.dialog, nodes);
watchedBoard = watched[g.BOARD] || {}; watchedBoard = watched[Main.BOARD] || {};
_ref3 = $$('.favicon'); _ref3 = $$('.favicon');
for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) { for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
favicon = _ref3[_j]; favicon = _ref3[_j];
@ -2724,7 +2720,7 @@
toggle: function(thread) { toggle: function(thread) {
var id; var id;
id = $('.favicon + input', thread).name; id = $('.favicon + input', thread).name;
return Watcher.watch(id) || Watcher.unwatch(id, g.BOARD); return Watcher.watch(id) || Watcher.unwatch(id, Main.BOARD);
}, },
unwatch: function(id, board) { unwatch: function(id, board) {
var watched; var watched;
@ -2738,9 +2734,9 @@
thread = $.id(id); thread = $.id(id);
if ($('.favicon', thread).src === Favicon["default"]) return false; if ($('.favicon', thread).src === Favicon["default"]) return false;
watched = $.get('watched', {}); watched = $.get('watched', {});
watched[_name = g.BOARD] || (watched[_name] = {}); watched[_name = Main.BOARD] || (watched[_name] = {});
watched[g.BOARD][id] = { watched[Main.BOARD][id] = {
href: "/" + g.BOARD + "/res/" + id, href: "/" + Main.BOARD + "/res/" + id,
textContent: GetTitle(thread) textContent: GetTitle(thread)
}; };
$.set('watched', watched); $.set('watched', watched);
@ -2751,7 +2747,7 @@
Anonymize = { Anonymize = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var name, node; var name, node;
@ -2768,7 +2764,7 @@
Sauce = { Sauce = {
init: function() { init: function() {
var link, _i, _len, _ref; var link, _i, _len, _ref;
if (g.BOARD === 'f') return; if (Main.BOARD === 'f') return;
this.links = []; this.links = [];
_ref = Conf['sauces'].split('\n'); _ref = Conf['sauces'].split('\n');
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -2777,7 +2773,7 @@
this.links.push(this.createSauceLink(link)); this.links.push(this.createSauceLink(link));
} }
if (!this.links.length) return; if (!this.links.length) return;
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
createSauceLink: function(link) { createSauceLink: function(link) {
var domain, el, href; var domain, el, href;
@ -2791,7 +2787,7 @@
case '$3': case '$3':
return "' + img.firstChild.getAttribute('md5').replace(/\=*$/, '') + '"; return "' + img.firstChild.getAttribute('md5').replace(/\=*$/, '') + '";
case '$4': case '$4':
return g.BOARD; return Main.BOARD;
} }
}); });
href = Function('img', "return '" + href + "'"); href = Function('img', "return '" + href + "'");
@ -2823,7 +2819,7 @@
RevealSpoilers = { RevealSpoilers = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var img; var img;
@ -2851,7 +2847,7 @@
hour = chanOffset + Number(hour); hour = chanOffset + Number(hour);
return new Date(year, month, day, hour, min); return new Date(year, month, day, hour, min);
}; };
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var node, time; var node, time;
@ -2942,9 +2938,9 @@
FileInfo = { FileInfo = {
init: function() { init: function() {
if (g.BOARD === 'f') return; if (Main.BOARD === 'f') return;
this.setFormats(); this.setFormats();
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var fullname, link, node, regexp, resolution, shortname, size, type, unit, _, _ref; var fullname, link, node, regexp, resolution, shortname, size, type, unit, _, _ref;
@ -3052,7 +3048,7 @@
span = $.el('span', { span = $.el('span', {
innerHTML: el.innerHTML.replace(/<br>/g, ' ') innerHTML: el.innerHTML.replace(/<br>/g, ' ')
}); });
return "/" + g.BOARD + "/ - " + span.textContent; return "/" + Main.BOARD + "/ - " + span.textContent;
}; };
TitlePost = { TitlePost = {
@ -3066,7 +3062,7 @@
var format; var format;
format = Conf['backlink'].replace(/%id/g, "' + id + '"); format = Conf['backlink'].replace(/%id/g, "' + id + '");
this.funk = Function('id', "return '" + format + "'"); this.funk = Function('id', "return '" + format + "'");
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var a, container, el, link, qid, quote, quotes, root, _i, _len, _ref; var a, container, el, link, qid, quote, quotes, root, _i, _len, _ref;
@ -3109,7 +3105,7 @@
QuoteInline = { QuoteInline = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var quote, _i, _j, _len, _len2, _ref, _ref2; var quote, _i, _j, _len, _len2, _ref, _ref2;
@ -3206,7 +3202,7 @@
quote = _ref[_i]; quote = _ref[_i];
if ((href = quote.getAttribute('href')) === quote.hash) { if ((href = quote.getAttribute('href')) === quote.hash) {
quote.pathname = pathname; quote.pathname = pathname;
} else if (!g.REPLY && href !== quote.href) { } else if (!Main.REPLY && href !== quote.href) {
quote.href = "res/" + href; quote.href = "res/" + href;
} }
} }
@ -3227,7 +3223,7 @@
QuotePreview = { QuotePreview = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var quote, _i, _j, _len, _len2, _ref, _ref2; var quote, _i, _j, _len, _len2, _ref, _ref2;
@ -3306,7 +3302,7 @@
QuoteOP = { QuoteOP = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var quote, _i, _len, _ref; var quote, _i, _len, _ref;
@ -3323,7 +3319,7 @@
QuoteCT = { QuoteCT = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var path, quote, _i, _len, _ref; var path, quote, _i, _len, _ref;
@ -3333,7 +3329,7 @@
quote = _ref[_i]; quote = _ref[_i];
if (!quote.hash) continue; if (!quote.hash) continue;
path = quote.pathname.split('/'); path = quote.pathname.split('/');
if (path[1] === g.BOARD && path[3] !== post.threadId) { if (path[1] === Main.BOARD && path[3] !== post.threadId) {
$.add(quote, $.tn('\u00A0(Cross-thread)')); $.add(quote, $.tn('\u00A0(Cross-thread)'));
} }
} }
@ -3342,7 +3338,7 @@
Quotify = { Quotify = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var a, board, data, i, id, index, m, node, nodes, quote, quotes, snapshot, text, _i, _len, _ref; var a, board, data, i, id, index, m, node, nodes, quote, quotes, snapshot, text, _i, _len, _ref;
@ -3362,7 +3358,7 @@
nodes.push(a = $.el('a', { nodes.push(a = $.el('a', {
textContent: "" + quote + "\u00A0(Dead)" textContent: "" + quote + "\u00A0(Dead)"
})); }));
if (board === g.BOARD && $.id(id)) { if (board === Main.BOARD && $.id(id)) {
a.href = "#" + id; a.href = "#" + id;
a.className = 'quotelink'; a.className = 'quotelink';
a.setAttribute('onclick', "replyhl('" + id + "');"); a.setAttribute('onclick', "replyhl('" + id + "');");
@ -3386,7 +3382,7 @@
innerHTML: '[&nbsp;!&nbsp;]', innerHTML: '[&nbsp;!&nbsp;]',
href: 'javascript:;' href: 'javascript:;'
}); });
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var a; var a;
@ -3398,7 +3394,7 @@
}, },
report: function() { report: function() {
var id, set, url; var id, set, url;
url = "//sys.4chan.org/" + g.BOARD + "/imgboard.php?mode=report&no=" + ($.x('preceding-sibling::input', this).name); url = "//sys.4chan.org/" + Main.BOARD + "/imgboard.php?mode=report&no=" + ($.x('preceding-sibling::input', this).name);
id = Date.now(); id = Date.now();
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200"; set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200";
return window.open(url, id, set); return window.open(url, id, set);
@ -3413,7 +3409,7 @@
$.add(d.body, dialog); $.add(d.body, dialog);
this.posts = this.images = 0; this.posts = this.images = 0;
this.imgLimit = (function() { this.imgLimit = (function() {
switch (g.BOARD) { switch (Main.BOARD) {
case 'a': case 'a':
case 'mlp': case 'mlp':
case 'v': case 'v':
@ -3424,7 +3420,7 @@
return 151; return 151;
} }
})(); })();
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var imgcount; var imgcount;
@ -3444,7 +3440,7 @@
this.title = d.title; this.title = d.title;
this.update(); this.update();
$.on(window, 'scroll', Unread.scroll); $.on(window, 'scroll', Unread.scroll);
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
replies: [], replies: [],
foresee: [], foresee: [],
@ -3484,11 +3480,11 @@
}, },
update: function(forceUpdate) { update: function(forceUpdate) {
var count; var count;
if (!g.REPLY) return; if (!Main.REPLY) return;
count = this.replies.length; count = this.replies.length;
if (Conf['Unread Count']) this.setTitle(count); if (Conf['Unread Count']) this.setTitle(count);
if (!(Conf['Unread Favicon'] && (count < 2 || forceUpdate))) return; if (!(Conf['Unread Favicon'] && (count < 2 || forceUpdate))) return;
Favicon.el.href = g.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"]; Favicon.el.href = Main.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"];
return $.add(d.head, Favicon.el); return $.add(d.head, Favicon.el);
} }
}; };
@ -3534,7 +3530,7 @@
Redirect = { Redirect = {
init: function() { init: function() {
var url; var url;
url = location.hostname === 'images.4chan.org' ? this.image(location.href) : /^\d+$/.test(g.THREAD_ID) ? this.thread() : void 0; url = location.hostname === 'images.4chan.org' ? this.image(location.href) : /^\d+$/.test(Main.THREAD_ID) ? this.thread() : void 0;
if (url) return location.href = url; if (url) return location.href = url;
}, },
image: function(href) { image: function(href) {
@ -3551,11 +3547,11 @@
} }
}, },
thread: function(board, id, mode) { thread: function(board, id, mode) {
if (board == null) board = g.BOARD; if (board == null) board = Main.BOARD;
if (id == null) id = g.THREAD_ID; if (id == null) id = Main.THREAD_ID;
if (mode == null) mode = 'thread'; if (mode == null) mode = 'thread';
if (!(Conf['404 Redirect'] || mode === 'post')) return; if (!(Conf['404 Redirect'] || mode === 'post')) return;
switch (g.BOARD) { switch (Main.BOARD) {
case 'a': case 'a':
case 'jp': case 'jp':
case 'm': case 'm':
@ -3606,7 +3602,7 @@
ImageHover = { ImageHover = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
if (!post.img) return; if (!post.img) return;
@ -3640,7 +3636,7 @@
AutoGif = { AutoGif = {
init: function() { init: function() {
return g.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var img, src; var img, src;
@ -3658,7 +3654,7 @@
ImageExpand = { ImageExpand = {
init: function() { init: function() {
g.callbacks.push(this.node); Main.callbacks.push(this.node);
return this.dialog(); return this.dialog();
}, },
node: function(post) { node: function(post) {
@ -3765,7 +3761,7 @@
ImageExpand.contract(thumb); ImageExpand.contract(thumb);
$.rm(this); $.rm(this);
if (!(this.src.split('/')[2] === 'images.4chan.org' && (url = Redirect.image(href)))) { if (!(this.src.split('/')[2] === 'images.4chan.org' && (url = Redirect.image(href)))) {
if (g.dead) return; if (Main.dead) return;
url = href + '?' + Date.now(); url = href + '?' + Date.now();
} }
timeoutID = setTimeout(ImageExpand.expand, 10000, thumb, url); timeoutID = setTimeout(ImageExpand.expand, 10000, thumb, url);
@ -3806,12 +3802,12 @@
var cutoff, hiddenThreads, id, key, now, path, pathname, temp, timestamp, val, _ref; var cutoff, hiddenThreads, id, key, now, path, pathname, temp, timestamp, val, _ref;
path = location.pathname; path = location.pathname;
pathname = path.slice(1).split('/'); pathname = path.slice(1).split('/');
g.BOARD = pathname[0], temp = pathname[1]; Main.BOARD = pathname[0], temp = pathname[1];
if (temp === 'res') { if (temp === 'res') {
g.REPLY = true; Main.REPLY = true;
g.THREAD_ID = pathname[2]; Main.THREAD_ID = pathname[2];
} else { } else {
g.PAGENUM = parseInt(temp) || 0; Main.PAGENUM = parseInt(temp) || 0;
} }
for (key in Conf) { for (key in Conf) {
val = Conf[key]; val = Conf[key];
@ -3851,7 +3847,7 @@
return; return;
} }
$.ready(Options.init); $.ready(Options.init);
if (Conf['Quick Reply'] && Conf['Hide Original Post Form'] && g.BOARD !== 'f') { if (Conf['Quick Reply'] && Conf['Hide Original Post Form'] && Main.BOARD !== 'f') {
Main.css += 'form[name=post] { display: none; }'; Main.css += 'form[name=post] { display: none; }';
} }
Main.addStyle(); Main.addStyle();
@ -3864,22 +3860,22 @@
}); });
$.set('lastUpdate', now); $.set('lastUpdate', now);
} }
g.hiddenReplies = $.get("hiddenReplies/" + g.BOARD + "/", {}); Main.hiddenReplies = $.get("hiddenReplies/" + Main.BOARD + "/", {});
if ($.get('lastChecked', 0) < now - 1 * DAY) { if ($.get('lastChecked', 0) < now - 1 * DAY) {
$.set('lastChecked', now); $.set('lastChecked', now);
cutoff = now - 7 * DAY; cutoff = now - 7 * DAY;
hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); hiddenThreads = $.get("hiddenThreads/" + Main.BOARD + "/", {});
for (id in hiddenThreads) { for (id in hiddenThreads) {
timestamp = hiddenThreads[id]; timestamp = hiddenThreads[id];
if (timestamp < cutoff) delete hiddenThreads[id]; if (timestamp < cutoff) delete hiddenThreads[id];
} }
_ref = g.hiddenReplies; _ref = Main.hiddenReplies;
for (id in _ref) { for (id in _ref) {
timestamp = _ref[id]; timestamp = _ref[id];
if (timestamp < cutoff) delete g.hiddenReplies[id]; if (timestamp < cutoff) delete Main.hiddenReplies[id];
} }
$.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); $.set("hiddenThreads/" + Main.BOARD + "/", hiddenThreads);
$.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); $.set("hiddenReplies/" + Main.BOARD + "/", Main.hiddenReplies);
} }
if (Conf['Filter']) Filter.init(); if (Conf['Filter']) Filter.init();
if (Conf['Reply Hiding']) ReplyHiding.init(); if (Conf['Reply Hiding']) ReplyHiding.init();
@ -3912,7 +3908,7 @@
_ref = ['navtop', 'navbot']; _ref = ['navtop', 'navbot'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
nav = _ref[_i]; nav = _ref[_i];
$.addClass($("a[href$='/" + g.BOARD + "/']", $.id(nav)), 'current'); $.addClass($("a[href$='/" + Main.BOARD + "/']", $.id(nav)), 'current');
} }
form = $('form[name=delform]'); form = $('form[name=delform]');
Threading.thread(form.firstElementChild); Threading.thread(form.firstElementChild);
@ -3929,7 +3925,7 @@
return Keybinds.init(); return Keybinds.init();
}); });
} }
if (g.REPLY) { if (Main.REPLY) {
if (Conf['Thread Updater']) { if (Conf['Thread Updater']) {
setTimeout(function() { setTimeout(function() {
return Updater.init(); return Updater.init();
@ -4010,7 +4006,7 @@
el: klass === 'op' ? node : node.firstChild.firstChild.lastChild, el: klass === 'op' ? node : node.firstChild.firstChild.lastChild,
"class": klass, "class": klass,
id: node.getElementsByTagName('input')[0].name, id: node.getElementsByTagName('input')[0].name,
threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).firstChild.id, threadId: Main.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).firstChild.id,
isOP: klass === 'op', isOP: klass === 'op',
isInlined: /\binline\b/.test(klass), isInlined: /\binline\b/.test(klass),
filesize: node.getElementsByClassName('filesize')[0] || false, filesize: node.getElementsByClassName('filesize')[0] || false,
@ -4022,7 +4018,7 @@
}, },
node: function(nodes, notify) { node: function(nodes, notify) {
var callback, node, _i, _j, _len, _len2, _ref; var callback, node, _i, _j, _len, _len2, _ref;
_ref = g.callbacks; _ref = Main.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
callback = _ref[_i]; callback = _ref[_i];
try { try {
@ -4055,6 +4051,7 @@
target = e.target; target = e.target;
if (target.nodeName === 'TABLE') return Main.node([Main.preParse(target)]); if (target.nodeName === 'TABLE') return Main.node([Main.preParse(target)]);
}, },
callbacks: [],
css: '\ css: '\
/* dialog styling */\ /* dialog styling */\
.dialog {\ .dialog {\

View File

@ -179,7 +179,6 @@ HOUR = 60*MINUTE
DAY = 24*HOUR DAY = 24*HOUR
engine = /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase() engine = /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase()
d = document d = document
g = callbacks: []
ui = ui =
dialog: (id, position, html) -> dialog: (id, position, html) ->
@ -471,7 +470,7 @@ Filter =
# and it's not specifically applicable to the current board. # and it's not specifically applicable to the current board.
# Defaults to global. # Defaults to global.
boards = filter.match(/boards:([^;]+)/)?[1].toLowerCase() or 'global' boards = filter.match(/boards:([^;]+)/)?[1].toLowerCase() or 'global'
if boards isnt 'global' and boards.split(',').indexOf(g.BOARD) is -1 if boards isnt 'global' and boards.split(',').indexOf(Main.BOARD) is -1
continue continue
try try
@ -507,7 +506,7 @@ Filter =
delete @filters[key] delete @filters[key]
if Object.keys(@filters).length if Object.keys(@filters).length
g.callbacks.push @node Main.callbacks.push @node
createFilter: (regexp, op, hl, top) -> createFilter: (regexp, op, hl, top) ->
test = test =
@ -540,7 +539,7 @@ Filter =
# Hide # Hide
if result is true if result is true
if isOP if isOP
unless g.REPLY unless Main.REPLY
ThreadHiding.hide post.el.parentNode ThreadHiding.hide post.el.parentNode
else else
continue continue
@ -553,7 +552,7 @@ Filter =
$.addClass el, result[0] $.addClass el, result[0]
else else
$.addClass el.parentNode, result[0] $.addClass el.parentNode, result[0]
if isOP and result[1] and not g.REPLY if isOP and result[1] and not Main.REPLY
# Put the highlighted OPs' threads on top of the board pages... # Put the highlighted OPs' threads on top of the board pages...
thisThread = el.parentNode thisThread = el.parentNode
# ...before the first non highlighted thread. # ...before the first non highlighted thread.
@ -612,7 +611,7 @@ Filter =
StrikethroughQuotes = StrikethroughQuotes =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.isInlined return if post.isInlined
for quote in post.quotes for quote in post.quotes
@ -649,7 +648,7 @@ ExpandComment =
quotes = node.getElementsByClassName 'quotelink' quotes = node.getElementsByClassName 'quotelink'
for quote in quotes for quote in quotes
if quote.hash is quote.getAttribute 'href' if quote.hash is quote.getAttribute 'href'
quote.pathname = "/#{g.BOARD}/res/#{threadID}" quote.pathname = "/#{Main.BOARD}/res/#{threadID}"
post = post =
el: node el: node
threadId: threadID threadId: threadID
@ -684,7 +683,7 @@ ExpandThread =
toggle: (thread) -> toggle: (thread) ->
threadID = thread.firstChild.id threadID = thread.firstChild.id
pathname = "/#{g.BOARD}/res/#{threadID}" pathname = "/#{Main.BOARD}/res/#{threadID}"
a = $ '.omittedposts', thread a = $ '.omittedposts', thread
# \u00d7 is &times; # \u00d7 is &times;
@ -702,7 +701,7 @@ ExpandThread =
when '-' when '-'
a.textContent = a.textContent.replace '-', '+' a.textContent = a.textContent.replace '-', '+'
#goddamit moot #goddamit moot
num = switch g.BOARD num = switch Main.BOARD
when 'b', 'vg' then 3 when 'b', 'vg' then 3
when 't' then 1 when 't' then 1
else 5 else 5
@ -747,7 +746,7 @@ ReplyHiding =
noWrap: true noWrap: true
className: 'replyhider' className: 'replyhider'
innerHTML: '<a href="javascript:;">[ - ]</a>' innerHTML: '<a href="javascript:;">[ - ]</a>'
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class return if post.class
@ -755,7 +754,7 @@ ReplyHiding =
$.on td.firstChild, 'click', ReplyHiding.toggle $.on td.firstChild, 'click', ReplyHiding.toggle
$.replace post.el.previousSibling, td $.replace post.el.previousSibling, td
if post.id of g.hiddenReplies if post.id of Main.hiddenReplies
ReplyHiding.hide post.root ReplyHiding.hide post.root
toggle: -> toggle: ->
@ -765,7 +764,7 @@ ReplyHiding =
id = parent.nextSibling.id id = parent.nextSibling.id
for quote in $$ ".quotelink[href='##{id}'], .backlink[href='##{id}']" for quote in $$ ".quotelink[href='##{id}'], .backlink[href='##{id}']"
$.addClass quote, 'filtered' $.addClass quote, 'filtered'
g.hiddenReplies[id] = Date.now() Main.hiddenReplies[id] = Date.now()
else else
table = parent.nextSibling table = parent.nextSibling
table.hidden = false table.hidden = false
@ -773,8 +772,8 @@ ReplyHiding =
id = table.firstChild.firstChild.lastChild.id id = table.firstChild.firstChild.lastChild.id
for quote in $$ ".quotelink[href='##{id}'], .backlink[href='##{id}']" for quote in $$ ".quotelink[href='##{id}'], .backlink[href='##{id}']"
$.removeClass quote, 'filtered' $.removeClass quote, 'filtered'
delete g.hiddenReplies[id] delete Main.hiddenReplies[id]
$.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies $.set "hiddenReplies/#{Main.BOARD}/", Main.hiddenReplies
hide: (table) -> hide: (table) ->
return if table.hidden # already hidden by filter return if table.hidden # already hidden by filter
@ -850,17 +849,17 @@ Keybinds =
Keybinds.img thread, true Keybinds.img thread, true
# Board Navigation # Board Navigation
when Conf.zero when Conf.zero
window.location = "/#{g.BOARD}/0#0" window.location = "/#{Main.BOARD}/0#0"
when Conf.nextPage when Conf.nextPage
$('input[value=Next]')?.click() $('input[value=Next]')?.click()
when Conf.previousPage when Conf.previousPage
$('input[value=Previous]')?.click() $('input[value=Previous]')?.click()
# Thread Navigation # Thread Navigation
when Conf.nextThread when Conf.nextThread
return if g.REPLY return if Main.REPLY
Nav.scroll +1 Nav.scroll +1
when Conf.previousThread when Conf.previousThread
return if g.REPLY return if Main.REPLY
Nav.scroll -1 Nav.scroll -1
when Conf.expandThread when Conf.expandThread
ExpandThread.toggle thread ExpandThread.toggle thread
@ -919,7 +918,7 @@ Keybinds =
open: (thread, tab) -> open: (thread, tab) ->
id = thread.firstChild.id id = thread.firstChild.id
url = "//boards.4chan.org/#{g.BOARD}/res/#{id}" url = "//boards.4chan.org/#{Main.BOARD}/res/#{id}"
if tab if tab
$.open url $.open url
else else
@ -941,7 +940,7 @@ Keybinds =
td.tabIndex = 0 td.tabIndex = 0
td.focus() td.focus()
return return
return unless g.REPLY or $.x('ancestor::div[@class="thread"]', next) is thread return unless Main.REPLY or $.x('ancestor::div[@class="thread"]', next) is thread
rect = next.getBoundingClientRect() rect = next.getBoundingClientRect()
if rect.top < 0 or rect.bottom > d.body.clientHeight if rect.top < 0 or rect.bottom > d.body.clientHeight
next.scrollIntoView delta is -1 next.scrollIntoView delta is -1
@ -979,13 +978,13 @@ Nav =
$.add d.body, span $.add d.body, span
prev: -> prev: ->
if g.REPLY if Main.REPLY
window.scrollTo 0, 0 window.scrollTo 0, 0
else else
Nav.scroll -1 Nav.scroll -1
next: -> next: ->
if g.REPLY if Main.REPLY
window.scrollTo 0, d.body.scrollHeight window.scrollTo 0, d.body.scrollHeight
else else
Nav.scroll +1 Nav.scroll +1
@ -1017,15 +1016,15 @@ Nav =
QR = QR =
init: -> init: ->
return unless $.id 'recaptcha_challenge_field_holder' return unless $.id 'recaptcha_challenge_field_holder'
g.callbacks.push @node Main.callbacks.push @node
setTimeout @asyncInit setTimeout @asyncInit
asyncInit: -> asyncInit: ->
if Conf['Hide Original Post Form'] if Conf['Hide Original Post Form']
link = $.el 'h1', innerHTML: "<a href=javascript:;>#{if g.REPLY then 'Quick Reply' else 'New Thread'}</a>" link = $.el 'h1', innerHTML: "<a href=javascript:;>#{if Main.REPLY then 'Quick Reply' else 'New Thread'}</a>"
$.on $('a', link), 'click', -> $.on $('a', link), 'click', ->
QR.open() QR.open()
$('select', QR.el).value = 'new' unless g.REPLY $('select', QR.el).value = 'new' unless Main.REPLY
$('textarea', QR.el).focus() $('textarea', QR.el).focus()
form = d.forms[0] form = d.forms[0]
$.before form, link $.before form, link
@ -1110,7 +1109,7 @@ QR =
else unless QR.status.ready else unless QR.status.ready
value = 'Loading' value = 'Loading'
disabled = true disabled = true
if g.dead if Main.dead
value = 404 value = 404
disabled = true disabled = true
QR.cooldown.auto = false QR.cooldown.auto = false
@ -1132,28 +1131,28 @@ QR =
cooldown: cooldown:
init: -> init: ->
return unless Conf['Cooldown'] return unless Conf['Cooldown']
QR.cooldown.start $.get "/#{g.BOARD}/cooldown", 0 QR.cooldown.start $.get "/#{Main.BOARD}/cooldown", 0
$.sync "/#{g.BOARD}/cooldown", QR.cooldown.start $.sync "/#{Main.BOARD}/cooldown", QR.cooldown.start
start: (timeout) -> start: (timeout) ->
seconds = Math.floor (timeout - Date.now()) / 1000 seconds = Math.floor (timeout - Date.now()) / 1000
QR.cooldown.count seconds QR.cooldown.count seconds
set: (seconds) -> set: (seconds) ->
return unless Conf['Cooldown'] return unless Conf['Cooldown']
QR.cooldown.count seconds QR.cooldown.count seconds
$.set "/#{g.BOARD}/cooldown", Date.now() + seconds*SECOND $.set "/#{Main.BOARD}/cooldown", Date.now() + seconds*SECOND
count: (seconds) -> count: (seconds) ->
return unless 0 <= seconds <= 60 return unless 0 <= seconds <= 60
setTimeout QR.cooldown.count, 1000, seconds-1 setTimeout QR.cooldown.count, 1000, seconds-1
QR.cooldown.seconds = seconds QR.cooldown.seconds = seconds
if seconds is 0 if seconds is 0
$.delete "/#{g.BOARD}/cooldown" $.delete "/#{Main.BOARD}/cooldown"
QR.submit() if QR.cooldown.auto QR.submit() if QR.cooldown.auto
QR.status() QR.status()
quote: (e) -> quote: (e) ->
e?.preventDefault() e?.preventDefault()
QR.open() QR.open()
unless g.REPLY unless Main.REPLY
$('select', QR.el).value = $.x('ancestor::div[@class="thread"]', @).firstChild.id $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', @).firstChild.id
# Make sure we get the correct number, even with XXX censors # Make sure we get the correct number, even with XXX censors
@ -1463,7 +1462,7 @@ QR =
spoiler = $ '#spoilerLabel', QR.el spoiler = $ '#spoilerLabel', QR.el
spoiler.hidden = !QR.spoiler spoiler.hidden = !QR.spoiler
unless g.REPLY unless Main.REPLY
# Make a list with visible threads and an option to create a new one. # Make a list with visible threads and an option to create a new one.
threads = '<option value=new>New thread</option>' threads = '<option value=new>New thread</option>'
for thread in $$ '.op' for thread in $$ '.op'
@ -1553,7 +1552,7 @@ QR =
return return
QR.cleanError() QR.cleanError()
threadID = g.THREAD_ID or $('select', QR.el).value threadID = Main.THREAD_ID or $('select', QR.el).value
# Enable auto-posting if we have stuff to post, disable it otherwise. # Enable auto-posting if we have stuff to post, disable it otherwise.
QR.cooldown.auto = QR.replies.length > 1 QR.cooldown.auto = QR.replies.length > 1
@ -1642,22 +1641,22 @@ QR =
if Conf['Thread Watcher'] and Conf['Auto Watch'] if Conf['Thread Watcher'] and Conf['Auto Watch']
$.set 'autoWatch', postNumber $.set 'autoWatch', postNumber
# auto-noko # auto-noko
location.pathname = "/#{g.BOARD}/res/#{postNumber}" location.pathname = "/#{Main.BOARD}/res/#{postNumber}"
else else
# Enable auto-posting if we have stuff to post, disable it otherwise. # Enable auto-posting if we have stuff to post, disable it otherwise.
QR.cooldown.auto = QR.replies.length > 1 QR.cooldown.auto = QR.replies.length > 1
QR.cooldown.set if /sage/i.test reply.email then 60 else 30 QR.cooldown.set if /sage/i.test reply.email then 60 else 30
if Conf['Open Reply in New Tab'] && !g.REPLY && !QR.cooldown.auto if Conf['Open Reply in New Tab'] && !Main.REPLY && !QR.cooldown.auto
$.open "//boards.4chan.org/#{g.BOARD}/res/#{thread}##{postNumber}" $.open "//boards.4chan.org/#{Main.BOARD}/res/#{thread}##{postNumber}"
if Conf['Persistent QR'] or QR.cooldown.auto if Conf['Persistent QR'] or QR.cooldown.auto
reply.rm() reply.rm()
else else
QR.close() QR.close()
if g.REPLY and (Conf['Unread Count'] or Conf['Unread Favicon']) if Main.REPLY and (Conf['Unread Count'] or Conf['Unread Favicon'])
Unread.foresee.push postNumber Unread.foresee.push postNumber
if g.REPLY and Conf['Thread Updater'] and Conf['Auto Update This'] if Main.REPLY and Conf['Thread Updater'] and Conf['Auto Update This']
Updater.update() Updater.update()
QR.status() QR.status()
@ -1904,8 +1903,8 @@ Options =
$.add ul, li $.add ul, li
$.add $('#main_tab + div', dialog), ul $.add $('#main_tab + div', dialog), ul
hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} hiddenThreads = $.get "hiddenThreads/#{Main.BOARD}/", {}
hiddenNum = Object.keys(g.hiddenReplies).length + Object.keys(hiddenThreads).length hiddenNum = Object.keys(Main.hiddenReplies).length + Object.keys(hiddenThreads).length
li = $.el 'li', li = $.el 'li',
innerHTML: "<button>hidden: #{hiddenNum}</button> <span class=description>: Forget all hidden posts. Useful if you accidentally hide a post and have \"Show Stubs\" disabled." innerHTML: "<button>hidden: #{hiddenNum}</button> <span class=description>: Forget all hidden posts. Useful if you accidentally hide a post and have \"Show Stubs\" disabled."
$.on $('button', li), 'click', Options.clearHidden $.on $('button', li), 'click', Options.clearHidden
@ -1972,10 +1971,10 @@ Options =
clearHidden: -> clearHidden: ->
#'hidden' might be misleading; it's the number of IDs we're *looking* for, #'hidden' might be misleading; it's the number of IDs we're *looking* for,
# not the number of posts actually hidden on the page. # not the number of posts actually hidden on the page.
$.delete "hiddenReplies/#{g.BOARD}/" $.delete "hiddenReplies/#{Main.BOARD}/"
$.delete "hiddenThreads/#{g.BOARD}/" $.delete "hiddenThreads/#{Main.BOARD}/"
@textContent = "hidden: 0" @textContent = "hidden: 0"
g.hiddenReplies = {} Main.hiddenReplies = {}
keybind: (e) -> keybind: (e) ->
return if e.keyCode is 9 return if e.keyCode is 9
e.preventDefault() e.preventDefault()
@ -2023,7 +2022,7 @@ Threading =
thread: (node) -> thread: (node) ->
node = Threading.op node node = Threading.op node
return if g.REPLY return if Main.REPLY
nodes = [] nodes = []
until node.nodeName is 'HR' until node.nodeName is 'HR'
@ -2041,7 +2040,7 @@ Threading =
ThreadHiding = ThreadHiding =
init: -> init: ->
hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} hiddenThreads = $.get "hiddenThreads/#{Main.BOARD}/", {}
for thread in $$ '.thread' for thread in $$ '.thread'
op = thread.firstChild op = thread.firstChild
a = $.el 'a', a = $.el 'a',
@ -2058,7 +2057,7 @@ ThreadHiding =
ThreadHiding.toggle @parentNode.parentNode ThreadHiding.toggle @parentNode.parentNode
toggle: (thread) -> toggle: (thread) ->
hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} hiddenThreads = $.get "hiddenThreads/#{Main.BOARD}/", {}
id = $('.op', thread).id id = $('.op', thread).id
if thread.hidden or thread.firstChild.className is 'block' if thread.hidden or thread.firstChild.className is 'block'
ThreadHiding.show thread ThreadHiding.show thread
@ -2066,7 +2065,7 @@ ThreadHiding =
else else
ThreadHiding.hide thread ThreadHiding.hide thread
hiddenThreads[id] = Date.now() hiddenThreads[id] = Date.now()
$.set "hiddenThreads/#{g.BOARD}/", hiddenThreads $.set "hiddenThreads/#{Main.BOARD}/", hiddenThreads
hide: (thread) -> hide: (thread) ->
unless Conf['Show Stubs'] unless Conf['Show Stubs']
@ -2175,7 +2174,7 @@ Updater =
Updater.count.textContent = 404 Updater.count.textContent = 404
Updater.count.className = 'warning' Updater.count.className = 'warning'
clearTimeout Updater.timeoutID clearTimeout Updater.timeoutID
g.dead = true Main.dead = true
if Conf['Unread Count'] if Conf['Unread Count']
Unread.title = Unread.title.match(/^.+-/)[0] + ' 404' Unread.title = Unread.title.match(/^.+-/)[0] + ' 404'
else else
@ -2260,8 +2259,8 @@ Watcher =
$.on favicon, 'click', @cb.toggle $.on favicon, 'click', @cb.toggle
$.before input, favicon $.before input, favicon
if g.THREAD_ID is $.get 'autoWatch', 0 if Main.THREAD_ID is $.get 'autoWatch', 0
@watch g.THREAD_ID @watch Main.THREAD_ID
$.delete 'autoWatch' $.delete 'autoWatch'
else else
#populate watcher, display watch buttons #populate watcher, display watch buttons
@ -2290,7 +2289,7 @@ Watcher =
$.rm div $.rm div
$.add Watcher.dialog, nodes $.add Watcher.dialog, nodes
watchedBoard = watched[g.BOARD] or {} watchedBoard = watched[Main.BOARD] or {}
for favicon in $$ '.favicon' for favicon in $$ '.favicon'
id = favicon.nextSibling.name id = favicon.nextSibling.name
if id of watchedBoard if id of watchedBoard
@ -2308,7 +2307,7 @@ Watcher =
toggle: (thread) -> toggle: (thread) ->
id = $('.favicon + input', thread).name id = $('.favicon + input', thread).name
Watcher.watch(id) or Watcher.unwatch id, g.BOARD Watcher.watch(id) or Watcher.unwatch id, Main.BOARD
unwatch: (id, board) -> unwatch: (id, board) ->
watched = $.get 'watched', {} watched = $.get 'watched', {}
@ -2321,9 +2320,9 @@ Watcher =
return false if $('.favicon', thread).src is Favicon.default return false if $('.favicon', thread).src is Favicon.default
watched = $.get 'watched', {} watched = $.get 'watched', {}
watched[g.BOARD] or= {} watched[Main.BOARD] or= {}
watched[g.BOARD][id] = watched[Main.BOARD][id] =
href: "/#{g.BOARD}/res/#{id}" href: "/#{Main.BOARD}/res/#{id}"
textContent: GetTitle thread textContent: GetTitle thread
$.set 'watched', watched $.set 'watched', watched
Watcher.refresh() Watcher.refresh()
@ -2331,7 +2330,7 @@ Watcher =
Anonymize = Anonymize =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class is 'inline' return if post.class is 'inline'
name = $ '.commentpostername, .postername', post.el name = $ '.commentpostername, .postername', post.el
@ -2342,13 +2341,13 @@ Anonymize =
Sauce = Sauce =
init: -> init: ->
return if g.BOARD is 'f' return if Main.BOARD is 'f'
@links = [] @links = []
for link in Conf['sauces'].split '\n' for link in Conf['sauces'].split '\n'
continue if link[0] is '#' continue if link[0] is '#'
@links.push @createSauceLink link @links.push @createSauceLink link
return unless @links.length return unless @links.length
g.callbacks.push @node Main.callbacks.push @node
createSauceLink: (link) -> createSauceLink: (link) ->
domain = link.match(/(\w+)\.\w+\//)[1] domain = link.match(/(\w+)\.\w+\//)[1]
@ -2361,7 +2360,7 @@ Sauce =
when '$3' when '$3'
"' + img.firstChild.getAttribute('md5').replace(/\=*$/, '') + '" "' + img.firstChild.getAttribute('md5').replace(/\=*$/, '') + '"
when '$4' when '$4'
g.BOARD Main.BOARD
href = Function 'img', "return '#{href}'" href = Function 'img', "return '#{href}'"
el = $.el 'a', el = $.el 'a',
target: '_blank' target: '_blank'
@ -2382,7 +2381,7 @@ Sauce =
RevealSpoilers = RevealSpoilers =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
{img} = post {img} = post
if not (img and /^Spoil/.test img.alt) or post.class is 'inline' if not (img and /^Spoil/.test img.alt) or post.class is 'inline'
@ -2412,7 +2411,7 @@ Time =
hour = chanOffset + Number hour hour = chanOffset + Number hour
new Date year, month, day, hour, min new Date year, month, day, hour, min
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class is 'inline' return if post.class is 'inline'
# .posttime exists on every board except /f/ # .posttime exists on every board except /f/
@ -2471,9 +2470,9 @@ Time =
FileInfo = FileInfo =
init: -> init: ->
return if g.BOARD is 'f' return if Main.BOARD is 'f'
@setFormats() @setFormats()
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class is 'inline' or not node = post.filesize return if post.class is 'inline' or not node = post.filesize
type = if node.childElementCount is 2 then 0 else 1 type = if node.childElementCount is 2 then 0 else 1
@ -2545,7 +2544,7 @@ GetTitle = (thread) ->
if not el.textContent if not el.textContent
el = $ '.postername', thread el = $ '.postername', thread
span = $.el 'span', innerHTML: el.innerHTML.replace /<br>/g, ' ' span = $.el 'span', innerHTML: el.innerHTML.replace /<br>/g, ' '
"/#{g.BOARD}/ - #{span.textContent}" "/#{Main.BOARD}/ - #{span.textContent}"
TitlePost = TitlePost =
init: -> init: ->
@ -2555,7 +2554,7 @@ QuoteBacklink =
init: -> init: ->
format = Conf['backlink'].replace /%id/g, "' + id + '" format = Conf['backlink'].replace /%id/g, "' + id + '"
@funk = Function 'id', "return '#{format}'" @funk = Function 'id', "return '#{format}'"
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.isInlined return if post.isInlined
quotes = {} quotes = {}
@ -2589,7 +2588,7 @@ QuoteBacklink =
QuoteInline = QuoteInline =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
for quote in post.quotes for quote in post.quotes
continue unless quote.hash continue unless quote.hash
@ -2666,7 +2665,7 @@ QuoteInline =
for quote in $$ '.quotelink', newInline for quote in $$ '.quotelink', newInline
if (href = quote.getAttribute 'href') is quote.hash #add pathname to normal quotes if (href = quote.getAttribute 'href') is quote.hash #add pathname to normal quotes
quote.pathname = pathname quote.pathname = pathname
else if !g.REPLY and href isnt quote.href #fix x-thread links, not x-board ones else if !Main.REPLY and href isnt quote.href #fix x-thread links, not x-board ones
quote.href = "res/#{href}" quote.href = "res/#{href}"
link = $ '.quotejs', newInline link = $ '.quotejs', newInline
link.href = "#{pathname}##{id}" link.href = "#{pathname}##{id}"
@ -2681,7 +2680,7 @@ QuoteInline =
QuotePreview = QuotePreview =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
for quote in post.quotes for quote in post.quotes
$.on quote, 'mouseover', QuotePreview.mouseover if quote.hash $.on quote, 'mouseover', QuotePreview.mouseover if quote.hash
@ -2748,7 +2747,7 @@ QuotePreview =
QuoteOP = QuoteOP =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class is 'inline' return if post.class is 'inline'
for quote in post.quotes for quote in post.quotes
@ -2759,7 +2758,7 @@ QuoteOP =
QuoteCT = QuoteCT =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class is 'inline' return if post.class is 'inline'
for quote in post.quotes for quote in post.quotes
@ -2768,14 +2767,14 @@ QuoteCT =
continue continue
path = quote.pathname.split '/' path = quote.pathname.split '/'
# If quote leads to a different thread id and is located on the same board. # If quote leads to a different thread id and is located on the same board.
if path[1] is g.BOARD and path[3] isnt post.threadId if path[1] is Main.BOARD and path[3] isnt post.threadId
# \u00A0 is nbsp # \u00A0 is nbsp
$.add quote, $.tn '\u00A0(Cross-thread)' $.add quote, $.tn '\u00A0(Cross-thread)'
return return
Quotify = Quotify =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class is 'inline' return if post.class is 'inline'
@ -2811,7 +2810,7 @@ Quotify =
# \u00A0 is nbsp # \u00A0 is nbsp
textContent: "#{quote}\u00A0(Dead)" textContent: "#{quote}\u00A0(Dead)"
if board is g.BOARD and $.id id if board is Main.BOARD and $.id id
a.href = "##{id}" a.href = "##{id}"
a.className = 'quotelink' a.className = 'quotelink'
a.setAttribute 'onclick', "replyhl('#{id}');" a.setAttribute 'onclick', "replyhl('#{id}');"
@ -2835,14 +2834,14 @@ ReportButton =
className: 'reportbutton' className: 'reportbutton'
innerHTML: '[&nbsp;!&nbsp;]' innerHTML: '[&nbsp;!&nbsp;]'
href: 'javascript:;' href: 'javascript:;'
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
unless a = $ '.reportbutton', post.el unless a = $ '.reportbutton', post.el
a = ReportButton.a.cloneNode true a = ReportButton.a.cloneNode true
$.after $('span[id]', post.el), [$.tn(' '), a] $.after $('span[id]', post.el), [$.tn(' '), a]
$.on a, 'click', ReportButton.report $.on a, 'click', ReportButton.report
report: -> report: ->
url = "//sys.4chan.org/#{g.BOARD}/imgboard.php?mode=report&no=#{$.x('preceding-sibling::input', @).name}" url = "//sys.4chan.org/#{Main.BOARD}/imgboard.php?mode=report&no=#{$.x('preceding-sibling::input', @).name}"
id = Date.now() id = Date.now()
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200" set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200"
window.open url, id, set window.open url, id, set
@ -2854,14 +2853,14 @@ ThreadStats =
$.add d.body, dialog $.add d.body, dialog
@posts = @images = 0 @posts = @images = 0
@imgLimit = @imgLimit =
switch g.BOARD switch Main.BOARD
when 'a', 'mlp', 'v' when 'a', 'mlp', 'v'
251 251
when 'vg' when 'vg'
501 501
else else
151 151
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.isInlined return if post.isInlined
$.id('postcount').textContent = ++ThreadStats.posts $.id('postcount').textContent = ++ThreadStats.posts
@ -2876,7 +2875,7 @@ Unread =
@title = d.title @title = d.title
@update() @update()
$.on window, 'scroll', Unread.scroll $.on window, 'scroll', Unread.scroll
g.callbacks.push @node Main.callbacks.push @node
replies: [] replies: []
foresee: [] foresee: []
@ -2911,7 +2910,7 @@ Unread =
), 5 ), 5
update: (forceUpdate) -> update: (forceUpdate) ->
return unless g.REPLY return unless Main.REPLY
count = @replies.length count = @replies.length
@ -2922,7 +2921,7 @@ Unread =
return return
Favicon.el.href = Favicon.el.href =
if g.dead if Main.dead
if count if count
Favicon.unreadDead Favicon.unreadDead
else else
@ -2975,19 +2974,19 @@ Redirect =
url = url =
if location.hostname is 'images.4chan.org' if location.hostname is 'images.4chan.org'
@image location.href @image location.href
else if /^\d+$/.test g.THREAD_ID else if /^\d+$/.test Main.THREAD_ID
@thread() @thread()
location.href = url if url location.href = url if url
image: (href) -> image: (href) ->
href = href.split '/' href = href.split '/'
# Do not use g.BOARD, the image url can originate from a cross-quote. # Do not use Main.BOARD, the image url can originate from a cross-quote.
return unless Conf['404 Redirect'] return unless Conf['404 Redirect']
switch href[3] switch href[3]
when 'a', 'jp', 'm', 'tg', 'u', 'vg' when 'a', 'jp', 'm', 'tg', 'u', 'vg'
"http://archive.foolz.us/#{href[3]}/full_image/#{href[5]}" "http://archive.foolz.us/#{href[3]}/full_image/#{href[5]}"
thread: (board=g.BOARD, id=g.THREAD_ID, mode='thread') -> thread: (board=Main.BOARD, id=Main.THREAD_ID, mode='thread') ->
return unless Conf['404 Redirect'] or mode is 'post' return unless Conf['404 Redirect'] or mode is 'post'
switch g.BOARD switch Main.BOARD
when 'a', 'jp', 'm', 'tg', 'tv', 'u', 'v', 'vg' when 'a', 'jp', 'm', 'tg', 'tv', 'u', 'v', 'vg'
"http://archive.foolz.us/#{board}/thread/#{id}/" "http://archive.foolz.us/#{board}/thread/#{id}/"
when 'lit' when 'lit'
@ -3004,7 +3003,7 @@ Redirect =
ImageHover = ImageHover =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return unless post.img return unless post.img
$.on post.img, 'mouseover', ImageHover.mouseover $.on post.img, 'mouseover', ImageHover.mouseover
@ -3030,7 +3029,7 @@ ImageHover =
AutoGif = AutoGif =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.root.hidden or not post.img return if post.root.hidden or not post.img
src = post.img.parentNode.href src = post.img.parentNode.href
@ -3043,7 +3042,7 @@ AutoGif =
ImageExpand = ImageExpand =
init: -> init: ->
g.callbacks.push @node Main.callbacks.push @node
@dialog() @dialog()
node: (post) -> node: (post) ->
@ -3125,7 +3124,7 @@ ImageExpand =
ImageExpand.contract thumb ImageExpand.contract thumb
$.rm @ $.rm @
unless @src.split('/')[2] is 'images.4chan.org' and url = Redirect.image href unless @src.split('/')[2] is 'images.4chan.org' and url = Redirect.image href
return if g.dead return if Main.dead
# CloudFlare may cache banned pages instead of images. # CloudFlare may cache banned pages instead of images.
# This will fool CloudFlare's cache. # This will fool CloudFlare's cache.
url = href + '?' + Date.now() url = href + '?' + Date.now()
@ -3160,12 +3159,12 @@ Main =
init: -> init: ->
path = location.pathname path = location.pathname
pathname = path[1..].split '/' pathname = path[1..].split '/'
[g.BOARD, temp] = pathname [Main.BOARD, temp] = pathname
if temp is 'res' if temp is 'res'
g.REPLY = true Main.REPLY = true
g.THREAD_ID = pathname[2] Main.THREAD_ID = pathname[2]
else else
g.PAGENUM = parseInt(temp) or 0 Main.PAGENUM = parseInt(temp) or 0
#load values from localStorage #load values from localStorage
for key, val of Conf for key, val of Conf
@ -3192,7 +3191,7 @@ Main =
$.ready Options.init $.ready Options.init
if Conf['Quick Reply'] and Conf['Hide Original Post Form'] and g.BOARD isnt 'f' if Conf['Quick Reply'] and Conf['Hide Original Post Form'] and Main.BOARD isnt 'f'
Main.css += 'form[name=post] { display: none; }' Main.css += 'form[name=post] { display: none; }'
Main.addStyle() Main.addStyle()
@ -3202,23 +3201,23 @@ Main =
$.ready -> $.add d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js' $.ready -> $.add d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js'
$.set 'lastUpdate', now $.set 'lastUpdate', now
g.hiddenReplies = $.get "hiddenReplies/#{g.BOARD}/", {} Main.hiddenReplies = $.get "hiddenReplies/#{Main.BOARD}/", {}
if $.get('lastChecked', 0) < now - 1*DAY if $.get('lastChecked', 0) < now - 1*DAY
$.set 'lastChecked', now $.set 'lastChecked', now
cutoff = now - 7*DAY cutoff = now - 7*DAY
hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} hiddenThreads = $.get "hiddenThreads/#{Main.BOARD}/", {}
for id, timestamp of hiddenThreads for id, timestamp of hiddenThreads
if timestamp < cutoff if timestamp < cutoff
delete hiddenThreads[id] delete hiddenThreads[id]
for id, timestamp of g.hiddenReplies for id, timestamp of Main.hiddenReplies
if timestamp < cutoff if timestamp < cutoff
delete g.hiddenReplies[id] delete Main.hiddenReplies[id]
$.set "hiddenThreads/#{g.BOARD}/", hiddenThreads $.set "hiddenThreads/#{Main.BOARD}/", hiddenThreads
$.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies $.set "hiddenReplies/#{Main.BOARD}/", Main.hiddenReplies
#major features #major features
@ -3284,7 +3283,7 @@ Main =
$.addClass d.body, "chanx_#{VERSION.split('.')[1]}" $.addClass d.body, "chanx_#{VERSION.split('.')[1]}"
$.addClass d.body, engine $.addClass d.body, engine
for nav in ['navtop', 'navbot'] for nav in ['navtop', 'navbot']
$.addClass $("a[href$='/#{g.BOARD}/']", $.id nav), 'current' $.addClass $("a[href$='/#{Main.BOARD}/']", $.id nav), 'current'
form = $ 'form[name=delform]' form = $ 'form[name=delform]'
Threading.thread form.firstElementChild Threading.thread form.firstElementChild
Favicon.init() Favicon.init()
@ -3302,7 +3301,7 @@ Main =
if Conf['Keybinds'] if Conf['Keybinds']
setTimeout -> Keybinds.init() setTimeout -> Keybinds.init()
if g.REPLY if Main.REPLY
if Conf['Thread Updater'] if Conf['Thread Updater']
setTimeout -> Updater.init() setTimeout -> Updater.init()
@ -3367,7 +3366,7 @@ Main =
el: if klass is 'op' then node else node.firstChild.firstChild.lastChild el: if klass is 'op' then node else node.firstChild.firstChild.lastChild
class: klass class: klass
id: node.getElementsByTagName('input')[0].name id: node.getElementsByTagName('input')[0].name
threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).firstChild.id threadId: Main.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).firstChild.id
isOP: klass is 'op' isOP: klass is 'op'
isInlined: /\binline\b/.test klass isInlined: /\binline\b/.test klass
filesize: node.getElementsByClassName('filesize')[0] or false filesize: node.getElementsByClassName('filesize')[0] or false
@ -3376,7 +3375,7 @@ Main =
post.img = if post.filesize then node.getElementsByTagName('img')[0] else false post.img = if post.filesize then node.getElementsByTagName('img')[0] else false
post post
node: (nodes, notify) -> node: (nodes, notify) ->
for callback in g.callbacks for callback in Main.callbacks
try try
callback node for node in nodes callback node for node in nodes
catch err catch err
@ -3392,6 +3391,7 @@ Main =
{target} = e {target} = e
Main.node [Main.preParse target] if target.nodeName is 'TABLE' Main.node [Main.preParse target] if target.nodeName is 'TABLE'
callbacks: []
css: ' css: '
/* dialog styling */ /* dialog styling */
.dialog { .dialog {