diff --git a/LICENSE b/LICENSE
index 23d30e4e0..72ad7e59c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,5 @@
/*
-* 4chan X - Version 1.2.13 - 2013-05-29
+* 4chan X - Version 1.2.13 - 2013-06-14
*
* Licensed under the MIT license.
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
diff --git a/builds/4chan-X.js b/builds/4chan-X.js
index 75255cfbb..09a2ab588 100644
--- a/builds/4chan-X.js
+++ b/builds/4chan-X.js
@@ -19,7 +19,7 @@
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC
// ==/UserScript==
/*
-* 4chan X - Version 1.2.13 - 2013-05-29
+* 4chan X - Version 1.2.13 - 2013-06-14
*
* Licensed under the MIT license.
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
@@ -113,7 +113,8 @@
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
Config = {
main: {
@@ -292,6 +293,7 @@
'Open thread tab': ['Shift+o', 'Open thread in new tab.'],
'Next reply': ['j', 'Select next reply.'],
'Previous reply': ['k', 'Select previous reply.'],
+ 'Deselect reply': ['Shift+d', 'Deselect reply.'],
'Hide': ['x', 'Hide thread.']
},
updater: {
@@ -1286,9 +1288,9 @@
var boardID, postID, threadID, val, _base, _base1, _base2;
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val;
- if (postID) {
+ if (postID !== void 0) {
((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val;
- } else if (threadID) {
+ } else if (threadID !== void 0) {
((_base2 = this.data.boards)[boardID] || (_base2[boardID] = {}))[threadID] = val;
} else {
this.data.boards[boardID] = val;
@@ -1326,13 +1328,9 @@
_ref = this.data.boards;
for (boardID in _ref) {
val = _ref[boardID];
- if (typeof this.data.boards[boardID] !== 'object') {
- delete this.data.boards[boardID];
- } else {
- this.deleteIfEmpty({
- boardID: boardID
- });
- }
+ this.deleteIfEmpty({
+ boardID: boardID
+ });
}
now = Date.now();
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
@@ -1779,7 +1777,7 @@
hashScroll: function() {
var hash, post;
- if (!((hash = this.location.hash) && (post = $.id(hash.slice(1))))) {
+ if (!((hash = this.location.hash.slice(1)) && (post = $.id(hash)))) {
return;
}
if ((Get.postFromRoot(post)).isHidden) {
@@ -1877,7 +1875,7 @@
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
*/
- var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileHtml, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
+ var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file;
isOP = postID === threadID;
@@ -1915,7 +1913,7 @@
}
flag = flagCode ? (" ") : '';
if (file != null ? file.isDeleted : void 0) {
- fileHtml = isOP ? ("
") + "
") + "
") + "
") + "';
case '[/code]':
@@ -2704,10 +2702,6 @@
}
for (key in Config.filter) {
this.filters[key] = [];
- if (Conf[key] === void 0) {
- $["delete"](key);
- continue;
- }
_ref = Conf[key].split('\n');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
filter = _ref[_i];
@@ -5602,7 +5596,7 @@
}), this.ready.bind(this));
},
ready: function() {
- var MutationObserver, imgContainer, input, observer, setLifetime,
+ var imgContainer, input, observer, setLifetime,
_this = this;
setLifetime = function(e) {
@@ -5628,7 +5622,7 @@
img: imgContainer.firstChild,
input: input
};
- if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) {
+ if (window.MutationObserver) {
observer = new MutationObserver(this.load.bind(this));
observer.observe(this.nodes.challenge, {
childList: true
@@ -7054,7 +7048,12 @@
return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning');
},
fetchPage: function() {
- if (ThreadStats.thread.isDead || !Conf["Page Count in Stats"]) {
+ if (!Conf["Page Count in Stats"]) {
+ return;
+ }
+ if (ThreadStats.thread.isDead) {
+ ThreadStats.pageCountEl.textContent = 'Dead';
+ $.addClass(ThreadStats.pageCountEl, 'warning');
return;
}
setTimeout(ThreadStats.fetchPage, 2 * $.MINUTE);
@@ -7395,7 +7394,7 @@
return $.after(root, [$.tn(' '), icon]);
},
parse: function(postObjects) {
- var ID, OP, count, deletedFiles, deletedPosts, files, index, key, node, num, post, postObject, posts, root, scroll, _i, _len, _ref;
+ var ID, OP, count, deletedFiles, deletedPosts, files, index, length, node, num, post, postObject, posts, scroll, sendEvent, threadID, _i, _len, _ref;
OP = postObjects[0];
Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler;
@@ -7436,67 +7435,53 @@
post.kill(true);
deletedFiles.push(post);
}
- if (ThreadUpdater.postID && ThreadUpdater.postID === ID) {
- ThreadUpdater.foundPost = true;
- }
}
+ sendEvent = function() {
+ return $.event('ThreadUpdate', {
+ 404: false,
+ thread: ThreadUpdater.thread,
+ newPosts: posts,
+ deletedPosts: deletedPosts,
+ deletedFiles: deletedFiles,
+ postCount: OP.replies + 1,
+ fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead)
+ });
+ };
if (!count) {
ThreadUpdater.set('status', null, null);
ThreadUpdater.outdateCount++;
- } else {
- ThreadUpdater.set('status', "+" + count, 'new');
- ThreadUpdater.outdateCount = 0;
- if (Conf['Beep'] && d.hidden && Unread.posts && !Unread.posts.length) {
- if (!ThreadUpdater.audio) {
- ThreadUpdater.audio = $.el('audio', {
- src: ThreadUpdater.beep
- });
- }
- ThreadUpdater.audio.play();
- }
- ThreadUpdater.lastPost = posts[count - 1].ID;
- Main.callbackNodes(Post, posts);
- scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25;
- for (key in posts) {
- post = posts[key];
- if (!posts.hasOwnProperty(key)) {
- continue;
- }
- root = post.nodes.root;
- if (post.cb) {
- if (!post.cb.call(post)) {
- $.add(ThreadUpdater.root, root);
- }
- } else {
- $.add(ThreadUpdater.root, root);
- }
- }
- if (scroll) {
- if (Conf['Bottom Scroll']) {
- doc.scrollTop = d.body.clientHeight;
- } else {
- if (root) {
- Header.scrollToPost(root);
- }
- }
- }
- $.queueTask(function() {
- var length, threadID;
-
- threadID = ThreadUpdater.thread.ID;
- length = $$('.thread > .postContainer', ThreadUpdater.root).length;
- return Fourchan.parseThread(threadID, length - count, length);
- });
+ sendEvent();
+ return;
+ }
+ ThreadUpdater.set('status', "+" + count, 'new');
+ ThreadUpdater.outdateCount = 0;
+ if (Conf['Beep'] && d.hidden && Unread.posts && !Unread.posts.length) {
+ if (!ThreadUpdater.audio) {
+ ThreadUpdater.audio = $.el('audio', {
+ src: ThreadUpdater.beep
+ });
+ }
+ ThreadUpdater.audio.play();
+ }
+ ThreadUpdater.lastPost = posts[count - 1].ID;
+ Main.callbackNodes(Post, posts);
+ scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25;
+ $.add(ThreadUpdater.root, nodes);
+ sendEvent();
+ if (scroll) {
+ if (Conf['Bottom Scroll']) {
+ doc.scrollTop = d.body.clientHeight;
+ } else {
+ Header.scrollToPost(nodes[0]);
+ }
+ }
+ threadID = ThreadUpdater.thread.ID;
+ length = $$('.thread > .postContainer', ThreadUpdater.root).length;
+ if (Conf['Enable 4chan\'s Extension']) {
+ return $.globalEval("Parser.parseThread(" + threadID + ", " + (-count) + ")");
+ } else {
+ return Fourchan.parseThread(threadID, length - count, length);
}
- return $.event('ThreadUpdate', {
- 404: false,
- thread: ThreadUpdater.thread,
- newPosts: posts,
- deletedPosts: deletedPosts,
- deletedFiles: deletedFiles,
- postCount: OP.replies + 1,
- fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead)
- });
}
};
@@ -7708,7 +7693,7 @@
}
},
scroll: function() {
- var hash, post, posts, prevID, root;
+ var checkPosition, hash, onload, post, posts, prevID, root;
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
return;
@@ -7725,11 +7710,27 @@
break;
}
}
- root.scrollIntoView(false);
- return;
+ onload = function() {
+ if (checkPosition(root)) {
+ return root.scrollIntoView(false);
+ }
+ };
+ } else {
+ posts = Object.keys(Unread.thread.posts);
+ root = Unread.thread.posts[posts[posts.length - 1]].nodes.root;
+ onload = function() {
+ if (checkPosition(root)) {
+ return Header.scrollToPost(root);
+ }
+ };
}
- posts = Object.keys(Unread.thread.posts);
- return Header.scrollToPost(Unread.thread.posts[posts[posts.length - 1]].nodes.root);
+ checkPosition = function(target) {
+ var height, top, _ref;
+
+ _ref = target.getBoundingClientRect(), top = _ref.top, height = _ref.height;
+ return top + height - doc.clientHeight > 0;
+ };
+ return $.on(window, 'load', onload);
},
sync: function() {
var lastReadPost;
@@ -7748,11 +7749,11 @@
Unread.setLine();
return Unread.update();
},
- addPosts: function(newPosts) {
- var ID, data, post, _i, _len;
+ addPosts: function(posts) {
+ var ID, data, post, _i, _len, _ref;
- for (_i = 0, _len = newPosts.length; _i < _len; _i++) {
- post = newPosts[_i];
+ for (_i = 0, _len = posts.length; _i < _len; _i++) {
+ post = posts[_i];
ID = post.ID;
if (ID <= Unread.lastReadPost || post.isHidden) {
continue;
@@ -7771,7 +7772,7 @@
Unread.addPostQuotingYou(post);
}
if (Conf['Unread Line']) {
- Unread.setLine(newPosts.contains(Unread.posts[0]));
+ Unread.setLine((_ref = Unread.posts[0], __indexOf.call(posts, _ref) >= 0));
}
Unread.read();
return Unread.update();
@@ -8022,8 +8023,8 @@
'http': true,
'https': true,
'software': 'fuuka',
- 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'tg', 'vr'],
- 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'vr']
+ 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'],
+ 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr']
}
},
to: function(dest, data) {
@@ -8093,7 +8094,7 @@
return $.on(d, '4chanXInitFinished', this.setup);
},
setup: function() {
- var btn, entry, items, psa;
+ var btn, entry, psa;
$.off(d, '4chanXInitFinished', PSAHiding.setup);
if (!(psa = $.id('globalMessage'))) {
@@ -8121,21 +8122,10 @@
href: 'javascript:;'
});
$.on(btn, 'click', PSAHiding.toggle);
- items = {
- hiddenPSA: 0,
- hiddenPSAs: null
- };
- $.get(items, function(_arg) {
- var hiddenPSA, hiddenPSAs;
+ $.get('hiddenPSA', 0, function(_arg) {
+ var hiddenPSA;
- hiddenPSA = _arg.hiddenPSA, hiddenPSAs = _arg.hiddenPSAs;
- if (hiddenPSAs) {
- $["delete"]('hiddenPSAs');
- if (hiddenPSAs.contains(psa.textContent.replace(/\W+/g, '').toLowerCase())) {
- hiddenPSA = +$.id('globalMessage').dataset.utc;
- $.set('hiddenPSA', hiddenPSA);
- }
- }
+ hiddenPSA = _arg.hiddenPSA;
PSAHiding.sync(hiddenPSA);
$.before(psa, btn);
return $.rmClass(doc, 'hide-announcement');
@@ -8256,7 +8246,7 @@
var rgb;
rgb = IDColor.ids[this] || IDColor.compute(this);
- return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black;" : "white; border-radius: 3px; padding: 0px 2px;");
+ return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black; border-radius: 3px; padding: 0px 2px;" : "white; border-radius: 3px; padding: 0px 2px;");
},
hash: function(str) {
var i, j, msg;
@@ -8708,7 +8698,7 @@
}
board = g.BOARD.ID;
if (board === 'g') {
- $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML.replace(/\\s/g, ' '));\n}, false);");
+ $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML);\n}, false);");
Post.prototype.callbacks.push({
name: 'Parse /g/ code',
cb: this.code
@@ -8932,6 +8922,9 @@
case Conf['Previous reply']:
Keybinds.hl(-1, threadRoot);
break;
+ case Conf['Deselect reply']:
+ Keybinds.hl(0, threadRoot);
+ break;
case Conf['Hide']:
if (g.VIEW === 'index') {
ThreadHiding.toggle(thread);
@@ -9042,6 +9035,12 @@
hl: function(delta, thread) {
var axe, headRect, next, postEl, rect, replies, reply, root, topMargin, _i, _len;
+ if (!delta) {
+ if (postEl = $('.reply.highlight', thread)) {
+ $.rmClass(postEl, 'highlight');
+ }
+ return;
+ }
if (Conf['Fixed Header'] && Conf['Bottom header']) {
topMargin = 0;
} else {
@@ -9293,22 +9292,23 @@
Report = {
init: function() {
- if (!/report/.test(location.search)) {
+ if (!(/report/.test(location.search) && d.cookie.indexOf('pass_enabled=1') === -1)) {
return;
}
- return $.ready(this.ready);
+ return $.asap((function() {
+ return $.id('recaptcha_response_field');
+ }), Report.ready);
},
ready: function() {
- var field, form;
+ var field;
- form = $('form');
field = $.id('recaptcha_response_field');
$.on(field, 'keydown', function(e) {
if (e.keyCode === 8 && !field.value) {
return $.globalEval('Recaptcha.reload("t")');
}
});
- return $.on(form, 'submit', function(e) {
+ return $.on($('form'), 'submit', function(e) {
var response;
e.preventDefault();
@@ -9316,7 +9316,7 @@
if (!/\s/.test(response)) {
field.value = "" + response + " " + response;
}
- return form.submit();
+ return this.submit();
});
}
};
@@ -10217,16 +10217,17 @@
return;
case 'images.4chan.org':
$.ready(function() {
- var url;
+ var URL;
if (Conf['404 Redirect'] && d.title === '4chan - 404 Not Found') {
Redirect.init();
- url = Redirect.to('file', {
- boardID: pathname[1],
- filename: pathname[3]
+ pathname = location.pathname.split('/');
+ URL = Redirect.to('file', {
+ boardID: g.BOARD.ID,
+ filename: pathname[pathname.length - 1]
});
- if (url) {
- return location.href = url;
+ if (URL) {
+ return location.replace(URL);
}
}
});
@@ -10309,7 +10310,7 @@
return $.ready(Main.initReady);
},
initStyle: function() {
- var MutationObserver, mainStyleSheet, observer, setStyle, style, styleSheets, _ref;
+ var mainStyleSheet, observer, setStyle, style, styleSheets, _ref;
$.off(d, '4chanMainInit', Main.initStyle);
if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) {
@@ -10346,7 +10347,7 @@
if (!mainStyleSheet) {
return;
}
- if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) {
+ if (window.MutationObserver) {
observer = new MutationObserver(setStyle);
return observer.observe(mainStyleSheet, {
attributes: true,
@@ -10366,7 +10367,7 @@
threadID: g.THREADID,
postID: +location.hash.match(/\d+/)
});
- location.href = href || ("/" + g.BOARD + "/");
+ location.replace(href || ("/" + g.BOARD + "/"));
}
return;
}
diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js
index 0517cec01..c94ebd736 100644
--- a/builds/4chan-X.user.js
+++ b/builds/4chan-X.user.js
@@ -19,7 +19,7 @@
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC
// ==/UserScript==
/*
-* 4chan X - Version 1.2.13 - 2013-05-29
+* 4chan X - Version 1.2.13 - 2013-06-14
*
* Licensed under the MIT license.
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
@@ -113,7 +113,8 @@
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
Config = {
main: {
@@ -293,6 +294,7 @@
'Open thread tab': ['Shift+o', 'Open thread in new tab.'],
'Next reply': ['j', 'Select next reply.'],
'Previous reply': ['k', 'Select previous reply.'],
+ 'Deselect reply': ['Shift+d', 'Deselect reply.'],
'Hide': ['x', 'Hide thread.']
},
updater: {
@@ -1282,9 +1284,9 @@
var boardID, postID, threadID, val, _base, _base1, _base2;
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val;
- if (postID) {
+ if (postID !== void 0) {
((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val;
- } else if (threadID) {
+ } else if (threadID !== void 0) {
((_base2 = this.data.boards)[boardID] || (_base2[boardID] = {}))[threadID] = val;
} else {
this.data.boards[boardID] = val;
@@ -1322,13 +1324,9 @@
_ref = this.data.boards;
for (boardID in _ref) {
val = _ref[boardID];
- if (typeof this.data.boards[boardID] !== 'object') {
- delete this.data.boards[boardID];
- } else {
- this.deleteIfEmpty({
- boardID: boardID
- });
- }
+ this.deleteIfEmpty({
+ boardID: boardID
+ });
}
now = Date.now();
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
@@ -1775,7 +1773,7 @@
hashScroll: function() {
var hash, post;
- if (!((hash = this.location.hash) && (post = $.id(hash.slice(1))))) {
+ if (!((hash = this.location.hash.slice(1)) && (post = $.id(hash)))) {
return;
}
if ((Get.postFromRoot(post)).isHidden) {
@@ -1873,7 +1871,7 @@
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
*/
- var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileHtml, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
+ var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file;
isOP = postID === threadID;
@@ -1911,7 +1909,7 @@
}
flag = flagCode ? ("
") : '';
if (file != null ? file.isDeleted : void 0) {
- fileHtml = isOP ? ("") + ("
") + "" : ("") + ("
") + "";
+ fileHTML = isOP ? ("") + ("
") + "" : ("") + ("
") + "";
} else if (file) {
ext = file.name.slice(-3);
if (!file.twidth && !file.theight && ext === 'gif') {
@@ -2166,9 +2164,9 @@
case '[/b]':
return '';
case '[spoiler]':
- return '';
+ return '';
case '[/spoiler]':
- return '';
+ return '';
case '[code]':
return '';
case '[/code]':
@@ -2700,10 +2698,6 @@
}
for (key in Config.filter) {
this.filters[key] = [];
- if (Conf[key] === void 0) {
- $["delete"](key);
- continue;
- }
_ref = Conf[key].split('\n');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
filter = _ref[_i];
@@ -5592,7 +5586,7 @@
}), this.ready.bind(this));
},
ready: function() {
- var MutationObserver, imgContainer, input, observer, setLifetime,
+ var imgContainer, input, observer, setLifetime,
_this = this;
setLifetime = function(e) {
@@ -5618,7 +5612,7 @@
img: imgContainer.firstChild,
input: input
};
- if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) {
+ if (window.MutationObserver) {
observer = new MutationObserver(this.load.bind(this));
observer.observe(this.nodes.challenge, {
childList: true
@@ -7048,7 +7042,12 @@
return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning');
},
fetchPage: function() {
- if (ThreadStats.thread.isDead || !Conf["Page Count in Stats"]) {
+ if (!Conf["Page Count in Stats"]) {
+ return;
+ }
+ if (ThreadStats.thread.isDead) {
+ ThreadStats.pageCountEl.textContent = 'Dead';
+ $.addClass(ThreadStats.pageCountEl, 'warning');
return;
}
setTimeout(ThreadStats.fetchPage, 2 * $.MINUTE);
@@ -7389,7 +7388,7 @@
return $.after(root, [$.tn(' '), icon]);
},
parse: function(postObjects) {
- var ID, OP, count, deletedFiles, deletedPosts, files, index, key, node, num, post, postObject, posts, root, scroll, _i, _len, _ref;
+ var ID, OP, count, deletedFiles, deletedPosts, files, index, length, node, num, post, postObject, posts, scroll, sendEvent, threadID, _i, _len, _ref;
OP = postObjects[0];
Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler;
@@ -7430,67 +7429,53 @@
post.kill(true);
deletedFiles.push(post);
}
- if (ThreadUpdater.postID && ThreadUpdater.postID === ID) {
- ThreadUpdater.foundPost = true;
- }
}
+ sendEvent = function() {
+ return $.event('ThreadUpdate', {
+ 404: false,
+ thread: ThreadUpdater.thread,
+ newPosts: posts,
+ deletedPosts: deletedPosts,
+ deletedFiles: deletedFiles,
+ postCount: OP.replies + 1,
+ fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead)
+ });
+ };
if (!count) {
ThreadUpdater.set('status', null, null);
ThreadUpdater.outdateCount++;
- } else {
- ThreadUpdater.set('status', "+" + count, 'new');
- ThreadUpdater.outdateCount = 0;
- if (Conf['Beep'] && d.hidden && Unread.posts && !Unread.posts.length) {
- if (!ThreadUpdater.audio) {
- ThreadUpdater.audio = $.el('audio', {
- src: ThreadUpdater.beep
- });
- }
- ThreadUpdater.audio.play();
- }
- ThreadUpdater.lastPost = posts[count - 1].ID;
- Main.callbackNodes(Post, posts);
- scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25;
- for (key in posts) {
- post = posts[key];
- if (!posts.hasOwnProperty(key)) {
- continue;
- }
- root = post.nodes.root;
- if (post.cb) {
- if (!post.cb.call(post)) {
- $.add(ThreadUpdater.root, root);
- }
- } else {
- $.add(ThreadUpdater.root, root);
- }
- }
- if (scroll) {
- if (Conf['Bottom Scroll']) {
- doc.scrollTop = d.body.clientHeight;
- } else {
- if (root) {
- Header.scrollToPost(root);
- }
- }
- }
- $.queueTask(function() {
- var length, threadID;
-
- threadID = ThreadUpdater.thread.ID;
- length = $$('.thread > .postContainer', ThreadUpdater.root).length;
- return Fourchan.parseThread(threadID, length - count, length);
- });
+ sendEvent();
+ return;
+ }
+ ThreadUpdater.set('status', "+" + count, 'new');
+ ThreadUpdater.outdateCount = 0;
+ if (Conf['Beep'] && d.hidden && Unread.posts && !Unread.posts.length) {
+ if (!ThreadUpdater.audio) {
+ ThreadUpdater.audio = $.el('audio', {
+ src: ThreadUpdater.beep
+ });
+ }
+ ThreadUpdater.audio.play();
+ }
+ ThreadUpdater.lastPost = posts[count - 1].ID;
+ Main.callbackNodes(Post, posts);
+ scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25;
+ $.add(ThreadUpdater.root, nodes);
+ sendEvent();
+ if (scroll) {
+ if (Conf['Bottom Scroll']) {
+ doc.scrollTop = d.body.clientHeight;
+ } else {
+ Header.scrollToPost(nodes[0]);
+ }
+ }
+ threadID = ThreadUpdater.thread.ID;
+ length = $$('.thread > .postContainer', ThreadUpdater.root).length;
+ if (Conf['Enable 4chan\'s Extension']) {
+ return $.globalEval("Parser.parseThread(" + threadID + ", " + (-count) + ")");
+ } else {
+ return Fourchan.parseThread(threadID, length - count, length);
}
- return $.event('ThreadUpdate', {
- 404: false,
- thread: ThreadUpdater.thread,
- newPosts: posts,
- deletedPosts: deletedPosts,
- deletedFiles: deletedFiles,
- postCount: OP.replies + 1,
- fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead)
- });
}
};
@@ -7702,7 +7687,7 @@
}
},
scroll: function() {
- var hash, post, posts, prevID, root;
+ var checkPosition, hash, onload, post, posts, prevID, root;
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
return;
@@ -7719,11 +7704,27 @@
break;
}
}
- root.scrollIntoView(false);
- return;
+ onload = function() {
+ if (checkPosition(root)) {
+ return root.scrollIntoView(false);
+ }
+ };
+ } else {
+ posts = Object.keys(Unread.thread.posts);
+ root = Unread.thread.posts[posts[posts.length - 1]].nodes.root;
+ onload = function() {
+ if (checkPosition(root)) {
+ return Header.scrollToPost(root);
+ }
+ };
}
- posts = Object.keys(Unread.thread.posts);
- return Header.scrollToPost(Unread.thread.posts[posts[posts.length - 1]].nodes.root);
+ checkPosition = function(target) {
+ var height, top, _ref;
+
+ _ref = target.getBoundingClientRect(), top = _ref.top, height = _ref.height;
+ return top + height - doc.clientHeight > 0;
+ };
+ return $.on(window, 'load', onload);
},
sync: function() {
var lastReadPost;
@@ -7742,11 +7743,11 @@
Unread.setLine();
return Unread.update();
},
- addPosts: function(newPosts) {
- var ID, data, post, _i, _len;
+ addPosts: function(posts) {
+ var ID, data, post, _i, _len, _ref;
- for (_i = 0, _len = newPosts.length; _i < _len; _i++) {
- post = newPosts[_i];
+ for (_i = 0, _len = posts.length; _i < _len; _i++) {
+ post = posts[_i];
ID = post.ID;
if (ID <= Unread.lastReadPost || post.isHidden) {
continue;
@@ -7765,7 +7766,7 @@
Unread.addPostQuotingYou(post);
}
if (Conf['Unread Line']) {
- Unread.setLine(newPosts.contains(Unread.posts[0]));
+ Unread.setLine((_ref = Unread.posts[0], __indexOf.call(posts, _ref) >= 0));
}
Unread.read();
return Unread.update();
@@ -8016,8 +8017,8 @@
'http': true,
'https': true,
'software': 'fuuka',
- 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'tg', 'vr'],
- 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'vr']
+ 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'],
+ 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr']
}
},
to: function(dest, data) {
@@ -8087,7 +8088,7 @@
return $.on(d, '4chanXInitFinished', this.setup);
},
setup: function() {
- var btn, entry, items, psa;
+ var btn, entry, psa;
$.off(d, '4chanXInitFinished', PSAHiding.setup);
if (!(psa = $.id('globalMessage'))) {
@@ -8115,21 +8116,10 @@
href: 'javascript:;'
});
$.on(btn, 'click', PSAHiding.toggle);
- items = {
- hiddenPSA: 0,
- hiddenPSAs: null
- };
- $.get(items, function(_arg) {
- var hiddenPSA, hiddenPSAs;
+ $.get('hiddenPSA', 0, function(_arg) {
+ var hiddenPSA;
- hiddenPSA = _arg.hiddenPSA, hiddenPSAs = _arg.hiddenPSAs;
- if (hiddenPSAs) {
- $["delete"]('hiddenPSAs');
- if (hiddenPSAs.contains(psa.textContent.replace(/\W+/g, '').toLowerCase())) {
- hiddenPSA = +$.id('globalMessage').dataset.utc;
- $.set('hiddenPSA', hiddenPSA);
- }
- }
+ hiddenPSA = _arg.hiddenPSA;
PSAHiding.sync(hiddenPSA);
$.before(psa, btn);
return $.rmClass(doc, 'hide-announcement');
@@ -8250,7 +8240,7 @@
var rgb;
rgb = IDColor.ids[this] || IDColor.compute(this);
- return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black;" : "white; border-radius: 3px; padding: 0px 2px;");
+ return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black; border-radius: 3px; padding: 0px 2px;" : "white; border-radius: 3px; padding: 0px 2px;");
},
hash: function(str) {
var i, j, msg;
@@ -8702,7 +8692,7 @@
}
board = g.BOARD.ID;
if (board === 'g') {
- $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML.replace(/\\s/g, ' '));\n}, false);");
+ $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML);\n}, false);");
Post.prototype.callbacks.push({
name: 'Parse /g/ code',
cb: this.code
@@ -8926,6 +8916,9 @@
case Conf['Previous reply']:
Keybinds.hl(-1, threadRoot);
break;
+ case Conf['Deselect reply']:
+ Keybinds.hl(0, threadRoot);
+ break;
case Conf['Hide']:
if (g.VIEW === 'index') {
ThreadHiding.toggle(thread);
@@ -9036,6 +9029,12 @@
hl: function(delta, thread) {
var axe, headRect, next, postEl, rect, replies, reply, root, topMargin, _i, _len;
+ if (!delta) {
+ if (postEl = $('.reply.highlight', thread)) {
+ $.rmClass(postEl, 'highlight');
+ }
+ return;
+ }
if (Conf['Fixed Header'] && Conf['Bottom header']) {
topMargin = 0;
} else {
@@ -9287,22 +9286,23 @@
Report = {
init: function() {
- if (!/report/.test(location.search)) {
+ if (!(/report/.test(location.search) && d.cookie.indexOf('pass_enabled=1') === -1)) {
return;
}
- return $.ready(this.ready);
+ return $.asap((function() {
+ return $.id('recaptcha_response_field');
+ }), Report.ready);
},
ready: function() {
- var field, form;
+ var field;
- form = $('form');
field = $.id('recaptcha_response_field');
$.on(field, 'keydown', function(e) {
if (e.keyCode === 8 && !field.value) {
return $.globalEval('Recaptcha.reload("t")');
}
});
- return $.on(form, 'submit', function(e) {
+ return $.on($('form'), 'submit', function(e) {
var response;
e.preventDefault();
@@ -9310,7 +9310,7 @@
if (!/\s/.test(response)) {
field.value = "" + response + " " + response;
}
- return form.submit();
+ return this.submit();
});
}
};
@@ -10213,16 +10213,17 @@
return;
case 'images.4chan.org':
$.ready(function() {
- var url;
+ var URL;
if (Conf['404 Redirect'] && d.title === '4chan - 404 Not Found') {
Redirect.init();
- url = Redirect.to('file', {
- boardID: pathname[1],
- filename: pathname[3]
+ pathname = location.pathname.split('/');
+ URL = Redirect.to('file', {
+ boardID: g.BOARD.ID,
+ filename: pathname[pathname.length - 1]
});
- if (url) {
- return location.href = url;
+ if (URL) {
+ return location.replace(URL);
}
}
});
@@ -10305,7 +10306,7 @@
return $.ready(Main.initReady);
},
initStyle: function() {
- var MutationObserver, mainStyleSheet, observer, setStyle, style, styleSheets, _ref;
+ var mainStyleSheet, observer, setStyle, style, styleSheets, _ref;
$.off(d, '4chanMainInit', Main.initStyle);
if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) {
@@ -10342,7 +10343,7 @@
if (!mainStyleSheet) {
return;
}
- if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) {
+ if (window.MutationObserver) {
observer = new MutationObserver(setStyle);
return observer.observe(mainStyleSheet, {
attributes: true,
@@ -10362,7 +10363,7 @@
threadID: g.THREADID,
postID: +location.hash.match(/\d+/)
});
- location.href = href || ("/" + g.BOARD + "/");
+ location.replace(href || ("/" + g.BOARD + "/"));
}
return;
}
diff --git a/builds/crx/script.js b/builds/crx/script.js
index 983292e62..2dfb2255f 100644
--- a/builds/crx/script.js
+++ b/builds/crx/script.js
@@ -1,6 +1,6 @@
// Generated by CoffeeScript
/*
-* 4chan X - Version 1.2.13 - 2013-05-29
+* 4chan X - Version 1.2.13 - 2013-06-14
*
* Licensed under the MIT license.
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
@@ -274,6 +274,7 @@
'Open thread tab': ['Shift+o', 'Open thread in new tab.'],
'Next reply': ['j', 'Select next reply.'],
'Previous reply': ['k', 'Select previous reply.'],
+ 'Deselect reply': ['Shift+d', 'Deselect reply.'],
'Hide': ['x', 'Hide thread.']
},
updater: {
@@ -781,9 +782,14 @@
(syncItems || (syncItems = {}))[key] = val;
}
}
- items = {};
count = 0;
done = function(item) {
+ var lastError;
+
+ lastError = chrome.runtime.lastError;
+ if (lastError) {
+ c.error(lastError, lastError.message || 'No message.');
+ }
$.extend(items, item);
if (!--count) {
return cb(items);
@@ -1284,9 +1290,9 @@
var boardID, postID, threadID, val, _base, _base1, _base2;
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val;
- if (postID) {
+ if (postID !== void 0) {
((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val;
- } else if (threadID) {
+ } else if (threadID !== void 0) {
((_base2 = this.data.boards)[boardID] || (_base2[boardID] = {}))[threadID] = val;
} else {
this.data.boards[boardID] = val;
@@ -1324,13 +1330,9 @@
_ref = this.data.boards;
for (boardID in _ref) {
val = _ref[boardID];
- if (typeof this.data.boards[boardID] !== 'object') {
- delete this.data.boards[boardID];
- } else {
- this.deleteIfEmpty({
- boardID: boardID
- });
- }
+ this.deleteIfEmpty({
+ boardID: boardID
+ });
}
now = Date.now();
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
@@ -1777,7 +1779,7 @@
hashScroll: function() {
var hash, post;
- if (!((hash = this.location.hash) && (post = $.id(hash.slice(1))))) {
+ if (!((hash = this.location.hash.slice(1)) && (post = $.id(hash)))) {
return;
}
if ((Get.postFromRoot(post)).isHidden) {
@@ -1875,7 +1877,7 @@
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
*/
- var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileHtml, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
+ var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file;
isOP = postID === threadID;
@@ -1913,7 +1915,7 @@
}
flag = flagCode ? ("
") : '';
if (file != null ? file.isDeleted : void 0) {
- fileHtml = isOP ? ("") + ("
") + "" : ("") + ("
") + "";
+ fileHTML = isOP ? ("") + ("
") + "" : ("") + ("
") + "";
} else if (file) {
ext = file.name.slice(-3);
if (!file.twidth && !file.theight && ext === 'gif') {
@@ -2168,9 +2170,9 @@
case '[/b]':
return '';
case '[spoiler]':
- return '';
+ return '';
case '[/spoiler]':
- return '';
+ return '';
case '[code]':
return '';
case '[/code]':
@@ -2702,10 +2704,6 @@
}
for (key in Config.filter) {
this.filters[key] = [];
- if (Conf[key] === void 0) {
- $["delete"](key);
- continue;
- }
_ref = Conf[key].split('\n');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
filter = _ref[_i];
@@ -5589,7 +5587,7 @@
}), this.ready.bind(this));
},
ready: function() {
- var MutationObserver, imgContainer, input, observer, setLifetime,
+ var imgContainer, input, observer, setLifetime,
_this = this;
setLifetime = function(e) {
@@ -5615,7 +5613,7 @@
img: imgContainer.firstChild,
input: input
};
- if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) {
+ if (window.MutationObserver) {
observer = new MutationObserver(this.load.bind(this));
observer.observe(this.nodes.challenge, {
childList: true
@@ -7026,7 +7024,12 @@
return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning');
},
fetchPage: function() {
- if (ThreadStats.thread.isDead || !Conf["Page Count in Stats"]) {
+ if (!Conf["Page Count in Stats"]) {
+ return;
+ }
+ if (ThreadStats.thread.isDead) {
+ ThreadStats.pageCountEl.textContent = 'Dead';
+ $.addClass(ThreadStats.pageCountEl, 'warning');
return;
}
setTimeout(ThreadStats.fetchPage, 2 * $.MINUTE);
@@ -7367,7 +7370,7 @@
return $.after(root, [$.tn(' '), icon]);
},
parse: function(postObjects) {
- var ID, OP, count, deletedFiles, deletedPosts, files, index, key, node, num, post, postObject, posts, root, scroll, _i, _len, _ref;
+ var ID, OP, count, deletedFiles, deletedPosts, files, index, length, node, num, post, postObject, posts, scroll, sendEvent, threadID, _i, _len, _ref;
OP = postObjects[0];
Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler;
@@ -7408,67 +7411,53 @@
post.kill(true);
deletedFiles.push(post);
}
- if (ThreadUpdater.postID && ThreadUpdater.postID === ID) {
- ThreadUpdater.foundPost = true;
- }
}
+ sendEvent = function() {
+ return $.event('ThreadUpdate', {
+ 404: false,
+ thread: ThreadUpdater.thread,
+ newPosts: posts,
+ deletedPosts: deletedPosts,
+ deletedFiles: deletedFiles,
+ postCount: OP.replies + 1,
+ fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead)
+ });
+ };
if (!count) {
ThreadUpdater.set('status', null, null);
ThreadUpdater.outdateCount++;
- } else {
- ThreadUpdater.set('status', "+" + count, 'new');
- ThreadUpdater.outdateCount = 0;
- if (Conf['Beep'] && d.hidden && Unread.posts && !Unread.posts.length) {
- if (!ThreadUpdater.audio) {
- ThreadUpdater.audio = $.el('audio', {
- src: ThreadUpdater.beep
- });
- }
- ThreadUpdater.audio.play();
- }
- ThreadUpdater.lastPost = posts[count - 1].ID;
- Main.callbackNodes(Post, posts);
- scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25;
- for (key in posts) {
- post = posts[key];
- if (!posts.hasOwnProperty(key)) {
- continue;
- }
- root = post.nodes.root;
- if (post.cb) {
- if (!post.cb.call(post)) {
- $.add(ThreadUpdater.root, root);
- }
- } else {
- $.add(ThreadUpdater.root, root);
- }
- }
- if (scroll) {
- if (Conf['Bottom Scroll']) {
- d.body.scrollTop = d.body.clientHeight;
- } else {
- if (root) {
- Header.scrollToPost(root);
- }
- }
- }
- $.queueTask(function() {
- var length, threadID;
-
- threadID = ThreadUpdater.thread.ID;
- length = $$('.thread > .postContainer', ThreadUpdater.root).length;
- return Fourchan.parseThread(threadID, length - count, length);
- });
+ sendEvent();
+ return;
+ }
+ ThreadUpdater.set('status', "+" + count, 'new');
+ ThreadUpdater.outdateCount = 0;
+ if (Conf['Beep'] && d.hidden && Unread.posts && !Unread.posts.length) {
+ if (!ThreadUpdater.audio) {
+ ThreadUpdater.audio = $.el('audio', {
+ src: ThreadUpdater.beep
+ });
+ }
+ ThreadUpdater.audio.play();
+ }
+ ThreadUpdater.lastPost = posts[count - 1].ID;
+ Main.callbackNodes(Post, posts);
+ scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25;
+ $.add(ThreadUpdater.root, nodes);
+ sendEvent();
+ if (scroll) {
+ if (Conf['Bottom Scroll']) {
+ d.body.scrollTop = d.body.clientHeight;
+ } else {
+ Header.scrollToPost(nodes[0]);
+ }
+ }
+ threadID = ThreadUpdater.thread.ID;
+ length = $$('.thread > .postContainer', ThreadUpdater.root).length;
+ if (Conf['Enable 4chan\'s Extension']) {
+ return $.globalEval("Parser.parseThread(" + threadID + ", " + (-count) + ")");
+ } else {
+ return Fourchan.parseThread(threadID, length - count, length);
}
- return $.event('ThreadUpdate', {
- 404: false,
- thread: ThreadUpdater.thread,
- newPosts: posts,
- deletedPosts: deletedPosts,
- deletedFiles: deletedFiles,
- postCount: OP.replies + 1,
- fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead)
- });
}
};
@@ -7680,7 +7669,7 @@
}
},
scroll: function() {
- var hash, post, posts, prevID, root;
+ var checkPosition, hash, onload, post, posts, prevID, root;
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
return;
@@ -7697,11 +7686,27 @@
break;
}
}
- root.scrollIntoView(false);
- return;
+ onload = function() {
+ if (checkPosition(root)) {
+ return root.scrollIntoView(false);
+ }
+ };
+ } else {
+ posts = Object.keys(Unread.thread.posts);
+ root = Unread.thread.posts[posts[posts.length - 1]].nodes.root;
+ onload = function() {
+ if (checkPosition(root)) {
+ return Header.scrollToPost(root);
+ }
+ };
}
- posts = Object.keys(Unread.thread.posts);
- return Header.scrollToPost(Unread.thread.posts[posts[posts.length - 1]].nodes.root);
+ checkPosition = function(target) {
+ var height, top, _ref;
+
+ _ref = target.getBoundingClientRect(), top = _ref.top, height = _ref.height;
+ return top + height - doc.clientHeight > 0;
+ };
+ return $.on(window, 'load', onload);
},
sync: function() {
var lastReadPost;
@@ -7720,11 +7725,11 @@
Unread.setLine();
return Unread.update();
},
- addPosts: function(newPosts) {
- var ID, data, post, _i, _len;
+ addPosts: function(posts) {
+ var ID, data, post, _i, _len, _ref;
- for (_i = 0, _len = newPosts.length; _i < _len; _i++) {
- post = newPosts[_i];
+ for (_i = 0, _len = posts.length; _i < _len; _i++) {
+ post = posts[_i];
ID = post.ID;
if (ID <= Unread.lastReadPost || post.isHidden) {
continue;
@@ -7743,7 +7748,7 @@
Unread.addPostQuotingYou(post);
}
if (Conf['Unread Line']) {
- Unread.setLine(newPosts.contains(Unread.posts[0]));
+ Unread.setLine((_ref = Unread.posts[0], __indexOf.call(posts, _ref) >= 0));
}
Unread.read();
return Unread.update();
@@ -7999,8 +8004,8 @@
'http': true,
'https': true,
'software': 'fuuka',
- 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'tg', 'vr'],
- 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'vr']
+ 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'],
+ 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr']
}
},
to: function(dest, data) {
@@ -8070,7 +8075,7 @@
return $.on(d, '4chanXInitFinished', this.setup);
},
setup: function() {
- var btn, entry, items, psa;
+ var btn, entry, psa;
$.off(d, '4chanXInitFinished', PSAHiding.setup);
if (!(psa = $.id('globalMessage'))) {
@@ -8098,21 +8103,10 @@
href: 'javascript:;'
});
$.on(btn, 'click', PSAHiding.toggle);
- items = {
- hiddenPSA: 0,
- hiddenPSAs: null
- };
- $.get(items, function(_arg) {
- var hiddenPSA, hiddenPSAs;
+ $.get('hiddenPSA', 0, function(_arg) {
+ var hiddenPSA;
- hiddenPSA = _arg.hiddenPSA, hiddenPSAs = _arg.hiddenPSAs;
- if (hiddenPSAs) {
- $["delete"]('hiddenPSAs');
- if (hiddenPSAs.contains(psa.textContent.replace(/\W+/g, '').toLowerCase())) {
- hiddenPSA = +$.id('globalMessage').dataset.utc;
- $.set('hiddenPSA', hiddenPSA);
- }
- }
+ hiddenPSA = _arg.hiddenPSA;
PSAHiding.sync(hiddenPSA);
$.before(psa, btn);
return $.rmClass(doc, 'hide-announcement');
@@ -8233,7 +8227,7 @@
var rgb;
rgb = IDColor.ids[this] || IDColor.compute(this);
- return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black;" : "white; border-radius: 3px; padding: 0px 2px;");
+ return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black; border-radius: 3px; padding: 0px 2px;" : "white; border-radius: 3px; padding: 0px 2px;");
},
hash: function(str) {
var i, j, msg;
@@ -8685,7 +8679,7 @@
}
board = g.BOARD.ID;
if (board === 'g') {
- $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML.replace(/\\s/g, ' '));\n}, false);");
+ $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML);\n}, false);");
Post.prototype.callbacks.push({
name: 'Parse /g/ code',
cb: this.code
@@ -8909,6 +8903,9 @@
case Conf['Previous reply']:
Keybinds.hl(-1, threadRoot);
break;
+ case Conf['Deselect reply']:
+ Keybinds.hl(0, threadRoot);
+ break;
case Conf['Hide']:
if (g.VIEW === 'index') {
ThreadHiding.toggle(thread);
@@ -9019,6 +9016,12 @@
hl: function(delta, thread) {
var axe, headRect, next, postEl, rect, replies, reply, root, topMargin, _i, _len;
+ if (!delta) {
+ if (postEl = $('.reply.highlight', thread)) {
+ $.rmClass(postEl, 'highlight');
+ }
+ return;
+ }
if (Conf['Fixed Header'] && Conf['Bottom header']) {
topMargin = 0;
} else {
@@ -9270,22 +9273,23 @@
Report = {
init: function() {
- if (!/report/.test(location.search)) {
+ if (!(/report/.test(location.search) && d.cookie.indexOf('pass_enabled=1') === -1)) {
return;
}
- return $.ready(this.ready);
+ return $.asap((function() {
+ return $.id('recaptcha_response_field');
+ }), Report.ready);
},
ready: function() {
- var field, form;
+ var field;
- form = $('form');
field = $.id('recaptcha_response_field');
$.on(field, 'keydown', function(e) {
if (e.keyCode === 8 && !field.value) {
return $.globalEval('Recaptcha.reload("t")');
}
});
- return $.on(form, 'submit', function(e) {
+ return $.on($('form'), 'submit', function(e) {
var response;
e.preventDefault();
@@ -9293,7 +9297,7 @@
if (!/\s/.test(response)) {
field.value = "" + response + " " + response;
}
- return form.submit();
+ return this.submit();
});
}
};
@@ -10194,16 +10198,17 @@
return;
case 'images.4chan.org':
$.ready(function() {
- var url;
+ var URL;
if (Conf['404 Redirect'] && d.title === '4chan - 404 Not Found') {
Redirect.init();
- url = Redirect.to('file', {
- boardID: pathname[1],
- filename: pathname[3]
+ pathname = location.pathname.split('/');
+ URL = Redirect.to('file', {
+ boardID: g.BOARD.ID,
+ filename: pathname[pathname.length - 1]
});
- if (url) {
- return location.href = url;
+ if (URL) {
+ return location.replace(URL);
}
}
});
@@ -10286,7 +10291,7 @@
return $.ready(Main.initReady);
},
initStyle: function() {
- var MutationObserver, mainStyleSheet, observer, setStyle, style, styleSheets, _ref;
+ var mainStyleSheet, observer, setStyle, style, styleSheets, _ref;
$.off(d, '4chanMainInit', Main.initStyle);
if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) {
@@ -10324,7 +10329,7 @@
if (!mainStyleSheet) {
return;
}
- if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) {
+ if (window.MutationObserver) {
observer = new MutationObserver(setStyle);
return observer.observe(mainStyleSheet, {
attributes: true,
@@ -10344,7 +10349,7 @@
threadID: g.THREADID,
postID: +location.hash.match(/\d+/)
});
- location.href = href || ("/" + g.BOARD + "/");
+ location.replace(href || ("/" + g.BOARD + "/"));
}
return;
}
diff --git a/package.json b/package.json
index fe11c768f..c0816aea3 100644
--- a/package.json
+++ b/package.json
@@ -25,10 +25,10 @@
"grunt-concurrent": "~0.2.0",
"grunt-contrib-clean": "~0.4.1",
"grunt-contrib-coffee": "~0.7.0",
- "grunt-contrib-compress": "~0.5.0",
+ "grunt-contrib-compress": "~0.5.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-copy": "~0.4.1",
- "grunt-contrib-watch": "~0.4.3",
+ "grunt-contrib-watch": "~0.4.4",
"grunt-shell": "~0.2.2"
},
"repository": {
diff --git a/src/Archive/Redirect.coffee b/src/Archive/Redirect.coffee
index 1936a9f1c..867abd15d 100644
--- a/src/Archive/Redirect.coffee
+++ b/src/Archive/Redirect.coffee
@@ -114,8 +114,8 @@ Redirect =
'http': true
'https': true
'software': 'fuuka'
- 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'tg', 'vr']
- 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'vr']
+ 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr']
+ 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr']
to: (dest, data) ->
archive = (if dest is 'search' then Redirect.thread else Redirect[dest])[data.boardID]
diff --git a/src/Filtering/Filter.coffee b/src/Filtering/Filter.coffee
index 382ef4e52..ca11455cb 100644
--- a/src/Filtering/Filter.coffee
+++ b/src/Filtering/Filter.coffee
@@ -8,11 +8,6 @@ Filter =
for key of Config.filter
@filters[key] = []
- if Conf[key] is undefined
- # XXX hopefully tmp fix for the rare people getting this mysterious error:
- # "Filter" initialization crashed. TypeError: Cannot call method 'split' of undefined
- $.delete key
- continue
for filter in Conf[key].split '\n'
continue if filter[0] is '#'
diff --git a/src/General/Build.coffee b/src/General/Build.coffee
index 67f6793e5..6d87269a1 100644
--- a/src/General/Build.coffee
+++ b/src/General/Build.coffee
@@ -116,7 +116,7 @@ Build =
''
if file?.isDeleted
- fileHtml = if isOP
+ fileHTML = if isOP
"" +
"
" +
""
diff --git a/src/General/Config.coffee b/src/General/Config.coffee
index 886cefe76..9993c09bc 100644
--- a/src/General/Config.coffee
+++ b/src/General/Config.coffee
@@ -614,6 +614,10 @@ http://iqdb.org/?url=%TURL
'k'
'Select previous reply.'
]
+ 'Deselect reply': [
+ 'Shift+d'
+ 'Deselect reply.'
+ ]
'Hide': [
'x'
'Hide thread.'
diff --git a/src/General/Get.coffee b/src/General/Get.coffee
index 8417d36f3..a66bce292 100644
--- a/src/General/Get.coffee
+++ b/src/General/Get.coffee
@@ -163,9 +163,9 @@ Get =
when '[/b]'
''
when '[spoiler]'
- ''
+ ''
when '[/spoiler]'
- ''
+ ''
when '[code]'
''
when '[/code]'
diff --git a/src/General/Header.coffee b/src/General/Header.coffee
index 66f19f2ac..278e2ebc6 100644
--- a/src/General/Header.coffee
+++ b/src/General/Header.coffee
@@ -294,7 +294,7 @@ Header =
$('input[name=boardnav]', settings).focus()
hashScroll: ->
- return unless (hash = @location.hash) and post = $.id hash[1..]
+ return unless (hash = @location.hash[1..]) and post = $.id hash
return if (Get.postFromRoot post).isHidden
Header.scrollToPost post
diff --git a/src/General/Main.coffee b/src/General/Main.coffee
index d1455c71c..bb661e8a5 100644
--- a/src/General/Main.coffee
+++ b/src/General/Main.coffee
@@ -49,10 +49,11 @@ Main =
$.ready ->
if Conf['404 Redirect'] and d.title is '4chan - 404 Not Found'
Redirect.init()
- url = Redirect.to 'file',
- boardID: pathname[1]
- filename: pathname[3]
- location.href = url if url
+ pathname = location.pathname.split '/'
+ URL = Redirect.to 'file',
+ boardID: g.BOARD.ID
+ filename: pathname[pathname.length - 1]
+ location.replace URL if URL
return
init = (features) ->
@@ -165,13 +166,12 @@ Main =
$.addClass doc, style
setStyle()
return unless mainStyleSheet
- if MutationObserver = window.MutationObserver or window.WebKitMutationObserver or window.OMutationObserver
+ if window.MutationObserver
observer = new MutationObserver setStyle
observer.observe mainStyleSheet,
attributes: true
attributeFilter: ['href']
else
- # XXX this doesn't seem to work?
$.on mainStyleSheet, 'DOMAttrModified', setStyle
initReady: ->
@@ -181,7 +181,7 @@ Main =
boardID: g.BOARD.ID
threadID: g.THREADID
postID: +location.hash.match /\d+/ # post number or 0
- location.href = href or "/#{g.BOARD}/"
+ location.replace href or "/#{g.BOARD}/"
return
unless $.hasClass doc, 'fourchan-x'
diff --git a/src/General/lib/$.coffee b/src/General/lib/$.coffee
index ce7f84737..a09700461 100644
--- a/src/General/lib/$.coffee
+++ b/src/General/lib/$.coffee
@@ -358,9 +358,11 @@ $.get = (key, val, cb) ->
else
(syncItems or= {})[key] = val
- items = {}
count = 0
done = (item) ->
+ {lastError} = chrome.runtime
+ if lastError
+ c.error lastError, lastError.message or 'No message.'
$.extend items, item
cb items unless --count
diff --git a/src/General/lib/databoard.class b/src/General/lib/databoard.class
index 90742cb88..80c190f17 100644
--- a/src/General/lib/databoard.class
+++ b/src/General/lib/databoard.class
@@ -33,9 +33,9 @@ class DataBoard
delete @data.boards[boardID]
set: ({boardID, threadID, postID, val}) ->
- if postID
+ if postID isnt undefined
((@data.boards[boardID] or= {})[threadID] or= {})[postID] = val
- else if threadID
+ else if threadID isnt undefined
(@data.boards[boardID] or= {})[threadID] = val
else
@data.boards[boardID] = val
@@ -60,12 +60,7 @@ class DataBoard
clean: ->
for boardID, val of @data.boards
- # XXX tmp fix for users that had the `null`
- # value for a board with the Unread features:
- if typeof @data.boards[boardID] isnt 'object'
- delete @data.boards[boardID]
- else
- @deleteIfEmpty {boardID}
+ @deleteIfEmpty {boardID}
now = Date.now()
if (@data.lastChecked or 0) < now - 2 * $.HOUR
diff --git a/src/Miscellaneous/AnnouncementHiding.coffee b/src/Miscellaneous/AnnouncementHiding.coffee
index 81dd3954e..411d3bbae 100644
--- a/src/Miscellaneous/AnnouncementHiding.coffee
+++ b/src/Miscellaneous/AnnouncementHiding.coffee
@@ -30,17 +30,7 @@ PSAHiding =
href: 'javascript:;'
$.on btn, 'click', PSAHiding.toggle
- # XXX remove hiddenPSAs workaround in the future.
- items =
- hiddenPSA: 0
- hiddenPSAs: null
-
- $.get items, ({hiddenPSA, hiddenPSAs}) ->
- if hiddenPSAs
- $.delete 'hiddenPSAs'
- if hiddenPSAs.contains psa.textContent.replace(/\W+/g, '').toLowerCase()
- hiddenPSA = +$.id('globalMessage').dataset.utc
- $.set 'hiddenPSA', hiddenPSA
+ $.get 'hiddenPSA', 0, ({hiddenPSA}) ->
PSAHiding.sync hiddenPSA
$.before psa, btn
$.rmClass doc, 'hide-announcement'
diff --git a/src/Miscellaneous/Fourchan.coffee b/src/Miscellaneous/Fourchan.coffee
index 4e1073d72..edb2fd36b 100644
--- a/src/Miscellaneous/Fourchan.coffee
+++ b/src/Miscellaneous/Fourchan.coffee
@@ -7,7 +7,7 @@ Fourchan =
$.globalEval """
window.addEventListener('prettyprint', function(e) {
var pre = e.detail;
- pre.innerHTML = prettyPrintOne(pre.innerHTML.replace(/\\s/g, ' '));
+ pre.innerHTML = prettyPrintOne(pre.innerHTML);
}, false);
"""
Post::callbacks.push
diff --git a/src/Miscellaneous/Keybinds.coffee b/src/Miscellaneous/Keybinds.coffee
index 303601dca..8a4923102 100644
--- a/src/Miscellaneous/Keybinds.coffee
+++ b/src/Miscellaneous/Keybinds.coffee
@@ -111,6 +111,8 @@ Keybinds =
Keybinds.hl +1, threadRoot
when Conf['Previous reply']
Keybinds.hl -1, threadRoot
+ when Conf['Deselect reply']
+ Keybinds.hl 0, threadRoot
when Conf['Hide']
ThreadHiding.toggle thread if g.VIEW is 'index'
else
@@ -194,6 +196,10 @@ Keybinds =
location.href = url
hl: (delta, thread) ->
+ unless delta
+ if postEl = $ '.reply.highlight', thread
+ $.rmClass postEl, 'highlight'
+ return
if Conf['Fixed Header'] and Conf['Bottom header']
topMargin = 0
else
diff --git a/src/Miscellaneous/Report.coffee b/src/Miscellaneous/Report.coffee
index eea172ddc..af505998d 100644
--- a/src/Miscellaneous/Report.coffee
+++ b/src/Miscellaneous/Report.coffee
@@ -1,14 +1,13 @@
Report =
init: ->
- return unless /report/.test location.search
- $.ready @ready
+ return unless /report/.test(location.search) and d.cookie.indexOf('pass_enabled=1') is -1
+ $.asap (-> $.id 'recaptcha_response_field'), Report.ready
ready: ->
- form = $ 'form'
field = $.id 'recaptcha_response_field'
$.on field, 'keydown', (e) ->
$.globalEval 'Recaptcha.reload("t")' if e.keyCode is 8 and not field.value
- $.on form, 'submit', (e) ->
+ $.on $('form'), 'submit', (e) ->
e.preventDefault()
response = field.value.trim()
field.value = "#{response} #{response}" unless /\s/.test response
- form.submit()
+ @submit()
diff --git a/src/Monitoring/ThreadStats.coffee b/src/Monitoring/ThreadStats.coffee
index 8cfae31c5..a8002a575 100644
--- a/src/Monitoring/ThreadStats.coffee
+++ b/src/Monitoring/ThreadStats.coffee
@@ -48,7 +48,11 @@ ThreadStats =
(if thread.fileLimit and !thread.isSticky then $.addClass else $.rmClass) fileCountEl, 'warning'
fetchPage: ->
- return if ThreadStats.thread.isDead or !Conf["Page Count in Stats"]
+ return if !Conf["Page Count in Stats"]
+ if ThreadStats.thread.isDead
+ ThreadStats.pageCountEl.textContent = 'Dead'
+ $.addClass ThreadStats.pageCountEl, 'warning'
+ return
setTimeout ThreadStats.fetchPage, 2 * $.MINUTE
$.ajax "//api.4chan.org/#{ThreadStats.thread.board}/threads.json", onload: ThreadStats.onThreadsLoad,
headers: 'If-Modified-Since': ThreadStats.lastModified
diff --git a/src/Monitoring/ThreadUpdater.coffee b/src/Monitoring/ThreadUpdater.coffee
index 5a4fc92a3..30edaaad5 100644
--- a/src/Monitoring/ThreadUpdater.coffee
+++ b/src/Monitoring/ThreadUpdater.coffee
@@ -288,53 +288,46 @@ ThreadUpdater =
post.kill true
deletedFiles.push post
- if ThreadUpdater.postID and ThreadUpdater.postID is ID
- ThreadUpdater.foundPost = true
+ sendEvent = ->
+ $.event 'ThreadUpdate',
+ 404: false
+ thread: ThreadUpdater.thread
+ newPosts: posts
+ deletedPosts: deletedPosts
+ deletedFiles: deletedFiles
+ postCount: OP.replies + 1
+ fileCount: OP.images + (!!ThreadUpdater.thread.OP.file and !ThreadUpdater.thread.OP.file.isDead)
unless count
ThreadUpdater.set 'status', null, null
ThreadUpdater.outdateCount++
+ sendEvent()
+ return
+ ThreadUpdater.set 'status', "+#{count}", 'new'
+ ThreadUpdater.outdateCount = 0
+ if Conf['Beep'] and d.hidden and Unread.posts and !Unread.posts.length
+ unless ThreadUpdater.audio
+ ThreadUpdater.audio = $.el 'audio', src: ThreadUpdater.beep
+ ThreadUpdater.audio.play()
+
+ ThreadUpdater.lastPost = posts[count - 1].ID
+ Main.callbackNodes Post, posts
+
+ scroll = Conf['Auto Scroll'] and ThreadUpdater.scrollBG() and
+ ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25
+ $.add ThreadUpdater.root, nodes
+ sendEvent()
+ if scroll
+ if Conf['Bottom Scroll']
+ <% if (type === 'crx') { %>d.body<% } else { %>doc<% } %>.scrollTop = d.body.clientHeight
+ else
+ Header.scrollToPost nodes[0]
+
+ # Enable 4chan features.
+ threadID = ThreadUpdater.thread.ID
+ {length} = $$ '.thread > .postContainer', ThreadUpdater.root
+ if Conf['Enable 4chan\'s Extension']
+ $.globalEval "Parser.parseThread(#{threadID}, #{-count})"
else
- ThreadUpdater.set 'status', "+#{count}", 'new'
- ThreadUpdater.outdateCount = 0
- if Conf['Beep'] and d.hidden and Unread.posts and !Unread.posts.length
- unless ThreadUpdater.audio
- ThreadUpdater.audio = $.el 'audio', src: ThreadUpdater.beep
- ThreadUpdater.audio.play()
-
- ThreadUpdater.lastPost = posts[count - 1].ID
- Main.callbackNodes Post, posts
-
- scroll = Conf['Auto Scroll'] and ThreadUpdater.scrollBG() and
- ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25
-
- for key, post of posts
- continue unless posts.hasOwnProperty key
- root = post.nodes.root
- if post.cb
- unless post.cb.call post
- $.add ThreadUpdater.root, root
- else
- $.add ThreadUpdater.root, root
-
- if scroll
- if Conf['Bottom Scroll']
- <% if (type === 'crx') { %>d.body<% } else { %>doc<% } %>.scrollTop = d.body.clientHeight
- else
- Header.scrollToPost root if root
-
- $.queueTask ->
- # Enable 4chan features.
- threadID = ThreadUpdater.thread.ID
- {length} = $$ '.thread > .postContainer', ThreadUpdater.root
- Fourchan.parseThread threadID, length - count, length
-
- $.event 'ThreadUpdate',
- 404: false
- thread: ThreadUpdater.thread
- newPosts: posts
- deletedPosts: deletedPosts
- deletedFiles: deletedFiles
- postCount: OP.replies + 1
- fileCount: OP.images + (!!ThreadUpdater.thread.OP.file and !ThreadUpdater.thread.OP.file.isDead)
+ Fourchan.parseThread threadID, length - count, length
diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee
index 2ddec7b1a..547d9a577 100644
--- a/src/Monitoring/Unread.coffee
+++ b/src/Monitoring/Unread.coffee
@@ -43,11 +43,21 @@ Unread =
break if prevID is post.ID
prevID = post.ID
break unless post.isHidden
- root.scrollIntoView false
- return
- # Scroll to the last read post.
- posts = Object.keys Unread.thread.posts
- Header.scrollToPost Unread.thread.posts[posts[posts.length - 1]].nodes.root
+ onload = -> root.scrollIntoView false if checkPosition root
+ else
+ # Scroll to the last read post.
+ posts = Object.keys Unread.thread.posts
+ {root} = Unread.thread.posts[posts[posts.length - 1]].nodes
+ onload = -> Header.scrollToPost root if checkPosition root
+ checkPosition = (target) ->
+ # Don't scroll to the target if
+ # - it's visible.
+ # - we've scrolled past it.
+ {top, height} = target.getBoundingClientRect()
+ top + height - doc.clientHeight > 0
+ # Prevent the browser to scroll back to
+ # the previous scroll location on page load.
+ $.on window, 'load', onload
sync: ->
lastReadPost = Unread.db.get
@@ -61,8 +71,8 @@ Unread =
Unread.setLine()
Unread.update()
- addPosts: (newPosts) ->
- for post in newPosts
+ addPosts: (posts) ->
+ for post in posts
{ID} = post
if ID <= Unread.lastReadPost or post.isHidden
continue
@@ -76,7 +86,7 @@ Unread =
Unread.addPostQuotingYou post
if Conf['Unread Line']
# Force line on visible threads if there were no unread posts previously.
- Unread.setLine newPosts.contains Unread.posts[0]
+ Unread.setLine Unread.posts[0] in posts
Unread.read()
Unread.update()
diff --git a/src/Posting/QuickReply.coffee b/src/Posting/QuickReply.coffee
index ed95d38ed..2219c8fa7 100644
--- a/src/Posting/QuickReply.coffee
+++ b/src/Posting/QuickReply.coffee
@@ -779,7 +779,7 @@ QR =
img: imgContainer.firstChild
input: input
- if MutationObserver = window.MutationObserver or window.WebKitMutationObserver or window.OMutationObserver
+ if window.MutationObserver
observer = new MutationObserver @load.bind @
observer.observe @nodes.challenge,
childList: true
") + "
") + "
") + "
") + "