Merge branch 'master' into Fx10
This commit is contained in:
commit
cc7be74f54
322
4chan_x.user.js
322
4chan_x.user.js
@ -1,11 +1,12 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 4chan x
|
// @name 4chan x
|
||||||
// @version 2.23.7
|
// @version 2.24.0
|
||||||
// @namespace aeosynth
|
// @namespace aeosynth
|
||||||
// @description Adds various features.
|
// @description Adds various features.
|
||||||
// @copyright 2009-2011 James Campos <james.r.campos@gmail.com>
|
// @copyright 2009-2011 James Campos <james.r.campos@gmail.com>
|
||||||
// @license MIT; http://en.wikipedia.org/wiki/Mit_license
|
// @license MIT; http://en.wikipedia.org/wiki/Mit_license
|
||||||
// @include http://boards.4chan.org/*
|
// @include http://boards.4chan.org/*
|
||||||
|
// @include http://images.4chan.org/*
|
||||||
// @include http://sys.4chan.org/*
|
// @include http://sys.4chan.org/*
|
||||||
// @run-at document-start
|
// @run-at document-start
|
||||||
// @updateURL https://raw.github.com/MayhemYDG/4chan-x/stable/4chan_x.user.js
|
// @updateURL https://raw.github.com/MayhemYDG/4chan-x/stable/4chan_x.user.js
|
||||||
@ -15,8 +16,9 @@
|
|||||||
/* LICENSE
|
/* LICENSE
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2011 James Campos <james.r.campos@gmail.com>
|
* Copyright (c) 2009-2011 James Campos <james.r.campos@gmail.com>
|
||||||
|
* Copyright (c) 2012 Nicolas Stepien <stepien.nicolas@gmail.com>
|
||||||
* http://mayhemydg.github.com/4chan-x/
|
* http://mayhemydg.github.com/4chan-x/
|
||||||
* 4chan X 2.23.7
|
* 4chan X 2.24.0
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
@ -70,7 +72,7 @@
|
|||||||
config = {
|
config = {
|
||||||
main: {
|
main: {
|
||||||
Enhancing: {
|
Enhancing: {
|
||||||
'404 Redirect': [true, 'Redirect dead threads'],
|
'404 Redirect': [true, 'Redirect dead threads and images'],
|
||||||
'Keybinds': [true, 'Binds actions to keys'],
|
'Keybinds': [true, 'Binds actions to keys'],
|
||||||
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time'],
|
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time'],
|
||||||
'Report Button': [true, 'Add report buttons'],
|
'Report Button': [true, 'Add report buttons'],
|
||||||
@ -133,11 +135,12 @@
|
|||||||
filesize: '',
|
filesize: '',
|
||||||
md5: ''
|
md5: ''
|
||||||
},
|
},
|
||||||
flavors: ['http://iqdb.org/?url=', 'http://google.com/searchbyimage?image_url=', '#http://tineye.com/search?url=', '#http://saucenao.com/search.php?db=999&url=', '#http://3d.iqdb.org/?url=', '#http://regex.info/exif.cgi?imgurl=', '#http://imgur.com/upload?url='].join('\n'),
|
flavors: ['http://iqdb.org/?url=', 'http://google.com/searchbyimage?image_url=', '#http://tineye.com/search?url=', '#http://saucenao.com/search.php?db=999&url=', '#http://3d.iqdb.org/?url=', '#http://regex.info/exif.cgi?imgurl=', '#http://imgur.com/upload?url=', '#http://ompldr.org/upload?url1='].join('\n'),
|
||||||
time: '%m/%d/%y(%a)%H:%M',
|
time: '%m/%d/%y(%a)%H:%M',
|
||||||
backlink: '>>%id',
|
backlink: '>>%id',
|
||||||
favicon: 'ferongr',
|
favicon: 'ferongr',
|
||||||
hotkeys: {
|
hotkeys: {
|
||||||
|
openOptions: 'ctrl+o',
|
||||||
close: 'Esc',
|
close: 'Esc',
|
||||||
spoiler: 'ctrl+s',
|
spoiler: 'ctrl+s',
|
||||||
openQR: 'i',
|
openQR: 'i',
|
||||||
@ -197,7 +200,7 @@
|
|||||||
|
|
||||||
NAMESPACE = '4chan_x.';
|
NAMESPACE = '4chan_x.';
|
||||||
|
|
||||||
VERSION = '2.23.7';
|
VERSION = '2.24.0';
|
||||||
|
|
||||||
SECOND = 1000;
|
SECOND = 1000;
|
||||||
|
|
||||||
@ -304,6 +307,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$.extend($, {
|
$.extend($, {
|
||||||
|
onLoad: function(fc) {
|
||||||
|
var cb;
|
||||||
|
if (/interactive|complete/.test(d.readyState)) return fc();
|
||||||
|
cb = function() {
|
||||||
|
$.off(d, 'DOMContentLoaded', cb);
|
||||||
|
return fc();
|
||||||
|
};
|
||||||
|
return $.on(d, 'DOMContentLoaded', cb);
|
||||||
|
},
|
||||||
id: function(id) {
|
id: function(id) {
|
||||||
return d.getElementById(id);
|
return d.getElementById(id);
|
||||||
},
|
},
|
||||||
@ -463,54 +475,44 @@
|
|||||||
|
|
||||||
$.cache.requests = {};
|
$.cache.requests = {};
|
||||||
|
|
||||||
if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) {
|
$.extend($, typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null ? {
|
||||||
$.extend($, {
|
"delete": function(name) {
|
||||||
"delete": function(name) {
|
name = NAMESPACE + name;
|
||||||
name = NAMESPACE + name;
|
return GM_deleteValue(name);
|
||||||
return GM_deleteValue(name);
|
},
|
||||||
},
|
get: function(name, defaultValue) {
|
||||||
get: function(name, defaultValue) {
|
var value;
|
||||||
var value;
|
name = NAMESPACE + name;
|
||||||
name = NAMESPACE + name;
|
if (value = GM_getValue(name)) {
|
||||||
if (value = GM_getValue(name)) {
|
return JSON.parse(value);
|
||||||
return JSON.parse(value);
|
} else {
|
||||||
} else {
|
return defaultValue;
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openInTab: function(url) {
|
|
||||||
return GM_openInTab(url);
|
|
||||||
},
|
|
||||||
set: function(name, value) {
|
|
||||||
name = NAMESPACE + name;
|
|
||||||
localStorage[name] = JSON.stringify(value);
|
|
||||||
return GM_setValue(name, JSON.stringify(value));
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
} else {
|
set: function(name, value) {
|
||||||
$.extend($, {
|
name = NAMESPACE + name;
|
||||||
"delete": function(name) {
|
localStorage[name] = JSON.stringify(value);
|
||||||
name = NAMESPACE + name;
|
return GM_setValue(name, JSON.stringify(value));
|
||||||
return delete localStorage[name];
|
}
|
||||||
},
|
} : {
|
||||||
get: function(name, defaultValue) {
|
"delete": function(name) {
|
||||||
var value;
|
name = NAMESPACE + name;
|
||||||
name = NAMESPACE + name;
|
return delete localStorage[name];
|
||||||
if (value = localStorage[name]) {
|
},
|
||||||
return JSON.parse(value);
|
get: function(name, defaultValue) {
|
||||||
} else {
|
var value;
|
||||||
return defaultValue;
|
name = NAMESPACE + name;
|
||||||
}
|
if (value = localStorage[name]) {
|
||||||
},
|
return JSON.parse(value);
|
||||||
openInTab: function(url) {
|
} else {
|
||||||
return window.open(url, "_blank");
|
return defaultValue;
|
||||||
},
|
|
||||||
set: function(name, value) {
|
|
||||||
name = NAMESPACE + name;
|
|
||||||
return localStorage[name] = JSON.stringify(value);
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
}
|
set: function(name, value) {
|
||||||
|
name = NAMESPACE + name;
|
||||||
|
return localStorage[name] = JSON.stringify(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
for (key in conf) {
|
for (key in conf) {
|
||||||
val = conf[key];
|
val = conf[key];
|
||||||
@ -891,8 +893,11 @@
|
|||||||
if (!(key = keybinds.keyCode(e))) return;
|
if (!(key = keybinds.keyCode(e))) return;
|
||||||
thread = nav.getThread();
|
thread = nav.getThread();
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
case conf.openOptions:
|
||||||
|
if (!$.id('overlay')) options.dialog();
|
||||||
|
break;
|
||||||
case conf.close:
|
case conf.close:
|
||||||
if (o = $('#overlay')) {
|
if (o = $.id('overlay')) {
|
||||||
$.rm(o);
|
$.rm(o);
|
||||||
} else if (qr.el) {
|
} else if (qr.el) {
|
||||||
qr.close();
|
qr.close();
|
||||||
@ -970,7 +975,7 @@
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case conf.unreadCountTo0:
|
case conf.unreadCountTo0:
|
||||||
unread.replies.length = 0;
|
unread.replies = [];
|
||||||
unread.updateTitle();
|
unread.updateTitle();
|
||||||
Favicon.update();
|
Favicon.update();
|
||||||
break;
|
break;
|
||||||
@ -1067,11 +1072,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
open: function(thread, tab) {
|
open: function(thread, tab) {
|
||||||
var id, url;
|
var id, open, url;
|
||||||
id = thread.firstChild.id;
|
id = thread.firstChild.id;
|
||||||
url = "http://boards.4chan.org/" + g.BOARD + "/res/" + id;
|
url = "http://boards.4chan.org/" + g.BOARD + "/res/" + id;
|
||||||
if (tab) {
|
if (tab) {
|
||||||
return $.openInTab(url);
|
open = GM_openInTab || window.open;
|
||||||
|
return open(url, "_blank");
|
||||||
} else {
|
} else {
|
||||||
return location.href = url;
|
return location.href = url;
|
||||||
}
|
}
|
||||||
@ -1303,6 +1309,7 @@
|
|||||||
<div class=error><code>Keybinds</code> are disabled.</div>\
|
<div class=error><code>Keybinds</code> are disabled.</div>\
|
||||||
<table><tbody>\
|
<table><tbody>\
|
||||||
<tr><th>Actions</th><th>Keybinds</th></tr>\
|
<tr><th>Actions</th><th>Keybinds</th></tr>\
|
||||||
|
<tr><td>Open Options</td><td><input name=openOptions></td></tr>\
|
||||||
<tr><td>Close Options or QR</td><td><input name=close></td></tr>\
|
<tr><td>Close Options or QR</td><td><input name=close></td></tr>\
|
||||||
<tr><td>Quick spoiler</td><td><input name=spoiler></td></tr>\
|
<tr><td>Quick spoiler</td><td><input name=spoiler></td></tr>\
|
||||||
<tr><td>Open QR with post number inserted</td><td><input name=openQR></td></tr>\
|
<tr><td>Open QR with post number inserted</td><td><input name=openQR></td></tr>\
|
||||||
@ -1425,10 +1432,10 @@
|
|||||||
time: function() {
|
time: function() {
|
||||||
Time.foo();
|
Time.foo();
|
||||||
Time.date = new Date();
|
Time.date = new Date();
|
||||||
return $('#timePreview').textContent = Time.funk(Time);
|
return $.id('timePreview').textContent = Time.funk(Time);
|
||||||
},
|
},
|
||||||
backlink: function() {
|
backlink: function() {
|
||||||
return $('#backlinkPreview').textContent = conf['backlink'].replace(/%id/, '123456789');
|
return $.id('backlinkPreview').textContent = conf['backlink'].replace(/%id/, '123456789');
|
||||||
},
|
},
|
||||||
favicon: function() {
|
favicon: function() {
|
||||||
Favicon["switch"]();
|
Favicon["switch"]();
|
||||||
@ -2027,7 +2034,7 @@
|
|||||||
input.disabled = true;
|
input.disabled = true;
|
||||||
input.value = 404;
|
input.value = 404;
|
||||||
}
|
}
|
||||||
d.title = d.title.match(/.+-/)[0] + ' 404';
|
d.title = d.title.match(/^.+-/)[0] + ' 404';
|
||||||
g.dead = true;
|
g.dead = true;
|
||||||
Favicon.update();
|
Favicon.update();
|
||||||
return;
|
return;
|
||||||
@ -2040,7 +2047,6 @@
|
|||||||
This saves bandwidth for both the user and the servers, avoid unnecessary computation,
|
This saves bandwidth for both the user and the servers, avoid unnecessary computation,
|
||||||
and won't load images and scripts when parsing the response.
|
and won't load images and scripts when parsing the response.
|
||||||
*/
|
*/
|
||||||
updater.lastModified = this.getResponseHeader('Last-Modified');
|
|
||||||
if (this.status === 304) {
|
if (this.status === 304) {
|
||||||
if (conf['Verbose']) {
|
if (conf['Verbose']) {
|
||||||
updater.count.textContent = '+0';
|
updater.count.textContent = '+0';
|
||||||
@ -2048,6 +2054,7 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
updater.lastModified = this.getResponseHeader('Last-Modified');
|
||||||
body = $.el('body', {
|
body = $.el('body', {
|
||||||
innerHTML: this.responseText
|
innerHTML: this.responseText
|
||||||
});
|
});
|
||||||
@ -2462,7 +2469,9 @@
|
|||||||
},
|
},
|
||||||
toggle: function(e) {
|
toggle: function(e) {
|
||||||
var id;
|
var id;
|
||||||
if (e.shiftKey || e.altKey || e.ctrlKey || e.button !== 0) return;
|
if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
id = this.hash.slice(1);
|
id = this.hash.slice(1);
|
||||||
if (/\binlined\b/.test(this.className)) {
|
if (/\binlined\b/.test(this.className)) {
|
||||||
@ -2474,10 +2483,15 @@
|
|||||||
return this.classList.toggle('inlined');
|
return this.classList.toggle('inlined');
|
||||||
},
|
},
|
||||||
add: function(q, id) {
|
add: function(q, id) {
|
||||||
var el, inline, pathname, root, threadID;
|
var el, i, inline, pathname, root, threadID;
|
||||||
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) {
|
||||||
|
unread.replies.splice(i, 1);
|
||||||
|
unread.updateTitle();
|
||||||
|
Favicon.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']) {
|
||||||
@ -2707,7 +2721,7 @@
|
|||||||
report: function() {
|
report: function() {
|
||||||
var id, set, url;
|
var id, set, url;
|
||||||
url = "http://sys.4chan.org/" + g.BOARD + "/imgboard.php?mode=report&no=" + ($.x('preceding-sibling::input', this).name);
|
url = "http://sys.4chan.org/" + g.BOARD + "/imgboard.php?mode=report&no=" + ($.x('preceding-sibling::input', this).name);
|
||||||
id = "" + NAMESPACE + "popup";
|
id = Date.now();
|
||||||
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200";
|
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200";
|
||||||
return window.open(url, id, set);
|
return window.open(url, id, set);
|
||||||
}
|
}
|
||||||
@ -2824,49 +2838,66 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
redirect = function() {
|
redirect = {
|
||||||
var url;
|
init: function() {
|
||||||
switch (g.BOARD) {
|
var url;
|
||||||
case 'a':
|
url = location.hostname === 'images.4chan.org' ? redirect.image(g.BOARD, location.pathname.split('/')[3]) : /^\d+$/.test(g.THREAD_ID) ? redirect.thread() : void 0;
|
||||||
case 'jp':
|
if (url) return location.href = url;
|
||||||
case 'm':
|
},
|
||||||
case 'tg':
|
image: function(board, filename) {
|
||||||
case 'tv':
|
switch (board) {
|
||||||
url = "http://oldarchive.foolz.us/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
case 'a':
|
||||||
break;
|
case 'jp':
|
||||||
case 'diy':
|
case 'm':
|
||||||
case 'g':
|
case 'tg':
|
||||||
case 'sci':
|
case 'tv':
|
||||||
url = "http://archive.installgentoo.net/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
case 'u':
|
||||||
break;
|
return "http://archive.foolz.us/" + board + "/full_image/" + filename;
|
||||||
case '3':
|
}
|
||||||
case 'adv':
|
},
|
||||||
case 'an':
|
thread: function() {
|
||||||
case 'ck':
|
switch (g.BOARD) {
|
||||||
case 'co':
|
case 'a':
|
||||||
case 'fa':
|
case 'jp':
|
||||||
case 'fit':
|
case 'm':
|
||||||
case 'int':
|
case 'tg':
|
||||||
case 'k':
|
case 'tv':
|
||||||
case 'mu':
|
case 'u':
|
||||||
case 'n':
|
return "http://archive.foolz.us/" + g.BOARD + "/thread/" + g.THREAD_ID + "/";
|
||||||
case 'o':
|
case 'lit':
|
||||||
case 'p':
|
return "http://fuuka.warosu.org/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
||||||
case 'po':
|
case 'diy':
|
||||||
case 'pol':
|
case 'g':
|
||||||
case 'soc':
|
case 'sci':
|
||||||
case 'sp':
|
return "http://archive.installgentoo.net/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
||||||
case 'toy':
|
case '3':
|
||||||
case 'trv':
|
case 'adv':
|
||||||
case 'v':
|
case 'an':
|
||||||
case 'vp':
|
case 'ck':
|
||||||
case 'x':
|
case 'co':
|
||||||
url = "http://archive.no-ip.org/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
case 'fa':
|
||||||
break;
|
case 'fit':
|
||||||
default:
|
case 'int':
|
||||||
url = "http://boards.4chan.org/" + g.BOARD;
|
case 'k':
|
||||||
|
case 'mu':
|
||||||
|
case 'n':
|
||||||
|
case 'o':
|
||||||
|
case 'p':
|
||||||
|
case 'po':
|
||||||
|
case 'pol':
|
||||||
|
case 'r9k':
|
||||||
|
case 'soc':
|
||||||
|
case 'sp':
|
||||||
|
case 'toy':
|
||||||
|
case 'trv':
|
||||||
|
case 'v':
|
||||||
|
case 'vp':
|
||||||
|
case 'x':
|
||||||
|
return "http://archive.no-ip.org/" + g.BOARD + "/thread/" + g.THREAD_ID;
|
||||||
|
default:
|
||||||
|
return "http://boards.4chan.org/" + g.BOARD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return location.href = url;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
imgHover = {
|
imgHover = {
|
||||||
@ -2881,7 +2912,7 @@
|
|||||||
},
|
},
|
||||||
mouseover: function() {
|
mouseover: function() {
|
||||||
ui.el = $.el('img', {
|
ui.el = $.el('img', {
|
||||||
id: 'iHover',
|
id: 'ihover',
|
||||||
src: this.parentNode.href
|
src: this.parentNode.href
|
||||||
});
|
});
|
||||||
return $.add(d.body, ui.el);
|
return $.add(d.body, ui.el);
|
||||||
@ -2915,7 +2946,9 @@
|
|||||||
},
|
},
|
||||||
cb: {
|
cb: {
|
||||||
toggle: function(e) {
|
toggle: function(e) {
|
||||||
if (e.shiftKey || e.altKey || e.ctrlKey || e.button !== 0) return;
|
if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return imgExpand.toggle(this);
|
return imgExpand.toggle(this);
|
||||||
},
|
},
|
||||||
@ -2978,26 +3011,29 @@
|
|||||||
thumb.hidden = false;
|
thumb.hidden = false;
|
||||||
return $.rm(thumb.nextSibling);
|
return $.rm(thumb.nextSibling);
|
||||||
},
|
},
|
||||||
expand: function(thumb) {
|
expand: function(thumb, url) {
|
||||||
var a, filesize, img, max;
|
var a, filesize, img, max;
|
||||||
a = thumb.parentNode;
|
a = thumb.parentNode;
|
||||||
img = $.el('img', {
|
img = $.el('img', {
|
||||||
src: a.href
|
src: url ? url : a.href
|
||||||
});
|
});
|
||||||
if (engine === 'gecko' && a.parentNode.className !== 'op') {
|
if (engine === 'gecko' && a.parentNode.className !== 'op') {
|
||||||
filesize = $.x('preceding-sibling::span[@class="filesize"]', a).textContent;
|
filesize = $.x('preceding-sibling::span[@class="filesize"]', a).textContent;
|
||||||
max = filesize.match(/(\d+)x/);
|
max = filesize.match(/(\d+)x/);
|
||||||
img.style.maxWidth = "" + max[1] + "px";
|
img.style.maxWidth = "" + max[1] + "px";
|
||||||
}
|
}
|
||||||
$.on(img, 'error', imgExpand.error);
|
if (conf['404 Redirect']) $.on(img, 'error', imgExpand.error);
|
||||||
thumb.hidden = true;
|
thumb.hidden = true;
|
||||||
return $.add(a, img);
|
return $.add(a, img);
|
||||||
},
|
},
|
||||||
error: function() {
|
error: function() {
|
||||||
var req, thumb;
|
var req, src, thumb, url;
|
||||||
thumb = this.previousSibling;
|
thumb = this.previousSibling;
|
||||||
imgExpand.contract(thumb);
|
imgExpand.contract(thumb);
|
||||||
if (engine === 'webkit') {
|
src = this.src.split('/');
|
||||||
|
if (url = redirect.image(src[3], src[5])) {
|
||||||
|
return imgExpand.expand(thumb, url);
|
||||||
|
} else if (engine === 'webkit') {
|
||||||
return req = $.ajax(this.src, (function() {
|
return req = $.ajax(this.src, (function() {
|
||||||
if (this.status !== 404) {
|
if (this.status !== 404) {
|
||||||
return setTimeout(imgExpand.retry, 10000, thumb);
|
return setTimeout(imgExpand.retry, 10000, thumb);
|
||||||
@ -3037,43 +3073,42 @@
|
|||||||
return $.prepend(form, controls);
|
return $.prepend(form, controls);
|
||||||
},
|
},
|
||||||
resize: function() {
|
resize: function() {
|
||||||
return imgExpand.style.innerHTML = ".fitheight [md5] + img {max-height:" + d.body.clientHeight + "px;}";
|
return imgExpand.style.innerHTML = ".fitheight img[md5] + img {max-height:" + d.body.clientHeight + "px;}";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Main = {
|
Main = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var cutoff, hiddenThreads, id, now, pathname, temp, timestamp, update, _ref;
|
var cutoff, hiddenThreads, id, now, pathname, temp, timestamp, _ref;
|
||||||
pathname = location.pathname.slice(1).split('/');
|
pathname = location.pathname.slice(1).split('/');
|
||||||
g.BOARD = pathname[0], temp = pathname[1];
|
g.BOARD = pathname[0], temp = pathname[1];
|
||||||
if (temp === 'res') {
|
if (temp === 'res') {
|
||||||
g.REPLY = temp;
|
g.REPLY = true;
|
||||||
g.THREAD_ID = pathname[2];
|
g.THREAD_ID = pathname[2];
|
||||||
} else {
|
} else {
|
||||||
g.PAGENUM = parseInt(temp) || 0;
|
g.PAGENUM = parseInt(temp) || 0;
|
||||||
}
|
}
|
||||||
if (location.hostname === 'sys.4chan.org') {
|
if (location.hostname === 'sys.4chan.org') {
|
||||||
if (/interactive|complete/.test(d.readyState)) {
|
$.onLoad(qr.sys);
|
||||||
qr.sys();
|
return;
|
||||||
} else {
|
}
|
||||||
$.on(d, 'DOMContentLoaded', qr.sys);
|
if (location.hostname === 'images.4chan.org') {
|
||||||
|
if (conf['404 Redirect']) {
|
||||||
|
$.onLoad(function() {
|
||||||
|
if (d.title === '4chan - 404') return redirect.init();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$.onLoad(options.init);
|
||||||
$.on(window, 'message', Main.message);
|
$.on(window, 'message', Main.message);
|
||||||
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) {
|
||||||
update = function() {
|
$.onLoad(function() {
|
||||||
$.off(d, 'DOMContentLoaded', update);
|
|
||||||
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'
|
||||||
}));
|
}));
|
||||||
};
|
});
|
||||||
if (/interactive|complete/.test(d.readyState)) {
|
|
||||||
update();
|
|
||||||
} else {
|
|
||||||
$.on(d, 'DOMContentLoaded', update);
|
|
||||||
}
|
|
||||||
$.set('lastUpdate', now);
|
$.set('lastUpdate', now);
|
||||||
}
|
}
|
||||||
g.hiddenReplies = $.get("hiddenReplies/" + g.BOARD + "/", {});
|
g.hiddenReplies = $.get("hiddenReplies/" + g.BOARD + "/", {});
|
||||||
@ -3107,25 +3142,20 @@
|
|||||||
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 (/interactive|complete/.test(d.readyState)) {
|
return $.onLoad(Main.onLoad);
|
||||||
return Main.onLoad();
|
|
||||||
} else {
|
|
||||||
return $.on(d, 'DOMContentLoaded', Main.onLoad);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLoad: function() {
|
onLoad: function() {
|
||||||
var callback, canPost, form, node, nodes, _i, _j, _len, _len2, _ref;
|
var callback, canPost, form, node, nodes, _i, _j, _len, _len2, _ref;
|
||||||
$.off(d, 'DOMContentLoaded', Main.onLoad);
|
if (conf['404 Redirect'] && d.title === '4chan - 404') {
|
||||||
if (conf['404 Redirect'] && d.title === '4chan - 404' && /^\d+$/.test(g.THREAD_ID)) {
|
redirect.init();
|
||||||
redirect();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!$('#navtopr')) return;
|
if (!$.id('navtopr')) return;
|
||||||
$.addClass(d.body, engine);
|
$.addClass(d.body, engine);
|
||||||
$.addStyle(Main.css);
|
$.addStyle(Main.css);
|
||||||
threading.init();
|
threading.init();
|
||||||
Favicon.init();
|
Favicon.init();
|
||||||
if ((form = $('form[name=post]')) && (canPost = !!$('#recaptcha_response_field'))) {
|
if ((form = $('form[name=post]')) && (canPost = !!$.id('recaptcha_response_field'))) {
|
||||||
Recaptcha.init();
|
Recaptcha.init();
|
||||||
if (g.REPLY && conf['Auto Watch Reply'] && conf['Thread Watcher']) {
|
if (g.REPLY && conf['Auto Watch Reply'] && conf['Thread Watcher']) {
|
||||||
$.on(form, 'submit', function() {
|
$.on(form, 'submit', function() {
|
||||||
@ -3142,10 +3172,10 @@
|
|||||||
if (conf['Quick Reply']) qr.init();
|
if (conf['Quick Reply']) qr.init();
|
||||||
if (conf['Thread Watcher']) watcher.init();
|
if (conf['Thread Watcher']) watcher.init();
|
||||||
if (conf['Keybinds']) keybinds.init();
|
if (conf['Keybinds']) keybinds.init();
|
||||||
if (conf['Reply Navigation'] || conf['Index Navigation']) nav.init();
|
|
||||||
if (g.REPLY) {
|
if (g.REPLY) {
|
||||||
if (conf['Thread Updater']) updater.init();
|
if (conf['Thread Updater']) updater.init();
|
||||||
if (conf['Thread Stats']) threadStats.init();
|
if (conf['Thread Stats']) threadStats.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']) unread.init();
|
||||||
if (conf['Quick Reply'] && conf['Persistent QR'] && canPost) {
|
if (conf['Quick Reply'] && conf['Persistent QR'] && canPost) {
|
||||||
@ -3156,6 +3186,7 @@
|
|||||||
if (conf['Thread Hiding']) threadHiding.init();
|
if (conf['Thread Hiding']) threadHiding.init();
|
||||||
if (conf['Thread Expansion']) expandThread.init();
|
if (conf['Thread Expansion']) expandThread.init();
|
||||||
if (conf['Comment Expansion']) expandComment.init();
|
if (conf['Comment Expansion']) expandComment.init();
|
||||||
|
if (conf['Index Navigation']) nav.init();
|
||||||
}
|
}
|
||||||
nodes = $$('.op, a + table');
|
nodes = $$('.op, a + table');
|
||||||
_ref = g.callbacks;
|
_ref = g.callbacks;
|
||||||
@ -3170,8 +3201,7 @@
|
|||||||
alert(err);
|
alert(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$.on($('form[name=delform]'), 'DOMNodeInserted', Main.node);
|
return $.on($('form[name=delform]'), 'DOMNodeInserted', Main.node);
|
||||||
return options.init();
|
|
||||||
},
|
},
|
||||||
message: function(e) {
|
message: function(e) {
|
||||||
var data, origin;
|
var data, origin;
|
||||||
@ -3213,7 +3243,6 @@
|
|||||||
text-decoration: none;\
|
text-decoration: none;\
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
[hidden], /* Firefox bug: hidden tables are not hidden. fixed in 9.0 */\
|
|
||||||
.thread.stub > :not(.block),\
|
.thread.stub > :not(.block),\
|
||||||
#content > [name=tab]:not(:checked) + div,\
|
#content > [name=tab]:not(:checked) + div,\
|
||||||
#updater:not(:hover) > :not(.move),\
|
#updater:not(:hover) > :not(.move),\
|
||||||
@ -3241,23 +3270,24 @@
|
|||||||
float: left;\
|
float: left;\
|
||||||
pointer-events: none;\
|
pointer-events: none;\
|
||||||
}\
|
}\
|
||||||
[md5], [md5] + img {\
|
img[md5], img[md5] + img {\
|
||||||
pointer-events: all;\
|
pointer-events: all;\
|
||||||
}\
|
}\
|
||||||
.fitwidth [md5] + img {\
|
.fitwidth img[md5] + img {\
|
||||||
max-width: 100%;\
|
max-width: 100%;\
|
||||||
}\
|
}\
|
||||||
.gecko > .fitwidth [md5] + img,\
|
.gecko > .fitwidth img[md5] + img,\
|
||||||
.presto > .fitwidth [md5] + img {\
|
.presto > .fitwidth img[md5] + img {\
|
||||||
width: 100%;\
|
width: 100%;\
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
#qp, #iHover {\
|
#qp, #ihover {\
|
||||||
position: fixed;\
|
position: fixed;\
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
#iHover {\
|
#ihover {\
|
||||||
max-height: 100%;\
|
max-height: 100%;\
|
||||||
|
max-width: 75%;\
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
#navlinks {\
|
#navlinks {\
|
||||||
|
|||||||
4
Cakefile
4
Cakefile
@ -2,7 +2,7 @@
|
|||||||
{exec} = require 'child_process'
|
{exec} = require 'child_process'
|
||||||
fs = require 'fs'
|
fs = require 'fs'
|
||||||
|
|
||||||
VERSION = '2.23.7'
|
VERSION = '2.24.0'
|
||||||
|
|
||||||
HEADER = """
|
HEADER = """
|
||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
@ -13,6 +13,7 @@ HEADER = """
|
|||||||
// @copyright 2009-2011 James Campos <james.r.campos@gmail.com>
|
// @copyright 2009-2011 James Campos <james.r.campos@gmail.com>
|
||||||
// @license MIT; http://en.wikipedia.org/wiki/Mit_license
|
// @license MIT; http://en.wikipedia.org/wiki/Mit_license
|
||||||
// @include http://boards.4chan.org/*
|
// @include http://boards.4chan.org/*
|
||||||
|
// @include http://images.4chan.org/*
|
||||||
// @include http://sys.4chan.org/*
|
// @include http://sys.4chan.org/*
|
||||||
// @run-at document-start
|
// @run-at document-start
|
||||||
// @updateURL https://raw.github.com/MayhemYDG/4chan-x/stable/4chan_x.user.js
|
// @updateURL https://raw.github.com/MayhemYDG/4chan-x/stable/4chan_x.user.js
|
||||||
@ -22,6 +23,7 @@ HEADER = """
|
|||||||
/* LICENSE
|
/* LICENSE
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2011 James Campos <james.r.campos@gmail.com>
|
* Copyright (c) 2009-2011 James Campos <james.r.campos@gmail.com>
|
||||||
|
* Copyright (c) 2012 Nicolas Stepien <stepien.nicolas@gmail.com>
|
||||||
* http://mayhemydg.github.com/4chan-x/
|
* http://mayhemydg.github.com/4chan-x/
|
||||||
* 4chan X #{VERSION}
|
* 4chan X #{VERSION}
|
||||||
*
|
*
|
||||||
|
|||||||
13
changelog
13
changelog
@ -1,4 +1,17 @@
|
|||||||
master
|
master
|
||||||
|
- mayhem
|
||||||
|
fix Open thread in new tab keybind for Safari with Ninjakit
|
||||||
|
fix Index/Reply Navigation working in both cases when only one is enabled
|
||||||
|
|
||||||
|
2.24.0
|
||||||
|
- mayhem
|
||||||
|
redirect 404'd pictures to archives when possible
|
||||||
|
new keybind to open the options: ctrl+o
|
||||||
|
the unread count will decrease when inlining quotes of unread posts
|
||||||
|
the report button can open multiple popups again
|
||||||
|
add omploader to the list of optional flavors (http://ompldr.org/upload?url1=)
|
||||||
|
update archive redirections, add /lit/ and /u/
|
||||||
|
fit horizontally for Image Hover
|
||||||
|
|
||||||
2.23.7
|
2.23.7
|
||||||
- mayhem
|
- mayhem
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
postMessage({version:'2.23.7'},'*');
|
postMessage({version:'2.24.0'},'*');
|
||||||
|
|||||||
163
script.coffee
163
script.coffee
@ -1,7 +1,7 @@
|
|||||||
config =
|
config =
|
||||||
main:
|
main:
|
||||||
Enhancing:
|
Enhancing:
|
||||||
'404 Redirect': [true, 'Redirect dead threads']
|
'404 Redirect': [true, 'Redirect dead threads and images']
|
||||||
'Keybinds': [true, 'Binds actions to keys']
|
'Keybinds': [true, 'Binds actions to keys']
|
||||||
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time']
|
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time']
|
||||||
'Report Button': [true, 'Add report buttons']
|
'Report Button': [true, 'Add report buttons']
|
||||||
@ -64,11 +64,13 @@ config =
|
|||||||
'#http://3d.iqdb.org/?url='
|
'#http://3d.iqdb.org/?url='
|
||||||
'#http://regex.info/exif.cgi?imgurl='
|
'#http://regex.info/exif.cgi?imgurl='
|
||||||
'#http://imgur.com/upload?url='
|
'#http://imgur.com/upload?url='
|
||||||
|
'#http://ompldr.org/upload?url1='
|
||||||
].join '\n'
|
].join '\n'
|
||||||
time: '%m/%d/%y(%a)%H:%M'
|
time: '%m/%d/%y(%a)%H:%M'
|
||||||
backlink: '>>%id'
|
backlink: '>>%id'
|
||||||
favicon: 'ferongr'
|
favicon: 'ferongr'
|
||||||
hotkeys:
|
hotkeys:
|
||||||
|
openOptions: 'ctrl+o'
|
||||||
close: 'Esc'
|
close: 'Esc'
|
||||||
spoiler: 'ctrl+s'
|
spoiler: 'ctrl+s'
|
||||||
openQR: 'i'
|
openQR: 'i'
|
||||||
@ -119,7 +121,7 @@ conf = {}
|
|||||||
) null, config
|
) null, config
|
||||||
|
|
||||||
NAMESPACE = '4chan_x.'
|
NAMESPACE = '4chan_x.'
|
||||||
VERSION = '2.23.7'
|
VERSION = '2.24.0'
|
||||||
SECOND = 1000
|
SECOND = 1000
|
||||||
MINUTE = 60*SECOND
|
MINUTE = 60*SECOND
|
||||||
HOUR = 60*MINUTE
|
HOUR = 60*MINUTE
|
||||||
@ -219,6 +221,13 @@ $.extend = (object, properties) ->
|
|||||||
object
|
object
|
||||||
|
|
||||||
$.extend $,
|
$.extend $,
|
||||||
|
onLoad: (fc) ->
|
||||||
|
if /interactive|complete/.test d.readyState
|
||||||
|
return fc()
|
||||||
|
cb = ->
|
||||||
|
$.off d, 'DOMContentLoaded', cb
|
||||||
|
fc()
|
||||||
|
$.on d, 'DOMContentLoaded', cb
|
||||||
id: (id) ->
|
id: (id) ->
|
||||||
d.getElementById id
|
d.getElementById id
|
||||||
globalEval: (code) ->
|
globalEval: (code) ->
|
||||||
@ -349,8 +358,8 @@ $.extend $,
|
|||||||
|
|
||||||
$.cache.requests = {}
|
$.cache.requests = {}
|
||||||
|
|
||||||
if GM_deleteValue?
|
$.extend $,
|
||||||
$.extend $,
|
if GM_deleteValue?
|
||||||
delete: (name) ->
|
delete: (name) ->
|
||||||
name = NAMESPACE + name
|
name = NAMESPACE + name
|
||||||
GM_deleteValue name
|
GM_deleteValue name
|
||||||
@ -360,15 +369,12 @@ if GM_deleteValue?
|
|||||||
JSON.parse value
|
JSON.parse value
|
||||||
else
|
else
|
||||||
defaultValue
|
defaultValue
|
||||||
openInTab: (url) ->
|
|
||||||
GM_openInTab url
|
|
||||||
set: (name, value) ->
|
set: (name, value) ->
|
||||||
name = NAMESPACE + name
|
name = NAMESPACE + name
|
||||||
# for `storage` events
|
# for `storage` events
|
||||||
localStorage[name] = JSON.stringify value
|
localStorage[name] = JSON.stringify value
|
||||||
GM_setValue name, JSON.stringify value
|
GM_setValue name, JSON.stringify value
|
||||||
else
|
else
|
||||||
$.extend $,
|
|
||||||
delete: (name) ->
|
delete: (name) ->
|
||||||
name = NAMESPACE + name
|
name = NAMESPACE + name
|
||||||
delete localStorage[name]
|
delete localStorage[name]
|
||||||
@ -378,8 +384,6 @@ else
|
|||||||
JSON.parse value
|
JSON.parse value
|
||||||
else
|
else
|
||||||
defaultValue
|
defaultValue
|
||||||
openInTab: (url) ->
|
|
||||||
window.open url, "_blank"
|
|
||||||
set: (name, value) ->
|
set: (name, value) ->
|
||||||
name = NAMESPACE + name
|
name = NAMESPACE + name
|
||||||
localStorage[name] = JSON.stringify value
|
localStorage[name] = JSON.stringify value
|
||||||
@ -647,8 +651,10 @@ keybinds =
|
|||||||
|
|
||||||
thread = nav.getThread()
|
thread = nav.getThread()
|
||||||
switch key
|
switch key
|
||||||
|
when conf.openOptions
|
||||||
|
options.dialog() unless $.id 'overlay'
|
||||||
when conf.close
|
when conf.close
|
||||||
if o = $ '#overlay'
|
if o = $.id 'overlay'
|
||||||
$.rm o
|
$.rm o
|
||||||
else if qr.el
|
else if qr.el
|
||||||
qr.close()
|
qr.close()
|
||||||
@ -707,7 +713,7 @@ keybinds =
|
|||||||
else
|
else
|
||||||
$('.postarea form').submit()
|
$('.postarea form').submit()
|
||||||
when conf.unreadCountTo0
|
when conf.unreadCountTo0
|
||||||
unread.replies.length = 0
|
unread.replies = []
|
||||||
unread.updateTitle()
|
unread.updateTitle()
|
||||||
Favicon.update()
|
Favicon.update()
|
||||||
else
|
else
|
||||||
@ -758,7 +764,8 @@ keybinds =
|
|||||||
id = thread.firstChild.id
|
id = thread.firstChild.id
|
||||||
url = "http://boards.4chan.org/#{g.BOARD}/res/#{id}"
|
url = "http://boards.4chan.org/#{g.BOARD}/res/#{id}"
|
||||||
if tab
|
if tab
|
||||||
$.openInTab url
|
open = GM_openInTab or window.open
|
||||||
|
open url, "_blank"
|
||||||
else
|
else
|
||||||
location.href = url
|
location.href = url
|
||||||
|
|
||||||
@ -964,6 +971,7 @@ options =
|
|||||||
<div class=error><code>Keybinds</code> are disabled.</div>
|
<div class=error><code>Keybinds</code> are disabled.</div>
|
||||||
<table><tbody>
|
<table><tbody>
|
||||||
<tr><th>Actions</th><th>Keybinds</th></tr>
|
<tr><th>Actions</th><th>Keybinds</th></tr>
|
||||||
|
<tr><td>Open Options</td><td><input name=openOptions></td></tr>
|
||||||
<tr><td>Close Options or QR</td><td><input name=close></td></tr>
|
<tr><td>Close Options or QR</td><td><input name=close></td></tr>
|
||||||
<tr><td>Quick spoiler</td><td><input name=spoiler></td></tr>
|
<tr><td>Quick spoiler</td><td><input name=spoiler></td></tr>
|
||||||
<tr><td>Open QR with post number inserted</td><td><input name=openQR></td></tr>
|
<tr><td>Open QR with post number inserted</td><td><input name=openQR></td></tr>
|
||||||
@ -1071,9 +1079,9 @@ options =
|
|||||||
time: ->
|
time: ->
|
||||||
Time.foo()
|
Time.foo()
|
||||||
Time.date = new Date()
|
Time.date = new Date()
|
||||||
$('#timePreview').textContent = Time.funk Time
|
$.id('timePreview').textContent = Time.funk Time
|
||||||
backlink: ->
|
backlink: ->
|
||||||
$('#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']
|
Favicon.update() if g.REPLY and conf['Unread Count']
|
||||||
@ -1626,8 +1634,7 @@ updater =
|
|||||||
for input in $$ '#com_submit'
|
for input in $$ '#com_submit'
|
||||||
input.disabled = true
|
input.disabled = true
|
||||||
input.value = 404
|
input.value = 404
|
||||||
# XXX trailing spaces are trimmed
|
d.title = d.title.match(/^.+-/)[0] + ' 404'
|
||||||
d.title = d.title.match(/.+-/)[0] + ' 404'
|
|
||||||
g.dead = true
|
g.dead = true
|
||||||
Favicon.update()
|
Favicon.update()
|
||||||
return
|
return
|
||||||
@ -1641,12 +1648,12 @@ updater =
|
|||||||
This saves bandwidth for both the user and the servers, avoid unnecessary computation,
|
This saves bandwidth for both the user and the servers, avoid unnecessary computation,
|
||||||
and won't load images and scripts when parsing the response.
|
and won't load images and scripts when parsing the response.
|
||||||
###
|
###
|
||||||
updater.lastModified = @getResponseHeader('Last-Modified')
|
|
||||||
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
|
||||||
|
updater.lastModified = @getResponseHeader 'Last-Modified'
|
||||||
|
|
||||||
body = $.el 'body',
|
body = $.el 'body',
|
||||||
innerHTML: @responseText
|
innerHTML: @responseText
|
||||||
@ -1956,7 +1963,7 @@ quoteInline =
|
|||||||
quote.removeAttribute 'onclick'
|
quote.removeAttribute 'onclick'
|
||||||
$.on quote, 'click', quoteInline.toggle
|
$.on quote, 'click', quoteInline.toggle
|
||||||
toggle: (e) ->
|
toggle: (e) ->
|
||||||
return if e.shiftKey or e.altKey or e.ctrlKey or e.button isnt 0
|
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
id = @hash[1..]
|
id = @hash[1..]
|
||||||
if /\binlined\b/.test @className
|
if /\binlined\b/.test @className
|
||||||
@ -1970,6 +1977,10 @@ 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
|
||||||
|
unread.replies.splice i, 1
|
||||||
|
unread.updateTitle()
|
||||||
|
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']
|
||||||
@ -2113,7 +2124,7 @@ reportButton =
|
|||||||
$.on a, 'click', reportButton.report
|
$.on a, 'click', reportButton.report
|
||||||
report: ->
|
report: ->
|
||||||
url = "http://sys.4chan.org/#{g.BOARD}/imgboard.php?mode=report&no=#{$.x('preceding-sibling::input', @).name}"
|
url = "http://sys.4chan.org/#{g.BOARD}/imgboard.php?mode=report&no=#{$.x('preceding-sibling::input', @).name}"
|
||||||
id = "#{NAMESPACE}popup"
|
id = Date.now()
|
||||||
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200"
|
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200"
|
||||||
window.open url, id, set
|
window.open url, id, set
|
||||||
|
|
||||||
@ -2226,17 +2237,31 @@ Favicon =
|
|||||||
favicon.href = null
|
favicon.href = null
|
||||||
$.replace favicon, clone
|
$.replace favicon, clone
|
||||||
|
|
||||||
redirect = ->
|
redirect =
|
||||||
switch g.BOARD
|
init: ->
|
||||||
when 'a', 'jp', 'm', 'tg', 'tv'
|
url =
|
||||||
url = "http://oldarchive.foolz.us/#{g.BOARD}/thread/#{g.THREAD_ID}"
|
# waiting for https://github.com/FoOlRulez/FoOlFuuka/issues/11
|
||||||
when 'diy', 'g', 'sci'
|
if location.hostname is 'images.4chan.org'
|
||||||
url = "http://archive.installgentoo.net/#{g.BOARD}/thread/#{g.THREAD_ID}"
|
redirect.image g.BOARD, location.pathname.split('/')[3]
|
||||||
when '3', 'adv', 'an', 'ck', 'co', 'fa', 'fit', 'int', 'k', 'mu', 'n', 'o', 'p', 'po', 'pol', 'soc', 'sp', 'toy', 'trv', 'v', 'vp', 'x'
|
else if /^\d+$/.test g.THREAD_ID
|
||||||
url = "http://archive.no-ip.org/#{g.BOARD}/thread/#{g.THREAD_ID}"
|
redirect.thread()
|
||||||
else
|
location.href = url if url
|
||||||
url = "http://boards.4chan.org/#{g.BOARD}"
|
image: (board, filename) -> #board must be given, the image can originate from a cross-quote
|
||||||
location.href = url
|
switch board
|
||||||
|
when 'a', 'jp', 'm', 'tg', 'tv', 'u'
|
||||||
|
"http://archive.foolz.us/#{board}/full_image/#{filename}"
|
||||||
|
thread: ->
|
||||||
|
switch g.BOARD
|
||||||
|
when 'a', 'jp', 'm', 'tg', 'tv', 'u'
|
||||||
|
"http://archive.foolz.us/#{g.BOARD}/thread/#{g.THREAD_ID}/"
|
||||||
|
when 'lit'
|
||||||
|
"http://fuuka.warosu.org/#{g.BOARD}/thread/#{g.THREAD_ID}"
|
||||||
|
when 'diy', 'g', 'sci'
|
||||||
|
"http://archive.installgentoo.net/#{g.BOARD}/thread/#{g.THREAD_ID}"
|
||||||
|
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}"
|
||||||
|
else
|
||||||
|
"http://boards.4chan.org/#{g.BOARD}"
|
||||||
|
|
||||||
imgHover =
|
imgHover =
|
||||||
init: ->
|
init: ->
|
||||||
@ -2247,7 +2272,7 @@ imgHover =
|
|||||||
$.on thumb, 'mouseout', ui.hoverend
|
$.on thumb, 'mouseout', ui.hoverend
|
||||||
mouseover: ->
|
mouseover: ->
|
||||||
ui.el = $.el 'img'
|
ui.el = $.el 'img'
|
||||||
id: 'iHover'
|
id: 'ihover'
|
||||||
src: @parentNode.href
|
src: @parentNode.href
|
||||||
$.add d.body, ui.el
|
$.add d.body, ui.el
|
||||||
|
|
||||||
@ -2272,7 +2297,7 @@ imgExpand =
|
|||||||
imgExpand.expand a.firstChild
|
imgExpand.expand a.firstChild
|
||||||
cb:
|
cb:
|
||||||
toggle: (e) ->
|
toggle: (e) ->
|
||||||
return if e.shiftKey or e.altKey or e.ctrlKey or e.button isnt 0
|
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
imgExpand.toggle @
|
imgExpand.toggle @
|
||||||
all: ->
|
all: ->
|
||||||
@ -2313,23 +2338,26 @@ imgExpand =
|
|||||||
thumb.hidden = false
|
thumb.hidden = false
|
||||||
$.rm thumb.nextSibling
|
$.rm thumb.nextSibling
|
||||||
|
|
||||||
expand: (thumb) ->
|
expand: (thumb, url) ->
|
||||||
a = thumb.parentNode
|
a = thumb.parentNode
|
||||||
img = $.el 'img',
|
img = $.el 'img',
|
||||||
src: a.href
|
src: if url then url else a.href
|
||||||
if engine is 'gecko' and a.parentNode.className isnt 'op'
|
if engine is 'gecko' and a.parentNode.className isnt 'op'
|
||||||
filesize = $.x('preceding-sibling::span[@class="filesize"]', a).textContent
|
filesize = $.x('preceding-sibling::span[@class="filesize"]', a).textContent
|
||||||
max = filesize.match /(\d+)x/
|
max = filesize.match /(\d+)x/
|
||||||
img.style.maxWidth = "#{max[1]}px"
|
img.style.maxWidth = "#{max[1]}px"
|
||||||
$.on img, 'error', imgExpand.error
|
$.on img, 'error', imgExpand.error if conf['404 Redirect']
|
||||||
thumb.hidden = true
|
thumb.hidden = true
|
||||||
$.add a, img
|
$.add a, img
|
||||||
|
|
||||||
error: ->
|
error: ->
|
||||||
thumb = @previousSibling
|
thumb = @previousSibling
|
||||||
imgExpand.contract thumb
|
imgExpand.contract thumb
|
||||||
|
src = @src.split '/'
|
||||||
|
if url = redirect.image src[3], src[5]
|
||||||
|
imgExpand.expand thumb, url
|
||||||
#navigator.online is not x-browser/os yet
|
#navigator.online is not x-browser/os yet
|
||||||
if engine is 'webkit'
|
else if engine is 'webkit'
|
||||||
req = $.ajax @src, (->
|
req = $.ajax @src, (->
|
||||||
setTimeout imgExpand.retry, 10000, thumb if @status isnt 404
|
setTimeout imgExpand.retry, 10000, thumb if @status isnt 404
|
||||||
), type: 'head', event: 'onreadystatechange'
|
), type: 'head', event: 'onreadystatechange'
|
||||||
@ -2361,36 +2389,33 @@ imgExpand =
|
|||||||
$.prepend form, controls
|
$.prepend form, controls
|
||||||
|
|
||||||
resize: ->
|
resize: ->
|
||||||
imgExpand.style.innerHTML = ".fitheight [md5] + img {max-height:#{d.body.clientHeight}px;}"
|
imgExpand.style.innerHTML = ".fitheight img[md5] + img {max-height:#{d.body.clientHeight}px;}"
|
||||||
|
|
||||||
Main =
|
Main =
|
||||||
init: ->
|
init: ->
|
||||||
pathname = location.pathname[1..].split('/')
|
pathname = location.pathname[1..].split('/')
|
||||||
[g.BOARD, temp] = pathname
|
[g.BOARD, temp] = pathname
|
||||||
if temp is 'res'
|
if temp is 'res'
|
||||||
g.REPLY = temp
|
g.REPLY = true
|
||||||
g.THREAD_ID = pathname[2]
|
g.THREAD_ID = pathname[2]
|
||||||
else
|
else
|
||||||
g.PAGENUM = parseInt(temp) or 0
|
g.PAGENUM = parseInt(temp) or 0
|
||||||
|
|
||||||
if location.hostname is 'sys.4chan.org'
|
if location.hostname is 'sys.4chan.org'
|
||||||
if /interactive|complete/.test d.readyState
|
$.onLoad qr.sys
|
||||||
qr.sys()
|
|
||||||
else
|
|
||||||
$.on d, 'DOMContentLoaded', qr.sys
|
|
||||||
return
|
return
|
||||||
|
if location.hostname is 'images.4chan.org'
|
||||||
|
if conf['404 Redirect']
|
||||||
|
$.onLoad -> redirect.init() if d.title is '4chan - 404'
|
||||||
|
return
|
||||||
|
|
||||||
|
$.onLoad options.init
|
||||||
|
|
||||||
$.on window, 'message', Main.message
|
$.on window, 'message', Main.message
|
||||||
|
|
||||||
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
|
||||||
update = ->
|
$.onLoad -> $.add d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js'
|
||||||
$.off d, 'DOMContentLoaded', update
|
|
||||||
$.add d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js'
|
|
||||||
if /interactive|complete/.test d.readyState
|
|
||||||
update()
|
|
||||||
else
|
|
||||||
$.on d, 'DOMContentLoaded', update
|
|
||||||
$.set 'lastUpdate', now
|
$.set 'lastUpdate', now
|
||||||
|
|
||||||
g.hiddenReplies = $.get "hiddenReplies/#{g.BOARD}/", {}
|
g.hiddenReplies = $.get "hiddenReplies/#{g.BOARD}/", {}
|
||||||
@ -2456,17 +2481,13 @@ Main =
|
|||||||
quoteDR.init()
|
quoteDR.init()
|
||||||
|
|
||||||
|
|
||||||
if /interactive|complete/.test d.readyState
|
$.onLoad Main.onLoad
|
||||||
Main.onLoad()
|
|
||||||
else
|
|
||||||
$.on d, 'DOMContentLoaded', Main.onLoad
|
|
||||||
|
|
||||||
onLoad: ->
|
onLoad: ->
|
||||||
$.off d, 'DOMContentLoaded', Main.onLoad
|
if conf['404 Redirect'] and d.title is '4chan - 404'
|
||||||
if conf['404 Redirect'] and d.title is '4chan - 404' and /^\d+$/.test g.THREAD_ID
|
redirect.init()
|
||||||
redirect()
|
|
||||||
return
|
return
|
||||||
if not $ '#navtopr'
|
if not $.id 'navtopr'
|
||||||
return
|
return
|
||||||
$.addClass d.body, engine
|
$.addClass d.body, engine
|
||||||
$.addStyle Main.css
|
$.addStyle Main.css
|
||||||
@ -2474,7 +2495,7 @@ Main =
|
|||||||
Favicon.init()
|
Favicon.init()
|
||||||
|
|
||||||
#recaptcha may be blocked, eg by noscript
|
#recaptcha may be blocked, eg by noscript
|
||||||
if (form = $ 'form[name=post]') and (canPost = !!$ '#recaptcha_response_field')
|
if (form = $ 'form[name=post]') and (canPost = !!$.id 'recaptcha_response_field')
|
||||||
Recaptcha.init()
|
Recaptcha.init()
|
||||||
if g.REPLY and conf['Auto Watch Reply'] and conf['Thread Watcher']
|
if g.REPLY and conf['Auto Watch Reply'] and conf['Thread Watcher']
|
||||||
$.on form, 'submit', -> if $('img.favicon').src is Favicon.empty
|
$.on form, 'submit', -> if $('img.favicon').src is Favicon.empty
|
||||||
@ -2502,9 +2523,6 @@ Main =
|
|||||||
if conf['Keybinds']
|
if conf['Keybinds']
|
||||||
keybinds.init()
|
keybinds.init()
|
||||||
|
|
||||||
if conf['Reply Navigation'] or conf['Index Navigation']
|
|
||||||
nav.init()
|
|
||||||
|
|
||||||
if g.REPLY
|
if g.REPLY
|
||||||
if conf['Thread Updater']
|
if conf['Thread Updater']
|
||||||
updater.init()
|
updater.init()
|
||||||
@ -2512,6 +2530,9 @@ Main =
|
|||||||
if conf['Thread Stats']
|
if conf['Thread Stats']
|
||||||
threadStats.init()
|
threadStats.init()
|
||||||
|
|
||||||
|
if conf['Reply Navigation']
|
||||||
|
nav.init()
|
||||||
|
|
||||||
if conf['Post in Title']
|
if conf['Post in Title']
|
||||||
titlePost.init()
|
titlePost.init()
|
||||||
|
|
||||||
@ -2533,6 +2554,9 @@ Main =
|
|||||||
if conf['Comment Expansion']
|
if conf['Comment Expansion']
|
||||||
expandComment.init()
|
expandComment.init()
|
||||||
|
|
||||||
|
if conf['Index Navigation']
|
||||||
|
nav.init()
|
||||||
|
|
||||||
|
|
||||||
nodes = $$ '.op, a + table'
|
nodes = $$ '.op, a + table'
|
||||||
for callback in g.callbacks
|
for callback in g.callbacks
|
||||||
@ -2542,7 +2566,6 @@ Main =
|
|||||||
catch err
|
catch err
|
||||||
alert err
|
alert err
|
||||||
$.on $('form[name=delform]'), 'DOMNodeInserted', Main.node
|
$.on $('form[name=delform]'), 'DOMNodeInserted', Main.node
|
||||||
options.init()
|
|
||||||
|
|
||||||
message: (e) ->
|
message: (e) ->
|
||||||
{origin, data} = e
|
{origin, data} = e
|
||||||
@ -2575,7 +2598,6 @@ Main =
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
[hidden], /* Firefox bug: hidden tables are not hidden. fixed in 9.0 */
|
|
||||||
.thread.stub > :not(.block),
|
.thread.stub > :not(.block),
|
||||||
#content > [name=tab]:not(:checked) + div,
|
#content > [name=tab]:not(:checked) + div,
|
||||||
#updater:not(:hover) > :not(.move),
|
#updater:not(:hover) > :not(.move),
|
||||||
@ -2603,23 +2625,24 @@ Main =
|
|||||||
float: left;
|
float: left;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
[md5], [md5] + img {
|
img[md5], img[md5] + img {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
.fitwidth [md5] + img {
|
.fitwidth img[md5] + img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
.gecko > .fitwidth [md5] + img,
|
.gecko > .fitwidth img[md5] + img,
|
||||||
.presto > .fitwidth [md5] + img {
|
.presto > .fitwidth img[md5] + img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qp, #iHover {
|
#qp, #ihover {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#iHover {
|
#ihover {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
max-width: 75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#navlinks {
|
#navlinks {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user