Add Quote Inlining. Close #501.
This commit is contained in:
parent
320cb1269c
commit
94b9ff9c36
231
4chan_x.user.js
231
4chan_x.user.js
@ -73,7 +73,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var $, $$, Board, Clone, Conf, Config, Main, Post, QuoteBacklink, Quotify, Thread, Time, UI, d, g,
|
var $, $$, Board, Clone, Conf, Config, Get, Main, Post, QuoteBacklink, QuoteInline, Quotify, Thread, Time, UI, d, g,
|
||||||
__hasProp = {}.hasOwnProperty,
|
__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; };
|
__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; };
|
||||||
|
|
||||||
@ -628,16 +628,10 @@
|
|||||||
return this.ID;
|
return this.ID;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Thread(root, board) {
|
function Thread(ID, board) {
|
||||||
var postInfo;
|
|
||||||
this.root = root;
|
|
||||||
this.board = board;
|
this.board = board;
|
||||||
this.ID = +root.id.slice(1);
|
this.ID = +ID;
|
||||||
this.hr = root.nextElementSibling;
|
|
||||||
this.posts = {};
|
this.posts = {};
|
||||||
postInfo = $('.postInfo', root.firstElementChild);
|
|
||||||
this.isClosed = !!$('img[title=Closed]', postInfo);
|
|
||||||
this.isSticky = !!$('img[title=Sticky]', postInfo);
|
|
||||||
g.threads["" + board + "." + this] = board.threads[this] = this;
|
g.threads["" + board + "." + this] = board.threads[this] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,7 +659,8 @@
|
|||||||
post: post,
|
post: post,
|
||||||
info: info,
|
info: info,
|
||||||
comment: $('.postMessage', post),
|
comment: $('.postMessage', post),
|
||||||
quotelinks: []
|
quotelinks: [],
|
||||||
|
backlinks: info.getElementsByClassName('backlink')
|
||||||
};
|
};
|
||||||
this.info = {};
|
this.info = {};
|
||||||
if (subject = $('.subject', info)) {
|
if (subject = $('.subject', info)) {
|
||||||
@ -753,12 +748,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
Post.prototype.rmClone = function(index) {
|
Post.prototype.rmClone = function(index) {
|
||||||
var clone, i, _i, _ref;
|
var i, _i, _ref;
|
||||||
clone = this.clones.splice(index, 1);
|
this.clones.splice(index, 1);
|
||||||
for (i = _i = index, _ref = this.clones.length; index <= _ref ? _i < _ref : _i > _ref; i = index <= _ref ? ++_i : --_i) {
|
for (i = _i = index, _ref = this.clones.length; index <= _ref ? _i < _ref : _i > _ref; i = index <= _ref ? ++_i : --_i) {
|
||||||
this.clones[i].nodes.root.setAttribute('data-clone', i);
|
this.clones[i].nodes.root.setAttribute('data-clone', i);
|
||||||
}
|
}
|
||||||
return $.rm(clone.nodes.root);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return Post;
|
return Post;
|
||||||
@ -770,7 +764,7 @@
|
|||||||
__extends(Clone, _super);
|
__extends(Clone, _super);
|
||||||
|
|
||||||
function Clone(origin) {
|
function Clone(origin) {
|
||||||
var file, index, info, key, nodes, post, quotelink, root, val, _i, _j, _len, _len1, _ref, _ref1, _ref2;
|
var file, index, info, inline, inlined, key, nodes, post, quotelink, root, val, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _ref4;
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
_ref = ['ID', 'board', 'thread', 'info', 'quotes', 'isReply'];
|
_ref = ['ID', 'board', 'thread', 'info', 'quotes', 'isReply'];
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
@ -786,8 +780,20 @@
|
|||||||
post: post,
|
post: post,
|
||||||
info: info,
|
info: info,
|
||||||
comment: $('.postMessage', post),
|
comment: $('.postMessage', post),
|
||||||
quotelinks: []
|
quotelinks: [],
|
||||||
|
backlinks: info.getElementsByClassName('backlink')
|
||||||
};
|
};
|
||||||
|
_ref1 = $$('.inline', post);
|
||||||
|
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||||
|
inline = _ref1[_j];
|
||||||
|
$.rm(inline);
|
||||||
|
}
|
||||||
|
_ref2 = $$('.inlined', post);
|
||||||
|
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
|
||||||
|
inlined = _ref2[_k];
|
||||||
|
$.rmClass(inlined, 'inlined');
|
||||||
|
}
|
||||||
|
$.rmClass(root, 'forwarded');
|
||||||
if (nodes.subject) {
|
if (nodes.subject) {
|
||||||
this.nodes.subject = $('.subject', info);
|
this.nodes.subject = $('.subject', info);
|
||||||
}
|
}
|
||||||
@ -812,18 +818,18 @@
|
|||||||
if (nodes.date) {
|
if (nodes.date) {
|
||||||
this.nodes.date = $('.dateTime', info);
|
this.nodes.date = $('.dateTime', info);
|
||||||
}
|
}
|
||||||
_ref1 = $$('.quotelink', this.nodes.comment);
|
_ref3 = $$('.quotelink', this.nodes.comment);
|
||||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
|
||||||
quotelink = _ref1[_j];
|
quotelink = _ref3[_l];
|
||||||
if (quotelink.hash || $.hasClass(quotelink, 'deadlink')) {
|
if (quotelink.hash || $.hasClass(quotelink, 'deadlink')) {
|
||||||
this.nodes.quotelinks.push(quotelink);
|
this.nodes.quotelinks.push(quotelink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (origin.file) {
|
if (origin.file) {
|
||||||
this.file = {};
|
this.file = {};
|
||||||
_ref2 = origin.file;
|
_ref4 = origin.file;
|
||||||
for (key in _ref2) {
|
for (key in _ref4) {
|
||||||
val = _ref2[key];
|
val = _ref4[key];
|
||||||
this.file[key] = val;
|
this.file[key] = val;
|
||||||
}
|
}
|
||||||
file = $('.file', post);
|
file = $('.file', post);
|
||||||
@ -832,7 +838,7 @@
|
|||||||
this.file.thumb = $('img[data-md5]', file);
|
this.file.thumb = $('img[data-md5]', file);
|
||||||
}
|
}
|
||||||
this.isClone = true;
|
this.isClone = true;
|
||||||
index = origin.clones.push(this);
|
index = origin.clones.push(this) - 1;
|
||||||
root.setAttribute('data-clone', index);
|
root.setAttribute('data-clone', index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,6 +926,13 @@
|
|||||||
$.log(err, 'Resurrect Quotes');
|
$.log(err, 'Resurrect Quotes');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Conf['Quote Inline']) {
|
||||||
|
try {
|
||||||
|
QuoteInline.init();
|
||||||
|
} catch (err) {
|
||||||
|
$.log(err, 'Quote Inline');
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Conf['Quote Backlinks']) {
|
if (Conf['Quote Backlinks']) {
|
||||||
try {
|
try {
|
||||||
QuoteBacklink.init();
|
QuoteBacklink.init();
|
||||||
@ -949,7 +962,7 @@
|
|||||||
if (!$.hasClass(boardChild, 'thread')) {
|
if (!$.hasClass(boardChild, 'thread')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
thread = new Thread(boardChild, g.BOARD);
|
thread = new Thread(boardChild.id.slice(1), g.BOARD);
|
||||||
threads.push(thread);
|
threads.push(thread);
|
||||||
_ref1 = boardChild.children;
|
_ref1 = boardChild.children;
|
||||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||||
@ -993,7 +1006,75 @@
|
|||||||
return $.on(d, 'DOMNodeInserted', Main.addStyle);
|
return $.on(d, 'DOMNodeInserted', Main.addStyle);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
css: "/* general */\n.move {\n cursor: move;\n}\nlabel {\n cursor: pointer;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\n display: block !important;\n}\n.post {\n overflow: visible !important;\n}\n\n/* header */\nbody.fourchan_x {\n margin-top: 2.5em;\n}\n#boardNavDesktop.reply {\n border-width: 0 0 1px;\n padding: 4px;\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n transition: opacity .1s ease-in-out;\n -o-transition: opacity .1s ease-in-out;\n -moz-transition: opacity .1s ease-in-out;\n -webkit-transition: opacity .1s ease-in-out;\n z-index: 1;\n}\n#boardNavDesktop.reply:not(:hover) {\n opacity: .4;\n transition: opacity 1.5s .5s ease-in-out;\n -o-transition: opacity 1.5s .5s ease-in-out;\n -moz-transition: opacity 1.5s .5s ease-in-out;\n -webkit-transition: opacity 1.5s .5s ease-in-out;\n}\n#boardNavDesktop.reply a {\n margin: -1px;\n}\n#settings {\n float: right;\n}"
|
css: "/* general */\n.move {\n cursor: move;\n}\nlabel {\n cursor: pointer;\n}\n.warning {\n color: red;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\n display: block !important;\n}\n.post {\n overflow: visible !important;\n}\n\n/* header */\nbody.fourchan_x {\n margin-top: 2.5em;\n}\n#boardNavDesktop.reply {\n border-width: 0 0 1px;\n padding: 4px;\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n transition: opacity .1s ease-in-out;\n -o-transition: opacity .1s ease-in-out;\n -moz-transition: opacity .1s ease-in-out;\n -webkit-transition: opacity .1s ease-in-out;\n z-index: 1;\n}\n#boardNavDesktop.reply:not(:hover) {\n opacity: .4;\n transition: opacity 1.5s .5s ease-in-out;\n -o-transition: opacity 1.5s .5s ease-in-out;\n -moz-transition: opacity 1.5s .5s ease-in-out;\n -webkit-transition: opacity 1.5s .5s ease-in-out;\n}\n#boardNavDesktop.reply a {\n margin: -1px;\n}\n#settings {\n float: right;\n}\n\n/* quotes */\n.inlined {\n opacity: .5;\n}\n.forwarded {\n display: none;\n}\n.inline {\n border: 1px solid rgba(128, 128, 128, 0.5);\n display: table;\n margin: 2px 0;\n}\n.inline .post {\n display: table !important;\n margin: 0 !important;\n padding: 1px 2px !important;\n border: 0 !important;\n}"
|
||||||
|
};
|
||||||
|
|
||||||
|
Get = {
|
||||||
|
post: function(board, threadID, postID, root) {
|
||||||
|
var clone, origin;
|
||||||
|
if (origin = g.posts["" + board + "." + postID]) {
|
||||||
|
clone = origin.addClone();
|
||||||
|
$.add(root, Get.cleanRoot(clone));
|
||||||
|
Main.callbackNodes(Post, [clone]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
root.textContent = "Loading post No." + postID + "...";
|
||||||
|
if (threadID) {
|
||||||
|
return $.cache("/" + board + "/res/" + threadID, function() {
|
||||||
|
return Get.parsePost(this, board, threadID, postID, root);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cleanRoot: function(clone) {
|
||||||
|
var child, post, root, _i, _len, _ref, _ref1;
|
||||||
|
_ref = clone.nodes, root = _ref.root, post = _ref.post;
|
||||||
|
_ref1 = Array.prototype.slice.call(root.childNodes);
|
||||||
|
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||||
|
child = _ref1[_i];
|
||||||
|
if (child !== post) {
|
||||||
|
$.rm(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
},
|
||||||
|
parsePost: function(req, board, threadID, postID, root) {
|
||||||
|
var clone, doc, href, inBoard, inThread, link, pc, post, quote, status, _i, _len, _ref;
|
||||||
|
status = req.status;
|
||||||
|
if (status !== 200) {
|
||||||
|
$.addClass(root, 'warning');
|
||||||
|
root.textContent = status === 404 ? "Thread No." + threadID + " has not been found." : "Error " + req.status + ": " + req.statusText + ".";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doc = d.implementation.createHTMLDocument('');
|
||||||
|
doc.documentElement.innerHTML = req.response;
|
||||||
|
if (!(pc = doc.getElementById("pc" + postID))) {
|
||||||
|
root.textContent = "Post No." + postID + " has not been found.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pc = d.importNode(pc, true);
|
||||||
|
_ref = $$('.quotelink', pc);
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
quote = _ref[_i];
|
||||||
|
href = quote.getAttribute('href');
|
||||||
|
if (href[0] === '/') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
quote.href = "/" + board + "/res/" + href;
|
||||||
|
}
|
||||||
|
link = $('a[title="Highlight this post"]', pc);
|
||||||
|
link.href = "/" + board + "/res/" + threadID + "#p" + postID;
|
||||||
|
link.nextSibling.href = "/" + board + "/res/" + threadID + "#q" + postID;
|
||||||
|
inBoard = g.boards[board] || new Board(board);
|
||||||
|
inThread = g.threads["" + board + "." + threadID] || new Thread(threadID, inBoard);
|
||||||
|
post = new Post(pc, inThread, inBoard);
|
||||||
|
Main.callbackNodes(Post, [post]);
|
||||||
|
if (!root.parentNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clone = post.addClone();
|
||||||
|
$.replace(root.firstChild, Get.cleanRoot(clone));
|
||||||
|
return Main.callbackNodes(Post, [clone]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Quotify = {
|
Quotify = {
|
||||||
@ -1044,6 +1125,100 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QuoteInline = {
|
||||||
|
init: function() {
|
||||||
|
return Post.prototype.callbacks.push({
|
||||||
|
name: 'Quote Inline',
|
||||||
|
cb: this.node
|
||||||
|
});
|
||||||
|
},
|
||||||
|
node: function() {
|
||||||
|
var link, _i, _j, _len, _len1, _ref, _ref1;
|
||||||
|
_ref = this.nodes.quotelinks;
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
link = _ref[_i];
|
||||||
|
$.on(link, 'click', QuoteInline.toggle);
|
||||||
|
}
|
||||||
|
_ref1 = this.nodes.backlinks;
|
||||||
|
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||||
|
link = _ref1[_j];
|
||||||
|
$.on(link, 'click', QuoteInline.toggle);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggle: function(e) {
|
||||||
|
var board, path, postID, threadID;
|
||||||
|
if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
path = this.pathname.split('/');
|
||||||
|
board = path[1];
|
||||||
|
threadID = path[3];
|
||||||
|
postID = this.hash.slice(2);
|
||||||
|
if ($.hasClass(this, 'inlined')) {
|
||||||
|
QuoteInline.rm(this, board, threadID, postID);
|
||||||
|
} else {
|
||||||
|
if ($.x("ancestor::div[@id='p" + postID + "']", this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QuoteInline.add(this, board, threadID, postID);
|
||||||
|
}
|
||||||
|
return this.classList.toggle('inlined');
|
||||||
|
},
|
||||||
|
add: function(quotelink, board, threadID, postID) {
|
||||||
|
var inline, isBacklink, post, root;
|
||||||
|
inline = $.el('div', {
|
||||||
|
id: "i" + postID,
|
||||||
|
className: 'inline'
|
||||||
|
});
|
||||||
|
root = (isBacklink = $.hasClass(quotelink, 'backlink')) ? quotelink.parentNode.parentNode : $.x('ancestor-or-self::*[parent::blockquote][1]', quotelink);
|
||||||
|
$.after(root, inline);
|
||||||
|
Get.post(board, threadID, postID, inline);
|
||||||
|
if (!(board === g.BOARD.ID && $.x("ancestor::div[@id='t" + threadID + "']", quotelink))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
post = g.posts["" + board + "." + postID];
|
||||||
|
if (isBacklink && Conf['Forward Hiding']) {
|
||||||
|
$.addClass(post.nodes.root, 'forwarded');
|
||||||
|
return post.forwarded++ || (post.forwarded = 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rm: function(quotelink, board, threadID, postID) {
|
||||||
|
var el, inThreadID, index, inline, inlines, path, post, root, _i, _len;
|
||||||
|
root = $.x("following::div[@id='i" + postID + "'][1]", quotelink);
|
||||||
|
$.rm(root);
|
||||||
|
if (!(el = root.firstElementChild)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
post = g.posts["" + board + "." + postID];
|
||||||
|
post.rmClone(el.dataset.clone);
|
||||||
|
inThreadID = $.x('ancestor::div[@class="thread"]', quotelink).id.slice(1);
|
||||||
|
if (Conf['Forward Hiding'] && board === g.BOARD.ID && threadID === inThreadID && $.hasClass(quotelink, 'backlink')) {
|
||||||
|
if (!--post.forwarded) {
|
||||||
|
delete post.forwarded;
|
||||||
|
$.rmClass(post.nodes.root, 'forwarded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inlines = $$('.inlined', el);
|
||||||
|
for (_i = 0, _len = inlines.length; _i < _len; _i++) {
|
||||||
|
inline = inlines[_i];
|
||||||
|
path = inline.pathname.split('/');
|
||||||
|
board = path[1];
|
||||||
|
threadID = path[3];
|
||||||
|
postID = inline.hash.slice(2);
|
||||||
|
index = $.x("following::div[@id='i" + postID + "'][1]/child::div", inline).dataset.clone;
|
||||||
|
post = g.posts["" + board + "." + postID];
|
||||||
|
post.rmClone(index);
|
||||||
|
if (Conf['Forward Hiding'] && board === g.BOARD.ID && threadID === inThreadID && $.hasClass(inline, 'backlink')) {
|
||||||
|
if (!--post.forwarded) {
|
||||||
|
delete post.forwarded;
|
||||||
|
$.rmClass(post.nodes.root, 'forwarded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
QuoteBacklink = {
|
QuoteBacklink = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var format;
|
var format;
|
||||||
@ -1083,6 +1258,9 @@
|
|||||||
for (_k = 0, _len2 = containers.length; _k < _len2; _k++) {
|
for (_k = 0, _len2 = containers.length; _k < _len2; _k++) {
|
||||||
container = containers[_k];
|
container = containers[_k];
|
||||||
link = a.cloneNode(true);
|
link = a.cloneNode(true);
|
||||||
|
if (Conf['Quote Inline']) {
|
||||||
|
$.on(link, 'click', QuoteInline.toggle);
|
||||||
|
}
|
||||||
$.add(container, [$.tn(' '), link]);
|
$.add(container, [$.tn(' '), link]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1090,9 +1268,7 @@
|
|||||||
secondNode: function() {
|
secondNode: function() {
|
||||||
var container;
|
var container;
|
||||||
if (this.isClone && this.origin.nodes.backlinkContainer) {
|
if (this.isClone && this.origin.nodes.backlinkContainer) {
|
||||||
container = $('.container', this.nodes.info);
|
this.nodes.backlinkContainer = $('.container', this.nodes.info);
|
||||||
this.nodes.backlinkContainer = container;
|
|
||||||
this.nodes.backlinks = container.getElementsByClassName('backlinks');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(Conf['OP Backlinks'] || this.isReply)) {
|
if (!(Conf['OP Backlinks'] || this.isReply)) {
|
||||||
@ -1100,7 +1276,6 @@
|
|||||||
}
|
}
|
||||||
container = QuoteBacklink.getContainer("" + this.board + "." + this);
|
container = QuoteBacklink.getContainer("" + this.board + "." + this);
|
||||||
this.nodes.backlinkContainer = container;
|
this.nodes.backlinkContainer = container;
|
||||||
this.nodes.backlinks = container.getElementsByClassName('backlinks');
|
|
||||||
return $.add(this.nodes.info, container);
|
return $.add(this.nodes.info, container);
|
||||||
},
|
},
|
||||||
getContainer: function(id) {
|
getContainer: function(id) {
|
||||||
|
|||||||
245
script.coffee
245
script.coffee
@ -486,14 +486,15 @@ class Thread
|
|||||||
callbacks: []
|
callbacks: []
|
||||||
toString: -> @ID
|
toString: -> @ID
|
||||||
|
|
||||||
constructor: (@root, @board) ->
|
constructor: (ID, @board) ->
|
||||||
@ID = +root.id[1..]
|
@ID = +ID
|
||||||
@hr = root.nextElementSibling
|
|
||||||
@posts = {}
|
@posts = {}
|
||||||
|
|
||||||
postInfo = $ '.postInfo', root.firstElementChild
|
# XXX Can't check when parsing single posts
|
||||||
@isClosed = !!$ 'img[title=Closed]', postInfo
|
# move to Post constructor? unless @isReply
|
||||||
@isSticky = !!$ 'img[title=Sticky]', postInfo
|
# postInfo = $ '.postInfo', root.firstElementChild
|
||||||
|
# @isClosed = !!$ 'img[title=Closed]', postInfo
|
||||||
|
# @isSticky = !!$ 'img[title=Sticky]', postInfo
|
||||||
|
|
||||||
g.threads["#{board}.#{@}"] = board.threads[@] = @
|
g.threads["#{board}.#{@}"] = board.threads[@] = @
|
||||||
|
|
||||||
@ -512,6 +513,7 @@ class Post
|
|||||||
info: info
|
info: info
|
||||||
comment: $ '.postMessage', post
|
comment: $ '.postMessage', post
|
||||||
quotelinks: []
|
quotelinks: []
|
||||||
|
backlinks: info.getElementsByClassName 'backlink'
|
||||||
|
|
||||||
@info = {}
|
@info = {}
|
||||||
if subject = $ '.subject', info
|
if subject = $ '.subject', info
|
||||||
@ -595,10 +597,10 @@ class Post
|
|||||||
addClone: ->
|
addClone: ->
|
||||||
new Clone @
|
new Clone @
|
||||||
rmClone: (index) ->
|
rmClone: (index) ->
|
||||||
clone = @clones.splice index, 1
|
@clones.splice index, 1
|
||||||
for i in [index...@clones.length]
|
for i in [index...@clones.length]
|
||||||
@clones[i].nodes.root.setAttribute 'data-clone', i
|
@clones[i].nodes.root.setAttribute 'data-clone', i
|
||||||
$.rm clone.nodes.root
|
return
|
||||||
|
|
||||||
class Clone extends Post
|
class Clone extends Post
|
||||||
constructor: (@origin) ->
|
constructor: (@origin) ->
|
||||||
@ -616,6 +618,17 @@ class Clone extends Post
|
|||||||
info: info
|
info: info
|
||||||
comment: $ '.postMessage', post
|
comment: $ '.postMessage', post
|
||||||
quotelinks: []
|
quotelinks: []
|
||||||
|
backlinks: info.getElementsByClassName 'backlink'
|
||||||
|
|
||||||
|
# Remove inlined posts inside of this post.
|
||||||
|
for inline in $$ '.inline', post
|
||||||
|
$.rm inline
|
||||||
|
for inlined in $$ '.inlined', post
|
||||||
|
$.rmClass inlined, 'inlined'
|
||||||
|
|
||||||
|
# root.hidden = false # post hiding
|
||||||
|
$.rmClass root, 'forwarded' # quote inlining
|
||||||
|
# $.rmClass post, 'highlight' # keybind navigation
|
||||||
|
|
||||||
if nodes.subject
|
if nodes.subject
|
||||||
@nodes.subject = $ '.subject', info
|
@nodes.subject = $ '.subject', info
|
||||||
@ -651,7 +664,7 @@ class Clone extends Post
|
|||||||
@file.thumb = $ 'img[data-md5]', file
|
@file.thumb = $ 'img[data-md5]', file
|
||||||
|
|
||||||
@isClone = true
|
@isClone = true
|
||||||
index = origin.clones.push @
|
index = origin.clones.push(@) - 1
|
||||||
root.setAttribute 'data-clone', index
|
root.setAttribute 'data-clone', index
|
||||||
|
|
||||||
|
|
||||||
@ -726,6 +739,13 @@ Main =
|
|||||||
# XXX handle error
|
# XXX handle error
|
||||||
$.log err, 'Resurrect Quotes'
|
$.log err, 'Resurrect Quotes'
|
||||||
|
|
||||||
|
if Conf['Quote Inline']
|
||||||
|
try
|
||||||
|
QuoteInline.init()
|
||||||
|
catch err
|
||||||
|
# XXX handle error
|
||||||
|
$.log err, 'Quote Inline'
|
||||||
|
|
||||||
if Conf['Quote Backlinks']
|
if Conf['Quote Backlinks']
|
||||||
try
|
try
|
||||||
QuoteBacklink.init()
|
QuoteBacklink.init()
|
||||||
@ -749,7 +769,7 @@ Main =
|
|||||||
|
|
||||||
for boardChild in $('.board').children
|
for boardChild in $('.board').children
|
||||||
continue unless $.hasClass boardChild, 'thread'
|
continue unless $.hasClass boardChild, 'thread'
|
||||||
thread = new Thread boardChild, g.BOARD
|
thread = new Thread boardChild.id[1..], g.BOARD
|
||||||
threads.push thread
|
threads.push thread
|
||||||
for threadChild in boardChild.children
|
for threadChild in boardChild.children
|
||||||
continue unless $.hasClass threadChild, 'postContainer'
|
continue unless $.hasClass threadChild, 'postContainer'
|
||||||
@ -793,6 +813,9 @@ Main =
|
|||||||
label {
|
label {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.warning {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
/* 4chan style fixes */
|
/* 4chan style fixes */
|
||||||
.opContainer, .op {
|
.opContainer, .op {
|
||||||
@ -832,10 +855,101 @@ body.fourchan_x {
|
|||||||
#settings {
|
#settings {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* quotes */
|
||||||
|
.inlined {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
.forwarded {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.inline {
|
||||||
|
border: 1px solid rgba(128, 128, 128, 0.5);
|
||||||
|
display: table;
|
||||||
|
margin: 2px 0;
|
||||||
|
}
|
||||||
|
.inline .post {
|
||||||
|
display: table !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 1px 2px !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Get =
|
||||||
|
post: (board, threadID, postID, root) ->
|
||||||
|
if origin = g.posts["#{board}.#{postID}"]
|
||||||
|
clone = origin.addClone()
|
||||||
|
$.add root, Get.cleanRoot clone
|
||||||
|
Main.callbackNodes Post, [clone]
|
||||||
|
return
|
||||||
|
|
||||||
|
root.textContent = "Loading post No.#{postID}..."
|
||||||
|
if threadID
|
||||||
|
$.cache "/#{board}/res/#{threadID}", ->
|
||||||
|
Get.parsePost @, board, threadID, postID, root
|
||||||
|
# else if url = Redirect.post board, postID
|
||||||
|
# $.cache url, ->
|
||||||
|
# Get.parseArchivedPost @, board, postID, root
|
||||||
|
cleanRoot: (clone) ->
|
||||||
|
{root, post} = clone.nodes
|
||||||
|
for child in Array::slice.call root.childNodes
|
||||||
|
$.rm child unless child is post
|
||||||
|
root
|
||||||
|
parsePost: (req, board, threadID, postID, root) ->
|
||||||
|
{status} = req
|
||||||
|
if status isnt 200
|
||||||
|
# The thread can die by the time we check a quote.
|
||||||
|
# XXX
|
||||||
|
# if url = Redirect.post board, postID
|
||||||
|
# $.cache url, ->
|
||||||
|
# Get.parseArchivedPost @, board, postID, root
|
||||||
|
# else
|
||||||
|
$.addClass root, 'warning'
|
||||||
|
root.textContent =
|
||||||
|
if status is 404
|
||||||
|
"Thread No.#{threadID} has not been found."
|
||||||
|
else
|
||||||
|
"Error #{req.status}: #{req.statusText}."
|
||||||
|
return
|
||||||
|
|
||||||
|
doc = d.implementation.createHTMLDocument ''
|
||||||
|
doc.documentElement.innerHTML = req.response
|
||||||
|
|
||||||
|
unless pc = doc.getElementById "pc#{postID}"
|
||||||
|
# The post can be deleted by the time we check a quote.
|
||||||
|
# XXX
|
||||||
|
# if url = Redirect.post board, postID
|
||||||
|
# $.cache url, ->
|
||||||
|
# Get.parseArchivedPost @, board, postID, root
|
||||||
|
# else
|
||||||
|
root.textContent = "Post No.#{postID} has not been found."
|
||||||
|
return
|
||||||
|
pc = d.importNode pc, true
|
||||||
|
|
||||||
|
for quote in $$ '.quotelink', pc
|
||||||
|
href = quote.getAttribute 'href'
|
||||||
|
continue if href[0] is '/' # Cross-board quote, or board link
|
||||||
|
quote.href = "/#{board}/res/#{href}" # Fix pathnames
|
||||||
|
link = $ 'a[title="Highlight this post"]', pc
|
||||||
|
link.href = "/#{board}/res/#{threadID}#p#{postID}"
|
||||||
|
link.nextSibling.href = "/#{board}/res/#{threadID}#q#{postID}"
|
||||||
|
|
||||||
|
inBoard = g.boards[board] or
|
||||||
|
new Board board
|
||||||
|
inThread = g.threads["#{board}.#{threadID}"] or
|
||||||
|
new Thread threadID, inBoard
|
||||||
|
post = new Post pc, inThread, inBoard
|
||||||
|
Main.callbackNodes Post, [post]
|
||||||
|
|
||||||
|
# Stop here if the container has been removed while loading.
|
||||||
|
return unless root.parentNode
|
||||||
|
clone = post.addClone()
|
||||||
|
$.replace root.firstChild, Get.cleanRoot clone
|
||||||
|
Main.callbackNodes Post, [clone]
|
||||||
|
|
||||||
Quotify =
|
Quotify =
|
||||||
init: ->
|
init: ->
|
||||||
Post::callbacks.push
|
Post::callbacks.push
|
||||||
@ -884,7 +998,6 @@ Quotify =
|
|||||||
# if board is g.BOARD and $.id "p#{ID}"
|
# if board is g.BOARD and $.id "p#{ID}"
|
||||||
# a.href = "#p#{ID}"
|
# a.href = "#p#{ID}"
|
||||||
# a.className = 'quotelink'
|
# a.className = 'quotelink'
|
||||||
# a.setAttribute 'onclick', "replyhl('#{ID}');"
|
|
||||||
# else
|
# else
|
||||||
# a.href = Redirect.thread board, 0, ID
|
# a.href = Redirect.thread board, 0, ID
|
||||||
# a.className = 'deadlink'
|
# a.className = 'deadlink'
|
||||||
@ -905,6 +1018,105 @@ Quotify =
|
|||||||
$.replace node, nodes
|
$.replace node, nodes
|
||||||
return
|
return
|
||||||
|
|
||||||
|
QuoteInline =
|
||||||
|
init: ->
|
||||||
|
Post::callbacks.push
|
||||||
|
name: 'Quote Inline'
|
||||||
|
cb: @node
|
||||||
|
node: ->
|
||||||
|
for link in @nodes.quotelinks
|
||||||
|
$.on link, 'click', QuoteInline.toggle
|
||||||
|
for link in @nodes.backlinks
|
||||||
|
$.on link, 'click', QuoteInline.toggle
|
||||||
|
return
|
||||||
|
toggle: (e) ->
|
||||||
|
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
||||||
|
e.preventDefault()
|
||||||
|
# XXX quote resurrection
|
||||||
|
# id = @dataset.id or @hash[2..]
|
||||||
|
path = @pathname.split '/'
|
||||||
|
board = path[1]
|
||||||
|
threadID = path[3]
|
||||||
|
postID = @hash[2..]
|
||||||
|
if $.hasClass @, 'inlined'
|
||||||
|
QuoteInline.rm @, board, threadID, postID
|
||||||
|
else
|
||||||
|
return if $.x "ancestor::div[@id='p#{postID}']", @
|
||||||
|
QuoteInline.add @, board, threadID, postID
|
||||||
|
@classList.toggle 'inlined'
|
||||||
|
|
||||||
|
add: (quotelink, board, threadID, postID) ->
|
||||||
|
inline = $.el 'div',
|
||||||
|
id: "i#{postID}"
|
||||||
|
className: 'inline'
|
||||||
|
|
||||||
|
root =
|
||||||
|
if isBacklink = $.hasClass quotelink, 'backlink'
|
||||||
|
quotelink.parentNode.parentNode
|
||||||
|
else
|
||||||
|
$.x 'ancestor-or-self::*[parent::blockquote][1]', quotelink
|
||||||
|
$.after root, inline
|
||||||
|
Get.post board, threadID, postID, inline
|
||||||
|
|
||||||
|
return unless board is g.BOARD.ID and $.x "ancestor::div[@id='t#{threadID}']", quotelink
|
||||||
|
post = g.posts["#{board}.#{postID}"]
|
||||||
|
|
||||||
|
# Hide forward post if it's a backlink of a post in this thread.
|
||||||
|
# Will only unhide if there's no inlined backlinks of it anymore.
|
||||||
|
if isBacklink and Conf['Forward Hiding']
|
||||||
|
$.addClass post.nodes.root, 'forwarded'
|
||||||
|
post.forwarded++ or post.forwarded = 1
|
||||||
|
|
||||||
|
# Decrease the unread count if this post is in the array of unread reply.
|
||||||
|
# XXX
|
||||||
|
# if (i = Unread.replies.indexOf el) isnt -1
|
||||||
|
# Unread.replies.splice i, 1
|
||||||
|
# Unread.update true
|
||||||
|
|
||||||
|
rm: (quotelink, board, threadID, postID) ->
|
||||||
|
# Select the corresponding inlined quote, and remove it.
|
||||||
|
root = $.x "following::div[@id='i#{postID}'][1]", quotelink
|
||||||
|
$.rm root
|
||||||
|
|
||||||
|
# Stop if it's still loading.
|
||||||
|
return unless el = root.firstElementChild
|
||||||
|
|
||||||
|
# Dereference clone.
|
||||||
|
post = g.posts["#{board}.#{postID}"]
|
||||||
|
post.rmClone el.dataset.clone
|
||||||
|
|
||||||
|
inThreadID = $.x('ancestor::div[@class="thread"]', quotelink).id[1..]
|
||||||
|
|
||||||
|
# Decrease forward count and unhide.
|
||||||
|
if Conf['Forward Hiding'] and
|
||||||
|
board is g.BOARD.ID and
|
||||||
|
threadID is inThreadID and
|
||||||
|
$.hasClass quotelink, 'backlink'
|
||||||
|
unless --post.forwarded
|
||||||
|
delete post.forwarded
|
||||||
|
$.rmClass post.nodes.root, 'forwarded'
|
||||||
|
|
||||||
|
# Repeat.
|
||||||
|
inlines = $$ '.inlined', el
|
||||||
|
for inline in inlines
|
||||||
|
# XXX resurrected quotes
|
||||||
|
path = inline.pathname.split '/'
|
||||||
|
board = path[1]
|
||||||
|
threadID = path[3]
|
||||||
|
postID = inline.hash[2..]
|
||||||
|
index = $.x("following::div[@id='i#{postID}'][1]/child::div", inline).dataset.clone
|
||||||
|
post = g.posts["#{board}.#{postID}"]
|
||||||
|
post.rmClone index
|
||||||
|
|
||||||
|
if Conf['Forward Hiding'] and
|
||||||
|
board is g.BOARD.ID and
|
||||||
|
threadID is inThreadID and
|
||||||
|
$.hasClass inline, 'backlink'
|
||||||
|
unless --post.forwarded
|
||||||
|
delete post.forwarded
|
||||||
|
$.rmClass post.nodes.root, 'forwarded'
|
||||||
|
return
|
||||||
|
|
||||||
QuoteBacklink =
|
QuoteBacklink =
|
||||||
# Backlinks appending need to work for:
|
# Backlinks appending need to work for:
|
||||||
# - previous, same, and following posts.
|
# - previous, same, and following posts.
|
||||||
@ -944,23 +1156,18 @@ QuoteBacklink =
|
|||||||
# XXX
|
# XXX
|
||||||
# if Conf['Quote Preview']
|
# if Conf['Quote Preview']
|
||||||
# $.on link, 'mouseover', QuotePreview.mouseover
|
# $.on link, 'mouseover', QuotePreview.mouseover
|
||||||
# if Conf['Quote Inline']
|
if Conf['Quote Inline']
|
||||||
# $.on link, 'click', QuoteInline.toggle
|
$.on link, 'click', QuoteInline.toggle
|
||||||
# else
|
|
||||||
# link.setAttribute 'onclick', "replyhl('#{post.ID}');"
|
|
||||||
$.add container, [$.tn(' '), link]
|
$.add container, [$.tn(' '), link]
|
||||||
return
|
return
|
||||||
secondNode: ->
|
secondNode: ->
|
||||||
if @isClone and @origin.nodes.backlinkContainer
|
if @isClone and @origin.nodes.backlinkContainer
|
||||||
container = $ '.container', @nodes.info
|
@nodes.backlinkContainer = $ '.container', @nodes.info
|
||||||
@nodes.backlinkContainer = container
|
|
||||||
@nodes.backlinks = container.getElementsByClassName 'backlinks'
|
|
||||||
return
|
return
|
||||||
# Don't backlink the OP.
|
# Don't backlink the OP.
|
||||||
return unless Conf['OP Backlinks'] or @isReply
|
return unless Conf['OP Backlinks'] or @isReply
|
||||||
container = QuoteBacklink.getContainer "#{@board}.#{@}"
|
container = QuoteBacklink.getContainer "#{@board}.#{@}"
|
||||||
@nodes.backlinkContainer = container
|
@nodes.backlinkContainer = container
|
||||||
@nodes.backlinks = container.getElementsByClassName 'backlinks'
|
|
||||||
$.add @nodes.info, container
|
$.add @nodes.info, container
|
||||||
getContainer: (id) ->
|
getContainer: (id) ->
|
||||||
@containers[id] or=
|
@containers[id] or=
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user