diff --git a/4chan_x.user.js b/4chan_x.user.js
index cd3fbea16..0f5cf364c 100644
--- a/4chan_x.user.js
+++ b/4chan_x.user.js
@@ -72,7 +72,7 @@
*/
(function() {
- var $, $$, Anonymize, AutoGif, Conf, Config, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, GetTitle, ImageExpand, ImageHover, Keybinds, Main, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, ReplyHiding, ReportButton, RevealSpoilers, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Time, TitlePost, UI, Unread, Updater, Watcher, d, g, _base;
+ var $, $$, Anonymize, AutoGif, Conf, Config, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Get, ImageExpand, ImageHover, Keybinds, Main, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, ReplyHiding, ReportButton, RevealSpoilers, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Time, TitlePost, UI, Unread, Updater, Watcher, d, g, _base;
Config = {
main: {
@@ -874,7 +874,7 @@
quote.href = "res/" + href;
}
id = reply.id.slice(2);
- link = $('.postInfo > .postNum > a:first-child', reply);
+ link = $('.postInfo > .postNum > a[title="Highlight this post"]', reply);
link.href = "res/" + threadID + "#p" + id;
link.nextSibling.href = "res/" + threadID + "#q" + id;
nodes.push(reply);
@@ -2686,7 +2686,7 @@
watched[_name = g.BOARD] || (watched[_name] = {});
watched[g.BOARD][id] = {
href: "/" + g.BOARD + "/res/" + id,
- textContent: GetTitle(thread)
+ textContent: Get.title(thread)
};
$.set('watched', watched);
Watcher.refresh();
@@ -2708,7 +2708,7 @@
if ((trip = name.nextElementSibling) && trip.className === 'postertrip') {
$.rm(trip);
}
- if ((parent = name.parentNode).className === 'useremail' && !/^sage$/i.test(parent.pathname)) {
+ if ((parent = name.parentNode).className === 'useremail' && !/^mailto:sage$/i.test(parent.href)) {
return $.replace(parent, name);
}
}
@@ -2992,25 +2992,95 @@
}
};
- GetTitle = function(thread) {
- var el, op, span;
- op = $('.op', thread);
- el = $('.subject', op);
- if (!el.textContent) {
- el = $('blockquote', op);
- if (!el.textContent) {
- el = $('.nameBlock', op);
+ Get = {
+ post: function(board, threadID, postID, root, cb) {
+ var post;
+ if (board === g.BOARD && (post = $.id("pc" + postID))) {
+ $.add(root, Get.cleanPost(post.cloneNode(true)));
+ return;
}
+ root.textContent = "Loading post No." + postID + "...";
+ if (threadID) {
+ return $.cache("/" + board + "/res/" + threadID, function() {
+ return Get.parsePost(this, board, threadID, postID, root, cb);
+ });
+ }
+ },
+ parsePost: function(req, board, threadID, postID, root, cb) {
+ var doc, href, link, pc, quote, status, _i, _len, _ref;
+ status = req.status;
+ if (status !== 200) {
+ 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 = Get.cleanPost(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 = $('.postInfo > .postNum > a[title="Highlight this post"]', pc);
+ link.href = "/" + board + "/res/" + threadID + "#p" + postID;
+ link.nextSibling.href = "/" + board + "/res/" + threadID + "#q" + postID;
+ $.replace(root.firstChild, pc);
+ if (cb) {
+ return cb();
+ }
+ },
+ parseArchivedPost: function(req, board, postID, root, cb) {},
+ cleanPost: function(root) {
+ var child, el, now, post, _i, _j, _len, _len1, _ref, _ref1;
+ post = $('.post', root);
+ _ref = Array.prototype.slice.call(root.childNodes);
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ if (child !== post) {
+ $.rm(child);
+ }
+ }
+ now = Date.now();
+ _ref1 = $$('[id]', root);
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ el = _ref1[_j];
+ el.id = "" + now + "_" + el.id;
+ }
+ $.rmClass(root, 'forwarded');
+ $.rmClass(root, 'qphl');
+ $.rmClass(post, 'highlight');
+ $.rmClass(post, 'qphl');
+ root.hidden = post.hidden = false;
+ return root;
+ },
+ title: function(thread) {
+ var el, op, span;
+ op = $('.op', thread);
+ el = $('.subject', op);
+ if (!el.textContent) {
+ el = $('blockquote', op);
+ if (!el.textContent) {
+ el = $('.nameBlock', op);
+ }
+ }
+ span = $.el('span', {
+ innerHTML: el.innerHTML.replace(/
/g, ' ')
+ });
+ return "/" + g.BOARD + "/ - " + (span.textContent.trim());
}
- span = $.el('span', {
- innerHTML: el.innerHTML.replace(/
/g, ' ')
- });
- return "/" + g.BOARD + "/ - " + (span.textContent.trim());
};
TitlePost = {
init: function() {
- return d.title = GetTitle();
+ return d.title = Get.title();
}
};
@@ -3103,49 +3173,36 @@
return this.classList.toggle('inlined');
},
add: function(q, id) {
- var clonePost, el, i, inline, isBacklink, pathname, root;
+ var el, i, inline, isBacklink, path, root;
if (!(isBacklink = /\bbacklink\b/.test(q.className))) {
root = q;
while (root.parentNode.nodeName !== 'BLOCKQUOTE') {
root = root.parentNode;
}
}
- if (el = $.id("p" + id)) {
- if (/\bop\b/.test(el.className)) {
- $.rmClass(el.parentNode, 'qphl');
- } else {
- $.rmClass(el, 'qphl');
- }
- clonePost = QuoteInline.clone(id, el);
- if (isBacklink) {
- $.after(q.parentNode, clonePost);
- if (Conf['Forward Hiding']) {
- $.addClass(el.parentNode, 'forwarded');
- ++el.dataset.forwarded || (el.dataset.forwarded = 1);
- }
- } else {
- $.after(root, clonePost);
- }
- if ((i = Unread.replies.indexOf(el)) !== -1) {
- Unread.replies.splice(i, 1);
- Unread.update(true);
- }
+ path = q.pathname.split('/');
+ el = path[1] === g.BOARD ? $.id("p" + id) : false;
+ inline = $.el('div', {
+ id: "i" + id,
+ className: el ? 'inline' : 'inline crosspost'
+ });
+ $.after((isBacklink ? q.parentNode : root), inline);
+ Get.post(path[1], path[3], id, inline);
+ if (!el) {
return;
}
- inline = $.el('div', {
- className: 'inline',
- id: "i" + id,
- textContent: "Loading " + id + "..."
- });
- $.after(root, inline);
- pathname = q.pathname;
- return $.cache(pathname, function() {
- return QuoteInline.parse(this, pathname, id, inline);
- });
+ if (isBacklink && Conf['Forward Hiding']) {
+ $.addClass(el.parentNode, 'forwarded');
+ ++el.dataset.forwarded || (el.dataset.forwarded = 1);
+ }
+ if ((i = Unread.replies.indexOf(el)) !== -1) {
+ Unread.replies.splice(i, 1);
+ return Unread.update(true);
+ }
},
rm: function(q, id) {
var div, inlined, _i, _len, _ref;
- div = $.x("following::div[@id='i_pc" + id + "']", q);
+ div = $.x("following::div[@id='i" + id + "']", q);
$.rm(div);
if (!Conf['Forward Hiding']) {
return;
@@ -3164,50 +3221,6 @@
return $.rmClass(div.parentNode, 'forwarded');
}
}
- },
- parse: function(req, pathname, id, inline) {
- var doc, href, link, newInline, node, quote, _i, _len, _ref;
- if (!inline.parentNode) {
- return;
- }
- if (req.status !== 200) {
- inline.textContent = "" + req.status + " " + req.statusText;
- return;
- }
- doc = d.implementation.createHTMLDocument('');
- doc.documentElement.innerHTML = req.response;
- node = doc.getElementById("p" + id);
- newInline = QuoteInline.clone(id, node);
- _ref = $$('.quotelink', newInline);
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- quote = _ref[_i];
- href = quote.getAttribute('href');
- if (href[0] === '/') {
- continue;
- }
- quote.href = "res/" + href;
- }
- link = $('.postInfo > .postNum > a:first-child', newInline);
- link.href = "" + pathname + "#p" + id;
- link.nextSibling.href = "" + pathname + "#q" + id;
- $.addClass(newInline, 'crosspost');
- return $.replace(inline, newInline);
- },
- clone: function(id, el) {
- var clone, node, post, _i, _len, _ref;
- clone = $.el('div', {
- className: 'postContainer inline',
- id: "i_pc" + id
- });
- post = el.cloneNode(true);
- post.hidden = false;
- $.add(clone, post);
- _ref = $$('[id]', clone);
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- node = _ref[_i];
- node.id = "i_" + node.id;
- }
- return clone;
}
};
@@ -3231,7 +3244,7 @@
}
},
mouseover: function(e) {
- var el, id, klass, qp, quote, replyID, _i, _j, _len, _len1, _ref, _ref1;
+ var el, id, parent, path, qp, quote, quoterID, _i, _len, _ref;
if (/\binlined\b/.test(this.className)) {
return;
}
@@ -3244,21 +3257,39 @@
if (UI.el) {
return;
}
+ path = this.pathname.split('/');
+ id = this.hash.slice(2);
qp = UI.el = $.el('div', {
id: 'qp',
- className: 'post reply dialog'
+ className: 'reply dialog'
});
+ UI.hover(e);
$.add(d.body, qp);
- id = this.hash.slice(2);
- if (el = $.id("p" + id)) {
- _ref = el.parentNode.className.split(' ');
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- klass = _ref[_i];
- if (!/^((op|reply|post)Container|forwarded)$/.test(klass)) {
- $.addClass(qp, klass);
+ Get.post(path[1], path[3], id, qp, function() {
+ var bq, fileInfo, img, post;
+ bq = $('blockquote', qp);
+ Main.prettify(bq);
+ post = {
+ el: qp
+ };
+ if (fileInfo = $('.fileInfo', qp)) {
+ img = fileInfo.nextElementSibling.firstElementChild;
+ if (img.alt !== 'File deleted.') {
+ post.fileInfo = fileInfo;
+ post.img = img;
}
}
- qp.innerHTML = el.innerHTML;
+ if (Conf['Image Auto-Gif']) {
+ AutoGif.node(post);
+ }
+ if (Conf['Time Formatting']) {
+ Time.node(post);
+ }
+ if (Conf['File Info Formatting']) {
+ return FileInfo.node(post);
+ }
+ });
+ if (path[1] === g.BOARD && (el = $.id("p" + id))) {
if (Conf['Quote Highlighting']) {
if (/\bop\b/.test(el.className)) {
$.addClass(el.parentNode, 'qphl');
@@ -3266,72 +3297,31 @@
$.addClass(el, 'qphl');
}
}
- replyID = $.x('ancestor::div[contains(@class,"postContainer")]', this).id.match(/\d+$/)[0];
- _ref1 = $$('.quotelink, .backlink', qp);
- for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
- quote = _ref1[_j];
- if (quote.hash.slice(2) === replyID) {
+ parent = this.parentNode;
+ while (!parent.id) {
+ parent = parent.parentNode;
+ }
+ quoterID = parent.id.match(/\d+$/)[0];
+ _ref = $$('.quotelink, .backlink', qp);
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ quote = _ref[_i];
+ if (quote.hash.slice(2) === quoterID) {
$.addClass(quote, 'forwardlink');
}
}
- } else {
- qp.textContent = "Loading " + id + "...";
- $.cache(this.pathname, function() {
- return QuotePreview.parse(this, id);
- });
}
- UI.hover(e);
$.on(this, 'mousemove', UI.hover);
return $.on(this, 'mouseout click', QuotePreview.mouseout);
},
- mouseout: function() {
+ mouseout: function(e) {
var el;
UI.hoverend();
if (el = $.id(this.hash.slice(1))) {
- if (/\bop\b/.test(el.className)) {
- $.rmClass(el.parentNode, 'qphl');
- } else {
- $.rmClass(el, 'qphl');
- }
+ $.rmClass(el, 'qphl');
+ $.rmClass(el.parentNode, 'qphl');
}
$.off(this, 'mousemove', UI.hover);
return $.off(this, 'mouseout click', QuotePreview.mouseout);
- },
- parse: function(req, id) {
- var bq, doc, fileInfo, img, node, post, qp;
- if (!((qp = UI.el) && qp.textContent === ("Loading " + id + "..."))) {
- return;
- }
- if (req.status !== 200) {
- qp.textContent = "" + req.status + " " + req.statusText;
- return;
- }
- doc = d.implementation.createHTMLDocument('');
- doc.documentElement.innerHTML = req.response;
- node = doc.getElementById("p" + id);
- qp.innerHTML = node.innerHTML;
- bq = $('blockquote', qp);
- bq.id += '_qp';
- Main.prettify(bq);
- post = {
- el: qp
- };
- if (fileInfo = $('.fileInfo', qp)) {
- img = fileInfo.nextElementSibling.firstElementChild;
- if (img.alt !== 'File deleted.') {
- post.fileInfo = fileInfo;
- post.img = img;
- }
- }
- if (Conf['Image Auto-Gif']) {
- AutoGif.node(post);
- }
- if (Conf['Time Formatting']) {
- Time.node(post);
- }
- if (Conf['File Info Formatting']) {
- return FileInfo.node(post);
- }
}
};
@@ -3401,7 +3391,7 @@
nodes.push($.tn(text));
}
id = quote.match(/\d+$/)[0];
- board = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : $('.postInfo > .postNum > a:first-child', post.el).pathname.split('/')[1];
+ board = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : $('.postInfo > .postNum > a[title="Highlight this post"]', post.el).pathname.split('/')[1];
nodes.push(a = $.el('a', {
textContent: "" + quote + "\u00A0(Dead)"
}));
@@ -4203,17 +4193,17 @@
}
},
preParse: function(node) {
- var el, fileInfo, img, post, rootClass;
- rootClass = node.className;
+ var el, fileInfo, img, parentClass, post;
+ parentClass = node.parentNode.className;
el = $('.post', node);
post = {
root: node,
el: el,
"class": el.className,
- id: el.id.slice(1),
- threadId: g.THREAD_ID || $.x('ancestor::div[parent::div[@class="board"]]', node).id.slice(1),
- isInlined: /\binline\b/.test(rootClass),
- isCrosspost: /\bcrosspost\b/.test(rootClass),
+ id: el.id.match(/\d+$/)[0],
+ threadId: g.THREAD_ID || $.x('ancestor::div[parent::div[@class="board"]]', node).id.match(/\d+$/)[0],
+ isInlined: /\binline\b/.test(parentClass),
+ isCrosspost: /\bcrosspost\b/.test(parentClass),
blockquote: el.lastElementChild,
quotes: el.getElementsByClassName('quotelink'),
backlinks: el.getElementsByClassName('backlink'),
@@ -4637,8 +4627,12 @@ textarea.field {\
}\
\
#qp {\
+ padding: 2px 2px 5px;\
+}\
+#qp .post {\
+ border: none;\
margin: 0;\
- padding: 1px 2px 5px;\
+ padding: 0;\
}\
#qp img {\
max-height: 300px;\
@@ -4647,26 +4641,15 @@ textarea.field {\
.qphl {\
outline: 2px solid rgba(216, 94, 49, .7);\
}\
-.qphl.opContainer {\
- outline-offset: -2px;\
-}\
-div.opContainer {\
- display: block !important;\
-}\
.inlined {\
opacity: .5;\
}\
-.inline {\
+.inline .post {\
background-color: rgba(255, 255, 255, 0.15);\
border: 1px solid rgba(128, 128, 128, 0.5);\
display: table;\
margin: 2px;\
-}\
-.inline .post {\
- background: none;\
- border: none;\
- margin: 0;\
- padding: 0;\
+ padding: 2px;\
}\
.opContainer.filter_highlight {\
box-shadow: inset 5px 0 rgba(255,0,0,0.5);\
diff --git a/script.coffee b/script.coffee
index efb5d60cf..2018fac47 100644
--- a/script.coffee
+++ b/script.coffee
@@ -663,7 +663,7 @@ ExpandThread =
continue if href[0] is '/' # Cross-board quote
quote.href = "res/#{href}" # Fix pathnames
id = reply.id[2..]
- link = $ '.postInfo > .postNum > a:first-child', reply
+ link = $ '.postInfo > .postNum > a[title="Highlight this post"]', reply
link.href = "res/#{threadID}#p#{id}"
link.nextSibling.href = "res/#{threadID}#q#{id}"
nodes.push reply
@@ -2099,7 +2099,7 @@ Watcher =
watched[g.BOARD] or= {}
watched[g.BOARD][id] =
href: "/#{g.BOARD}/res/#{id}"
- textContent: GetTitle thread
+ textContent: Get.title thread
$.set 'watched', watched
Watcher.refresh()
true
@@ -2113,7 +2113,7 @@ Anonymize =
name.textContent = 'Anonymous'
if (trip = name.nextElementSibling) and trip.className is 'postertrip'
$.rm trip
- if (parent = name.parentNode).className is 'useremail' and not /^sage$/i.test parent.pathname
+ if (parent = name.parentNode).className is 'useremail' and not /^mailto:sage$/i.test parent.href
$.replace parent, name
Sauce =
@@ -2282,19 +2282,87 @@ FileInfo =
M: -> FileInfo.convertUnit 'MB'
r: -> FileInfo.data.resolution
-GetTitle = (thread) ->
- op = $ '.op', thread
- el = $ '.subject', op
- unless el.textContent
- el = $ 'blockquote', op
+Get =
+ post: (board, threadID, postID, root, cb) ->
+ if board is g.BOARD and post = $.id "pc#{postID}"
+ $.add root, Get.cleanPost post.cloneNode true
+ return
+
+ root.textContent = "Loading post No.#{postID}..."
+ if threadID
+ $.cache "/#{board}/res/#{threadID}", ->
+ Get.parsePost @, board, threadID, postID, root, cb
+ # else if url = Redirect.???
+ # $.cache url, ->
+ # Get.parseArchivedPost @, board, postID, root, cb
+ parsePost: (req, board, threadID, postID, root, cb) ->
+ {status} = req
+ if status isnt 200
+ # thread can die by the time we check a post
+ # try archive if possible
+ # else
+ 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}"
+ # post can be deleted by the time we check for it
+ # try archive if possible
+ # else
+ root.textContent = "Post No.#{postID} has not been found."
+ return
+ pc = Get.cleanPost 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 = $ '.postInfo > .postNum > a[title="Highlight this post"]', pc
+ link.href = "/#{board}/res/#{threadID}#p#{postID}"
+ link.nextSibling.href = "/#{board}/res/#{threadID}#q#{postID}"
+
+ $.replace root.firstChild, pc
+ cb() if cb
+ parseArchivedPost: (req, board, postID, root, cb) ->
+ # $.replace root.firstChild,
+ cleanPost: (root) ->
+ post = $ '.post', root
+ for child in Array::slice.call root.childNodes
+ $.rm child unless child is post
+
+ # Don't mess with other features
+ now = Date.now()
+ for el in $$ '[id]', root
+ el.id = "#{now}_#{el.id}"
+
+ # $.rmClass post, 'opContainer'
+ # $.rmClass post, 'replyContainer'
+ $.rmClass root, 'forwarded'
+ $.rmClass root, 'qphl' # op
+ $.rmClass post, 'highlight'
+ $.rmClass post, 'qphl' # reply
+ root.hidden = post.hidden = false
+
+ root
+ title: (thread) ->
+ op = $ '.op', thread
+ el = $ '.subject', op
unless el.textContent
- el = $ '.nameBlock', op
- span = $.el 'span', innerHTML: el.innerHTML.replace /
/g, ' '
- "/#{g.BOARD}/ - #{span.textContent.trim()}"
+ el = $ 'blockquote', op
+ unless el.textContent
+ el = $ '.nameBlock', op
+ span = $.el 'span', innerHTML: el.innerHTML.replace /
/g, ' '
+ "/#{g.BOARD}/ - #{span.textContent.trim()}"
TitlePost =
init: ->
- d.title = GetTitle()
+ d.title = Get.title()
QuoteBacklink =
init: ->
@@ -2357,39 +2425,33 @@ QuoteInline =
# Can't use this because Firefox a shit:
# root = $.x 'ancestor::*[parent::blockquote]', q
unless isBacklink = /\bbacklink\b/.test q.className
- root = q
- while root.parentNode.nodeName isnt 'BLOCKQUOTE'
+ root = q
+ until root.parentNode.nodeName is 'BLOCKQUOTE'
root = root.parentNode
- if el = $.id "p#{id}"
- if /\bop\b/.test el.className
- $.rmClass el.parentNode, 'qphl'
- else
- $.rmClass el, 'qphl'
- clonePost = QuoteInline.clone id, el
- if isBacklink
- $.after q.parentNode, clonePost
- if Conf['Forward Hiding']
- $.addClass el.parentNode, 'forwarded'
- # Will only unhide if there's no inlined backlinks of it anymore.
- ++el.dataset.forwarded or el.dataset.forwarded = 1
- else
- $.after root, clonePost
- if (i = Unread.replies.indexOf el) isnt -1
- Unread.replies.splice i, 1
- Unread.update true
- return
+ path = q.pathname.split '/'
+ el = if path[1] is g.BOARD then $.id "p#{id}" else false
inline = $.el 'div',
- className: 'inline'
id: "i#{id}"
- textContent: "Loading #{id}..."
- $.after root, inline
- {pathname} = q
- $.cache pathname, -> QuoteInline.parse @, pathname, id, inline
+ className: if el then 'inline' else 'inline crosspost'
+ $.after (if isBacklink then q.parentNode else root), inline
+ Get.post path[1], path[3], id, inline
+
+ return unless el
+
+ # Will only unhide if there's no inlined backlinks of it anymore.
+ if isBacklink and Conf['Forward Hiding']
+ $.addClass el.parentNode, 'forwarded'
+ ++el.dataset.forwarded or el.dataset.forwarded = 1
+
+ # Decrease the unread count if this post is in the array of unread reply.
+ if (i = Unread.replies.indexOf el) isnt -1
+ Unread.replies.splice i, 1
+ Unread.update true
rm: (q, id) ->
# select the corresponding inlined quote or loading quote
- div = $.x "following::div[@id='i_pc#{id}']", q
+ div = $.x "following::div[@id='i#{id}']", q
$.rm div
return unless Conf['Forward Hiding']
for inlined in $$ '.backlink.inlined', div
@@ -2399,40 +2461,6 @@ QuoteInline =
div = $.id "p#{id}"
$.rmClass div.parentNode, 'forwarded' unless --div.dataset.forwarded
- parse: (req, pathname, id, inline) ->
- return unless inline.parentNode
-
- if req.status isnt 200
- inline.textContent = "#{req.status} #{req.statusText}"
- return
-
- doc = d.implementation.createHTMLDocument ''
- doc.documentElement.innerHTML = req.response
-
- node = doc.getElementById "p#{id}"
- newInline = QuoteInline.clone id, node
- for quote in $$ '.quotelink', newInline
- href = quote.getAttribute 'href'
- continue if href[0] is '/' # Cross-board quote
- quote.href = "res/#{href}" # Fix pathnames
- link = $ '.postInfo > .postNum > a:first-child', newInline
- link.href = "#{pathname}#p#{id}"
- link.nextSibling.href = "#{pathname}#q#{id}"
- $.addClass newInline, 'crosspost'
- $.replace inline, newInline
-
- clone: (id, el) ->
- clone = $.el 'div',
- className: 'postContainer inline'
- id: "i_pc#{id}"
- post = el.cloneNode true
- post.hidden = false
- $.add clone, post
- for node in $$ '[id]', clone
- # Don't mess with other features
- node.id = "i_#{node.id}"
- clone
-
QuotePreview =
init: ->
Main.callbacks.push @node
@@ -2455,70 +2483,53 @@ QuotePreview =
# Don't stop other elements from dragging
return if UI.el
- qp = UI.el = $.el 'div',
+ path = @pathname.split '/'
+ id = @hash[2..]
+ qp = UI.el = $.el 'div',
id: 'qp'
- className: 'post reply dialog'
+ className: 'reply dialog'
+ UI.hover e
$.add d.body, qp
+ Get.post path[1], path[3], id, qp, ->
+ bq = $ 'blockquote', qp
+ Main.prettify bq
+ post =
+ el: qp
+ if fileInfo = $ '.fileInfo', qp
+ img = fileInfo.nextElementSibling.firstElementChild
+ if img.alt isnt 'File deleted.'
+ post.fileInfo = fileInfo
+ post.img = img
+ if Conf['Image Auto-Gif']
+ AutoGif.node post
+ if Conf['Time Formatting']
+ Time.node post
+ if Conf['File Info Formatting']
+ FileInfo.node post
- id = @hash[2..]
- if el = $.id "p#{id}"
- for klass in el.parentNode.className.split ' '
- # preserve highlight classes
- unless /^((op|reply|post)Container|forwarded)$/.test klass
- $.addClass qp, klass
- qp.innerHTML = el.innerHTML
+ if path[1] is g.BOARD and el = $.id "p#{id}"
if Conf['Quote Highlighting']
if /\bop\b/.test el.className
$.addClass el.parentNode, 'qphl'
else
$.addClass el, 'qphl'
- replyID = $.x('ancestor::div[contains(@class,"postContainer")]', @).id.match(/\d+$/)[0]
+ # can't use xpath because >firefox
+ parent = @parentNode
+ until parent.id
+ parent = parent.parentNode
+ quoterID = parent.id.match(/\d+$/)[0]
for quote in $$ '.quotelink, .backlink', qp
- if quote.hash[2..] is replyID
+ if quote.hash[2..] is quoterID
$.addClass quote, 'forwardlink'
- else
- qp.textContent = "Loading #{id}..."
- $.cache @pathname, -> QuotePreview.parse @, id
- UI.hover e
$.on @, 'mousemove', UI.hover
$.on @, 'mouseout click', QuotePreview.mouseout
- mouseout: ->
+ mouseout: (e) ->
UI.hoverend()
if el = $.id @hash[1..]
- if /\bop\b/.test el.className
- $.rmClass el.parentNode, 'qphl'
- else
- $.rmClass el, 'qphl'
+ $.rmClass el, 'qphl' # reply
+ $.rmClass el.parentNode, 'qphl' # op
$.off @, 'mousemove', UI.hover
$.off @, 'mouseout click', QuotePreview.mouseout
- parse: (req, id) ->
- return unless (qp = UI.el) and qp.textContent is "Loading #{id}..."
-
- if req.status isnt 200
- qp.textContent = "#{req.status} #{req.statusText}"
- return
-
- doc = d.implementation.createHTMLDocument ''
- doc.documentElement.innerHTML = req.response
-
- node = doc.getElementById "p#{id}"
- qp.innerHTML = node.innerHTML
- bq = $ 'blockquote', qp
- bq.id += '_qp'
- Main.prettify bq
- post =
- el: qp
- if fileInfo = $ '.fileInfo', qp
- img = fileInfo.nextElementSibling.firstElementChild
- if img.alt isnt 'File deleted.'
- post.fileInfo = fileInfo
- post.img = img
- if Conf['Image Auto-Gif']
- AutoGif.node post
- if Conf['Time Formatting']
- Time.node post
- if Conf['File Info Formatting']
- FileInfo.node post
QuoteOP =
init: ->
@@ -2579,7 +2590,7 @@ Quotify =
m[1]
else
# Get the post's board, whether it's inlined or not.
- $('.postInfo > .postNum > a:first-child', post.el).pathname.split('/')[1]
+ $('.postInfo > .postNum > a[title="Highlight this post"]', post.el).pathname.split('/')[1]
nodes.push a = $.el 'a',
# \u00A0 is nbsp
@@ -2592,6 +2603,7 @@ Quotify =
else
a.href = Redirect.thread board, id, 'post'
a.className = 'deadlink'
+ # a.className = if JSONable then 'quotelink deadlink' else 'deadlink'
a.target = '_blank'
data = data[index + quote.length..]
@@ -3197,16 +3209,16 @@ Main =
window.location = "https://raw.github.com/mayhemydg/4chan-x/#{version}/4chan_x.user.js"
preParse: (node) ->
- rootClass = node.className
+ parentClass = node.parentNode.className
el = $ '.post', node
post =
root: node
el: el
class: el.className
- id: el.id[1..]
- threadId: g.THREAD_ID or $.x('ancestor::div[parent::div[@class="board"]]', node).id[1..]
- isInlined: /\binline\b/.test rootClass
- isCrosspost: /\bcrosspost\b/.test rootClass
+ id: el.id.match(/\d+$/)[0]
+ threadId: g.THREAD_ID or $.x('ancestor::div[parent::div[@class="board"]]', node).id.match(/\d+$/)[0]
+ isInlined: /\binline\b/.test parentClass
+ isCrosspost: /\bcrosspost\b/.test parentClass
blockquote: el.lastElementChild
quotes: el.getElementsByClassName 'quotelink'
backlinks: el.getElementsByClassName 'backlink'
@@ -3597,8 +3609,12 @@ textarea.field {
}
#qp {
+ padding: 2px 2px 5px;
+}
+#qp .post {
+ border: none;
margin: 0;
- padding: 1px 2px 5px;
+ padding: 0;
}
#qp img {
max-height: 300px;
@@ -3607,26 +3623,15 @@ textarea.field {
.qphl {
outline: 2px solid rgba(216, 94, 49, .7);
}
-.qphl.opContainer {
- outline-offset: -2px;
-}
-div.opContainer {
- display: block !important;
-}
.inlined {
opacity: .5;
}
-.inline {
+.inline .post {
background-color: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(128, 128, 128, 0.5);
display: table;
margin: 2px;
-}
-.inline .post {
- background: none;
- border: none;
- margin: 0;
- padding: 0;
+ padding: 2px;
}
.opContainer.filter_highlight {
box-shadow: inset 5px 0 rgba(255,0,0,0.5);