conf{ig} -> Conf{ig}

This commit is contained in:
James Campos 2012-03-15 23:08:31 -07:00
parent 3ae36e2492
commit 8cb14a9af2
2 changed files with 272 additions and 272 deletions

View File

@ -73,9 +73,9 @@
*/ */
(function() { (function() {
var $, $$, Anonymize, AutoGif, 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, conf, config, 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, g, log, ui, _base;
config = { Config = {
main: { main: {
Enhancing: { Enhancing: {
'404 Redirect': [true, 'Redirect dead threads and images'], '404 Redirect': [true, 'Redirect dead threads and images'],
@ -194,21 +194,21 @@
log = typeof (_base = console.log).bind === "function" ? _base.bind(console) : void 0; log = typeof (_base = console.log).bind === "function" ? _base.bind(console) : void 0;
conf = {}; Conf = {};
(flatten = function(parent, obj) { (flatten = function(parent, obj) {
var key, val; var key, val;
if (obj instanceof Array) { if (obj instanceof Array) {
conf[parent] = obj[0]; Conf[parent] = obj[0];
} else if (typeof obj === 'object') { } else if (typeof obj === 'object') {
for (key in obj) { for (key in obj) {
val = obj[key]; val = obj[key];
flatten(key, val); flatten(key, val);
} }
} else { } else {
conf[parent] = obj; Conf[parent] = obj;
} }
})(null, config); })(null, Config);
NAMESPACE = '4chan_x.'; NAMESPACE = '4chan_x.';
@ -384,11 +384,11 @@
cb: { cb: {
checked: function() { checked: function() {
$.set(this.name, this.checked); $.set(this.name, this.checked);
return conf[this.name] = this.checked; return Conf[this.name] = this.checked;
}, },
value: function() { value: function() {
$.set(this.name, this.value.trim()); $.set(this.name, this.value.trim());
return conf[this.name] = this.value; return Conf[this.name] = this.value;
} }
}, },
addStyle: function(css) { addStyle: function(css) {
@ -544,9 +544,9 @@
filters: {}, filters: {},
init: function() { init: function() {
var boards, filter, hl, key, op, regexp, top, _i, _len, _ref, _ref2, _ref3, _ref4, _ref5; var boards, filter, hl, key, op, regexp, top, _i, _len, _ref, _ref2, _ref3, _ref4, _ref5;
for (key in config.filter) { for (key in Config.filter) {
this.filters[key] = []; this.filters[key] = [];
_ref = conf[key].split('\n'); _ref = Conf[key].split('\n');
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
filter = _ref[_i]; filter = _ref[_i];
if (filter[0] === '#') continue; if (filter[0] === '#') continue;
@ -710,7 +710,7 @@
quote = _ref[_i]; quote = _ref[_i];
if ((el = $.id(quote.hash.slice(1))) && el.parentNode.parentNode.parentNode.hidden) { if ((el = $.id(quote.hash.slice(1))) && el.parentNode.parentNode.parentNode.hidden) {
$.addClass(quote, 'filtered'); $.addClass(quote, 'filtered');
if (conf['Recursive Filtering']) ReplyHiding.hide(post.root); if (Conf['Recursive Filtering']) ReplyHiding.hide(post.root);
} }
} }
} }
@ -759,11 +759,11 @@
quotes: quotes, quotes: quotes,
backlinks: [] backlinks: []
}; };
if (conf['Resurrect Quotes']) Quotify.node(post); if (Conf['Resurrect Quotes']) Quotify.node(post);
if (conf['Quote Preview']) QuotePreview.node(post); if (Conf['Quote Preview']) QuotePreview.node(post);
if (conf['Quote Inline']) QuoteInline.node(post); if (Conf['Quote Inline']) QuoteInline.node(post);
if (conf['Indicate OP quote']) QuoteOP.node(post); if (Conf['Indicate OP quote']) QuoteOP.node(post);
if (conf['Indicate Cross-thread Quotes']) QuoteCT.node(post); if (Conf['Indicate Cross-thread Quotes']) QuoteCT.node(post);
return $.replace(a.parentNode.parentNode, node.lastChild); return $.replace(a.parentNode.parentNode, node.lastChild);
} }
}; };
@ -920,7 +920,7 @@
var div, name, trip, uid, _ref, _ref2; var div, name, trip, uid, _ref, _ref2;
if (table.hidden) return; if (table.hidden) return;
table.hidden = true; table.hidden = true;
if (!conf['Show Stubs']) return; if (!Conf['Show Stubs']) return;
name = $('.commentpostername', table).textContent; name = $('.commentpostername', table).textContent;
uid = ((_ref = $('.posteruid', table)) != null ? _ref.textContent : void 0) || ''; uid = ((_ref = $('.posteruid', table)) != null ? _ref.textContent : void 0) || '';
trip = ((_ref2 = $('.postertrip', table)) != null ? _ref2.textContent : void 0) || ''; trip = ((_ref2 = $('.postertrip', table)) != null ? _ref2.textContent : void 0) || '';
@ -950,26 +950,26 @@
} }
thread = Nav.getThread(); thread = Nav.getThread();
switch (key) { switch (key) {
case conf.openQR: case Conf.openQR:
Keybinds.qr(thread, true); Keybinds.qr(thread, true);
break; break;
case conf.openEmptyQR: case Conf.openEmptyQR:
Keybinds.qr(thread); Keybinds.qr(thread);
break; break;
case conf.openOptions: case Conf.openOptions:
if (!$.id('overlay')) Options.dialog(); if (!$.id('overlay')) Options.dialog();
break; break;
case conf.close: case Conf.close:
if (o = $.id('overlay')) { if (o = $.id('overlay')) {
Options.close.call(o); Options.close.call(o);
} else if (QR.el) { } else if (QR.el) {
QR.close(); QR.close();
} }
break; break;
case conf.submit: case Conf.submit:
if (QR.el && !QR.status()) QR.submit(); if (QR.el && !QR.status()) QR.submit();
break; break;
case conf.spoiler: case Conf.spoiler:
ta = e.target; ta = e.target;
if (ta.nodeName !== 'TEXTAREA') return; if (ta.nodeName !== 'TEXTAREA') return;
value = ta.value; value = ta.value;
@ -979,55 +979,55 @@
range = 9 + selEnd; range = 9 + selEnd;
ta.setSelectionRange(range, range); ta.setSelectionRange(range, range);
break; break;
case conf.watch: case Conf.watch:
Watcher.toggle(thread); Watcher.toggle(thread);
break; break;
case conf.update: case Conf.update:
Updater.update(); Updater.update();
break; break;
case conf.unreadCountTo0: case Conf.unreadCountTo0:
Unread.replies = []; Unread.replies = [];
Unread.update(); Unread.update();
break; break;
case conf.expandImage: case Conf.expandImage:
Keybinds.img(thread); Keybinds.img(thread);
break; break;
case conf.expandAllImages: case Conf.expandAllImages:
Keybinds.img(thread, true); Keybinds.img(thread, true);
break; break;
case conf.zero: case Conf.zero:
window.location = "/" + g.BOARD + "/0#0"; window.location = "/" + g.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();
break; break;
case conf.previousPage: case Conf.previousPage:
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 (g.REPLY) return;
Nav.scroll(+1); Nav.scroll(+1);
break; break;
case conf.previousThread: case Conf.previousThread:
if (g.REPLY) return; if (g.REPLY) return;
Nav.scroll(-1); Nav.scroll(-1);
break; break;
case conf.expandThread: case Conf.expandThread:
ExpandThread.toggle(thread); ExpandThread.toggle(thread);
break; break;
case conf.openThread: case Conf.openThread:
Keybinds.open(thread); Keybinds.open(thread);
break; break;
case conf.openThreadTab: case Conf.openThreadTab:
Keybinds.open(thread, true); Keybinds.open(thread, true);
break; break;
case conf.nextReply: case Conf.nextReply:
Keybinds.hl(+1, thread); Keybinds.hl(+1, thread);
break; break;
case conf.previousReply: case Conf.previousReply:
Keybinds.hl(-1, thread); Keybinds.hl(-1, thread);
break; break;
case conf.hide: case Conf.hide:
if (/\bthread\b/.test(thread.className)) ThreadHiding.toggle(thread); if (/\bthread\b/.test(thread.className)) ThreadHiding.toggle(thread);
break; break;
default: default:
@ -1241,7 +1241,7 @@
}, },
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:;>" + (g.REPLY ? 'Quick Reply' : 'New Thread') + "</a>"
}); });
@ -1285,9 +1285,9 @@
}); });
$.add(d.head, script); $.add(d.head, script);
$.rm(script); $.rm(script);
if (conf['Persistent QR']) { if (Conf['Persistent QR']) {
QR.dialog(); QR.dialog();
if (conf['Auto Hide QR']) QR.hide(); if (Conf['Auto Hide QR']) QR.hide();
} }
$.on(d, 'dragover', QR.dragOver); $.on(d, 'dragover', QR.dragOver);
$.on(d, 'drop', QR.dropFile); $.on(d, 'drop', QR.dropFile);
@ -1321,7 +1321,7 @@
QR.cooldown.auto = false; QR.cooldown.auto = false;
QR.status(); QR.status();
QR.resetFileInput(); QR.resetFileInput();
if (!conf['Remember Spoiler'] && (spoiler = $.id('spoiler')).checked) { if (!Conf['Remember Spoiler'] && (spoiler = $.id('spoiler')).checked) {
spoiler.click(); spoiler.click();
} }
return QR.cleanError(); return QR.cleanError();
@ -1374,12 +1374,12 @@
} }
if (!QR.el) return; if (!QR.el) return;
input = QR.status.input; input = QR.status.input;
input.value = QR.cooldown.auto && conf['Cooldown'] ? value ? "Auto " + value : 'Auto' : value || 'Submit'; input.value = QR.cooldown.auto && Conf['Cooldown'] ? value ? "Auto " + value : 'Auto' : value || 'Submit';
return input.disabled = disabled || false; return input.disabled = disabled || false;
}, },
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("/" + g.BOARD + "/cooldown", 0));
return $.sync("/" + g.BOARD + "/cooldown", QR.cooldown.start); return $.sync("/" + g.BOARD + "/cooldown", QR.cooldown.start);
}, },
@ -1389,7 +1389,7 @@
return QR.cooldown.count(seconds); return QR.cooldown.count(seconds);
}, },
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("/" + g.BOARD + "/cooldown", Date.now() + seconds * SECOND);
}, },
@ -1491,8 +1491,8 @@
persona = $.get('QR.persona', {}); persona = $.get('QR.persona', {});
this.name = prev ? prev.name : persona.name || null; this.name = prev ? prev.name : persona.name || null;
this.email = prev && !/^sage$/.test(prev.email) ? prev.email : persona.email || null; this.email = prev && !/^sage$/.test(prev.email) ? prev.email : persona.email || null;
this.sub = prev && conf['Remember Subject'] ? prev.sub : conf['Remember Subject'] ? persona.sub : null; this.sub = prev && Conf['Remember Subject'] ? prev.sub : Conf['Remember Subject'] ? persona.sub : null;
this.spoiler = prev && conf['Remember Spoiler'] ? prev.spoiler : false; this.spoiler = prev && Conf['Remember Spoiler'] ? prev.spoiler : false;
this.com = null; this.com = null;
this.el = $.el('a', { this.el = $.el('a', {
className: 'preview', className: 'preview',
@ -1746,7 +1746,7 @@
<label id=spoilerLabel><input type=checkbox id=spoiler> Spoiler Image</label>\ <label id=spoilerLabel><input type=checkbox id=spoiler> Spoiler Image</label>\
<div class=warning></div>\ <div class=warning></div>\
</form>'); </form>');
if (conf['Remember QR size'] && engine === 'gecko') { if (Conf['Remember QR size'] && engine === 'gecko') {
$.on(ta = $('textarea', QR.el), 'mouseup', function() { $.on(ta = $('textarea', QR.el), 'mouseup', function() {
return $.set('QR.size', this.style.cssText); return $.set('QR.size', this.style.cssText);
}); });
@ -1880,8 +1880,8 @@
QR.cleanError(); QR.cleanError();
threadID = g.THREAD_ID || $('select', QR.el).value; threadID = g.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') {
Watcher.watch(threadID); Watcher.watch(threadID);
} }
post = { post = {
@ -1957,31 +1957,31 @@
persona = { persona = {
name: reply.name, name: reply.name,
email: /^sage$/.test(reply.email) ? persona.email : reply.email, email: /^sage$/.test(reply.email) ? persona.email : reply.email,
sub: conf['Remember Subject'] ? reply.sub : null sub: Conf['Remember Subject'] ? reply.sub : null
}; };
$.set('QR.persona', persona); $.set('QR.persona', persona);
_ref = b.lastChild.textContent.match(/thread:(\d+),no:(\d+)/), _ = _ref[0], thread = _ref[1], postNumber = _ref[2]; _ref = b.lastChild.textContent.match(/thread:(\d+),no:(\d+)/), _ = _ref[0], thread = _ref[1], postNumber = _ref[2];
if (thread === '0') { if (thread === '0') {
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 = "/" + g.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'] && !g.REPLY && !QR.cooldown.auto) {
$.open("//boards.4chan.org/" + g.BOARD + "/res/" + thread + "#" + postNumber); $.open("//boards.4chan.org/" + g.BOARD + "/res/" + thread + "#" + postNumber);
} }
} }
if (conf['Persistent QR'] || QR.cooldown.auto) { if (Conf['Persistent QR'] || QR.cooldown.auto) {
reply.rm(); reply.rm();
} else { } else {
QR.close(); QR.close();
} }
if (g.REPLY && (conf['Unread Count'] || conf['Unread Favicon'])) { if (g.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 (g.REPLY && Conf['Thread Updater'] && Conf['Auto Update This']) {
Updater.update(); Updater.update();
} }
QR.status(); QR.status();
@ -2247,7 +2247,7 @@
</div>\ </div>\
</div>' </div>'
}); });
_ref = config.main; _ref = Config.main;
for (key in _ref) { for (key in _ref) {
obj = _ref[key]; obj = _ref[key];
ul = $.el('ul', { ul = $.el('ul', {
@ -2255,7 +2255,7 @@
}); });
for (key in obj) { for (key in obj) {
arr = obj[key]; arr = obj[key];
checked = conf[key] ? 'checked' : ''; checked = Conf[key] ? 'checked' : '';
description = arr[1]; description = arr[1];
li = $.el('li', { li = $.el('li', {
innerHTML: "<label><input type=checkbox name=\"" + key + "\" " + checked + ">" + key + "</label><span class=description>: " + description + "</span>" innerHTML: "<label><input type=checkbox name=\"" + key + "\" " + checked + ">" + key + "</label><span class=description>: " + description + "</span>"
@ -2275,13 +2275,13 @@
_ref2 = $$('textarea', dialog); _ref2 = $$('textarea', dialog);
for (_i = 0, _len = _ref2.length; _i < _len; _i++) { for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
ta = _ref2[_i]; ta = _ref2[_i];
ta.textContent = conf[ta.name]; ta.textContent = Conf[ta.name];
$.on(ta, 'change', $.cb.value); $.on(ta, 'change', $.cb.value);
} }
(back = $('[name=backlink]', dialog)).value = conf['backlink']; (back = $('[name=backlink]', dialog)).value = Conf['backlink'];
(time = $('[name=time]', dialog)).value = conf['time']; (time = $('[name=time]', dialog)).value = Conf['time'];
(fileInfoR = $('[name=fileInfoR]', dialog)).value = conf['fileInfoR']; (fileInfoR = $('[name=fileInfoR]', dialog)).value = Conf['fileInfoR'];
(fileInfoT = $('[name=fileInfoT]', dialog)).value = conf['fileInfoT']; (fileInfoT = $('[name=fileInfoT]', dialog)).value = Conf['fileInfoT'];
$.on(back, 'keyup', $.cb.value); $.on(back, 'keyup', $.cb.value);
$.on(back, 'keyup', Options.backlink); $.on(back, 'keyup', Options.backlink);
$.on(time, 'keyup', $.cb.value); $.on(time, 'keyup', $.cb.value);
@ -2291,17 +2291,17 @@
$.on(fileInfoT, 'keyup', $.cb.value); $.on(fileInfoT, 'keyup', $.cb.value);
$.on(fileInfoT, 'keyup', Options.fileInfo); $.on(fileInfoT, 'keyup', Options.fileInfo);
favicon = $('select', dialog); favicon = $('select', dialog);
favicon.value = conf['favicon']; favicon.value = Conf['favicon'];
$.on(favicon, 'change', $.cb.value); $.on(favicon, 'change', $.cb.value);
$.on(favicon, 'change', Options.favicon); $.on(favicon, 'change', Options.favicon);
_ref3 = config.hotkeys; _ref3 = Config.hotkeys;
for (key in _ref3) { for (key in _ref3) {
arr = _ref3[key]; arr = _ref3[key];
tr = $.el('tr', { tr = $.el('tr', {
innerHTML: "<td>" + arr[1] + "</td><td><input name=" + key + "></td>" innerHTML: "<td>" + arr[1] + "</td><td><input name=" + key + "></td>"
}); });
input = $('input', tr); input = $('input', tr);
input.value = conf[key]; input.value = Conf[key];
$.on(input, 'keydown', Options.keybind); $.on(input, 'keydown', Options.keybind);
$.add($('#keybinds_tab + div tbody', dialog), tr); $.add($('#keybinds_tab + div tbody', dialog), tr);
} }
@ -2310,7 +2310,7 @@
for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) { for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
indicator = _ref4[_j]; indicator = _ref4[_j];
key = indicator.firstChild.textContent; key = indicator.firstChild.textContent;
indicator.hidden = conf[key]; indicator.hidden = Conf[key];
indicators[key] = indicator; indicators[key] = indicator;
$.on($("[name='" + key + "']", dialog), 'click', function() { $.on($("[name='" + key + "']", dialog), 'click', function() {
return indicators[this.name].hidden = this.checked; return indicators[this.name].hidden = this.checked;
@ -2357,7 +2357,7 @@
return $.id('timePreview').textContent = Time.funk(Time); return $.id('timePreview').textContent = Time.funk(Time);
}, },
backlink: function() { backlink: function() {
return $.id('backlinkPreview').textContent = conf['backlink'].replace(/%id/, '123456789'); return $.id('backlinkPreview').textContent = Conf['backlink'].replace(/%id/, '123456789');
}, },
fileInfo: function() { fileInfo: function() {
var type; var type;
@ -2454,7 +2454,7 @@
}, },
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;
if (!conf['Show Stubs']) { if (!Conf['Show Stubs']) {
thread.hidden = true; thread.hidden = true;
thread.nextSibling.hidden = true; thread.nextSibling.hidden = true;
return; return;
@ -2491,15 +2491,15 @@
Updater = { Updater = {
init: function() { init: function() {
var checkbox, checked, dialog, html, input, name, title, _i, _len, _ref; var checkbox, checked, dialog, html, input, name, title, _i, _len, _ref;
html = "<div class=move><span id=count></span> <span id=timer>-" + conf['Interval'] + "</span></div>"; html = "<div class=move><span id=count></span> <span id=timer>-" + Conf['Interval'] + "</span></div>";
checkbox = config.updater.checkbox; checkbox = Config.updater.checkbox;
for (name in checkbox) { for (name in checkbox) {
title = checkbox[name][1]; title = checkbox[name][1];
checked = conf[name] ? 'checked' : ''; checked = Conf[name] ? 'checked' : '';
html += "<div><label title='" + title + "'>" + name + "<input name='" + name + "' type=checkbox " + checked + "></label></div>"; html += "<div><label title='" + title + "'>" + name + "<input name='" + name + "' type=checkbox " + checked + "></label></div>";
} }
checked = conf['Auto Update'] ? 'checked' : ''; checked = Conf['Auto Update'] ? 'checked' : '';
html += " <div><label title='Controls whether *this* thread automatically updates or not'>Auto Update This<input name='Auto Update This' type=checkbox " + checked + "></label></div> <div><label>Interval (s)<input name=Interval value=" + conf['Interval'] + " type=text></label></div> <div><input value='Update Now' type=button></div>"; html += " <div><label title='Controls whether *this* thread automatically updates or not'>Auto Update This<input name='Auto Update This' type=checkbox " + checked + "></label></div> <div><label>Interval (s)<input name=Interval value=" + Conf['Interval'] + " type=text></label></div> <div><input value='Update Now' type=button></div>";
dialog = ui.dialog('updater', 'bottom: 0; right: 0;', html); dialog = ui.dialog('updater', 'bottom: 0; right: 0;', html);
this.count = $('#count', dialog); this.count = $('#count', dialog);
this.timer = $('#timer', dialog); this.timer = $('#timer', dialog);
@ -2519,11 +2519,11 @@
} else if (input.name === 'Auto Update This') { } else if (input.name === 'Auto Update This') {
$.on(input, 'click', this.cb.autoUpdate); $.on(input, 'click', this.cb.autoUpdate);
this.cb.autoUpdate.call(input); this.cb.autoUpdate.call(input);
conf[input.name] = input.checked; Conf[input.name] = input.checked;
} }
} else if (input.name === 'Interval') { } else if (input.name === 'Interval') {
$.on(input, 'change', function() { $.on(input, 'change', function() {
return conf['Interval'] = this.value = parseInt(this.value, 10) || conf['Interval']; return Conf['Interval'] = this.value = parseInt(this.value, 10) || Conf['Interval'];
}); });
$.on(input, 'change', $.cb.value); $.on(input, 'change', $.cb.value);
} else if (input.type === 'button') { } else if (input.type === 'button') {
@ -2536,7 +2536,7 @@
}, },
cb: { cb: {
verbose: function() { verbose: function() {
if (conf['Verbose']) { if (Conf['Verbose']) {
Updater.count.textContent = '+0'; Updater.count.textContent = '+0';
return Updater.timer.hidden = false; return Updater.timer.hidden = false;
} else { } else {
@ -2569,7 +2569,7 @@
Updater.count.className = 'warning'; Updater.count.className = 'warning';
clearTimeout(Updater.timeoutID); clearTimeout(Updater.timeoutID);
g.dead = true; g.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 {
d.title = d.title.match(/^.+-/)[0] + ' 404'; d.title = d.title.match(/^.+-/)[0] + ' 404';
@ -2582,7 +2582,7 @@
return; return;
} }
Updater.retryCoef = 10; Updater.retryCoef = 10;
Updater.timer.textContent = '-' + conf['Interval']; Updater.timer.textContent = '-' + Conf['Interval'];
/* /*
Status Code 304: Not modified Status Code 304: Not modified
By sending the `If-Modified-Since` header we get a proper status code, and no response. By sending the `If-Modified-Since` header we get a proper status code, and no response.
@ -2590,7 +2590,7 @@
and won't load images and scripts when parsing the response. and won't load images and scripts when parsing the response.
*/ */
if (this.status === 304) { if (this.status === 304) {
if (conf['Verbose']) { if (Conf['Verbose']) {
Updater.count.textContent = '+0'; Updater.count.textContent = '+0';
Updater.count.className = null; Updater.count.className = null;
} }
@ -2608,8 +2608,8 @@
nodes.push(reply.parentNode.parentNode.parentNode); nodes.push(reply.parentNode.parentNode.parentNode);
} }
newPosts = nodes.length; newPosts = nodes.length;
scroll = conf['Scrolling'] && Updater.scrollBG() && newPosts && Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25; scroll = Conf['Scrolling'] && Updater.scrollBG() && newPosts && Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25;
if (conf['Verbose']) { if (Conf['Verbose']) {
Updater.count.textContent = "+" + newPosts; Updater.count.textContent = "+" + newPosts;
Updater.count.className = newPosts ? 'new' : null; Updater.count.className = newPosts ? 'new' : null;
} }
@ -2770,7 +2770,7 @@
var link, _i, _len, _ref; var link, _i, _len, _ref;
if (g.BOARD === 'f') return; if (g.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++) {
link = _ref[_i]; link = _ref[_i];
if (link[0] === '#') continue; if (link[0] === '#') continue;
@ -2865,7 +2865,7 @@
}, },
foo: function() { foo: function() {
var code; var code;
code = conf['time'].replace(/%([A-Za-z])/g, function(s, c) { code = Conf['time'].replace(/%([A-Za-z])/g, function(s, c) {
if (c in Time.formatters) { if (c in Time.formatters) {
return "' + Time.formatters." + c + "() + '"; return "' + Time.formatters." + c + "() + '";
} else { } else {
@ -2967,7 +2967,7 @@
var code, format, funks, i, param; var code, format, funks, i, param;
funks = []; funks = [];
for (i = 0; i <= 1; i++) { for (i = 0; i <= 1; i++) {
format = i ? conf['fileInfoT'] : conf['fileInfoR']; format = i ? Conf['fileInfoT'] : Conf['fileInfoR'];
param = i ? /%([BKlMrs])/g : /%([BKlLMnNrs])/g; param = i ? /%([BKlMrs])/g : /%([BKlLMnNrs])/g;
code = format.replace(param, function(s, c) { code = format.replace(param, function(s, c) {
if (c in FileInfo.formatters) { if (c in FileInfo.formatters) {
@ -3064,7 +3064,7 @@
QuoteBacklink = { QuoteBacklink = {
init: function() { init: function() {
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 g.callbacks.push(this.node);
}, },
@ -3083,12 +3083,12 @@
textContent: QuoteBacklink.funk(post.id) textContent: QuoteBacklink.funk(post.id)
}); });
for (qid in quotes) { for (qid in quotes) {
if (!(el = $.id(qid)) || el.className === 'op' && !conf['OP Backlinks']) { if (!(el = $.id(qid)) || el.className === 'op' && !Conf['OP Backlinks']) {
continue; continue;
} }
link = a.cloneNode(true); link = a.cloneNode(true);
if (conf['Quote Preview']) $.on(link, 'mouseover', QuotePreview.mouseover); if (Conf['Quote Preview']) $.on(link, 'mouseover', QuotePreview.mouseover);
if (conf['Quote Inline']) { if (Conf['Quote Inline']) {
$.on(link, 'click', QuoteInline.toggle); $.on(link, 'click', QuoteInline.toggle);
} else { } else {
link.setAttribute('onclick', "replyhl('" + post.id + "');"); link.setAttribute('onclick', "replyhl('" + post.id + "');");
@ -3152,7 +3152,7 @@
} }
if (/\bbacklink\b/.test(q.className)) { if (/\bbacklink\b/.test(q.className)) {
$.after(q.parentNode, inline); $.after(q.parentNode, inline);
if (conf['Forward Hiding']) { if (Conf['Forward Hiding']) {
table = $.x('ancestor::table', el); table = $.x('ancestor::table', el);
$.addClass(table, 'forwarded'); $.addClass(table, 'forwarded');
++table.title || (table.title = 1); ++table.title || (table.title = 1);
@ -3178,7 +3178,7 @@
var inlined, table, _i, _len, _ref; var inlined, table, _i, _len, _ref;
table = $.x("following::*[@id='i" + id + "']", q); table = $.x("following::*[@id='i" + id + "']", q);
$.rm(table); $.rm(table);
if (!conf['Forward Hiding']) return; if (!Conf['Forward Hiding']) return;
_ref = $$('.backlink.inlined', table); _ref = $$('.backlink.inlined', table);
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
inlined = _ref[_i]; inlined = _ref[_i];
@ -3253,7 +3253,7 @@
id = this.hash.slice(1); id = this.hash.slice(1);
if (el = $.id(id)) { if (el = $.id(id)) {
qp.innerHTML = el.innerHTML; qp.innerHTML = el.innerHTML;
if (conf['Quote Highlighting']) $.addClass(el, 'qphl'); if (Conf['Quote Highlighting']) $.addClass(el, 'qphl');
if (/\bbacklink\b/.test(this.className)) { if (/\bbacklink\b/.test(this.className)) {
replyID = $.x('preceding-sibling::input', this.parentNode).name; replyID = $.x('preceding-sibling::input', this.parentNode).name;
_ref = $$('.quotelink', qp); _ref = $$('.quotelink', qp);
@ -3298,9 +3298,9 @@
filesize: $('.filesize', qp), filesize: $('.filesize', qp),
img: $('img[md5]', qp) img: $('img[md5]', qp)
}; };
if (conf['Image Auto-Gif']) AutoGif.node(post); if (Conf['Image Auto-Gif']) AutoGif.node(post);
if (conf['Time Formatting']) Time.node(post); if (Conf['Time Formatting']) Time.node(post);
if (conf['File Info Formatting']) return FileInfo.node(post); if (Conf['File Info Formatting']) return FileInfo.node(post);
} }
}; };
@ -3486,8 +3486,8 @@
var count; var count;
if (!g.REPLY) return; if (!g.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 = g.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"];
return $.add(d.head, Favicon.el); return $.add(d.head, Favicon.el);
} }
@ -3504,7 +3504,7 @@
return this["switch"](); return this["switch"]();
}, },
"switch": function() { "switch": function() {
switch (conf['favicon']) { switch (Conf['favicon']) {
case 'ferongr': case 'ferongr':
this.unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAOMHAOgLAnMFAL8AAOgLAukMA/+AgP+rq////////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw=='; this.unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAOMHAOgLAnMFAL8AAOgLAukMA/+AgP+rq////////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw==';
this.unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAOMHAADX8QBwfgC2zADX8QDY8nnl8qLp8v///////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw=='; this.unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAOMHAADX8QBwfgC2zADX8QDY8nnl8qLp8v///////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw==';
@ -3539,7 +3539,7 @@
}, },
image: function(href) { image: function(href) {
href = href.split('/'); href = href.split('/');
if (!conf['404 Redirect']) return; if (!Conf['404 Redirect']) return;
switch (href[3]) { switch (href[3]) {
case 'a': case 'a':
case 'jp': case 'jp':
@ -3554,7 +3554,7 @@
if (board == null) board = g.BOARD; if (board == null) board = g.BOARD;
if (id == null) id = g.THREAD_ID; if (id == null) id = g.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 (g.BOARD) {
case 'a': case 'a':
case 'jp': case 'jp':
@ -3683,7 +3683,7 @@
ImageExpand.on = this.checked; ImageExpand.on = this.checked;
if (ImageExpand.on) { if (ImageExpand.on) {
thumbs = $$('img[md5]'); thumbs = $$('img[md5]');
if (conf['Expand From Current']) { if (Conf['Expand From Current']) {
for (i = 0, _len = thumbs.length; i < _len; i++) { for (i = 0, _len = thumbs.length; i < _len; i++) {
thumb = thumbs[i]; thumb = thumbs[i];
if (thumb.getBoundingClientRect().top > 0) break; if (thumb.getBoundingClientRect().top > 0) break;
@ -3813,9 +3813,9 @@
} else { } else {
g.PAGENUM = parseInt(temp) || 0; g.PAGENUM = parseInt(temp) || 0;
} }
for (key in conf) { for (key in Conf) {
val = conf[key]; val = Conf[key];
conf[key] = $.get(key, val); Conf[key] = $.get(key, val);
} }
$.on(window, 'message', Main.message); $.on(window, 'message', Main.message);
switch (location.hostname) { switch (location.hostname) {
@ -3851,12 +3851,12 @@
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'] && g.BOARD !== 'f') {
Main.css += 'form[name=post] { display: none; }'; Main.css += 'form[name=post] { display: none; }';
} }
Main.addStyle(); Main.addStyle();
now = Date.now(); now = Date.now();
if (conf['Check for Updates'] && $.get('lastUpdate', 0) < now - 6 * HOUR) { if (Conf['Check for Updates'] && $.get('lastUpdate', 0) < now - 6 * HOUR) {
$.ready(function() { $.ready(function() {
return $.add(d.head, $.el('script', { return $.add(d.head, $.el('script', {
src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js' src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js'
@ -3881,23 +3881,23 @@
$.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); $.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads);
$.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies);
} }
if (conf['Filter']) Filter.init(); if (Conf['Filter']) Filter.init();
if (conf['Reply Hiding']) ReplyHiding.init(); if (Conf['Reply Hiding']) ReplyHiding.init();
if (conf['Filter'] || conf['Reply Hiding']) StrikethroughQuotes.init(); if (Conf['Filter'] || Conf['Reply Hiding']) StrikethroughQuotes.init();
if (conf['Anonymize']) Anonymize.init(); if (Conf['Anonymize']) Anonymize.init();
if (conf['Time Formatting']) Time.init(); if (Conf['Time Formatting']) Time.init();
if (conf['File Info Formatting']) FileInfo.init(); if (Conf['File Info Formatting']) FileInfo.init();
if (conf['Sauce']) Sauce.init(); if (Conf['Sauce']) Sauce.init();
if (conf['Reveal Spoilers']) RevealSpoilers.init(); if (Conf['Reveal Spoilers']) RevealSpoilers.init();
if (conf['Image Auto-Gif']) AutoGif.init(); if (Conf['Image Auto-Gif']) AutoGif.init();
if (conf['Image Hover']) ImageHover.init(); if (Conf['Image Hover']) ImageHover.init();
if (conf['Report Button']) ReportButton.init(); if (Conf['Report Button']) ReportButton.init();
if (conf['Resurrect Quotes']) Quotify.init(); if (Conf['Resurrect Quotes']) Quotify.init();
if (conf['Quote Inline']) QuoteInline.init(); if (Conf['Quote Inline']) QuoteInline.init();
if (conf['Quote Preview']) QuotePreview.init(); if (Conf['Quote Preview']) QuotePreview.init();
if (conf['Quote Backlinks']) QuoteBacklink.init(); if (Conf['Quote Backlinks']) QuoteBacklink.init();
if (conf['Indicate OP quote']) QuoteOP.init(); if (Conf['Indicate OP quote']) QuoteOP.init();
if (conf['Indicate Cross-thread Quotes']) QuoteCT.init(); if (Conf['Indicate Cross-thread Quotes']) QuoteCT.init();
return $.ready(Main.ready); return $.ready(Main.ready);
}, },
ready: function() { ready: function() {
@ -3917,49 +3917,49 @@
form = $('form[name=delform]'); form = $('form[name=delform]');
Threading.thread(form.firstElementChild); Threading.thread(form.firstElementChild);
Favicon.init(); Favicon.init();
if (conf['Quick Reply']) QR.init(); if (Conf['Quick Reply']) QR.init();
if (conf['Image Expansion']) ImageExpand.init(); if (Conf['Image Expansion']) ImageExpand.init();
if (conf['Thread Watcher']) { if (Conf['Thread Watcher']) {
setTimeout(function() { setTimeout(function() {
return Watcher.init(); return Watcher.init();
}); });
} }
if (conf['Keybinds']) { if (Conf['Keybinds']) {
setTimeout(function() { setTimeout(function() {
return Keybinds.init(); return Keybinds.init();
}); });
} }
if (g.REPLY) { if (g.REPLY) {
if (conf['Thread Updater']) { if (Conf['Thread Updater']) {
setTimeout(function() { setTimeout(function() {
return Updater.init(); return Updater.init();
}); });
} }
if (conf['Thread Stats']) ThreadStats.init(); if (Conf['Thread Stats']) ThreadStats.init();
if (conf['Reply Navigation']) { if (Conf['Reply Navigation']) {
setTimeout(function() { setTimeout(function() {
return Nav.init(); return Nav.init();
}); });
} }
if (conf['Post in Title']) TitlePost.init(); if (Conf['Post in Title']) TitlePost.init();
if (conf['Unread Count'] || conf['Unread Favicon']) Unread.init(); if (Conf['Unread Count'] || Conf['Unread Favicon']) Unread.init();
} else { } else {
if (conf['Thread Hiding']) { if (Conf['Thread Hiding']) {
setTimeout(function() { setTimeout(function() {
return ThreadHiding.init(); return ThreadHiding.init();
}); });
} }
if (conf['Thread Expansion']) { if (Conf['Thread Expansion']) {
setTimeout(function() { setTimeout(function() {
return ExpandThread.init(); return ExpandThread.init();
}); });
} }
if (conf['Comment Expansion']) { if (Conf['Comment Expansion']) {
setTimeout(function() { setTimeout(function() {
return ExpandComment.init(); return ExpandComment.init();
}); });
} }
if (conf['Index Navigation']) { if (Conf['Index Navigation']) {
setTimeout(function() { setTimeout(function() {
return Nav.init(); return Nav.init();
}); });

View File

@ -1,4 +1,4 @@
config = Config =
main: main:
Enhancing: Enhancing:
'404 Redirect': [true, 'Redirect dead threads and images'] '404 Redirect': [true, 'Redirect dead threads and images']
@ -159,17 +159,17 @@ config =
log = console.log.bind? console log = console.log.bind? console
# flatten the config # flatten the config
conf = {} Conf = {}
(flatten = (parent, obj) -> (flatten = (parent, obj) ->
if obj instanceof Array if obj instanceof Array
conf[parent] = obj[0] Conf[parent] = obj[0]
else if typeof obj is 'object' else if typeof obj is 'object'
for key, val of obj for key, val of obj
flatten key, val flatten key, val
else # string or number else # string or number
conf[parent] = obj Conf[parent] = obj
return return
) null, config ) null, Config
NAMESPACE = '4chan_x.' NAMESPACE = '4chan_x.'
VERSION = '2.29.1' VERSION = '2.29.1'
@ -312,10 +312,10 @@ $.extend $,
cb: cb:
checked: -> checked: ->
$.set @name, @checked $.set @name, @checked
conf[@name] = @checked Conf[@name] = @checked
value: -> value: ->
$.set @name, @value.trim() $.set @name, @value.trim()
conf[@name] = @value Conf[@name] = @value
addStyle: (css) -> addStyle: (css) ->
style = $.el 'style', style = $.el 'style',
textContent: css textContent: css
@ -456,9 +456,9 @@ $$ = (selector, root=d.body) ->
Filter = Filter =
filters: {} filters: {}
init: -> init: ->
for key of config.filter for key of Config.filter
@filters[key] = [] @filters[key] = []
for filter in conf[key].split '\n' for filter in Conf[key].split '\n'
continue if filter[0] is '#' continue if filter[0] is '#'
unless regexp = filter.match /\/(.+)\/(\w*)/ unless regexp = filter.match /\/(.+)\/(\w*)/
@ -618,7 +618,7 @@ StrikethroughQuotes =
for quote in post.quotes for quote in post.quotes
if (el = $.id quote.hash[1..]) and el.parentNode.parentNode.parentNode.hidden if (el = $.id quote.hash[1..]) and el.parentNode.parentNode.parentNode.hidden
$.addClass quote, 'filtered' $.addClass quote, 'filtered'
ReplyHiding.hide post.root if conf['Recursive Filtering'] ReplyHiding.hide post.root if Conf['Recursive Filtering']
return return
ExpandComment = ExpandComment =
@ -655,15 +655,15 @@ ExpandComment =
threadId: threadID threadId: threadID
quotes: quotes quotes: quotes
backlinks: [] backlinks: []
if conf['Resurrect Quotes'] if Conf['Resurrect Quotes']
Quotify.node post Quotify.node post
if conf['Quote Preview'] if Conf['Quote Preview']
QuotePreview.node post QuotePreview.node post
if conf['Quote Inline'] if Conf['Quote Inline']
QuoteInline.node post QuoteInline.node post
if conf['Indicate OP quote'] if Conf['Indicate OP quote']
QuoteOP.node post QuoteOP.node post
if conf['Indicate Cross-thread Quotes'] if Conf['Indicate Cross-thread Quotes']
QuoteCT.node post QuoteCT.node post
$.replace a.parentNode.parentNode, node.lastChild $.replace a.parentNode.parentNode, node.lastChild
@ -781,7 +781,7 @@ ReplyHiding =
table.hidden = true table.hidden = true
return unless conf['Show Stubs'] return unless Conf['Show Stubs']
name = $('.commentpostername', table).textContent name = $('.commentpostername', table).textContent
uid = $('.posteruid', table)?.textContent or '' uid = $('.posteruid', table)?.textContent or ''
@ -806,20 +806,20 @@ Keybinds =
thread = Nav.getThread() thread = Nav.getThread()
switch key switch key
# QR & Options # QR & Options
when conf.openQR when Conf.openQR
Keybinds.qr thread, true Keybinds.qr thread, true
when conf.openEmptyQR when Conf.openEmptyQR
Keybinds.qr thread Keybinds.qr thread
when conf.openOptions when Conf.openOptions
Options.dialog() unless $.id 'overlay' Options.dialog() unless $.id 'overlay'
when conf.close when Conf.close
if o = $.id 'overlay' if o = $.id 'overlay'
Options.close.call o Options.close.call o
else if QR.el else if QR.el
QR.close() QR.close()
when conf.submit when Conf.submit
QR.submit() if QR.el and !QR.status() QR.submit() if QR.el and !QR.status()
when conf.spoiler when Conf.spoiler
ta = e.target ta = e.target
return if ta.nodeName isnt 'TEXTAREA' return if ta.nodeName isnt 'TEXTAREA'
@ -836,44 +836,44 @@ Keybinds =
# Move the caret to the end of the selection. # Move the caret to the end of the selection.
ta.setSelectionRange range, range ta.setSelectionRange range, range
# Thread related # Thread related
when conf.watch when Conf.watch
Watcher.toggle thread Watcher.toggle thread
when conf.update when Conf.update
Updater.update() Updater.update()
when conf.unreadCountTo0 when Conf.unreadCountTo0
Unread.replies = [] Unread.replies = []
Unread.update() Unread.update()
# Images # Images
when conf.expandImage when Conf.expandImage
Keybinds.img thread Keybinds.img thread
when conf.expandAllImages when Conf.expandAllImages
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 = "/#{g.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 g.REPLY
Nav.scroll +1 Nav.scroll +1
when conf.previousThread when Conf.previousThread
return if g.REPLY return if g.REPLY
Nav.scroll -1 Nav.scroll -1
when conf.expandThread when Conf.expandThread
ExpandThread.toggle thread ExpandThread.toggle thread
when conf.openThread when Conf.openThread
Keybinds.open thread Keybinds.open thread
when conf.openThreadTab when Conf.openThreadTab
Keybinds.open thread, true Keybinds.open thread, true
# Reply Navigation # Reply Navigation
when conf.nextReply when Conf.nextReply
Keybinds.hl +1, thread Keybinds.hl +1, thread
when conf.previousReply when Conf.previousReply
Keybinds.hl -1, thread Keybinds.hl -1, thread
when conf.hide when Conf.hide
ThreadHiding.toggle thread if /\bthread\b/.test thread.className ThreadHiding.toggle thread if /\bthread\b/.test thread.className
else else
return return
@ -1021,7 +1021,7 @@ QR =
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 g.REPLY then 'Quick Reply' else 'New Thread'}</a>"
$.on $('a', link), 'click', -> $.on $('a', link), 'click', ->
QR.open() QR.open()
@ -1051,9 +1051,9 @@ QR =
$.add d.head, script $.add d.head, script
$.rm script $.rm script
if conf['Persistent QR'] if Conf['Persistent QR']
QR.dialog() QR.dialog()
QR.hide() if conf['Auto Hide QR'] QR.hide() if Conf['Auto Hide QR']
$.on d, 'dragover', QR.dragOver $.on d, 'dragover', QR.dragOver
$.on d, 'drop', QR.dropFile $.on d, 'drop', QR.dropFile
$.on d, 'dragstart', QR.drag $.on d, 'dragstart', QR.drag
@ -1078,7 +1078,7 @@ QR =
QR.cooldown.auto = false QR.cooldown.auto = false
QR.status() QR.status()
QR.resetFileInput() QR.resetFileInput()
if not conf['Remember Spoiler'] and (spoiler = $.id 'spoiler').checked if not Conf['Remember Spoiler'] and (spoiler = $.id 'spoiler').checked
spoiler.click() spoiler.click()
QR.cleanError() QR.cleanError()
hide: -> hide: ->
@ -1123,7 +1123,7 @@ QR =
return unless QR.el return unless QR.el
{input} = QR.status {input} = QR.status
input.value = input.value =
if QR.cooldown.auto and conf['Cooldown'] if QR.cooldown.auto and Conf['Cooldown']
if value then "Auto #{value}" else 'Auto' if value then "Auto #{value}" else 'Auto'
else else
value or 'Submit' value or 'Submit'
@ -1131,14 +1131,14 @@ 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 "/#{g.BOARD}/cooldown", 0
$.sync "/#{g.BOARD}/cooldown", QR.cooldown.start $.sync "/#{g.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 "/#{g.BOARD}/cooldown", Date.now() + seconds*SECOND
count: (seconds) -> count: (seconds) ->
@ -1234,8 +1234,8 @@ QR =
persona = $.get 'QR.persona', {} persona = $.get 'QR.persona', {}
@name = if prev then prev.name else persona.name or null @name = if prev then prev.name else persona.name or null
@email = if prev and !/^sage$/.test prev.email then prev.email else persona.email or null @email = if prev and !/^sage$/.test prev.email then prev.email else persona.email or null
@sub = if prev and conf['Remember Subject'] then prev.sub else if conf['Remember Subject'] then persona.sub else null @sub = if prev and Conf['Remember Subject'] then prev.sub else if Conf['Remember Subject'] then persona.sub else null
@spoiler = if prev and conf['Remember Spoiler'] then prev.spoiler else false @spoiler = if prev and Conf['Remember Spoiler'] then prev.spoiler else false
@com = null @com = null
@el = $.el 'a', @el = $.el 'a',
@ -1438,7 +1438,7 @@ QR =
<div class=warning></div> <div class=warning></div>
</form>' </form>'
if conf['Remember QR size'] and engine is 'gecko' if Conf['Remember QR size'] and engine is 'gecko'
$.on ta = $('textarea', QR.el), 'mouseup', -> $.on ta = $('textarea', QR.el), 'mouseup', ->
$.set 'QR.size', @style.cssText $.set 'QR.size', @style.cssText
ta.style.cssText = $.get 'QR.size', '' ta.style.cssText = $.get 'QR.size', ''
@ -1557,9 +1557,9 @@ QR =
# 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
if conf['Auto Hide QR'] and not QR.cooldown.auto if Conf['Auto Hide QR'] and not QR.cooldown.auto
QR.hide() QR.hide()
if conf['Thread Watcher'] and conf['Auto Watch Reply'] and threadID isnt 'new' if Conf['Thread Watcher'] and Conf['Auto Watch Reply'] and threadID isnt 'new'
Watcher.watch threadID Watcher.watch threadID
post = post =
@ -1634,12 +1634,12 @@ QR =
persona = persona =
name: reply.name name: reply.name
email: if /^sage$/.test reply.email then persona.email else reply.email email: if /^sage$/.test reply.email then persona.email else reply.email
sub: if conf['Remember Subject'] then reply.sub else null sub: if Conf['Remember Subject'] then reply.sub else null
$.set 'QR.persona', persona $.set 'QR.persona', persona
[_, thread, postNumber] = b.lastChild.textContent.match /thread:(\d+),no:(\d+)/ [_, thread, postNumber] = b.lastChild.textContent.match /thread:(\d+),no:(\d+)/
if thread is '0' # new thread if thread is '0' # new thread
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 = "/#{g.BOARD}/res/#{postNumber}"
@ -1647,17 +1647,17 @@ QR =
# 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'] && !g.REPLY && !QR.cooldown.auto
$.open "//boards.4chan.org/#{g.BOARD}/res/#{thread}##{postNumber}" $.open "//boards.4chan.org/#{g.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 g.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 g.REPLY and Conf['Thread Updater'] and Conf['Auto Update This']
Updater.update() Updater.update()
QR.status() QR.status()
@ -1892,11 +1892,11 @@ Options =
</div>' </div>'
#main #main
for key, obj of config.main for key, obj of Config.main
ul = $.el 'ul', ul = $.el 'ul',
textContent: key textContent: key
for key, arr of obj for key, arr of obj
checked = if conf[key] then 'checked' else '' checked = if Conf[key] then 'checked' else ''
description = arr[1] description = arr[1]
li = $.el 'li', li = $.el 'li',
innerHTML: "<label><input type=checkbox name=\"#{key}\" #{checked}>#{key}</label><span class=description>: #{description}</span>" innerHTML: "<label><input type=checkbox name=\"#{key}\" #{checked}>#{key}</label><span class=description>: #{description}</span>"
@ -1913,14 +1913,14 @@ Options =
#filter & sauce #filter & sauce
for ta in $$ 'textarea', dialog for ta in $$ 'textarea', dialog
ta.textContent = conf[ta.name] ta.textContent = Conf[ta.name]
$.on ta, 'change', $.cb.value $.on ta, 'change', $.cb.value
#rice #rice
(back = $ '[name=backlink]', dialog).value = conf['backlink'] (back = $ '[name=backlink]', dialog).value = Conf['backlink']
(time = $ '[name=time]', dialog).value = conf['time'] (time = $ '[name=time]', dialog).value = Conf['time']
(fileInfoR = $ '[name=fileInfoR]', dialog).value = conf['fileInfoR'] (fileInfoR = $ '[name=fileInfoR]', dialog).value = Conf['fileInfoR']
(fileInfoT = $ '[name=fileInfoT]', dialog).value = conf['fileInfoT'] (fileInfoT = $ '[name=fileInfoT]', dialog).value = Conf['fileInfoT']
$.on back, 'keyup', $.cb.value $.on back, 'keyup', $.cb.value
$.on back, 'keyup', Options.backlink $.on back, 'keyup', Options.backlink
$.on time, 'keyup', $.cb.value $.on time, 'keyup', $.cb.value
@ -1930,16 +1930,16 @@ Options =
$.on fileInfoT, 'keyup', $.cb.value $.on fileInfoT, 'keyup', $.cb.value
$.on fileInfoT, 'keyup', Options.fileInfo $.on fileInfoT, 'keyup', Options.fileInfo
favicon = $ 'select', dialog favicon = $ 'select', dialog
favicon.value = conf['favicon'] favicon.value = Conf['favicon']
$.on favicon, 'change', $.cb.value $.on favicon, 'change', $.cb.value
$.on favicon, 'change', Options.favicon $.on favicon, 'change', Options.favicon
#keybinds #keybinds
for key, arr of config.hotkeys for key, arr of Config.hotkeys
tr = $.el 'tr', tr = $.el 'tr',
innerHTML: "<td>#{arr[1]}</td><td><input name=#{key}></td>" innerHTML: "<td>#{arr[1]}</td><td><input name=#{key}></td>"
input = $ 'input', tr input = $ 'input', tr
input.value = conf[key] input.value = Conf[key]
$.on input, 'keydown', Options.keybind $.on input, 'keydown', Options.keybind
$.add $('#keybinds_tab + div tbody', dialog), tr $.add $('#keybinds_tab + div tbody', dialog), tr
@ -1947,7 +1947,7 @@ Options =
indicators = {} indicators = {}
for indicator in $$ '.warning', dialog for indicator in $$ '.warning', dialog
key = indicator.firstChild.textContent key = indicator.firstChild.textContent
indicator.hidden = conf[key] indicator.hidden = Conf[key]
indicators[key] = indicator indicators[key] = indicator
$.on $("[name='#{key}']", dialog), 'click', -> $.on $("[name='#{key}']", dialog), 'click', ->
indicators[@name].hidden = @checked indicators[@name].hidden = @checked
@ -1988,7 +1988,7 @@ Options =
Time.date = new Date() Time.date = new Date()
$.id('timePreview').textContent = Time.funk Time $.id('timePreview').textContent = Time.funk Time
backlink: -> backlink: ->
$.id('backlinkPreview').textContent = conf['backlink'].replace /%id/, '123456789' $.id('backlinkPreview').textContent = Conf['backlink'].replace /%id/, '123456789'
fileInfo: -> fileInfo: ->
type = if @name is 'fileInfoR' then 0 else 1 type = if @name is 'fileInfoR' then 0 else 1
FileInfo.data = FileInfo.data =
@ -2069,7 +2069,7 @@ ThreadHiding =
$.set "hiddenThreads/#{g.BOARD}/", hiddenThreads $.set "hiddenThreads/#{g.BOARD}/", hiddenThreads
hide: (thread) -> hide: (thread) ->
unless conf['Show Stubs'] unless Conf['Show Stubs']
thread.hidden = true thread.hidden = true
thread.nextSibling.hidden = true thread.nextSibling.hidden = true
return return
@ -2104,17 +2104,17 @@ ThreadHiding =
Updater = Updater =
init: -> init: ->
html = "<div class=move><span id=count></span> <span id=timer>-#{conf['Interval']}</span></div>" html = "<div class=move><span id=count></span> <span id=timer>-#{Conf['Interval']}</span></div>"
{checkbox} = config.updater {checkbox} = Config.updater
for name of checkbox for name of checkbox
title = checkbox[name][1] title = checkbox[name][1]
checked = if conf[name] then 'checked' else '' checked = if Conf[name] then 'checked' else ''
html += "<div><label title='#{title}'>#{name}<input name='#{name}' type=checkbox #{checked}></label></div>" html += "<div><label title='#{title}'>#{name}<input name='#{name}' type=checkbox #{checked}></label></div>"
checked = if conf['Auto Update'] then 'checked' else '' checked = if Conf['Auto Update'] then 'checked' else ''
html += " html += "
<div><label title='Controls whether *this* thread automatically updates or not'>Auto Update This<input name='Auto Update This' type=checkbox #{checked}></label></div> <div><label title='Controls whether *this* thread automatically updates or not'>Auto Update This<input name='Auto Update This' type=checkbox #{checked}></label></div>
<div><label>Interval (s)<input name=Interval value=#{conf['Interval']} type=text></label></div> <div><label>Interval (s)<input name=Interval value=#{Conf['Interval']} type=text></label></div>
<div><input value='Update Now' type=button></div>" <div><input value='Update Now' type=button></div>"
dialog = ui.dialog 'updater', 'bottom: 0; right: 0;', html dialog = ui.dialog 'updater', 'bottom: 0; right: 0;', html
@ -2136,9 +2136,9 @@ Updater =
$.on input, 'click', @cb.autoUpdate $.on input, 'click', @cb.autoUpdate
@cb.autoUpdate.call input @cb.autoUpdate.call input
# Required for the QR's update after posting. # Required for the QR's update after posting.
conf[input.name] = input.checked Conf[input.name] = input.checked
else if input.name is 'Interval' else if input.name is 'Interval'
$.on input, 'change', -> conf['Interval'] = @value = parseInt(@value, 10) or conf['Interval'] $.on input, 'change', -> Conf['Interval'] = @value = parseInt(@value, 10) or Conf['Interval']
$.on input, 'change', $.cb.value $.on input, 'change', $.cb.value
else if input.type is 'button' else if input.type is 'button'
$.on input, 'click', @update $.on input, 'click', @update
@ -2150,7 +2150,7 @@ Updater =
cb: cb:
verbose: -> verbose: ->
if conf['Verbose'] if Conf['Verbose']
Updater.count.textContent = '+0' Updater.count.textContent = '+0'
Updater.timer.hidden = false Updater.timer.hidden = false
else else
@ -2176,7 +2176,7 @@ Updater =
Updater.count.className = 'warning' Updater.count.className = 'warning'
clearTimeout Updater.timeoutID clearTimeout Updater.timeoutID
g.dead = true g.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
d.title = d.title.match(/^.+-/)[0] + ' 404' d.title = d.title.match(/^.+-/)[0] + ' 404'
@ -2186,7 +2186,7 @@ Updater =
return return
Updater.retryCoef = 10 Updater.retryCoef = 10
Updater.timer.textContent = '-' + conf['Interval'] Updater.timer.textContent = '-' + Conf['Interval']
### ###
Status Code 304: Not modified Status Code 304: Not modified
@ -2195,7 +2195,7 @@ Updater =
and won't load images and scripts when parsing the response. and won't load images and scripts when parsing the response.
### ###
if @status is 304 if @status is 304
if conf['Verbose'] if Conf['Verbose']
Updater.count.textContent = '+0' Updater.count.textContent = '+0'
Updater.count.className = null Updater.count.className = null
return return
@ -2211,9 +2211,9 @@ Updater =
nodes.push reply.parentNode.parentNode.parentNode #table nodes.push reply.parentNode.parentNode.parentNode #table
newPosts = nodes.length newPosts = nodes.length
scroll = conf['Scrolling'] && Updater.scrollBG() && newPosts && scroll = Conf['Scrolling'] && Updater.scrollBG() && newPosts &&
Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25 Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25
if conf['Verbose'] if Conf['Verbose']
Updater.count.textContent = "+#{newPosts}" Updater.count.textContent = "+#{newPosts}"
Updater.count.className = if newPosts then 'new' else null Updater.count.className = if newPosts then 'new' else null
@ -2344,7 +2344,7 @@ Sauce =
init: -> init: ->
return if g.BOARD is 'f' return if g.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
@ -2422,7 +2422,7 @@ Time =
textContent: ' ' + Time.funk(Time) + ' ' textContent: ' ' + Time.funk(Time) + ' '
$.replace node, time $.replace node, time
foo: -> foo: ->
code = conf['time'].replace /%([A-Za-z])/g, (s, c) -> code = Conf['time'].replace /%([A-Za-z])/g, (s, c) ->
if c of Time.formatters if c of Time.formatters
"' + Time.formatters.#{c}() + '" "' + Time.formatters.#{c}() + '"
else else
@ -2496,7 +2496,7 @@ FileInfo =
setFormats: -> setFormats: ->
funks = [] funks = []
for i in [0..1] for i in [0..1]
format = if i then conf['fileInfoT'] else conf['fileInfoR'] format = if i then Conf['fileInfoT'] else Conf['fileInfoR']
param = if i then /%([BKlMrs])/g else /%([BKlLMnNrs])/g param = if i then /%([BKlMrs])/g else /%([BKlLMnNrs])/g
code = format.replace param, (s, c) -> code = format.replace param, (s, c) ->
if c of FileInfo.formatters if c of FileInfo.formatters
@ -2553,7 +2553,7 @@ TitlePost =
QuoteBacklink = 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 g.callbacks.push @node
node: (post) -> node: (post) ->
@ -2570,11 +2570,11 @@ QuoteBacklink =
textContent: QuoteBacklink.funk post.id textContent: QuoteBacklink.funk post.id
for qid of quotes for qid of quotes
# Don't backlink the OP. # Don't backlink the OP.
continue if !(el = $.id qid) or el.className is 'op' and !conf['OP Backlinks'] continue if !(el = $.id qid) or el.className is 'op' and !Conf['OP Backlinks']
link = a.cloneNode true link = a.cloneNode true
if conf['Quote Preview'] if Conf['Quote Preview']
$.on link, 'mouseover', QuotePreview.mouseover $.on link, 'mouseover', QuotePreview.mouseover
if conf['Quote Inline'] if Conf['Quote Inline']
$.on link, 'click', QuoteInline.toggle $.on link, 'click', QuoteInline.toggle
else else
link.setAttribute 'onclick', "replyhl('#{post.id}');" link.setAttribute 'onclick', "replyhl('#{post.id}');"
@ -2618,7 +2618,7 @@ QuoteInline =
Unread.update() Unread.update()
if /\bbacklink\b/.test q.className if /\bbacklink\b/.test q.className
$.after q.parentNode, inline $.after q.parentNode, inline
if conf['Forward Hiding'] if Conf['Forward Hiding']
table = $.x 'ancestor::table', el table = $.x 'ancestor::table', el
$.addClass table, 'forwarded' $.addClass table, 'forwarded'
# Will only unhide if there's no inlined backlinks of it anymore. # Will only unhide if there's no inlined backlinks of it anymore.
@ -2639,7 +2639,7 @@ QuoteInline =
#select the corresponding table or loading td #select the corresponding table or loading td
table = $.x "following::*[@id='i#{id}']", q table = $.x "following::*[@id='i#{id}']", q
$.rm table $.rm table
return unless conf['Forward Hiding'] return unless Conf['Forward Hiding']
for inlined in $$ '.backlink.inlined', table for inlined in $$ '.backlink.inlined', table
table = $.x 'ancestor::table', $.id inlined.hash[1..] table = $.x 'ancestor::table', $.id inlined.hash[1..]
$.removeClass table, 'forwarded' unless --table.title $.removeClass table, 'forwarded' unless --table.title
@ -2698,7 +2698,7 @@ QuotePreview =
id = @hash[1..] id = @hash[1..]
if el = $.id id if el = $.id id
qp.innerHTML = el.innerHTML qp.innerHTML = el.innerHTML
$.addClass el, 'qphl' if conf['Quote Highlighting'] $.addClass el, 'qphl' if Conf['Quote Highlighting']
if /\bbacklink\b/.test @className if /\bbacklink\b/.test @className
replyID = $.x('preceding-sibling::input', @parentNode).name replyID = $.x('preceding-sibling::input', @parentNode).name
for quote in $$ '.quotelink', qp for quote in $$ '.quotelink', qp
@ -2739,11 +2739,11 @@ QuotePreview =
root: qp root: qp
filesize: $ '.filesize', qp filesize: $ '.filesize', qp
img: $ 'img[md5]', qp img: $ 'img[md5]', qp
if conf['Image Auto-Gif'] if Conf['Image Auto-Gif']
AutoGif.node post AutoGif.node post
if conf['Time Formatting'] if Conf['Time Formatting']
Time.node post Time.node post
if conf['File Info Formatting'] if Conf['File Info Formatting']
FileInfo.node post FileInfo.node post
QuoteOP = QuoteOP =
@ -2915,10 +2915,10 @@ Unread =
count = @replies.length count = @replies.length
if conf['Unread Count'] if Conf['Unread Count']
@setTitle count @setTitle count
unless conf['Unread Favicon'] and (count < 2 or forceUpdate) unless Conf['Unread Favicon'] and (count < 2 or forceUpdate)
return return
Favicon.el.href = Favicon.el.href =
@ -2948,7 +2948,7 @@ Favicon =
@switch() @switch()
switch: -> switch: ->
switch conf['favicon'] switch Conf['favicon']
when 'ferongr' when 'ferongr'
@unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAOMHAOgLAnMFAL8AAOgLAukMA/+AgP+rq////////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw==' @unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAOMHAOgLAnMFAL8AAOgLAukMA/+AgP+rq////////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw=='
@unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAOMHAADX8QBwfgC2zADX8QDY8nnl8qLp8v///////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw==' @unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAOMHAADX8QBwfgC2zADX8QDY8nnl8qLp8v///////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw=='
@ -2981,12 +2981,12 @@ Redirect =
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 g.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=g.BOARD, id=g.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 g.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}/"
@ -3061,7 +3061,7 @@ ImageExpand =
ImageExpand.on = @checked ImageExpand.on = @checked
if ImageExpand.on #expand if ImageExpand.on #expand
thumbs = $$ 'img[md5]' thumbs = $$ 'img[md5]'
if conf['Expand From Current'] if Conf['Expand From Current']
for thumb, i in thumbs for thumb, i in thumbs
if thumb.getBoundingClientRect().top > 0 if thumb.getBoundingClientRect().top > 0
break break
@ -3168,8 +3168,8 @@ Main =
g.PAGENUM = parseInt(temp) or 0 g.PAGENUM = parseInt(temp) or 0
#load values from localStorage #load values from localStorage
for key, val of conf for key, val of Conf
conf[key] = $.get key, val Conf[key] = $.get key, val
$.on window, 'message', Main.message $.on window, 'message', Main.message
@ -3192,13 +3192,13 @@ 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 g.BOARD isnt 'f'
Main.css += 'form[name=post] { display: none; }' Main.css += 'form[name=post] { display: none; }'
Main.addStyle() Main.addStyle()
now = Date.now() now = Date.now()
if conf['Check for Updates'] and $.get('lastUpdate', 0) < now - 6*HOUR if Conf['Check for Updates'] and $.get('lastUpdate', 0) < now - 6*HOUR
$.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
@ -3222,55 +3222,55 @@ Main =
#major features #major features
if conf['Filter'] if Conf['Filter']
Filter.init() Filter.init()
if conf['Reply Hiding'] if Conf['Reply Hiding']
ReplyHiding.init() ReplyHiding.init()
if conf['Filter'] or conf['Reply Hiding'] if Conf['Filter'] or Conf['Reply Hiding']
StrikethroughQuotes.init() StrikethroughQuotes.init()
if conf['Anonymize'] if Conf['Anonymize']
Anonymize.init() Anonymize.init()
if conf['Time Formatting'] if Conf['Time Formatting']
Time.init() Time.init()
if conf['File Info Formatting'] if Conf['File Info Formatting']
FileInfo.init() FileInfo.init()
if conf['Sauce'] if Conf['Sauce']
Sauce.init() Sauce.init()
if conf['Reveal Spoilers'] if Conf['Reveal Spoilers']
RevealSpoilers.init() RevealSpoilers.init()
if conf['Image Auto-Gif'] if Conf['Image Auto-Gif']
AutoGif.init() AutoGif.init()
if conf['Image Hover'] if Conf['Image Hover']
ImageHover.init() ImageHover.init()
if conf['Report Button'] if Conf['Report Button']
ReportButton.init() ReportButton.init()
if conf['Resurrect Quotes'] if Conf['Resurrect Quotes']
Quotify.init() Quotify.init()
if conf['Quote Inline'] if Conf['Quote Inline']
QuoteInline.init() QuoteInline.init()
if conf['Quote Preview'] if Conf['Quote Preview']
QuotePreview.init() QuotePreview.init()
if conf['Quote Backlinks'] if Conf['Quote Backlinks']
QuoteBacklink.init() QuoteBacklink.init()
if conf['Indicate OP quote'] if Conf['Indicate OP quote']
QuoteOP.init() QuoteOP.init()
if conf['Indicate Cross-thread Quotes'] if Conf['Indicate Cross-thread Quotes']
QuoteCT.init() QuoteCT.init()
$.ready Main.ready $.ready Main.ready
@ -3290,45 +3290,45 @@ Main =
Favicon.init() Favicon.init()
# Major features. # Major features.
if conf['Quick Reply'] if Conf['Quick Reply']
QR.init() QR.init()
if conf['Image Expansion'] if Conf['Image Expansion']
ImageExpand.init() ImageExpand.init()
if conf['Thread Watcher'] if Conf['Thread Watcher']
setTimeout -> Watcher.init() setTimeout -> Watcher.init()
if conf['Keybinds'] if Conf['Keybinds']
setTimeout -> Keybinds.init() setTimeout -> Keybinds.init()
if g.REPLY if g.REPLY
if conf['Thread Updater'] if Conf['Thread Updater']
setTimeout -> Updater.init() setTimeout -> Updater.init()
if conf['Thread Stats'] if Conf['Thread Stats']
ThreadStats.init() ThreadStats.init()
if conf['Reply Navigation'] if Conf['Reply Navigation']
setTimeout -> Nav.init() setTimeout -> Nav.init()
if conf['Post in Title'] if Conf['Post in Title']
TitlePost.init() TitlePost.init()
if conf['Unread Count'] or conf['Unread Favicon'] if Conf['Unread Count'] or Conf['Unread Favicon']
Unread.init() Unread.init()
else #not reply else #not reply
if conf['Thread Hiding'] if Conf['Thread Hiding']
setTimeout -> ThreadHiding.init() setTimeout -> ThreadHiding.init()
if conf['Thread Expansion'] if Conf['Thread Expansion']
setTimeout -> ExpandThread.init() setTimeout -> ExpandThread.init()
if conf['Comment Expansion'] if Conf['Comment Expansion']
setTimeout -> ExpandComment.init() setTimeout -> ExpandComment.init()
if conf['Index Navigation'] if Conf['Index Navigation']
setTimeout -> Nav.init() setTimeout -> Nav.init()
nodes = [] nodes = []