Merge branch 'master' of git://github.com/MayhemYDG/4chan-x into qrsize
Conflicts: changelog
This commit is contained in:
commit
b4bfe17a95
252
4chan_x.user.js
252
4chan_x.user.js
@ -91,6 +91,7 @@
|
|||||||
'Anonymize': [false, 'Make everybody anonymous'],
|
'Anonymize': [false, 'Make everybody anonymous'],
|
||||||
'Filter': [false, 'Self-moderation placebo'],
|
'Filter': [false, 'Self-moderation placebo'],
|
||||||
'Filter OPs': [false, 'Filter OPs along with their threads'],
|
'Filter OPs': [false, 'Filter OPs along with their threads'],
|
||||||
|
'Recursive Filtering': [false, 'Filter replies of filtered posts, recursively'],
|
||||||
'Reply Hiding': [true, 'Hide single replies'],
|
'Reply Hiding': [true, 'Hide single replies'],
|
||||||
'Thread Hiding': [true, 'Hide entire threads'],
|
'Thread Hiding': [true, 'Hide entire threads'],
|
||||||
'Show Stubs': [true, 'Of hidden threads / replies']
|
'Show Stubs': [true, 'Of hidden threads / replies']
|
||||||
@ -105,6 +106,7 @@
|
|||||||
Monitoring: {
|
Monitoring: {
|
||||||
'Thread Updater': [true, 'Update threads. Has more options in its own dialog.'],
|
'Thread Updater': [true, 'Update threads. Has more options in its own dialog.'],
|
||||||
'Unread Count': [true, 'Show unread post count in tab title'],
|
'Unread Count': [true, 'Show unread post count in tab title'],
|
||||||
|
'Unread Favicon': [true, 'Show a different favicon when there are unread posts'],
|
||||||
'Post in Title': [true, 'Show the op\'s post in the tab title'],
|
'Post in Title': [true, 'Show the op\'s post in the tab title'],
|
||||||
'Thread Stats': [true, 'Display reply and image count'],
|
'Thread Stats': [true, 'Display reply and image count'],
|
||||||
'Thread Watcher': [true, 'Bookmark threads'],
|
'Thread Watcher': [true, 'Bookmark threads'],
|
||||||
@ -168,7 +170,7 @@
|
|||||||
expandImages: ['m', 'Expand selected image'],
|
expandImages: ['m', 'Expand selected image'],
|
||||||
expandAllImages: ['M', 'Expand all images'],
|
expandAllImages: ['M', 'Expand all images'],
|
||||||
update: ['u', 'Update now'],
|
update: ['u', 'Update now'],
|
||||||
unreadCountTo0: ['z', 'Reset unread count to 0']
|
unreadCountTo0: ['z', 'Reset unread status']
|
||||||
},
|
},
|
||||||
updater: {
|
updater: {
|
||||||
checkbox: {
|
checkbox: {
|
||||||
@ -187,17 +189,15 @@
|
|||||||
|
|
||||||
(flatten = function(parent, obj) {
|
(flatten = function(parent, obj) {
|
||||||
var key, val, _results;
|
var key, val, _results;
|
||||||
if (typeof obj === 'object') {
|
if (obj instanceof Array) {
|
||||||
if (obj.length) {
|
return conf[parent] = obj[0];
|
||||||
return conf[parent] = obj[0];
|
} else if (typeof obj === 'object') {
|
||||||
} else {
|
_results = [];
|
||||||
_results = [];
|
for (key in obj) {
|
||||||
for (key in obj) {
|
val = obj[key];
|
||||||
val = obj[key];
|
_results.push(flatten(key, val));
|
||||||
_results.push(flatten(key, val));
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
}
|
}
|
||||||
|
return _results;
|
||||||
} else {
|
} else {
|
||||||
return conf[parent] = obj;
|
return conf[parent] = obj;
|
||||||
}
|
}
|
||||||
@ -613,23 +613,16 @@
|
|||||||
strikethroughQuotes = {
|
strikethroughQuotes = {
|
||||||
init: function() {
|
init: function() {
|
||||||
return g.callbacks.push(function(root) {
|
return g.callbacks.push(function(root) {
|
||||||
var el, quote, _i, _len, _ref, _results;
|
var el, quote, _i, _len, _ref;
|
||||||
if (root.className === 'inline') return;
|
if (root.className === 'inline') return;
|
||||||
_ref = $$('.quotelink', root);
|
_ref = $$('.quotelink', root);
|
||||||
_results = [];
|
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
quote = _ref[_i];
|
quote = _ref[_i];
|
||||||
if (el = $.id(quote.hash.slice(1))) {
|
if ((el = $.id(quote.hash.slice(1))) && el.parentNode.parentNode.parentNode.hidden) {
|
||||||
if (el.parentNode.parentNode.parentNode.hidden) {
|
$.addClass(quote, 'filtered');
|
||||||
_results.push($.addClass(quote, 'filtered'));
|
if (conf['Recursive Filtering']) root.hidden = true;
|
||||||
} else {
|
|
||||||
_results.push(void 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_results.push(void 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _results;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -898,7 +891,7 @@
|
|||||||
break;
|
break;
|
||||||
case conf.close:
|
case conf.close:
|
||||||
if (o = $.id('overlay')) {
|
if (o = $.id('overlay')) {
|
||||||
$.rm(o);
|
options.close.call(o);
|
||||||
} else if (qr.el) {
|
} else if (qr.el) {
|
||||||
qr.close();
|
qr.close();
|
||||||
}
|
}
|
||||||
@ -974,8 +967,7 @@
|
|||||||
break;
|
break;
|
||||||
case conf.unreadCountTo0:
|
case conf.unreadCountTo0:
|
||||||
unread.replies = [];
|
unread.replies = [];
|
||||||
unread.updateTitle();
|
unread.update();
|
||||||
Favicon.update();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@ -1201,11 +1193,13 @@
|
|||||||
if (!$.id('recaptcha_challenge_field_holder')) return;
|
if (!$.id('recaptcha_challenge_field_holder')) return;
|
||||||
if (conf['Hide Original Post Form']) {
|
if (conf['Hide Original Post Form']) {
|
||||||
link = $.el('h1', {
|
link = $.el('h1', {
|
||||||
innerHTML: "<a href=javascript:;>" + (g.REPLY ? 'Open the Quick Reply' : 'Create a New Thread') + "</a>"
|
innerHTML: "<a href=javascript:;>" + (g.REPLY ? 'Quick Reply' : 'New Thread') + "</a>"
|
||||||
|
});
|
||||||
|
$.on($('a', link), 'click', function() {
|
||||||
|
qr.open();
|
||||||
|
return $('textarea', qr.el).focus();
|
||||||
});
|
});
|
||||||
$.on($('a', link), 'click', qr.open);
|
|
||||||
form = d.forms[0];
|
form = d.forms[0];
|
||||||
form.hidden = true;
|
|
||||||
$.before(form, link);
|
$.before(form, link);
|
||||||
}
|
}
|
||||||
g.callbacks.push(function(root) {
|
g.callbacks.push(function(root) {
|
||||||
@ -1214,7 +1208,7 @@
|
|||||||
iframe = $.el('iframe', {
|
iframe = $.el('iframe', {
|
||||||
id: 'iframe',
|
id: 'iframe',
|
||||||
hidden: true,
|
hidden: true,
|
||||||
src: 'http://sys.4chan.org/post'
|
src: 'http://sys.4chan.org/robots.txt'
|
||||||
});
|
});
|
||||||
$.on(iframe, 'error', function() {
|
$.on(iframe, 'error', function() {
|
||||||
return this.src = this.src;
|
return this.src = this.src;
|
||||||
@ -1223,20 +1217,22 @@
|
|||||||
if (!qr.status.ready) {
|
if (!qr.status.ready) {
|
||||||
iframe.src = 'about:blank';
|
iframe.src = 'about:blank';
|
||||||
return setTimeout((function() {
|
return setTimeout((function() {
|
||||||
return iframe.src = 'http://sys.4chan.org/post';
|
return iframe.src = 'http://sys.4chan.org/robots.txt';
|
||||||
}), 250);
|
}), 250);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$.on(iframe, 'load', function() {
|
$.on(iframe, 'load', function() {
|
||||||
if (this.src !== 'about:blank') return setTimeout(loadChecking, 250, this);
|
if (this.src !== 'about:blank') return setTimeout(loadChecking, 500, this);
|
||||||
});
|
});
|
||||||
$.add(d.body, iframe);
|
$.add(d.body, iframe);
|
||||||
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.fileDrop);
|
$.on(d, 'dragover', qr.dragOver);
|
||||||
$.on(d, 'drop', qr.fileDrop);
|
$.on(d, 'drop', qr.dropFile);
|
||||||
|
$.on(d, 'dragstart', qr.drag);
|
||||||
|
$.on(d, 'dragend', qr.drag);
|
||||||
return window.location = 'javascript:void(Recaptcha.focus_response_field=function(){})';
|
return window.location = 'javascript:void(Recaptcha.focus_response_field=function(){})';
|
||||||
},
|
},
|
||||||
open: function() {
|
open: function() {
|
||||||
@ -1284,6 +1280,7 @@
|
|||||||
el.textContent = err;
|
el.textContent = err;
|
||||||
if (node) $.replace(el.firstChild, node);
|
if (node) $.replace(el.firstChild, node);
|
||||||
qr.open();
|
qr.open();
|
||||||
|
if (/captcha|verification/i.test(err)) $('[autocomplete]', qr.el).focus();
|
||||||
if (d.hidden || d.oHidden || d.mozHidden || d.webkitHidden) {
|
if (d.hidden || d.oHidden || d.mozHidden || d.webkitHidden) {
|
||||||
return alert(err);
|
return alert(err);
|
||||||
}
|
}
|
||||||
@ -1359,17 +1356,22 @@
|
|||||||
ta.focus();
|
ta.focus();
|
||||||
return ta.selectionEnd = ta.selectionStart = caretPos + text.length;
|
return ta.selectionEnd = ta.selectionStart = caretPos + text.length;
|
||||||
},
|
},
|
||||||
fileDrop: function(e) {
|
drag: function(e) {
|
||||||
if (/TEXTAREA|INPUT/.test(e.target.nodeName)) return;
|
var i;
|
||||||
|
i = e.type === 'dragstart' ? 'off' : 'on';
|
||||||
|
$[i](d, 'dragover', qr.dragOver);
|
||||||
|
return $[i](d, 'drop', qr.dropFile);
|
||||||
|
},
|
||||||
|
dragOver: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
return e.dataTransfer.dropEffect = 'copy';
|
||||||
e.dataTransfer.dropEffect = 'copy';
|
},
|
||||||
if (e.type === 'drop') {
|
dropFile: function(e) {
|
||||||
if (!e.dataTransfer.files.length) return;
|
if (!e.dataTransfer.files.length) return;
|
||||||
qr.open();
|
e.preventDefault();
|
||||||
qr.fileInput.call(e.dataTransfer);
|
qr.open();
|
||||||
return $.addClass(qr.el, 'dump');
|
qr.fileInput.call(e.dataTransfer);
|
||||||
}
|
return $.addClass(qr.el, 'dump');
|
||||||
},
|
},
|
||||||
fileInput: function() {
|
fileInput: function() {
|
||||||
var file, _i, _len, _ref;
|
var file, _i, _len, _ref;
|
||||||
@ -1544,7 +1546,7 @@
|
|||||||
case 0:
|
case 0:
|
||||||
return 'Verification (Shift + Enter to cache)';
|
return 'Verification (Shift + Enter to cache)';
|
||||||
case 1:
|
case 1:
|
||||||
return 'Vertification (1 cached captcha)';
|
return 'Verification (1 cached captcha)';
|
||||||
default:
|
default:
|
||||||
return "Verification (" + count + " cached captchas)";
|
return "Verification (" + count + " cached captchas)";
|
||||||
}
|
}
|
||||||
@ -1586,7 +1588,7 @@
|
|||||||
<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 = qr.el.querySelector('textarea'), 'mouseup', function() {
|
$.on(ta = $('textarea', qr.el), 'mouseup', function() {
|
||||||
return $.set('qr.size', this.style.cssText);
|
return $.set('qr.size', this.style.cssText);
|
||||||
});
|
});
|
||||||
ta.style.cssText = $.get('qr.size', '');
|
ta.style.cssText = $.get('qr.size', '');
|
||||||
@ -1654,7 +1656,7 @@
|
|||||||
}
|
}
|
||||||
$.sync('qr.persona', function(persona) {
|
$.sync('qr.persona', function(persona) {
|
||||||
var key, val, _results;
|
var key, val, _results;
|
||||||
if (qr.replies.length !== 1) return;
|
if (!qr.el.hidden) return;
|
||||||
_results = [];
|
_results = [];
|
||||||
for (key in persona) {
|
for (key in persona) {
|
||||||
val = persona[key];
|
val = persona[key];
|
||||||
@ -1817,6 +1819,7 @@
|
|||||||
textContent: "window.addEventListener('message'," + code + ",false)"
|
textContent: "window.addEventListener('message'," + code + ",false)"
|
||||||
});
|
});
|
||||||
ready = function() {
|
ready = function() {
|
||||||
|
$.add(d.documentElement, script);
|
||||||
if (location.hostname === 'sys.4chan.org') {
|
if (location.hostname === 'sys.4chan.org') {
|
||||||
qr.message.send({
|
qr.message.send({
|
||||||
req: 'status',
|
req: 'status',
|
||||||
@ -1826,14 +1829,10 @@
|
|||||||
return $.rm(script);
|
return $.rm(script);
|
||||||
};
|
};
|
||||||
if (d.documentElement) {
|
if (d.documentElement) {
|
||||||
$.add(d.documentElement, script);
|
|
||||||
ready();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return $.ready(function() {
|
|
||||||
$.add(d.head, script);
|
|
||||||
return ready();
|
return ready();
|
||||||
});
|
} else {
|
||||||
|
return $.ready(ready);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
send: function(data) {
|
send: function(data) {
|
||||||
data.changeContext = true;
|
data.changeContext = true;
|
||||||
@ -2035,21 +2034,20 @@
|
|||||||
<li>Hour: %k, %H, %l (lowercase L), %I (uppercase i), %p, %P</li>\
|
<li>Hour: %k, %H, %l (lowercase L), %I (uppercase i), %p, %P</li>\
|
||||||
<li>Minutes: %M</li>\
|
<li>Minutes: %M</li>\
|
||||||
</ul>\
|
</ul>\
|
||||||
<div class=warning><code>Unread Count</code> is disabled.</div>\
|
<div class=warning><code>Unread Favicon</code> is disabled.</div>\
|
||||||
Unread favicons<br>\
|
Unread favicons<br>\
|
||||||
<select name=favicon>\
|
<select name=favicon>\
|
||||||
<option value=ferongr>ferongr</option>\
|
<option value=ferongr>ferongr</option>\
|
||||||
<option value=xat->xat-</option>\
|
<option value=xat->xat-</option>\
|
||||||
<option value=Mayhem>Mayhem</option>\
|
<option value=Mayhem>Mayhem</option>\
|
||||||
<option value=Original>Original</option>\
|
<option value=Original>Original</option>\
|
||||||
<option value=None>None</option>\
|
|
||||||
</select>\
|
</select>\
|
||||||
<span></span>\
|
<span></span>\
|
||||||
</div>\
|
</div>\
|
||||||
<input type=radio name=tab hidden id=keybinds_tab>\
|
<input type=radio name=tab hidden id=keybinds_tab>\
|
||||||
<div>\
|
<div>\
|
||||||
<div class=warning><code>Keybinds</code> are disabled.</div>\
|
<div class=warning><code>Keybinds</code> are disabled.</div>\
|
||||||
<div>Allowed keys: Ctrl, Alt, a-z, A-Z, 0-1, Up, Down, Right, Left.</div>\
|
<div>Allowed keys: Ctrl, Alt, a-z, A-Z, 0-9, Up, Down, Right, Left.</div>\
|
||||||
<table><tbody>\
|
<table><tbody>\
|
||||||
<tr><th>Actions</th><th>Keybinds</th></tr>\
|
<tr><th>Actions</th><th>Keybinds</th></tr>\
|
||||||
</tbody></table>\
|
</tbody></table>\
|
||||||
@ -2122,18 +2120,21 @@
|
|||||||
overlay = $.el('div', {
|
overlay = $.el('div', {
|
||||||
id: 'overlay'
|
id: 'overlay'
|
||||||
});
|
});
|
||||||
$.on(overlay, 'click', function() {
|
$.on(overlay, 'click', options.close);
|
||||||
return $.rm(overlay);
|
|
||||||
});
|
|
||||||
$.on(dialog, 'click', function(e) {
|
$.on(dialog, 'click', function(e) {
|
||||||
return e.stopPropagation();
|
return e.stopPropagation();
|
||||||
});
|
});
|
||||||
$.add(overlay, dialog);
|
$.add(overlay, dialog);
|
||||||
$.add(d.body, overlay);
|
$.add(d.body, overlay);
|
||||||
|
d.body.style.setProperty('overflow', 'hidden', null);
|
||||||
options.backlink.call(back);
|
options.backlink.call(back);
|
||||||
options.time.call(time);
|
options.time.call(time);
|
||||||
return options.favicon.call(favicon);
|
return options.favicon.call(favicon);
|
||||||
},
|
},
|
||||||
|
close: function() {
|
||||||
|
$.rm(this);
|
||||||
|
return d.body.style.removeProperty('overflow');
|
||||||
|
},
|
||||||
clearHidden: function() {
|
clearHidden: function() {
|
||||||
$["delete"]("hiddenReplies/" + g.BOARD + "/");
|
$["delete"]("hiddenReplies/" + g.BOARD + "/");
|
||||||
$["delete"]("hiddenThreads/" + g.BOARD + "/");
|
$["delete"]("hiddenThreads/" + g.BOARD + "/");
|
||||||
@ -2158,7 +2159,7 @@
|
|||||||
},
|
},
|
||||||
favicon: function() {
|
favicon: function() {
|
||||||
Favicon["switch"]();
|
Favicon["switch"]();
|
||||||
if (g.REPLY && conf['Unread Count']) Favicon.update();
|
unread.update(true);
|
||||||
return this.nextElementSibling.innerHTML = "<img src=" + Favicon.unreadSFW + "> <img src=" + Favicon.unreadNSFW + "> <img src=" + Favicon.unreadDead + ">";
|
return this.nextElementSibling.innerHTML = "<img src=" + Favicon.unreadSFW + "> <img src=" + Favicon.unreadNSFW + "> <img src=" + Favicon.unreadDead + ">";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2374,8 +2375,13 @@
|
|||||||
updater.count.textContent = 404;
|
updater.count.textContent = 404;
|
||||||
updater.count.className = 'warning';
|
updater.count.className = 'warning';
|
||||||
clearTimeout(updater.timeoutID);
|
clearTimeout(updater.timeoutID);
|
||||||
d.title = d.title.match(/^.+-/)[0] + ' 404';
|
|
||||||
g.dead = true;
|
g.dead = true;
|
||||||
|
if (conf['Unread Count']) {
|
||||||
|
unread.title = unread.title.match(/^.+-/)[0] + ' 404';
|
||||||
|
} else {
|
||||||
|
d.title = d.title.match(/^.+-/)[0] + ' 404';
|
||||||
|
}
|
||||||
|
unread.update(true);
|
||||||
qr.message.send({
|
qr.message.send({
|
||||||
req: 'abort'
|
req: 'abort'
|
||||||
});
|
});
|
||||||
@ -2581,12 +2587,24 @@
|
|||||||
|
|
||||||
sauce = {
|
sauce = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var link, links, _i, _len;
|
var domain, fc, link, links, _i, _len;
|
||||||
links = conf['sauces'].match(/^[^#].+$/gm);
|
links = conf['sauces'].match(/^[^#].+$/gm);
|
||||||
|
if (!links.length) return;
|
||||||
this.links = [];
|
this.links = [];
|
||||||
for (_i = 0, _len = links.length; _i < _len; _i++) {
|
for (_i = 0, _len = links.length; _i < _len; _i++) {
|
||||||
link = links[_i];
|
link = links[_i];
|
||||||
this.links.push([link, link.match(/(\w+)\.\w+\//)[1]]);
|
domain = link.match(/(\w+)\.\w+\//)[1];
|
||||||
|
fc = link.replace(/\$\d/, function(fragment) {
|
||||||
|
switch (fragment) {
|
||||||
|
case '$1':
|
||||||
|
return "' + img.src + '";
|
||||||
|
case '$2':
|
||||||
|
return "' + img.parentNode.href + '";
|
||||||
|
case '$3':
|
||||||
|
return "' + img.getAttribute('md5').replace(/\=*$/, '') + '";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.links.push([Function('img', "return '" + fc + "'"), domain]);
|
||||||
}
|
}
|
||||||
return g.callbacks.push(this.node);
|
return g.callbacks.push(this.node);
|
||||||
},
|
},
|
||||||
@ -2598,24 +2616,12 @@
|
|||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
link = _ref[_i];
|
link = _ref[_i];
|
||||||
a = $.el('a', {
|
a = $.el('a', {
|
||||||
textContent: link[1],
|
href: link[0](img),
|
||||||
href: sauce.href(link[0], img),
|
target: '_blank',
|
||||||
target: '_blank'
|
textContent: link[1]
|
||||||
});
|
});
|
||||||
$.add(span, $.tn(' '), a);
|
$.add(span, $.tn(' '), a);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
href: function(link, img) {
|
|
||||||
return link.replace(/\$\d/, function(fragment) {
|
|
||||||
switch (fragment) {
|
|
||||||
case '$1':
|
|
||||||
return img.src;
|
|
||||||
case '$2':
|
|
||||||
return img.parentNode.href;
|
|
||||||
case '$3':
|
|
||||||
return img.getAttribute('md5').replace(/\=+$/, '');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2839,10 +2845,9 @@
|
|||||||
root = q.parentNode.nodeName === 'FONT' ? q.parentNode : q.nextSibling ? q.nextSibling : q;
|
root = q.parentNode.nodeName === 'FONT' ? q.parentNode : q.nextSibling ? q.nextSibling : q;
|
||||||
if (el = $.id(id)) {
|
if (el = $.id(id)) {
|
||||||
inline = quoteInline.table(id, el.innerHTML);
|
inline = quoteInline.table(id, el.innerHTML);
|
||||||
if (g.REPLY && conf['Unread Count'] && (i = unread.replies.indexOf(el.parentNode.parentNode.parentNode)) !== -1) {
|
if ((i = unread.replies.indexOf(el.parentNode.parentNode.parentNode)) !== -1) {
|
||||||
unread.replies.splice(i, 1);
|
unread.replies.splice(i, 1);
|
||||||
unread.updateTitle();
|
unread.update();
|
||||||
Favicon.update();
|
|
||||||
}
|
}
|
||||||
if (/\bbacklink\b/.test(q.className)) {
|
if (/\bbacklink\b/.test(q.className)) {
|
||||||
$.after(q.parentNode, inline);
|
$.after(q.parentNode, inline);
|
||||||
@ -3112,7 +3117,8 @@
|
|||||||
|
|
||||||
unread = {
|
unread = {
|
||||||
init: function() {
|
init: function() {
|
||||||
d.title = '(0) ' + d.title;
|
this.title = d.title;
|
||||||
|
unread.update();
|
||||||
$.on(window, 'scroll', unread.scroll);
|
$.on(window, 'scroll', unread.scroll);
|
||||||
return g.callbacks.push(unread.node);
|
return g.callbacks.push(unread.node);
|
||||||
},
|
},
|
||||||
@ -3120,8 +3126,7 @@
|
|||||||
node: function(root) {
|
node: function(root) {
|
||||||
if (root.hidden || root.className) return;
|
if (root.hidden || root.className) return;
|
||||||
unread.replies.push(root);
|
unread.replies.push(root);
|
||||||
unread.updateTitle();
|
return unread.update();
|
||||||
if (unread.replies.length === 1) return Favicon.update();
|
|
||||||
},
|
},
|
||||||
scroll: function() {
|
scroll: function() {
|
||||||
var bottom, height, i, reply, _len, _ref;
|
var bottom, height, i, reply, _len, _ref;
|
||||||
@ -3134,20 +3139,25 @@
|
|||||||
}
|
}
|
||||||
if (i === 0) return;
|
if (i === 0) return;
|
||||||
unread.replies = unread.replies.slice(i);
|
unread.replies = unread.replies.slice(i);
|
||||||
unread.updateTitle();
|
return unread.update();
|
||||||
if (unread.replies.length === 0) return Favicon.update();
|
|
||||||
},
|
},
|
||||||
updateTitle: function() {
|
update: function(forceUpdate) {
|
||||||
return d.title = d.title.replace(/\d+/, unread.replies.length);
|
var count;
|
||||||
|
if (!g.REPLY) return;
|
||||||
|
count = unread.replies.length;
|
||||||
|
if (conf['Unread Count']) d.title = "(" + count + ") " + unread.title;
|
||||||
|
if (!(conf['Unread Favicon'] && count < 2 || forceUpdate)) return;
|
||||||
|
Favicon.el.href = g.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"];
|
||||||
|
return $.add(d.head, Favicon.el);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Favicon = {
|
Favicon = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var favicon, href;
|
var href;
|
||||||
favicon = $('link[rel="shortcut icon"]', d.head);
|
this.el = $('link[rel="shortcut icon"]', d.head);
|
||||||
favicon.type = 'image/x-icon';
|
this.el.type = 'image/x-icon';
|
||||||
href = favicon.href;
|
href = this.el.href;
|
||||||
this.SFW = /ws.ico$/.test(href);
|
this.SFW = /ws.ico$/.test(href);
|
||||||
this["default"] = href;
|
this["default"] = href;
|
||||||
return this["switch"]();
|
return this["switch"]();
|
||||||
@ -3173,43 +3183,34 @@
|
|||||||
this.unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=';
|
this.unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=';
|
||||||
this.unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAKECAAAAAC6Xw////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=';
|
this.unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAKECAAAAAC6Xw////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=';
|
||||||
this.unreadNSFW = 'data:unreadNSFW;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=';
|
this.unreadNSFW = 'data:unreadNSFW;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=';
|
||||||
break;
|
|
||||||
case 'None':
|
|
||||||
this.unreadDead = this.dead;
|
|
||||||
this.unreadSFW = 'http://static.4chan.org/image/favicon-ws.ico';
|
|
||||||
this.unreadNSFW = 'http://static.4chan.org/image/favicon.ico';
|
|
||||||
}
|
}
|
||||||
return this.unread = this.SFW ? this.unreadSFW : this.unreadNSFW;
|
return this.unread = this.SFW ? this.unreadSFW : this.unreadNSFW;
|
||||||
},
|
},
|
||||||
empty: 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///9vb2////yH5BAEAAAMALAAAAAAQABAAAAIvnI+pq+D9DBAUoFkPFnbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==',
|
empty: 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///9vb2////yH5BAEAAAMALAAAAAAQABAAAAIvnI+pq+D9DBAUoFkPFnbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==',
|
||||||
dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==',
|
dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw=='
|
||||||
update: function() {
|
|
||||||
var favicon, l;
|
|
||||||
l = unread.replies.length;
|
|
||||||
favicon = $('link[rel="shortcut icon"]', d.head);
|
|
||||||
favicon.href = g.dead ? l ? this.unreadDead : this.dead : l ? this.unread : this["default"];
|
|
||||||
if (engine !== 'webkit') return $.add(d.head, $.rm(favicon));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
redirect = {
|
redirect = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var url;
|
var url;
|
||||||
url = location.hostname === 'images.4chan.org' ? redirect.image(g.BOARD, location.pathname.split('/')[3]) : /^\d+$/.test(g.THREAD_ID) ? redirect.thread() : void 0;
|
url = location.hostname === 'images.4chan.org' ? redirect.image(location.href) : /^\d+$/.test(g.THREAD_ID) ? redirect.thread() : void 0;
|
||||||
if (url) return location.href = url;
|
if (url) return location.href = url;
|
||||||
},
|
},
|
||||||
image: function(board, filename) {
|
image: function(href) {
|
||||||
switch (board) {
|
href = href.split('/');
|
||||||
|
if (!conf['404 Redirect']) return;
|
||||||
|
switch (href[3]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'jp':
|
case 'jp':
|
||||||
case 'm':
|
case 'm':
|
||||||
case 'tg':
|
case 'tg':
|
||||||
case 'tv':
|
case 'tv':
|
||||||
case 'u':
|
case 'u':
|
||||||
return "http://archive.foolz.us/" + board + "/full_image/" + filename;
|
return "http://archive.foolz.us/" + href[3] + "/full_image/" + href[5];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
thread: function() {
|
thread: function() {
|
||||||
|
if (!conf['404 Redirect']) return;
|
||||||
switch (g.BOARD) {
|
switch (g.BOARD) {
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'jp':
|
case 'jp':
|
||||||
@ -3249,7 +3250,7 @@
|
|||||||
case 'x':
|
case 'x':
|
||||||
return "http://archive.no-ip.org/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
return "http://archive.no-ip.org/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
||||||
default:
|
default:
|
||||||
return "http://boards.4chan.org/" + g.BOARD;
|
return "http://boards.4chan.org/" + g.BOARD + "/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3380,17 +3381,16 @@
|
|||||||
img = $.el('img', {
|
img = $.el('img', {
|
||||||
src: url || a.href
|
src: url || a.href
|
||||||
});
|
});
|
||||||
if (conf['404 Redirect']) $.on(img, 'error', imgExpand.error);
|
$.on(img, 'error', imgExpand.error);
|
||||||
return $.add(a, img);
|
return $.add(a, img);
|
||||||
},
|
},
|
||||||
error: function() {
|
error: function() {
|
||||||
var href, src, thumb, timeoutID, url;
|
var href, thumb, timeoutID, url;
|
||||||
href = this.parentNode.href;
|
href = this.parentNode.href;
|
||||||
thumb = this.previousSibling;
|
thumb = this.previousSibling;
|
||||||
src = href.split('/');
|
|
||||||
imgExpand.contract(thumb);
|
imgExpand.contract(thumb);
|
||||||
$.rm(this);
|
$.rm(this);
|
||||||
if (!(this.src.split('/')[2] === 'images.4chan.org' && (url = redirect.image(src[3], src[5])))) {
|
if (!(this.src.split('/')[2] === 'images.4chan.org' && (url = redirect.image(href)))) {
|
||||||
if (g.dead) return;
|
if (g.dead) return;
|
||||||
url = href + '?' + Date.now();
|
url = href + '?' + Date.now();
|
||||||
}
|
}
|
||||||
@ -3440,7 +3440,7 @@
|
|||||||
}
|
}
|
||||||
$.on(window, 'message', Main.message);
|
$.on(window, 'message', Main.message);
|
||||||
if (location.hostname === 'sys.4chan.org') {
|
if (location.hostname === 'sys.4chan.org') {
|
||||||
if (location.pathname === '/post') {
|
if (location.pathname === '/robots.txt') {
|
||||||
qr.message.init();
|
qr.message.init();
|
||||||
} else if (/report/.test(location.search)) {
|
} else if (/report/.test(location.search)) {
|
||||||
$.ready(function() {
|
$.ready(function() {
|
||||||
@ -3501,17 +3501,21 @@
|
|||||||
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']) quoteDR.init();
|
if (conf['Indicate Cross-thread Quotes']) quoteDR.init();
|
||||||
|
if (conf['Quick Reply'] && conf['Hide Original Post Form']) {
|
||||||
|
Main.css += 'form[name=post] { display: none; }';
|
||||||
|
}
|
||||||
|
Main.addStyle();
|
||||||
return $.ready(Main.ready);
|
return $.ready(Main.ready);
|
||||||
},
|
},
|
||||||
ready: function() {
|
ready: function() {
|
||||||
var callback, form, node, nodes, _i, _j, _len, _len2, _ref;
|
var callback, form, node, nodes, _i, _j, _len, _len2, _ref;
|
||||||
if (conf['404 Redirect'] && d.title === '4chan - 404') {
|
if (d.title === '4chan - 404') {
|
||||||
redirect.init();
|
redirect.init();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!$.id('navtopr')) return;
|
if (!$.id('navtopr')) return;
|
||||||
|
$.addClass(d.body, "chanx_" + (VERSION.match(/\.(\d+)/)[1]));
|
||||||
$.addClass(d.body, engine);
|
$.addClass(d.body, engine);
|
||||||
$.addStyle(Main.css);
|
|
||||||
threading.init();
|
threading.init();
|
||||||
Favicon.init();
|
Favicon.init();
|
||||||
if (conf['Quick Reply']) qr.init();
|
if (conf['Quick Reply']) qr.init();
|
||||||
@ -3523,7 +3527,7 @@
|
|||||||
if (conf['Thread Stats']) threadStats.init();
|
if (conf['Thread Stats']) threadStats.init();
|
||||||
if (conf['Reply Navigation']) nav.init();
|
if (conf['Reply Navigation']) nav.init();
|
||||||
if (conf['Post in Title']) titlePost.init();
|
if (conf['Post in Title']) titlePost.init();
|
||||||
if (conf['Unread Count']) unread.init();
|
if (conf['Unread Count'] || conf['Unread Favicon']) unread.init();
|
||||||
} else {
|
} else {
|
||||||
if (conf['Thread Hiding']) threadHiding.init();
|
if (conf['Thread Hiding']) threadHiding.init();
|
||||||
if (conf['Thread Expansion']) expandThread.init();
|
if (conf['Thread Expansion']) expandThread.init();
|
||||||
@ -3546,6 +3550,14 @@
|
|||||||
}
|
}
|
||||||
return $.on(form, 'DOMNodeInserted', Main.node);
|
return $.on(form, 'DOMNodeInserted', Main.node);
|
||||||
},
|
},
|
||||||
|
addStyle: function() {
|
||||||
|
$.off(d, 'DOMNodeInserted', Main.addStyle);
|
||||||
|
if (d.head) {
|
||||||
|
return $.addStyle(Main.css);
|
||||||
|
} else {
|
||||||
|
return $.on(d, 'DOMNodeInserted', Main.addStyle);
|
||||||
|
}
|
||||||
|
},
|
||||||
message: function(e) {
|
message: function(e) {
|
||||||
var data, version;
|
var data, version;
|
||||||
data = e.data;
|
data = e.data;
|
||||||
@ -3756,6 +3768,7 @@ textarea.field {\
|
|||||||
}\
|
}\
|
||||||
#qr [type=submit] {\
|
#qr [type=submit] {\
|
||||||
margin: 1px 0;\
|
margin: 1px 0;\
|
||||||
|
padding: 1px; /* not Gecko */\
|
||||||
padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */\
|
padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */\
|
||||||
width: 30%;\
|
width: 30%;\
|
||||||
}\
|
}\
|
||||||
@ -3901,7 +3914,8 @@ img[md5], img[md5] + img {\
|
|||||||
}\
|
}\
|
||||||
.filtered {\
|
.filtered {\
|
||||||
text-decoration: line-through;\
|
text-decoration: line-through;\
|
||||||
}'
|
}\
|
||||||
|
'
|
||||||
};
|
};
|
||||||
|
|
||||||
Main.init();
|
Main.init();
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
master
|
master
|
||||||
- desuwa
|
- desuwa
|
||||||
New option: remember the size of the QR on Firefox.
|
New option: remember the size of the QR on Firefox.
|
||||||
|
- aeosynth
|
||||||
|
prevent post form flicker
|
||||||
- Mayhem
|
- Mayhem
|
||||||
|
Load QR's iframe to sys.4chan.org faster, unless you use Greasemonkey. Thanks desuwa.
|
||||||
Increase Sauce linking possibilites:
|
Increase Sauce linking possibilites:
|
||||||
Thumbnails, full images, MD5 hashes.
|
Thumbnails, full images, MD5 hashes.
|
||||||
|
New option: Recursive Filtering: Filter replies of filtered posts.
|
||||||
|
Unread Favicon is now optional, independent of Unread Count.
|
||||||
|
Fix some compatibility issues with file drag and drop, notably with QuickDrag extension.
|
||||||
|
|
||||||
2.25.5
|
2.25.5
|
||||||
- Mayhem
|
- Mayhem
|
||||||
|
|||||||
247
script.coffee
247
script.coffee
@ -14,6 +14,7 @@ config =
|
|||||||
'Anonymize': [false, 'Make everybody anonymous']
|
'Anonymize': [false, 'Make everybody anonymous']
|
||||||
'Filter': [false, 'Self-moderation placebo']
|
'Filter': [false, 'Self-moderation placebo']
|
||||||
'Filter OPs': [false, 'Filter OPs along with their threads']
|
'Filter OPs': [false, 'Filter OPs along with their threads']
|
||||||
|
'Recursive Filtering': [false, 'Filter replies of filtered posts, recursively']
|
||||||
'Reply Hiding': [true, 'Hide single replies']
|
'Reply Hiding': [true, 'Hide single replies']
|
||||||
'Thread Hiding': [true, 'Hide entire threads']
|
'Thread Hiding': [true, 'Hide entire threads']
|
||||||
'Show Stubs': [true, 'Of hidden threads / replies']
|
'Show Stubs': [true, 'Of hidden threads / replies']
|
||||||
@ -26,6 +27,7 @@ config =
|
|||||||
Monitoring:
|
Monitoring:
|
||||||
'Thread Updater': [true, 'Update threads. Has more options in its own dialog.']
|
'Thread Updater': [true, 'Update threads. Has more options in its own dialog.']
|
||||||
'Unread Count': [true, 'Show unread post count in tab title']
|
'Unread Count': [true, 'Show unread post count in tab title']
|
||||||
|
'Unread Favicon': [true, 'Show a different favicon when there are unread posts']
|
||||||
'Post in Title': [true, 'Show the op\'s post in the tab title']
|
'Post in Title': [true, 'Show the op\'s post in the tab title']
|
||||||
'Thread Stats': [true, 'Display reply and image count']
|
'Thread Stats': [true, 'Display reply and image count']
|
||||||
'Thread Watcher': [true, 'Bookmark threads']
|
'Thread Watcher': [true, 'Bookmark threads']
|
||||||
@ -97,7 +99,7 @@ config =
|
|||||||
expandImages: ['m', 'Expand selected image']
|
expandImages: ['m', 'Expand selected image']
|
||||||
expandAllImages: ['M', 'Expand all images']
|
expandAllImages: ['M', 'Expand all images']
|
||||||
update: ['u', 'Update now']
|
update: ['u', 'Update now']
|
||||||
unreadCountTo0: ['z', 'Reset unread count to 0']
|
unreadCountTo0: ['z', 'Reset unread status']
|
||||||
updater:
|
updater:
|
||||||
checkbox:
|
checkbox:
|
||||||
'Scrolling': [false, 'Scroll updated posts into view. Only enabled at bottom of page.']
|
'Scrolling': [false, 'Scroll updated posts into view. Only enabled at bottom of page.']
|
||||||
@ -113,12 +115,10 @@ log = console.log.bind? console
|
|||||||
# flatten the config
|
# flatten the config
|
||||||
conf = {}
|
conf = {}
|
||||||
(flatten = (parent, obj) ->
|
(flatten = (parent, obj) ->
|
||||||
if typeof obj is 'object'
|
if obj instanceof Array
|
||||||
# array
|
conf[parent] = obj[0]
|
||||||
if obj.length
|
else if typeof obj is 'object'
|
||||||
conf[parent] = obj[0]
|
for key, val of obj
|
||||||
# object
|
|
||||||
else 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
|
||||||
@ -458,9 +458,10 @@ strikethroughQuotes =
|
|||||||
g.callbacks.push (root) ->
|
g.callbacks.push (root) ->
|
||||||
return if root.className is 'inline'
|
return if root.className is 'inline'
|
||||||
for quote in $$ '.quotelink', root
|
for quote in $$ '.quotelink', root
|
||||||
if el = $.id quote.hash[1..]
|
if (el = $.id quote.hash[1..]) and el.parentNode.parentNode.parentNode.hidden
|
||||||
if el.parentNode.parentNode.parentNode.hidden
|
$.addClass quote, 'filtered'
|
||||||
$.addClass quote, 'filtered'
|
root.hidden = true if conf['Recursive Filtering']
|
||||||
|
return
|
||||||
|
|
||||||
expandComment =
|
expandComment =
|
||||||
init: ->
|
init: ->
|
||||||
@ -658,7 +659,7 @@ keybinds =
|
|||||||
options.dialog() unless $.id 'overlay'
|
options.dialog() unless $.id 'overlay'
|
||||||
when conf.close
|
when conf.close
|
||||||
if o = $.id 'overlay'
|
if o = $.id 'overlay'
|
||||||
$.rm o
|
options.close.call o
|
||||||
else if qr.el
|
else if qr.el
|
||||||
qr.close()
|
qr.close()
|
||||||
when conf.spoiler
|
when conf.spoiler
|
||||||
@ -716,8 +717,7 @@ keybinds =
|
|||||||
qr.submit() if qr.el and !qr.status()
|
qr.submit() if qr.el and !qr.status()
|
||||||
when conf.unreadCountTo0
|
when conf.unreadCountTo0
|
||||||
unread.replies = []
|
unread.replies = []
|
||||||
unread.updateTitle()
|
unread.update()
|
||||||
Favicon.update()
|
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@ -869,10 +869,11 @@ qr =
|
|||||||
init: ->
|
init: ->
|
||||||
return unless $.id 'recaptcha_challenge_field_holder'
|
return unless $.id 'recaptcha_challenge_field_holder'
|
||||||
if conf['Hide Original Post Form']
|
if conf['Hide Original Post Form']
|
||||||
link = $.el 'h1', innerHTML: "<a href=javascript:;>#{if g.REPLY then 'Open the Quick Reply' else 'Create a New Thread'}</a>"
|
link = $.el 'h1', innerHTML: "<a href=javascript:;>#{if g.REPLY then 'Quick Reply' else 'New Thread'}</a>"
|
||||||
$.on $('a', link), 'click', qr.open
|
$.on $('a', link), 'click', ->
|
||||||
|
qr.open()
|
||||||
|
$('textarea', qr.el).focus()
|
||||||
form = d.forms[0]
|
form = d.forms[0]
|
||||||
form.hidden = true
|
|
||||||
$.before form, link
|
$.before form, link
|
||||||
g.callbacks.push (root) ->
|
g.callbacks.push (root) ->
|
||||||
$.on $('.quotejs + .quotejs', root), 'click', qr.quote
|
$.on $('.quotejs + .quotejs', root), 'click', qr.quote
|
||||||
@ -880,21 +881,23 @@ qr =
|
|||||||
iframe = $.el 'iframe',
|
iframe = $.el 'iframe',
|
||||||
id: 'iframe'
|
id: 'iframe'
|
||||||
hidden: true
|
hidden: true
|
||||||
src: 'http://sys.4chan.org/post'
|
src: 'http://sys.4chan.org/robots.txt'
|
||||||
$.on iframe, 'error', -> @src = @src
|
$.on iframe, 'error', -> @src = @src
|
||||||
# Greasemonkey ghetto fix
|
# Greasemonkey ghetto fix
|
||||||
loadChecking = (iframe) ->
|
loadChecking = (iframe) ->
|
||||||
unless qr.status.ready
|
unless qr.status.ready
|
||||||
iframe.src = 'about:blank'
|
iframe.src = 'about:blank'
|
||||||
setTimeout (-> iframe.src = 'http://sys.4chan.org/post'), 250
|
setTimeout (-> iframe.src = 'http://sys.4chan.org/robots.txt'), 250
|
||||||
$.on iframe, 'load', -> unless @src is 'about:blank' then setTimeout loadChecking, 250, @
|
$.on iframe, 'load', -> unless @src is 'about:blank' then setTimeout loadChecking, 500, @
|
||||||
$.add d.body, iframe
|
$.add d.body, iframe
|
||||||
|
|
||||||
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.fileDrop
|
$.on d, 'dragover', qr.dragOver
|
||||||
$.on d, 'drop', qr.fileDrop
|
$.on d, 'drop', qr.dropFile
|
||||||
|
$.on d, 'dragstart', qr.drag
|
||||||
|
$.on d, 'dragend', qr.drag
|
||||||
# prevent original captcha input from being focused on reload
|
# prevent original captcha input from being focused on reload
|
||||||
window.location = 'javascript:void(Recaptcha.focus_response_field=function(){})'
|
window.location = 'javascript:void(Recaptcha.focus_response_field=function(){})'
|
||||||
|
|
||||||
@ -931,6 +934,9 @@ qr =
|
|||||||
el.textContent = err
|
el.textContent = err
|
||||||
$.replace el.firstChild, node if node
|
$.replace el.firstChild, node if node
|
||||||
qr.open()
|
qr.open()
|
||||||
|
if /captcha|verification/i.test err
|
||||||
|
# Focus the captcha input on captcha error.
|
||||||
|
$('[autocomplete]', qr.el).focus()
|
||||||
alert err if d.hidden or d.oHidden or d.mozHidden or d.webkitHidden
|
alert err if d.hidden or d.oHidden or d.mozHidden or d.webkitHidden
|
||||||
cleanError: ->
|
cleanError: ->
|
||||||
$('.warning', qr.el).textContent = null
|
$('.warning', qr.el).textContent = null
|
||||||
@ -1004,16 +1010,21 @@ qr =
|
|||||||
# Move the caret to the end of the new quote.
|
# Move the caret to the end of the new quote.
|
||||||
ta.selectionEnd = ta.selectionStart = caretPos + text.length
|
ta.selectionEnd = ta.selectionStart = caretPos + text.length
|
||||||
|
|
||||||
fileDrop: (e) ->
|
drag: (e) ->
|
||||||
return if /TEXTAREA|INPUT/.test e.target.nodeName
|
# Let it drag anything from the page.
|
||||||
|
i = if e.type is 'dragstart' then 'off' else 'on'
|
||||||
|
$[i] d, 'dragover', qr.dragOver
|
||||||
|
$[i] d, 'drop', qr.dropFile
|
||||||
|
dragOver: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
|
||||||
e.dataTransfer.dropEffect = 'copy' # cursor feedback
|
e.dataTransfer.dropEffect = 'copy' # cursor feedback
|
||||||
if e.type is 'drop'
|
dropFile: (e) ->
|
||||||
return unless e.dataTransfer.files.length # let it only drop files
|
# Let it only handle files from the desktop.
|
||||||
qr.open()
|
return unless e.dataTransfer.files.length
|
||||||
qr.fileInput.call e.dataTransfer
|
e.preventDefault()
|
||||||
$.addClass qr.el, 'dump'
|
qr.open()
|
||||||
|
qr.fileInput.call e.dataTransfer
|
||||||
|
$.addClass qr.el, 'dump'
|
||||||
fileInput: ->
|
fileInput: ->
|
||||||
qr.cleanError()
|
qr.cleanError()
|
||||||
# Set or change current reply's file.
|
# Set or change current reply's file.
|
||||||
@ -1144,7 +1155,7 @@ qr =
|
|||||||
when 0
|
when 0
|
||||||
'Verification (Shift + Enter to cache)'
|
'Verification (Shift + Enter to cache)'
|
||||||
when 1
|
when 1
|
||||||
'Vertification (1 cached captcha)'
|
'Verification (1 cached captcha)'
|
||||||
else
|
else
|
||||||
"Verification (#{count} cached captchas)"
|
"Verification (#{count} cached captchas)"
|
||||||
@input.alt = count # For XTRM RICE.
|
@input.alt = count # For XTRM RICE.
|
||||||
@ -1180,7 +1191,7 @@ qr =
|
|||||||
</form>'
|
</form>'
|
||||||
|
|
||||||
if conf['Remember QR size'] and engine is 'gecko'
|
if conf['Remember QR size'] and engine is 'gecko'
|
||||||
$.on ta = qr.el.querySelector('textarea'), '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', ''
|
||||||
|
|
||||||
@ -1229,7 +1240,7 @@ qr =
|
|||||||
$.on input, 'change', -> qr.selected[@name] = @value
|
$.on input, 'change', -> qr.selected[@name] = @value
|
||||||
# sync between tabs
|
# sync between tabs
|
||||||
$.sync 'qr.persona', (persona) ->
|
$.sync 'qr.persona', (persona) ->
|
||||||
return if qr.replies.length isnt 1
|
return unless qr.el.hidden
|
||||||
for key, val of persona
|
for key, val of persona
|
||||||
qr.selected[key] = val
|
qr.selected[key] = val
|
||||||
$("[name=#{key}]", qr.el).value = val
|
$("[name=#{key}]", qr.el).value = val
|
||||||
@ -1395,18 +1406,15 @@ qr =
|
|||||||
parent.postMessage data, '*'
|
parent.postMessage data, '*'
|
||||||
script = $.el 'script', textContent: "window.addEventListener('message',#{code},false)"
|
script = $.el 'script', textContent: "window.addEventListener('message',#{code},false)"
|
||||||
ready = ->
|
ready = ->
|
||||||
|
$.add d.documentElement, script
|
||||||
if location.hostname is 'sys.4chan.org'
|
if location.hostname is 'sys.4chan.org'
|
||||||
qr.message.send req: 'status', ready: true
|
qr.message.send req: 'status', ready: true
|
||||||
$.rm script
|
$.rm script
|
||||||
# Chrome can access the documentElement on document-start
|
# Chrome can access the documentElement on document-start
|
||||||
if d.documentElement
|
if d.documentElement
|
||||||
$.add d.documentElement, script
|
|
||||||
ready()
|
ready()
|
||||||
return
|
|
||||||
# other browsers will have to wait
|
# other browsers will have to wait
|
||||||
$.ready ->
|
else $.ready ready
|
||||||
$.add d.head, script
|
|
||||||
ready()
|
|
||||||
send: (data) ->
|
send: (data) ->
|
||||||
data.changeContext = true
|
data.changeContext = true
|
||||||
data.qr = true
|
data.qr = true
|
||||||
@ -1579,21 +1587,20 @@ options =
|
|||||||
<li>Hour: %k, %H, %l (lowercase L), %I (uppercase i), %p, %P</li>
|
<li>Hour: %k, %H, %l (lowercase L), %I (uppercase i), %p, %P</li>
|
||||||
<li>Minutes: %M</li>
|
<li>Minutes: %M</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class=warning><code>Unread Count</code> is disabled.</div>
|
<div class=warning><code>Unread Favicon</code> is disabled.</div>
|
||||||
Unread favicons<br>
|
Unread favicons<br>
|
||||||
<select name=favicon>
|
<select name=favicon>
|
||||||
<option value=ferongr>ferongr</option>
|
<option value=ferongr>ferongr</option>
|
||||||
<option value=xat->xat-</option>
|
<option value=xat->xat-</option>
|
||||||
<option value=Mayhem>Mayhem</option>
|
<option value=Mayhem>Mayhem</option>
|
||||||
<option value=Original>Original</option>
|
<option value=Original>Original</option>
|
||||||
<option value=None>None</option>
|
|
||||||
</select>
|
</select>
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
<input type=radio name=tab hidden id=keybinds_tab>
|
<input type=radio name=tab hidden id=keybinds_tab>
|
||||||
<div>
|
<div>
|
||||||
<div class=warning><code>Keybinds</code> are disabled.</div>
|
<div class=warning><code>Keybinds</code> are disabled.</div>
|
||||||
<div>Allowed keys: Ctrl, Alt, a-z, A-Z, 0-1, Up, Down, Right, Left.</div>
|
<div>Allowed keys: Ctrl, Alt, a-z, A-Z, 0-9, Up, Down, Right, Left.</div>
|
||||||
<table><tbody>
|
<table><tbody>
|
||||||
<tr><th>Actions</th><th>Keybinds</th></tr>
|
<tr><th>Actions</th><th>Keybinds</th></tr>
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
@ -1656,15 +1663,20 @@ options =
|
|||||||
indicators[@name].hidden = @checked
|
indicators[@name].hidden = @checked
|
||||||
|
|
||||||
overlay = $.el 'div', id: 'overlay'
|
overlay = $.el 'div', id: 'overlay'
|
||||||
$.on overlay, 'click', -> $.rm overlay
|
$.on overlay, 'click', options.close
|
||||||
$.on dialog, 'click', (e) -> e.stopPropagation()
|
$.on dialog, 'click', (e) -> e.stopPropagation()
|
||||||
$.add overlay, dialog
|
$.add overlay, dialog
|
||||||
$.add d.body, overlay
|
$.add d.body, overlay
|
||||||
|
d.body.style.setProperty 'overflow', 'hidden', null
|
||||||
|
|
||||||
options.backlink.call back
|
options.backlink.call back
|
||||||
options.time.call time
|
options.time.call time
|
||||||
options.favicon.call favicon
|
options.favicon.call favicon
|
||||||
|
|
||||||
|
close: ->
|
||||||
|
$.rm this
|
||||||
|
d.body.style.removeProperty 'overflow'
|
||||||
|
|
||||||
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.
|
||||||
@ -1687,7 +1699,7 @@ options =
|
|||||||
$.id('backlinkPreview').textContent = conf['backlink'].replace /%id/, '123456789'
|
$.id('backlinkPreview').textContent = conf['backlink'].replace /%id/, '123456789'
|
||||||
favicon: ->
|
favicon: ->
|
||||||
Favicon.switch()
|
Favicon.switch()
|
||||||
Favicon.update() if g.REPLY and conf['Unread Count']
|
unread.update true
|
||||||
@nextElementSibling.innerHTML = "<img src=#{Favicon.unreadSFW}> <img src=#{Favicon.unreadNSFW}> <img src=#{Favicon.unreadDead}>"
|
@nextElementSibling.innerHTML = "<img src=#{Favicon.unreadSFW}> <img src=#{Favicon.unreadNSFW}> <img src=#{Favicon.unreadDead}>"
|
||||||
|
|
||||||
threading =
|
threading =
|
||||||
@ -1871,8 +1883,12 @@ updater =
|
|||||||
updater.count.textContent = 404
|
updater.count.textContent = 404
|
||||||
updater.count.className = 'warning'
|
updater.count.className = 'warning'
|
||||||
clearTimeout updater.timeoutID
|
clearTimeout updater.timeoutID
|
||||||
d.title = d.title.match(/^.+-/)[0] + ' 404'
|
|
||||||
g.dead = true
|
g.dead = true
|
||||||
|
if conf['Unread Count']
|
||||||
|
unread.title = unread.title.match(/^.+-/)[0] + ' 404'
|
||||||
|
else
|
||||||
|
d.title = d.title.match(/^.+-/)[0] + ' 404'
|
||||||
|
unread.update true
|
||||||
qr.message.send req: 'abort'
|
qr.message.send req: 'abort'
|
||||||
qr.status()
|
qr.status()
|
||||||
Favicon.update()
|
Favicon.update()
|
||||||
@ -2042,31 +2058,31 @@ anonymize =
|
|||||||
|
|
||||||
sauce =
|
sauce =
|
||||||
init: ->
|
init: ->
|
||||||
# return unless
|
|
||||||
links = conf['sauces'].match /^[^#].+$/gm
|
links = conf['sauces'].match /^[^#].+$/gm
|
||||||
|
return unless links.length
|
||||||
@links = []
|
@links = []
|
||||||
for link in links
|
for link in links
|
||||||
@links.push [link, link.match(/(\w+)\.\w+\//)[1]]
|
domain = link.match(/(\w+)\.\w+\//)[1]
|
||||||
|
fc = link.replace /\$\d/, (fragment) ->
|
||||||
|
switch fragment
|
||||||
|
when '$1'
|
||||||
|
"' + img.src + '"
|
||||||
|
when '$2'
|
||||||
|
"' + img.parentNode.href + '"
|
||||||
|
when '$3'
|
||||||
|
"' + img.getAttribute('md5').replace(/\=*$/, '') + '"
|
||||||
|
@links.push [Function('img', "return '#{fc}'"), domain]
|
||||||
g.callbacks.push @node
|
g.callbacks.push @node
|
||||||
node: (root) ->
|
node: (root) ->
|
||||||
return if root.className is 'inline' or not span = $ '.filesize', root
|
return if root.className is 'inline' or not span = $ '.filesize', root
|
||||||
img = $ 'img', root
|
img = $ 'img', root
|
||||||
for link in sauce.links
|
for link in sauce.links
|
||||||
a = $.el 'a',
|
a = $.el 'a',
|
||||||
textContent: link[1]
|
href: link[0] img
|
||||||
href: sauce.href link[0], img
|
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
|
textContent: link[1]
|
||||||
$.add span, $.tn(' '), a
|
$.add span, $.tn(' '), a
|
||||||
return
|
return
|
||||||
href: (link, img) ->
|
|
||||||
link.replace /\$\d/, (fragment) ->
|
|
||||||
switch fragment
|
|
||||||
when '$1'
|
|
||||||
img.src
|
|
||||||
when '$2'
|
|
||||||
img.parentNode.href
|
|
||||||
when '$3'
|
|
||||||
img.getAttribute('md5').replace /\=+$/, ''
|
|
||||||
|
|
||||||
revealSpoilers =
|
revealSpoilers =
|
||||||
init: ->
|
init: ->
|
||||||
@ -2223,10 +2239,9 @@ quoteInline =
|
|||||||
root = if q.parentNode.nodeName is 'FONT' then q.parentNode else if q.nextSibling then q.nextSibling else q
|
root = if q.parentNode.nodeName is 'FONT' then q.parentNode else if q.nextSibling then q.nextSibling else q
|
||||||
if el = $.id id
|
if el = $.id id
|
||||||
inline = quoteInline.table id, el.innerHTML
|
inline = quoteInline.table id, el.innerHTML
|
||||||
if g.REPLY and conf['Unread Count'] and (i = unread.replies.indexOf el.parentNode.parentNode.parentNode) isnt -1
|
if (i = unread.replies.indexOf el.parentNode.parentNode.parentNode) isnt -1
|
||||||
unread.replies.splice i, 1
|
unread.replies.splice i, 1
|
||||||
unread.updateTitle()
|
unread.update()
|
||||||
Favicon.update()
|
|
||||||
if /\bbacklink\b/.test q.className
|
if /\bbacklink\b/.test q.className
|
||||||
$.after q.parentNode, inline
|
$.after q.parentNode, inline
|
||||||
$.addClass $.x('ancestor::table', el), 'forwarded' if conf['Forward Hiding']
|
$.addClass $.x('ancestor::table', el), 'forwarded' if conf['Forward Hiding']
|
||||||
@ -2398,7 +2413,8 @@ threadStats =
|
|||||||
|
|
||||||
unread =
|
unread =
|
||||||
init: ->
|
init: ->
|
||||||
d.title = '(0) ' + d.title
|
@title = d.title
|
||||||
|
unread.update()
|
||||||
$.on window, 'scroll', unread.scroll
|
$.on window, 'scroll', unread.scroll
|
||||||
g.callbacks.push unread.node
|
g.callbacks.push unread.node
|
||||||
|
|
||||||
@ -2407,9 +2423,7 @@ unread =
|
|||||||
node: (root) ->
|
node: (root) ->
|
||||||
return if root.hidden or root.className
|
return if root.hidden or root.className
|
||||||
unread.replies.push root
|
unread.replies.push root
|
||||||
unread.updateTitle()
|
unread.update()
|
||||||
if unread.replies.length is 1
|
|
||||||
Favicon.update()
|
|
||||||
|
|
||||||
scroll: ->
|
scroll: ->
|
||||||
height = d.body.clientHeight
|
height = d.body.clientHeight
|
||||||
@ -2420,18 +2434,41 @@ unread =
|
|||||||
return if i is 0
|
return if i is 0
|
||||||
|
|
||||||
unread.replies = unread.replies[i..]
|
unread.replies = unread.replies[i..]
|
||||||
unread.updateTitle()
|
unread.update()
|
||||||
if unread.replies.length is 0
|
|
||||||
Favicon.update()
|
|
||||||
|
|
||||||
updateTitle: ->
|
update: (forceUpdate) ->
|
||||||
d.title = d.title.replace /\d+/, unread.replies.length
|
return unless g.REPLY
|
||||||
|
|
||||||
|
count = unread.replies.length
|
||||||
|
|
||||||
|
if conf['Unread Count']
|
||||||
|
d.title = "(#{count}) #{unread.title}"
|
||||||
|
|
||||||
|
unless conf['Unread Favicon'] and count < 2 or forceUpdate
|
||||||
|
return
|
||||||
|
|
||||||
|
Favicon.el.href =
|
||||||
|
if g.dead
|
||||||
|
if count
|
||||||
|
Favicon.unreadDead
|
||||||
|
else
|
||||||
|
Favicon.dead
|
||||||
|
else
|
||||||
|
if count
|
||||||
|
Favicon.unread
|
||||||
|
else
|
||||||
|
Favicon.default
|
||||||
|
|
||||||
|
#`favicon.href = href` doesn't work on Firefox
|
||||||
|
#`favicon.href = href` isn't enough on Opera
|
||||||
|
#Opera won't always update the favicon if the href didn't not change
|
||||||
|
$.add d.head, Favicon.el
|
||||||
|
|
||||||
Favicon =
|
Favicon =
|
||||||
init: ->
|
init: ->
|
||||||
favicon = $ 'link[rel="shortcut icon"]', d.head
|
@el = $ 'link[rel="shortcut icon"]', d.head
|
||||||
favicon.type = 'image/x-icon'
|
@el.type = 'image/x-icon'
|
||||||
{href} = favicon
|
{href} = @el
|
||||||
@SFW = /ws.ico$/.test href
|
@SFW = /ws.ico$/.test href
|
||||||
@default = href
|
@default = href
|
||||||
@switch()
|
@switch()
|
||||||
@ -2454,50 +2491,28 @@ Favicon =
|
|||||||
@unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='
|
@unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='
|
||||||
@unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAKECAAAAAC6Xw////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='
|
@unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAKECAAAAAC6Xw////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='
|
||||||
@unreadNSFW = 'data:unreadNSFW;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='
|
@unreadNSFW = 'data:unreadNSFW;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='
|
||||||
when 'None'
|
|
||||||
@unreadDead = @dead
|
|
||||||
@unreadSFW = 'http://static.4chan.org/image/favicon-ws.ico'
|
|
||||||
@unreadNSFW = 'http://static.4chan.org/image/favicon.ico'
|
|
||||||
@unread = if @SFW then @unreadSFW else @unreadNSFW
|
@unread = if @SFW then @unreadSFW else @unreadNSFW
|
||||||
|
|
||||||
empty: 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///9vb2////yH5BAEAAAMALAAAAAAQABAAAAIvnI+pq+D9DBAUoFkPFnbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw=='
|
empty: 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///9vb2////yH5BAEAAAMALAAAAAAQABAAAAIvnI+pq+D9DBAUoFkPFnbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw=='
|
||||||
dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw=='
|
dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw=='
|
||||||
|
|
||||||
update: ->
|
|
||||||
l = unread.replies.length
|
|
||||||
|
|
||||||
favicon = $ 'link[rel="shortcut icon"]', d.head
|
|
||||||
favicon.href =
|
|
||||||
if g.dead
|
|
||||||
if l
|
|
||||||
@unreadDead
|
|
||||||
else
|
|
||||||
@dead
|
|
||||||
else
|
|
||||||
if l
|
|
||||||
@unread
|
|
||||||
else
|
|
||||||
@default
|
|
||||||
|
|
||||||
#`favicon.href = href` doesn't work on Firefox
|
|
||||||
#`favicon.href = href` isn't enough on Opera
|
|
||||||
#Opera won't always update the favicon if the href do not change
|
|
||||||
if engine isnt 'webkit'
|
|
||||||
$.add d.head, $.rm favicon
|
|
||||||
|
|
||||||
redirect =
|
redirect =
|
||||||
init: ->
|
init: ->
|
||||||
url =
|
url =
|
||||||
if location.hostname is 'images.4chan.org'
|
if location.hostname is 'images.4chan.org'
|
||||||
redirect.image g.BOARD, location.pathname.split('/')[3]
|
redirect.image location.href
|
||||||
else if /^\d+$/.test g.THREAD_ID
|
else if /^\d+$/.test g.THREAD_ID
|
||||||
redirect.thread()
|
redirect.thread()
|
||||||
location.href = url if url
|
location.href = url if url
|
||||||
image: (board, filename) -> #board must be given, the image can originate from a cross-quote
|
image: (href) ->
|
||||||
switch board
|
href = href.split '/'
|
||||||
|
# Do not use g.BOARD, the image url can originate from a cross-quote.
|
||||||
|
return unless conf['404 Redirect']
|
||||||
|
switch href[3]
|
||||||
when 'a', 'jp', 'm', 'tg', 'tv', 'u'
|
when 'a', 'jp', 'm', 'tg', 'tv', 'u'
|
||||||
"http://archive.foolz.us/#{board}/full_image/#{filename}"
|
"http://archive.foolz.us/#{href[3]}/full_image/#{href[5]}"
|
||||||
thread: ->
|
thread: ->
|
||||||
|
return unless conf['404 Redirect']
|
||||||
switch g.BOARD
|
switch g.BOARD
|
||||||
when 'a', 'jp', 'm', 'tg', 'tv', 'u'
|
when 'a', 'jp', 'm', 'tg', 'tv', 'u'
|
||||||
"http://archive.foolz.us/#{g.BOARD}/thread/#{g.THREAD_ID}/"
|
"http://archive.foolz.us/#{g.BOARD}/thread/#{g.THREAD_ID}/"
|
||||||
@ -2508,7 +2523,7 @@ redirect =
|
|||||||
when '3', 'adv', 'an', 'ck', 'co', 'fa', 'fit', 'int', 'k', 'mu', 'n', 'o', 'p', 'po', 'pol', 'r9k', 'soc', 'sp', 'toy', 'trv', 'v', 'vp', 'x'
|
when '3', 'adv', 'an', 'ck', 'co', 'fa', 'fit', 'int', 'k', 'mu', 'n', 'o', 'p', 'po', 'pol', 'r9k', 'soc', 'sp', 'toy', 'trv', 'v', 'vp', 'x'
|
||||||
"http://archive.no-ip.org/#{g.BOARD}/thread/#{g.THREAD_ID}"
|
"http://archive.no-ip.org/#{g.BOARD}/thread/#{g.THREAD_ID}"
|
||||||
else
|
else
|
||||||
"http://boards.4chan.org/#{g.BOARD}"
|
"http://boards.4chan.org/#{g.BOARD}/"
|
||||||
|
|
||||||
imgHover =
|
imgHover =
|
||||||
init: ->
|
init: ->
|
||||||
@ -2599,16 +2614,15 @@ imgExpand =
|
|||||||
a = thumb.parentNode
|
a = thumb.parentNode
|
||||||
img = $.el 'img',
|
img = $.el 'img',
|
||||||
src: url or a.href
|
src: url or a.href
|
||||||
$.on img, 'error', imgExpand.error if conf['404 Redirect']
|
$.on img, 'error', imgExpand.error
|
||||||
$.add a, img
|
$.add a, img
|
||||||
|
|
||||||
error: ->
|
error: ->
|
||||||
href = @parentNode.href
|
href = @parentNode.href
|
||||||
thumb = @previousSibling
|
thumb = @previousSibling
|
||||||
src = href.split '/'
|
|
||||||
imgExpand.contract thumb
|
imgExpand.contract thumb
|
||||||
$.rm @
|
$.rm @
|
||||||
unless @src.split('/')[2] is 'images.4chan.org' and url = redirect.image src[3], src[5]
|
unless @src.split('/')[2] is 'images.4chan.org' and url = redirect.image href
|
||||||
return if g.dead
|
return if g.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.
|
||||||
@ -2653,7 +2667,7 @@ Main =
|
|||||||
$.on window, 'message', Main.message
|
$.on window, 'message', Main.message
|
||||||
|
|
||||||
if location.hostname is 'sys.4chan.org'
|
if location.hostname is 'sys.4chan.org'
|
||||||
if location.pathname is '/post'
|
if location.pathname is '/robots.txt'
|
||||||
qr.message.init()
|
qr.message.init()
|
||||||
else if /report/.test location.search
|
else if /report/.test location.search
|
||||||
$.ready ->
|
$.ready ->
|
||||||
@ -2736,17 +2750,21 @@ Main =
|
|||||||
if conf['Indicate Cross-thread Quotes']
|
if conf['Indicate Cross-thread Quotes']
|
||||||
quoteDR.init()
|
quoteDR.init()
|
||||||
|
|
||||||
|
if conf['Quick Reply'] and conf['Hide Original Post Form']
|
||||||
|
Main.css += 'form[name=post] { display: none; }'
|
||||||
|
|
||||||
|
Main.addStyle()
|
||||||
|
|
||||||
$.ready Main.ready
|
$.ready Main.ready
|
||||||
|
|
||||||
ready: ->
|
ready: ->
|
||||||
if conf['404 Redirect'] and d.title is '4chan - 404'
|
if d.title is '4chan - 404'
|
||||||
redirect.init()
|
redirect.init()
|
||||||
return
|
return
|
||||||
if not $.id 'navtopr'
|
if not $.id 'navtopr'
|
||||||
return
|
return
|
||||||
|
$.addClass d.body, "chanx_#{VERSION.match(/\.(\d+)/)[1]}"
|
||||||
$.addClass d.body, engine
|
$.addClass d.body, engine
|
||||||
$.addStyle Main.css
|
|
||||||
threading.init()
|
threading.init()
|
||||||
Favicon.init()
|
Favicon.init()
|
||||||
|
|
||||||
@ -2776,7 +2794,7 @@ Main =
|
|||||||
if conf['Post in Title']
|
if conf['Post in Title']
|
||||||
titlePost.init()
|
titlePost.init()
|
||||||
|
|
||||||
if conf['Unread Count']
|
if conf['Unread Count'] or conf['Unread Favicon']
|
||||||
unread.init()
|
unread.init()
|
||||||
|
|
||||||
else #not reply
|
else #not reply
|
||||||
@ -2803,6 +2821,13 @@ Main =
|
|||||||
alert err
|
alert err
|
||||||
$.on form, 'DOMNodeInserted', Main.node
|
$.on form, 'DOMNodeInserted', Main.node
|
||||||
|
|
||||||
|
addStyle: ->
|
||||||
|
$.off d, 'DOMNodeInserted', Main.addStyle
|
||||||
|
if d.head
|
||||||
|
$.addStyle Main.css
|
||||||
|
else # XXX fox
|
||||||
|
$.on d, 'DOMNodeInserted', Main.addStyle
|
||||||
|
|
||||||
message: (e) ->
|
message: (e) ->
|
||||||
{data} = e
|
{data} = e
|
||||||
{version} = data
|
{version} = data
|
||||||
@ -3004,6 +3029,7 @@ textarea.field {
|
|||||||
}
|
}
|
||||||
#qr [type=submit] {
|
#qr [type=submit] {
|
||||||
margin: 1px 0;
|
margin: 1px 0;
|
||||||
|
padding: 1px; /* not Gecko */
|
||||||
padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */
|
padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */
|
||||||
width: 30%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
@ -3149,6 +3175,7 @@ img[md5], img[md5] + img {
|
|||||||
}
|
}
|
||||||
.filtered {
|
.filtered {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}'
|
}
|
||||||
|
'
|
||||||
|
|
||||||
Main.init()
|
Main.init()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user