From 94b9ff9c366853efcaba1cd8d2d407b712a716ad Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 3 Sep 2012 21:28:14 +0200 Subject: [PATCH] Add Quote Inlining. Close #501. --- 4chan_x.user.js | 231 +++++++++++++++++++++++++++++++++++++++------ script.coffee | 245 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 429 insertions(+), 47 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 46069f63c..393cedb73 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -73,7 +73,7 @@ */ (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, __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; }; - function Thread(root, board) { - var postInfo; - this.root = root; + function Thread(ID, board) { this.board = board; - this.ID = +root.id.slice(1); - this.hr = root.nextElementSibling; + this.ID = +ID; 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; } @@ -665,7 +659,8 @@ post: post, info: info, comment: $('.postMessage', post), - quotelinks: [] + quotelinks: [], + backlinks: info.getElementsByClassName('backlink') }; this.info = {}; if (subject = $('.subject', info)) { @@ -753,12 +748,11 @@ }; Post.prototype.rmClone = function(index) { - var clone, i, _i, _ref; - clone = this.clones.splice(index, 1); + var i, _i, _ref; + this.clones.splice(index, 1); 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); } - return $.rm(clone.nodes.root); }; return Post; @@ -770,7 +764,7 @@ __extends(Clone, _super); 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; _ref = ['ID', 'board', 'thread', 'info', 'quotes', 'isReply']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -786,8 +780,20 @@ post: post, info: info, 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) { this.nodes.subject = $('.subject', info); } @@ -812,18 +818,18 @@ if (nodes.date) { this.nodes.date = $('.dateTime', info); } - _ref1 = $$('.quotelink', this.nodes.comment); - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - quotelink = _ref1[_j]; + _ref3 = $$('.quotelink', this.nodes.comment); + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + quotelink = _ref3[_l]; if (quotelink.hash || $.hasClass(quotelink, 'deadlink')) { this.nodes.quotelinks.push(quotelink); } } if (origin.file) { this.file = {}; - _ref2 = origin.file; - for (key in _ref2) { - val = _ref2[key]; + _ref4 = origin.file; + for (key in _ref4) { + val = _ref4[key]; this.file[key] = val; } file = $('.file', post); @@ -832,7 +838,7 @@ this.file.thumb = $('img[data-md5]', file); } this.isClone = true; - index = origin.clones.push(this); + index = origin.clones.push(this) - 1; root.setAttribute('data-clone', index); } @@ -920,6 +926,13 @@ $.log(err, 'Resurrect Quotes'); } } + if (Conf['Quote Inline']) { + try { + QuoteInline.init(); + } catch (err) { + $.log(err, 'Quote Inline'); + } + } if (Conf['Quote Backlinks']) { try { QuoteBacklink.init(); @@ -949,7 +962,7 @@ if (!$.hasClass(boardChild, 'thread')) { continue; } - thread = new Thread(boardChild, g.BOARD); + thread = new Thread(boardChild.id.slice(1), g.BOARD); threads.push(thread); _ref1 = boardChild.children; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { @@ -993,7 +1006,75 @@ 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 = { @@ -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 = { init: function() { var format; @@ -1083,6 +1258,9 @@ for (_k = 0, _len2 = containers.length; _k < _len2; _k++) { container = containers[_k]; link = a.cloneNode(true); + if (Conf['Quote Inline']) { + $.on(link, 'click', QuoteInline.toggle); + } $.add(container, [$.tn(' '), link]); } } @@ -1090,9 +1268,7 @@ secondNode: function() { var container; if (this.isClone && this.origin.nodes.backlinkContainer) { - container = $('.container', this.nodes.info); - this.nodes.backlinkContainer = container; - this.nodes.backlinks = container.getElementsByClassName('backlinks'); + this.nodes.backlinkContainer = $('.container', this.nodes.info); return; } if (!(Conf['OP Backlinks'] || this.isReply)) { @@ -1100,7 +1276,6 @@ } container = QuoteBacklink.getContainer("" + this.board + "." + this); this.nodes.backlinkContainer = container; - this.nodes.backlinks = container.getElementsByClassName('backlinks'); return $.add(this.nodes.info, container); }, getContainer: function(id) { diff --git a/script.coffee b/script.coffee index 9c70564e3..fa3a25d72 100644 --- a/script.coffee +++ b/script.coffee @@ -486,14 +486,15 @@ class Thread callbacks: [] toString: -> @ID - constructor: (@root, @board) -> - @ID = +root.id[1..] - @hr = root.nextElementSibling + constructor: (ID, @board) -> + @ID = +ID @posts = {} - postInfo = $ '.postInfo', root.firstElementChild - @isClosed = !!$ 'img[title=Closed]', postInfo - @isSticky = !!$ 'img[title=Sticky]', postInfo + # XXX Can't check when parsing single posts + # move to Post constructor? unless @isReply + # postInfo = $ '.postInfo', root.firstElementChild + # @isClosed = !!$ 'img[title=Closed]', postInfo + # @isSticky = !!$ 'img[title=Sticky]', postInfo g.threads["#{board}.#{@}"] = board.threads[@] = @ @@ -512,6 +513,7 @@ class Post info: info comment: $ '.postMessage', post quotelinks: [] + backlinks: info.getElementsByClassName 'backlink' @info = {} if subject = $ '.subject', info @@ -595,10 +597,10 @@ class Post addClone: -> new Clone @ rmClone: (index) -> - clone = @clones.splice index, 1 + @clones.splice index, 1 for i in [index...@clones.length] @clones[i].nodes.root.setAttribute 'data-clone', i - $.rm clone.nodes.root + return class Clone extends Post constructor: (@origin) -> @@ -616,6 +618,17 @@ class Clone extends Post info: info comment: $ '.postMessage', post 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 @nodes.subject = $ '.subject', info @@ -651,7 +664,7 @@ class Clone extends Post @file.thumb = $ 'img[data-md5]', file @isClone = true - index = origin.clones.push @ + index = origin.clones.push(@) - 1 root.setAttribute 'data-clone', index @@ -726,6 +739,13 @@ Main = # XXX handle error $.log err, 'Resurrect Quotes' + if Conf['Quote Inline'] + try + QuoteInline.init() + catch err + # XXX handle error + $.log err, 'Quote Inline' + if Conf['Quote Backlinks'] try QuoteBacklink.init() @@ -749,7 +769,7 @@ Main = for boardChild in $('.board').children continue unless $.hasClass boardChild, 'thread' - thread = new Thread boardChild, g.BOARD + thread = new Thread boardChild.id[1..], g.BOARD threads.push thread for threadChild in boardChild.children continue unless $.hasClass threadChild, 'postContainer' @@ -793,6 +813,9 @@ Main = label { cursor: pointer; } +.warning { + color: red; +} /* 4chan style fixes */ .opContainer, .op { @@ -832,10 +855,101 @@ body.fourchan_x { #settings { 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 = init: -> Post::callbacks.push @@ -884,7 +998,6 @@ Quotify = # if board is g.BOARD and $.id "p#{ID}" # a.href = "#p#{ID}" # a.className = 'quotelink' - # a.setAttribute 'onclick', "replyhl('#{ID}');" # else # a.href = Redirect.thread board, 0, ID # a.className = 'deadlink' @@ -905,6 +1018,105 @@ Quotify = $.replace node, nodes 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 = # Backlinks appending need to work for: # - previous, same, and following posts. @@ -944,23 +1156,18 @@ QuoteBacklink = # XXX # if Conf['Quote Preview'] # $.on link, 'mouseover', QuotePreview.mouseover - # if Conf['Quote Inline'] - # $.on link, 'click', QuoteInline.toggle - # else - # link.setAttribute 'onclick', "replyhl('#{post.ID}');" + if Conf['Quote Inline'] + $.on link, 'click', QuoteInline.toggle $.add container, [$.tn(' '), link] return secondNode: -> if @isClone and @origin.nodes.backlinkContainer - container = $ '.container', @nodes.info - @nodes.backlinkContainer = container - @nodes.backlinks = container.getElementsByClassName 'backlinks' + @nodes.backlinkContainer = $ '.container', @nodes.info return # Don't backlink the OP. return unless Conf['OP Backlinks'] or @isReply container = QuoteBacklink.getContainer "#{@board}.#{@}" @nodes.backlinkContainer = container - @nodes.backlinks = container.getElementsByClassName 'backlinks' $.add @nodes.info, container getContainer: (id) -> @containers[id] or=