From 55cbf0ddf40a7ad97c5e94d604d601e62912a053 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sat, 28 Apr 2012 14:54:48 +0200 Subject: [PATCH 01/52] Start working on the new HTML format. --- 4chan_x.user.js | 96 +++++++++++++++------------------------------- script.coffee | 100 +++++++++++++++--------------------------------- 2 files changed, 61 insertions(+), 135 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 7b2a01f44..971398873 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, Threading, Time, TitlePost, UI, Unread, Updater, Watcher, d, g, _base; + 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; Config = { main: { @@ -791,7 +791,6 @@ } doc = d.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = req.response; - Threading.op($('body > form', doc).firstChild); node = d.importNode(doc.getElementById(replyID)); quotes = node.getElementsByClassName('quotelink'); for (_i = 0, _len = quotes.length; _i < _len; _i++) { @@ -1347,7 +1346,7 @@ } return $('textarea', QR.el).focus(); }); - $.before($('form[name=post]'), link); + $.before($.id('postForm'), link); } script = $.el('script', { textContent: 'Recaptcha.focus_response_field=function(){}' @@ -1841,7 +1840,7 @@ }); ta.style.cssText = $.get('QR.size', ''); } - mimeTypes = $('.rules').firstChild.textContent.match(/: (.+) /)[1].toLowerCase().replace(/\w+/g, function(type) { + mimeTypes = $('ul.rules').firstElementChild.textContent.match(/: (.+) /)[1].toLowerCase().replace(/\w+/g, function(type) { switch (type) { case 'jpg': return 'image/jpeg'; @@ -2379,46 +2378,6 @@ } }; - Threading = { - op: function(node) { - var nodes, op; - nodes = []; - while (node.nodeName !== 'BLOCKQUOTE') { - nodes.push(node); - node = node.nextSibling; - } - nodes.push(node); - node = node.nextSibling; - op = $.el('div', { - className: 'op' - }); - $.add(op, nodes); - op.id = $('input', op).name; - return $.before(node, op); - }, - thread: function(node) { - var div, nodes; - node = Threading.op(node); - if (g.REPLY) { - return; - } - nodes = []; - while (node.nodeName !== 'HR') { - nodes.push(node); - node = node.nextElementSibling; - } - div = $.el('div', { - className: 'thread' - }); - $.add(div, nodes); - $.before(node, div); - node = node.nextElementSibling; - if (!(node.align || node.nodeName === 'CENTER')) { - return Threading.thread(node); - } - } - }; - ThreadHiding = { init: function() { var a, hiddenThreads, op, thread, _i, _len, _ref; @@ -3078,18 +3037,19 @@ }; GetTitle = function(thread) { - var el, span; - el = $('.filetitle', thread); + var el, op, span; + op = $('.op', thread); + el = $('.subject', op); if (!el.textContent) { - el = $('blockquote', thread); + el = $('blockquote', op); if (!el.textContent) { - el = $('.postername', thread); + el = $('.nameBlock', op); } } span = $.el('span', { innerHTML: el.innerHTML.replace(/
/g, ' ') }); - return "/" + g.BOARD + "/ - " + span.textContent; + return "/" + g.BOARD + "/ - " + (span.textContent.trim()); }; TitlePost = { @@ -3254,7 +3214,7 @@ } doc = d.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = req.response; - node = id === threadID ? Threading.op($('body > form', doc).firstChild) : doc.getElementById(id); + node = doc.getElementById(id); newInline = QuoteInline.table(id, node.innerHTML); _ref = $$('.quotelink', newInline); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -3355,7 +3315,7 @@ } doc = d.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = req.response; - node = id === threadID ? Threading.op($('body > form', doc).firstChild) : doc.getElementById(id); + node = doc.getElementById(id); qp.innerHTML = node.innerHTML; post = { root: qp, @@ -3961,7 +3921,6 @@ val = Conf[key]; Conf[key] = $.get(key, val); } - $.on(window, 'message', Main.message); switch (location.hostname) { case 'sys.4chan.org': if (/report/.test(location.search)) { @@ -3984,11 +3943,12 @@ } $.ready(Options.init); if (Conf['Quick Reply'] && Conf['Hide Original Post Form'] && g.BOARD !== 'f') { - Main.css += 'form[name=post] { display: none; }'; + Main.css += '#postForm { display: none; }'; } Main.addStyle(); now = Date.now(); if (Conf['Check for Updates'] && $.get('lastUpdate', 0) < now - 6 * $.HOUR) { + $.on(window, 'message', Main.message); $.ready(function() { return $.add(d.head, $.el('script', { src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js' @@ -4071,7 +4031,7 @@ return $.ready(Main.ready); }, ready: function() { - var MutationObserver, form, nav, node, nodes, observer, _i, _j, _len, _len1, _ref, _ref1; + var MutationObserver, a, board, nav, node, nodes, observer, _i, _j, _len, _len1, _ref, _ref1; if (d.title === '4chan - 404') { Redirect.init(); return; @@ -4081,13 +4041,13 @@ } $.addClass(d.body, "chanx_" + (Main.version.split('.')[1])); $.addClass(d.body, $.engine); - _ref = ['navtop', 'navbot']; + _ref = ['boardNavDesktop', 'boardNavDesktopFoot']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { nav = _ref[_i]; - $.addClass($("a[href$='/" + g.BOARD + "/']", $.id(nav)), 'current'); + if (a = $("a[href$='/" + g.BOARD + "/']", $.id(nav))) { + $.addClass(a, 'current'); + } } - form = $('form[name=delform]'); - Threading.thread(form.firstElementChild); Favicon.init(); if (Conf['Quick Reply']) { QR.init(); @@ -4147,8 +4107,9 @@ }); } } + board = $('.board'); nodes = []; - _ref1 = $$('.op, a + table', form); + _ref1 = $$('.post', board); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { node = _ref1[_j]; nodes.push(Main.preParse(node)); @@ -4156,12 +4117,12 @@ Main.node(nodes, true); if (MutationObserver = window.WebKitMutationObserver || window.MozMutationObserver || window.OMutationObserver || window.MutationObserver) { observer = new MutationObserver(Main.observer); - return observer.observe(form, { + return observer.observe(board, { childList: true, subtree: true }); } else { - return $.on(form, 'DOMNodeInserted', Main.listener); + return $.on(board, 'DOMNodeInserted', Main.listener); } }, flatten: function(parent, obj) { @@ -4196,13 +4157,13 @@ var klass, post; klass = node.className; post = { - root: node, - el: klass === 'op' ? node : node.firstChild.firstChild.lastChild, + root: node.parentNode, + el: node, "class": klass, - id: node.getElementsByTagName('input')[0].name, - threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).firstChild.id, + id: node.id.slice(1), + threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).id.slice(1), isInlined: /\binline\b/.test(klass), - filesize: node.getElementsByClassName('filesize')[0] || false, + fileinfo: node.getElementsByClassName('fileInfo')[0] || false, quotes: node.getElementsByClassName('quotelink'), backlinks: node.getElementsByClassName('backlink') }; @@ -4275,6 +4236,9 @@ a[href="javascript:;"] {\ display: none;\ }\ \ +h1 {\ + text-align: center;\ +}\ .autohide:not(:hover) > form {\ display: none;\ }\ diff --git a/script.coffee b/script.coffee index 8e930ed96..fc88e1e05 100644 --- a/script.coffee +++ b/script.coffee @@ -628,7 +628,6 @@ ExpandComment = doc = d.implementation.createHTMLDocument '' doc.documentElement.innerHTML = req.response - Threading.op $('body > form', doc).firstChild # Import the node to fix quote.hashes # as they're empty when in a different document. node = d.importNode doc.getElementById replyID @@ -1014,9 +1013,9 @@ QR = link = $.el 'h1', innerHTML: "#{if g.REPLY then 'Quick Reply' else 'New Thread'}" $.on link.firstChild, 'click', -> QR.open() - $('select', QR.el).value = 'new' unless g.REPLY + $('select', QR.el).value = 'new' unless g.REPLY $('textarea', QR.el).focus() - $.before $('form[name=post]'), link + $.before $.id('postForm'), link # Prevent original captcha input from being focused on reload. script = $.el 'script', @@ -1405,7 +1404,7 @@ QR = ta.style.cssText = $.get 'QR.size', '' # Allow only this board's supported files. - mimeTypes = $('.rules').firstChild.textContent.match(/: (.+) /)[1].toLowerCase().replace /\w+/g, (type) -> + mimeTypes = $('ul.rules').firstElementChild.textContent.match(/: (.+) /)[1].toLowerCase().replace /\w+/g, (type) -> switch type when 'jpg' 'image/jpeg' @@ -1876,39 +1875,6 @@ Options = Unread.update true @nextElementSibling.innerHTML = " " -Threading = - op: (node) -> - nodes = [] - until node.nodeName is 'BLOCKQUOTE' - nodes.push node - node = node.nextSibling - nodes.push node # Add the blockquote. - node = node.nextSibling - op = $.el 'div', - className: 'op' - $.add op, nodes - op.id = $('input', op).name - $.before node, op - - thread: (node) -> - node = Threading.op node - - return if g.REPLY - - nodes = [] - until node.nodeName is 'HR' - nodes.push node - node = node.nextElementSibling # Skip text nodes. - div = $.el 'div', - className: 'thread' - $.add div, nodes - $.before node, div - - node = node.nextElementSibling - # {N,}SFW - unless node.align or node.nodeName is 'CENTER' - Threading.thread node - ThreadHiding = init: -> hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} @@ -2407,13 +2373,14 @@ FileInfo = r: -> FileInfo.data.resolution GetTitle = (thread) -> - el = $ '.filetitle', thread - if not el.textContent - el = $ 'blockquote', thread - if not el.textContent - el = $ '.postername', thread + op = $ '.op', thread + el = $ '.subject', op + unless el.textContent + el = $ 'blockquote', op + unless el.textContent + el = $ '.nameBlock', op span = $.el 'span', innerHTML: el.innerHTML.replace /
/g, ' ' - "/#{g.BOARD}/ - #{span.textContent}" + "/#{g.BOARD}/ - #{span.textContent.trim()}" TitlePost = init: -> @@ -2525,11 +2492,7 @@ QuoteInline = doc = d.implementation.createHTMLDocument '' doc.documentElement.innerHTML = req.response - node = - if id is threadID #OP - Threading.op $('body > form', doc).firstChild - else - doc.getElementById id + node = doc.getElementById id newInline = QuoteInline.table id, node.innerHTML for quote in $$ '.quotelink', newInline if (href = quote.getAttribute 'href') is quote.hash #add pathname to normal quotes @@ -2599,11 +2562,7 @@ QuotePreview = doc = d.implementation.createHTMLDocument '' doc.documentElement.innerHTML = req.response - node = - if id is threadID #OP - Threading.op $('body > form', doc).firstChild - else - doc.getElementById id + node = doc.getElementById id qp.innerHTML = node.innerHTML post = root: qp @@ -3043,12 +3002,10 @@ Main = g.REPLY = true g.THREAD_ID = pathname[2] - #load values from localStorage + # Load values from localStorage. for key, val of Conf Conf[key] = $.get key, val - $.on window, 'message', Main.message - switch location.hostname when 'sys.4chan.org' if /report/.test location.search @@ -3063,12 +3020,13 @@ Main = $.ready Options.init if Conf['Quick Reply'] and Conf['Hide Original Post Form'] and g.BOARD isnt 'f' - Main.css += 'form[name=post] { display: none; }' + Main.css += '#postForm { display: none; }' Main.addStyle() now = Date.now() if Conf['Check for Updates'] and $.get('lastUpdate', 0) < now - 6*$.HOUR + $.on window, 'message', Main.message $.ready -> $.add d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js' $.set 'lastUpdate', now @@ -3153,10 +3111,10 @@ Main = return $.addClass d.body, "chanx_#{Main.version.split('.')[1]}" $.addClass d.body, $.engine - for nav in ['navtop', 'navbot'] - $.addClass $("a[href$='/#{g.BOARD}/']", $.id nav), 'current' - form = $ 'form[name=delform]' - Threading.thread form.firstElementChild + for nav in ['boardNavDesktop', 'boardNavDesktopFoot'] + if a = $ "a[href$='/#{g.BOARD}/']", $.id nav + # Gotta make it work in temporary boards. + $.addClass a, 'current' Favicon.init() # Major features. @@ -3201,18 +3159,19 @@ Main = if Conf['Index Navigation'] setTimeout -> Nav.init() + board = $ '.board' nodes = [] - for node in $$ '.op, a + table', form + for node in $$ '.post', board nodes.push Main.preParse node Main.node nodes, true if MutationObserver = window.WebKitMutationObserver or window.MozMutationObserver or window.OMutationObserver or window.MutationObserver observer = new MutationObserver Main.observer - observer.observe form, + observer.observe board, childList: true subtree: true else - $.on form, 'DOMNodeInserted', Main.listener + $.on board, 'DOMNodeInserted', Main.listener flatten: (parent, obj) -> if obj instanceof Array @@ -3239,13 +3198,13 @@ Main = preParse: (node) -> klass = node.className post = - root: node - el: if klass is 'op' then node else node.firstChild.firstChild.lastChild + root: node.parentNode + el: node class: klass - id: node.getElementsByTagName('input')[0].name - threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).firstChild.id + id: node.id[1..] + threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).id[1..] isInlined: /\binline\b/.test klass - filesize: node.getElementsByClassName('filesize')[0] or false + fileinfo: node.getElementsByClassName('fileInfo')[0] or false quotes: node.getElementsByClassName 'quotelink' backlinks: node.getElementsByClassName 'backlink' post.img = if post.filesize then node.getElementsByTagName('img')[0] else false @@ -3292,6 +3251,9 @@ a[href="javascript:;"] { display: none; } +h1 { + text-align: center; +} .autohide:not(:hover) > form { display: none; } From 1cdac37ecf788a26f132844566d56b64b0d6c4ce Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sat, 28 Apr 2012 16:24:17 +0200 Subject: [PATCH 02/52] More new HTML work. --- 4chan_x.user.js | 114 +++++++++++++++++++++++------------------------- script.coffee | 105 ++++++++++++++++++++++---------------------- 2 files changed, 108 insertions(+), 111 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 971398873..e9a4f794e 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -621,8 +621,8 @@ if (post.isInlined) { return; } - post.isOP = post["class"] === 'op'; - isOP = post.isOP, el = post.el; + isOP = post["class"] === 'op'; + el = post.el; for (key in Filter.filters) { value = Filter[key](post); if (value === false) { @@ -647,13 +647,13 @@ return; } if (isOP) { - $.addClass(el, result[0]); - } else { $.addClass(el.parentNode, result[0]); + } else { + $.addClass(el, result[0]); } if (isOP && result[1] && !g.REPLY) { - thisThread = el.parentNode; - if (firstThread = $('div[class=op]')) { + thisThread = el.parentNode.parentNode; + if (firstThread = $('div[class="postContainer opContainer"]')) { $.before(firstThread.parentNode, [thisThread, thisThread.nextElementSibling]); } } @@ -661,9 +661,7 @@ } }, name: function(post) { - var name; - name = post.isOP ? $('.postername', post.el) : $('.commentpostername', post.el); - return name.textContent; + return $('.name', post.el).textContent || false; }, uniqueid: function(post) { var uid; @@ -681,44 +679,42 @@ }, mod: function(post) { var mod; - if (mod = (post.isOP ? $('.commentpostername', post.el) : $('.commentpostername ~ .commentpostername', post.el))) { + if (mod = $('.capcode', post.el)) { return mod.textContent; } return false; }, email: function(post) { var mail; - if (mail = $('.linkmail', post.el)) { + if (mail = $('.useremail', post.el)) { return mail.href; } return false; }, subject: function(post) { - var sub; - sub = post.isOP ? $('.filetitle', post.el) : $('.replytitle', post.el); - return sub.textContent; + return $('.subject', post.el).textContent || false; }, comment: function(post) { var data, i, nodes, text, _i, _ref; text = []; - nodes = d.evaluate('.//br|.//text()', post.el.lastChild, null, 7, null); + nodes = d.evaluate('.//br|.//text()', post.el.lastElementChild, null, 7, null); for (i = _i = 0, _ref = nodes.snapshotLength; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { text.push((data = nodes.snapshotItem(i).data) ? data : '\n'); } return text.join(''); }, filename: function(post) { - var file, filesize; - filesize = post.filesize; - if (filesize && (file = $('span', filesize))) { + var file, fileinfo; + fileinfo = post.fileinfo; + if (fileinfo && (file = $('span', fileinfo))) { return file.title; } return false; }, dimensions: function(post) { - var filesize, match; - filesize = post.filesize; - if (filesize && (match = filesize.textContent.match(/\d+x\d+/))) { + var fileinfo, match; + fileinfo = post.fileinfo; + if (fileinfo && (match = fileinfo.textContent.match(/\d+x\d+/))) { return match[0]; } return false; @@ -735,7 +731,7 @@ var img; img = post.img; if (img) { - return img.getAttribute('md5'); + return img.dataset.md5; } return false; } @@ -1197,7 +1193,7 @@ if (all) { return $.id('imageExpand').click(); } else { - thumb = $('img[md5]', $('.replyhl', thread) || thread); + thumb = $('img[data-md5]', $('.replyhl', thread) || thread); return ImageExpand.toggle(thumb.parentNode); } }, @@ -2807,11 +2803,10 @@ node: function(post) { var img; img = post.img; - if (!(img && /^Spoil/.test(img.alt)) || post["class"] === 'inline') { + if (!(img && /\bimgspoiler\b/.test(img.parentNode.className)) || post["class"] === 'inline') { return; } - img.removeAttribute('height'); - img.removeAttribute('width'); + img.removeAttribute('style'); return img.src = "//thumbs.4chan.org" + (img.parentNode.pathname.replace(/src(\/\d+).+$/, 'thumb$1s.jpg')); } }; @@ -2824,11 +2819,11 @@ if ($.isDST()) { chanOffset--; } - this.parse = Date.parse('10/11/11(Tue)18:53') === 1318351980000 ? function(node) { - return new Date(Date.parse(node.textContent) + chanOffset * $.HOUR); - } : function(node) { + this.parse = Date.parse('10/11/11(Tue)18:53') === 1318351980000 ? function(text) { + return new Date(Date.parse(text) + chanOffset * $.HOUR); + } : function(text) { var day, hour, min, month, year, _, _ref; - _ref = node.textContent.match(/(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/), _ = _ref[0], month = _ref[1], day = _ref[2], year = _ref[3], hour = _ref[4], min = _ref[5]; + _ref = text.match(/(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/), _ = _ref[0], month = _ref[1], day = _ref[2], year = _ref[3], hour = _ref[4], min = _ref[5]; year = "20" + year; month--; hour = chanOffset + Number(hour); @@ -2837,17 +2832,14 @@ return Main.callbacks.push(this.node); }, node: function(post) { - var node, time; + var node; if (post["class"] === 'inline') { return; } - node = $('.posttime', post.el) || $('span[id]', post.el).previousSibling; - Time.date = Time.parse(node); - time = $.el('time', { - textContent: ' ' + Time.funk(Time) + ' ' - }); - time.setAttribute('datetime', Time.date.toISOString()); - return $.replace(node, time); + node = $('.dateTime', post.el); + Time.date = Time.parse(node.textContent); + node.textContent = Time.funk(Time); + return node.dataset.time = Time.date.toISOString(); }, foo: function() { var code; @@ -3320,7 +3312,7 @@ post = { root: qp, filesize: $('.filesize', qp), - img: $('img[md5]', qp) + img: $('img[data-md5]', qp) }; if (Conf['Image Auto-Gif']) { AutoGif.node(post); @@ -3346,7 +3338,7 @@ _ref = post.quotes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { quote = _ref[_i]; - if (quote.hash.slice(1) === post.threadId) { + if (quote.hash.slice(2) === post.threadId) { $.add(quote, $.tn('\u00A0(OP)')); } } @@ -3385,7 +3377,7 @@ if (post["class"] === 'inline') { return; } - snapshot = d.evaluate('.//text()[not(parent::a)]', post.el.lastChild, null, 6, null); + snapshot = d.evaluate('.//text()[not(parent::a)]', post.el.lastElementChild, null, 6, null); for (i = _i = 0, _ref = snapshot.snapshotLength; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { node = snapshot.snapshotItem(i); data = node.data; @@ -3505,7 +3497,7 @@ if (post.root.hidden || post["class"]) { return; } - count = Unread.replies.push(post.root); + count = Unread.replies.push(post.el); return Unread.update(count === 1); }, scroll: function() { @@ -3773,7 +3765,7 @@ var i, thumb, thumbs, _i, _j, _k, _len, _len1, _len2, _ref; ImageExpand.on = this.checked; if (ImageExpand.on) { - thumbs = $$('img[md5]'); + thumbs = $$('img[data-md5]'); if (Conf['Expand From Current']) { for (i = _i = 0, _len = thumbs.length; _i < _len; i = ++_i) { thumb = thumbs[i]; @@ -3788,7 +3780,7 @@ ImageExpand.expand(thumb); } } else { - _ref = $$('img[md5][hidden]'); + _ref = $$('img[data-md5][hidden]'); for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) { thumb = _ref[_k]; ImageExpand.contract(thumb); @@ -3886,7 +3878,7 @@ }); }, dialog: function() { - var controls, form, imageType, select; + var controls, imageType, select; controls = $.el('div', { id: 'imgControls', innerHTML: "" @@ -3898,11 +3890,10 @@ $.on(select, 'change', $.cb.value); $.on(select, 'change', ImageExpand.cb.typeChange); $.on($('input', controls), 'click', ImageExpand.cb.all); - form = $('body > form'); - return $.prepend(form, controls); + return $.prepend($.id('delform'), controls); }, resize: function() { - return ImageExpand.style.textContent = ".fitheight img[md5] + img {max-height:" + d.body.clientHeight + "px;}"; + return ImageExpand.style.textContent = ".fitheight img[data-md5] + img {max-height:" + d.body.clientHeight + "px;}"; } }; @@ -4154,7 +4145,7 @@ } }, preParse: function(node) { - var klass, post; + var file, klass, post; klass = node.className; post = { root: node.parentNode, @@ -4163,11 +4154,16 @@ id: node.id.slice(1), threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).id.slice(1), isInlined: /\binline\b/.test(klass), - fileinfo: node.getElementsByClassName('fileInfo')[0] || false, quotes: node.getElementsByClassName('quotelink'), backlinks: node.getElementsByClassName('backlink') }; - post.img = post.filesize ? node.getElementsByTagName('img')[0] : false; + if (file = $('.file', node)) { + post.fileinfo = file.firstElementChild; + post.img = file.lastElementChild.firstElementChild; + } else { + post.fileinfo = false; + post.img = false; + } return post; }, node: function(nodes, notify) { @@ -4195,7 +4191,7 @@ _ref = mutation.addedNodes; for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { addedNode = _ref[_j]; - if (addedNode.nodeName === 'TABLE') { + if (addedNode.nodeName === 'DIV' && /\bpostContainer\b/.test(addedNode.className)) { nodes.push(Main.preParse(addedNode)); } } @@ -4207,7 +4203,7 @@ listener: function(e) { var target; target = e.target; - if (target.nodeName === 'TABLE') { + if (target.nodeName === 'DIV' && /\bpostContainer\b/.test(addedNode.className)) { return Main.node([Main.preParse(target)]); } }, @@ -4445,23 +4441,23 @@ textarea.field {\ .filename:not(:hover) > .fnfull {\ display: none;\ }\ -img[md5], img[md5] + img {\ +img[data-md5], img[data-md5] + img {\ pointer-events: all;\ }\ -.fitwidth img[md5] + img {\ +.fitwidth img[data-md5] + img {\ max-width: 100%;\ }\ -.gecko > .fitwidth img[md5] + img,\ -.presto > .fitwidth img[md5] + img {\ +.gecko > .fitwidth img[data-md5] + img,\ +.presto > .fitwidth img[data-md5] + img {\ width: 100%;\ }\ /* revealed spoilers do not have height/width,\ this fixes "expanded" auto-gifs */\ -img[md5] {\ +img[data-md5] {\ max-height: 252px;\ max-width: 252px;\ }\ -input ~ a > img[md5] {\ +input ~ a > img[data-md5] {\ max-height: 127px;\ max-width: 127px;\ }\ diff --git a/script.coffee b/script.coffee index fc88e1e05..a3f25dcc2 100644 --- a/script.coffee +++ b/script.coffee @@ -513,8 +513,8 @@ Filter = node: (post) -> return if post.isInlined - post.isOP = post.class is 'op' - {isOP, el} = post + isOP = post.class is 'op' + {el} = post for key of Filter.filters value = Filter[key] post if value is false @@ -537,20 +537,20 @@ Filter = # Highlight if isOP - $.addClass el, result[0] - else $.addClass el.parentNode, result[0] + else + $.addClass el, result[0] if isOP and result[1] and not g.REPLY # Put the highlighted OPs' threads on top of the board pages... - thisThread = el.parentNode + thisThread = el.parentNode.parentNode # ...before the first non highlighted thread. - if firstThread = $ 'div[class=op]' + if firstThread = $ 'div[class="postContainer opContainer"]' $.before firstThread.parentNode, [thisThread, thisThread.nextElementSibling] name: (post) -> - name = if post.isOP then $ '.postername', post.el else $ '.commentpostername', post.el - name.textContent + $('.name', post.el).textContent or false uniqueid: (post) -> + # NEW FORMAT ??? if uid = $ '.posteruid', post.el return uid.textContent false @@ -559,31 +559,30 @@ Filter = return trip.textContent false mod: (post) -> - if mod = (if post.isOP then $ '.commentpostername', post.el else $ '.commentpostername ~ .commentpostername', post.el) + if mod = $ '.capcode', post.el return mod.textContent false email: (post) -> - if mail = $ '.linkmail', post.el + if mail = $ '.useremail', post.el return mail.href false subject: (post) -> - sub = if post.isOP then $ '.filetitle', post.el else $ '.replytitle', post.el - sub.textContent + $('.subject', post.el).textContent or false comment: (post) -> text = [] # XPathResult.ORDERED_NODE_SNAPSHOT_TYPE is 7 - nodes = d.evaluate './/br|.//text()', post.el.lastChild, null, 7, null + nodes = d.evaluate './/br|.//text()', post.el.lastElementChild, null, 7, null for i in [0...nodes.snapshotLength] text.push if data = nodes.snapshotItem(i).data then data else '\n' text.join '' filename: (post) -> - {filesize} = post - if filesize and file = $ 'span', filesize + {fileinfo} = post + if fileinfo and file = $ 'span', fileinfo return file.title false dimensions: (post) -> - {filesize} = post - if filesize and match = filesize.textContent.match /\d+x\d+/ + {fileinfo} = post + if fileinfo and match = fileinfo.textContent.match /\d+x\d+/ return match[0] false filesize: (post) -> @@ -594,7 +593,7 @@ Filter = md5: (post) -> {img} = post if img - return img.getAttribute 'md5' + return img.dataset.md5 false StrikethroughQuotes = @@ -895,7 +894,7 @@ Keybinds = if all $.id('imageExpand').click() else - thumb = $ 'img[md5]', $('.replyhl', thread) or thread + thumb = $ 'img[data-md5]', $('.replyhl', thread) or thread ImageExpand.toggle thumb.parentNode qr: (thread, quote) -> @@ -2220,10 +2219,9 @@ RevealSpoilers = Main.callbacks.push @node node: (post) -> {img} = post - if not (img and /^Spoil/.test img.alt) or post.class is 'inline' + if not (img and /\bimgspoiler\b/.test img.parentNode.className) or post.class is 'inline' return - img.removeAttribute 'height' - img.removeAttribute 'width' + img.removeAttribute 'style' img.src = "//thumbs.4chan.org#{img.parentNode.pathname.replace(/src(\/\d+).+$/, 'thumb$1s.jpg')}" Time = @@ -2237,11 +2235,11 @@ Time = @parse = if Date.parse('10/11/11(Tue)18:53') is 1318351980000 - (node) -> new Date Date.parse(node.textContent) + chanOffset*$.HOUR + (text) -> new Date Date.parse(text) + chanOffset*$.HOUR else # Firefox and Opera do not parse 4chan's time format correctly - (node) -> + (text) -> [_, month, day, year, hour, min] = - node.textContent.match /(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/ + text.match /(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/ year = "20#{year}" month-- # Months start at 0 hour = chanOffset + Number hour @@ -2251,13 +2249,11 @@ Time = node: (post) -> return if post.class is 'inline' # .posttime exists on every board except /f/ - node = $('.posttime', post.el) or $('span[id]', post.el).previousSibling - Time.date = Time.parse node - time = $.el 'time', - textContent: ' ' + Time.funk(Time) + ' ' + node = $ '.dateTime', post.el + Time.date = Time.parse node.textContent + node.textContent = Time.funk(Time) # Set the datetime attribute, ISO'd. - time.setAttribute 'datetime', Time.date.toISOString() - $.replace node, time + node.dataset.time = Time.date.toISOString() foo: -> code = Conf['time'].replace /%([A-Za-z])/g, (s, c) -> if c of Time.formatters @@ -2566,8 +2562,8 @@ QuotePreview = qp.innerHTML = node.innerHTML post = root: qp - filesize: $ '.filesize', qp - img: $ 'img[md5]', qp + filesize: $ '.filesize', qp + img: $ 'img[data-md5]', qp if Conf['Image Auto-Gif'] AutoGif.node post if Conf['Time Formatting'] @@ -2581,7 +2577,7 @@ QuoteOP = node: (post) -> return if post.class is 'inline' for quote in post.quotes - if quote.hash[1..] is post.threadId + if quote.hash[2..] is post.threadId # \u00A0 is nbsp $.add quote, $.tn '\u00A0(OP)' return @@ -2610,7 +2606,7 @@ Quotify = # XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE is 6 # Get all the text nodes that are not inside an anchor. - snapshot = d.evaluate './/text()[not(parent::a)]', post.el.lastChild, null, 6, null + snapshot = d.evaluate './/text()[not(parent::a)]', post.el.lastElementChild, null, 6, null for i in [0...snapshot.snapshotLength] node = snapshot.snapshotItem i @@ -2715,7 +2711,7 @@ Unread = Unread.foresee.splice index, 1 return return if post.root.hidden or post.class - count = Unread.replies.push post.root + count = Unread.replies.push post.el Unread.update count is 1 scroll: -> @@ -2895,7 +2891,7 @@ ImageExpand = all: -> ImageExpand.on = @checked if ImageExpand.on #expand - thumbs = $$ 'img[md5]' + thumbs = $$ 'img[data-md5]' if Conf['Expand From Current'] for thumb, i in thumbs if thumb.getBoundingClientRect().top > 0 @@ -2904,7 +2900,7 @@ ImageExpand = for thumb in thumbs ImageExpand.expand thumb else #contract - for thumb in $$ 'img[md5][hidden]' + for thumb in $$ 'img[data-md5][hidden]' ImageExpand.contract thumb return typeChange: -> @@ -2985,11 +2981,10 @@ ImageExpand = $.on select, 'change', ImageExpand.cb.typeChange $.on $('input', controls), 'click', ImageExpand.cb.all - form = $ 'body > form' - $.prepend form, controls + $.prepend $.id('delform'), controls resize: -> - ImageExpand.style.textContent = ".fitheight img[md5] + img {max-height:#{d.body.clientHeight}px;}" + ImageExpand.style.textContent = ".fitheight img[data-md5] + img {max-height:#{d.body.clientHeight}px;}" Main = init: -> @@ -3197,17 +3192,21 @@ Main = preParse: (node) -> klass = node.className - post = + post = root: node.parentNode el: node class: klass id: node.id[1..] threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).id[1..] isInlined: /\binline\b/.test klass - fileinfo: node.getElementsByClassName('fileInfo')[0] or false quotes: node.getElementsByClassName 'quotelink' backlinks: node.getElementsByClassName 'backlink' - post.img = if post.filesize then node.getElementsByTagName('img')[0] else false + if file = $ '.file', node + post.fileinfo = file.firstElementChild + post.img = file.lastElementChild.firstElementChild + else + post.fileinfo = false + post.img = false post node: (nodes, notify) -> for callback in Main.callbacks @@ -3220,11 +3219,13 @@ Main = nodes = [] for mutation in mutations for addedNode in mutation.addedNodes - nodes.push Main.preParse addedNode if addedNode.nodeName is 'TABLE' + if addedNode.nodeName is 'DIV' and /\bpostContainer\b/.test addedNode.className + nodes.push Main.preParse addedNode Main.node nodes if nodes.length listener: (e) -> {target} = e - Main.node [Main.preParse target] if target.nodeName is 'TABLE' + if target.nodeName is 'DIV' and /\bpostContainer\b/.test addedNode.className + Main.node [Main.preParse target] namespace: '4chan_x.' version: '2.29.3' @@ -3460,23 +3461,23 @@ textarea.field { .filename:not(:hover) > .fnfull { display: none; } -img[md5], img[md5] + img { +img[data-md5], img[data-md5] + img { pointer-events: all; } -.fitwidth img[md5] + img { +.fitwidth img[data-md5] + img { max-width: 100%; } -.gecko > .fitwidth img[md5] + img, -.presto > .fitwidth img[md5] + img { +.gecko > .fitwidth img[data-md5] + img, +.presto > .fitwidth img[data-md5] + img { width: 100%; } /* revealed spoilers do not have height/width, this fixes "expanded" auto-gifs */ -img[md5] { +img[data-md5] { max-height: 252px; max-width: 252px; } -input ~ a > img[md5] { +input ~ a > img[data-md5] { max-height: 127px; max-width: 127px; } From f22ea17429a575080835f0f48696708715680389 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 14:26:46 +0200 Subject: [PATCH 03/52] Fix Sauces. NBSPs seem to be necessary. --- 4chan_x.user.js | 6 +++--- script.coffee | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index e9a4f794e..29011bdd6 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2762,7 +2762,7 @@ case '$2': return "' + img.href + '"; case '$3': - return "' + img.firstChild.getAttribute('md5').replace(/\=*$/, '') + '"; + return "' + img.firstChild.dataset.md5.replace(/\=*$/, '') + '"; case '$4': return g.BOARD; } @@ -2790,9 +2790,9 @@ _ref = Sauce.links; for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; - nodes.push($.tn(' '), link(img)); + nodes.push($.tn('\u00A0'), link(img)); } - return $.add(post.filesize, nodes); + return $.add(post.fileinfo, nodes); } }; diff --git a/script.coffee b/script.coffee index a3f25dcc2..d3e157bb9 100644 --- a/script.coffee +++ b/script.coffee @@ -2193,7 +2193,7 @@ Sauce = when '$2' "' + img.href + '" when '$3' - "' + img.firstChild.getAttribute('md5').replace(/\=*$/, '') + '" + "' + img.firstChild.dataset.md5.replace(/\=*$/, '') + '" when '$4' g.BOARD href = Function 'img', "return '#{href}'" @@ -2211,8 +2211,9 @@ Sauce = img = img.parentNode nodes = [] for link in Sauce.links - nodes.push $.tn(' '), link img - $.add post.filesize, nodes + # \u00A0 is nbsp + nodes.push $.tn('\u00A0'), link img + $.add post.fileinfo, nodes RevealSpoilers = init: -> From d7b464205a45e4c2d4e7d2ac9cd7815949112076 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 14:31:53 +0200 Subject: [PATCH 04/52] Fix Anonymizer. --- 4chan_x.user.js | 5 ++--- script.coffee | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 29011bdd6..6517e3657 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2723,10 +2723,9 @@ if (post["class"] === 'inline') { return; } - name = $('.commentpostername, .postername', post.el); + name = $('.name', post.el); name.textContent = 'Anonymous'; - node = name.nextElementSibling; - if (node.className === 'postertrip' || node.nodeName === 'A') { + if (node = name.nextElementSibling) { return $.rm(node); } } diff --git a/script.coffee b/script.coffee index d3e157bb9..b9f93844e 100644 --- a/script.coffee +++ b/script.coffee @@ -2168,10 +2168,9 @@ Anonymize = Main.callbacks.push @node node: (post) -> return if post.class is 'inline' - name = $ '.commentpostername, .postername', post.el + name = $ '.name', post.el name.textContent = 'Anonymous' - node = name.nextElementSibling - if node.className is 'postertrip' or node.nodeName is 'A' + if node = name.nextElementSibling $.rm node Sauce = From f1a7942d56c354a7ed71acab866886933d01ad0f Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 14:34:25 +0200 Subject: [PATCH 05/52] Fix Thread Watcher. --- 4chan_x.user.js | 8 ++++---- script.coffee | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 6517e3657..b99c61db4 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2615,13 +2615,13 @@ Watcher = { init: function() { - var favicon, html, input, inputs, _i, _len; + var favicon, html, input, _i, _len, _ref; html = '
Thread Watcher
'; this.dialog = UI.dialog('watcher', 'top: 50px; left: 0px;', html); $.add(d.body, this.dialog); - inputs = $$('.op > input'); - for (_i = 0, _len = inputs.length; _i < _len; _i++) { - input = inputs[_i]; + _ref = $$('.op input'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + input = _ref[_i]; favicon = $.el('img', { className: 'favicon' }); diff --git a/script.coffee b/script.coffee index b9f93844e..791f7ae21 100644 --- a/script.coffee +++ b/script.coffee @@ -2087,8 +2087,7 @@ Watcher = $.add d.body, @dialog #add watch buttons - inputs = $$ '.op > input' - for input in inputs + for input in $$ '.op input' favicon = $.el 'img', className: 'favicon' $.on favicon, 'click', @cb.toggle From def88abec60223ae82cff5c6628d8f92cbdc5ab0 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 14:52:43 +0200 Subject: [PATCH 06/52] Fix file deleted preParsing. --- 4chan_x.user.js | 32 +++++++++++++++++--------------- script.coffee | 23 ++++++++++++----------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index b99c61db4..d96208cfc 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -704,17 +704,17 @@ return text.join(''); }, filename: function(post) { - var file, fileinfo; - fileinfo = post.fileinfo; - if (fileinfo && (file = $('span', fileinfo))) { + var file, fileInfo; + fileInfo = post.fileInfo; + if (fileInfo && (file = $('span', fileInfo))) { return file.title; } return false; }, dimensions: function(post) { - var fileinfo, match; - fileinfo = post.fileinfo; - if (fileinfo && (match = fileinfo.textContent.match(/\d+x\d+/))) { + var fileInfo, match; + fileInfo = post.fileInfo; + if (fileInfo && (match = fileInfo.textContent.match(/\d+x\d+/))) { return match[0]; } return false; @@ -2791,7 +2791,7 @@ link = _ref[_i]; nodes.push($.tn('\u00A0'), link(img)); } - return $.add(post.fileinfo, nodes); + return $.add(post.fileInfo, nodes); } }; @@ -4144,7 +4144,7 @@ } }, preParse: function(node) { - var file, klass, post; + var fileInfo, img, klass, post; klass = node.className; post = { root: node.parentNode, @@ -4154,14 +4154,16 @@ threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).id.slice(1), isInlined: /\binline\b/.test(klass), quotes: node.getElementsByClassName('quotelink'), - backlinks: node.getElementsByClassName('backlink') + backlinks: node.getElementsByClassName('backlink'), + fileInfo: false, + img: false }; - if (file = $('.file', node)) { - post.fileinfo = file.firstElementChild; - post.img = file.lastElementChild.firstElementChild; - } else { - post.fileinfo = false; - post.img = false; + if (fileInfo = $('.fileInfo', node)) { + img = fileInfo.nextElementSibling.firstElementChild; + if (img.alt !== 'File deleted.') { + post.fileInfo = fileInfo; + post.img = img; + } } return post; }, diff --git a/script.coffee b/script.coffee index 791f7ae21..83b3ca41a 100644 --- a/script.coffee +++ b/script.coffee @@ -576,13 +576,13 @@ Filter = text.push if data = nodes.snapshotItem(i).data then data else '\n' text.join '' filename: (post) -> - {fileinfo} = post - if fileinfo and file = $ 'span', fileinfo + {fileInfo} = post + if fileInfo and file = $ 'span', fileInfo return file.title false dimensions: (post) -> - {fileinfo} = post - if fileinfo and match = fileinfo.textContent.match /\d+x\d+/ + {fileInfo} = post + if fileInfo and match = fileInfo.textContent.match /\d+x\d+/ return match[0] false filesize: (post) -> @@ -2211,7 +2211,7 @@ Sauce = for link in Sauce.links # \u00A0 is nbsp nodes.push $.tn('\u00A0'), link img - $.add post.fileinfo, nodes + $.add post.fileInfo, nodes RevealSpoilers = init: -> @@ -3200,12 +3200,13 @@ Main = isInlined: /\binline\b/.test klass quotes: node.getElementsByClassName 'quotelink' backlinks: node.getElementsByClassName 'backlink' - if file = $ '.file', node - post.fileinfo = file.firstElementChild - post.img = file.lastElementChild.firstElementChild - else - post.fileinfo = false - post.img = false + fileInfo: false + img: false + if fileInfo = $ '.fileInfo', node + img = fileInfo.nextElementSibling.firstElementChild + if img.alt isnt 'File deleted.' + post.fileInfo = fileInfo + post.img = img post node: (nodes, notify) -> for callback in Main.callbacks From 18ec912ec7495ec79cdb410d56d9ac8b9395c3ff Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 15:01:21 +0200 Subject: [PATCH 07/52] Fix Quotifier. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index d96208cfc..4fe8d61ad 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3391,7 +3391,7 @@ nodes.push($.tn(text)); } id = quote.match(/\d+$/)[0]; - board = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : $('.quotejs', post.el).pathname.split('/')[1]; + board = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : $('.postNum.desktop', post.el).firstElementChild.pathname.split('/')[1]; nodes.push(a = $.el('a', { textContent: "" + quote + "\u00A0(Dead)" })); diff --git a/script.coffee b/script.coffee index 83b3ca41a..dafdc8029 100644 --- a/script.coffee +++ b/script.coffee @@ -2629,7 +2629,7 @@ Quotify = m[1] else # Get the post's board, whether it's inlined or not. - $('.quotejs', post.el).pathname.split('/')[1] + $('.postNum.desktop', post.el).firstElementChild.pathname.split('/')[1] nodes.push a = $.el 'a', # \u00A0 is nbsp From 059be4fab58e2a0627dfb6249aa2a0e748f82fb9 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 15:07:55 +0200 Subject: [PATCH 08/52] Fix report buttons. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 4fe8d61ad..a21d717e2 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3427,7 +3427,7 @@ var a; if (!(a = $('.reportbutton', post.el))) { a = ReportButton.a.cloneNode(true); - $.after($('span[id]', post.el), [$.tn(' '), a]); + $.add($('.postInfo', post.el), a); } return $.on(a, 'click', ReportButton.report); }, diff --git a/script.coffee b/script.coffee index dafdc8029..affc84de4 100644 --- a/script.coffee +++ b/script.coffee @@ -2663,7 +2663,7 @@ ReportButton = node: (post) -> unless a = $ '.reportbutton', post.el a = ReportButton.a.cloneNode true - $.after $('span[id]', post.el), [$.tn(' '), a] + $.add $('.postInfo', post.el), a $.on a, 'click', ReportButton.report report: -> url = "//sys.4chan.org/#{g.BOARD}/imgboard.php?mode=report&no=#{$.x('preceding-sibling::input', @).name}" From 59f5adaf7d73c2c9c8971dd5560015ae7447152b Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 15:09:18 +0200 Subject: [PATCH 09/52] Fix time formatting for OPs. --- 4chan_x.user.js | 2 +- script.coffee | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index a21d717e2..22bf9f56d 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2835,7 +2835,7 @@ if (post["class"] === 'inline') { return; } - node = $('.dateTime', post.el); + node = $('.postInfo > .dateTime', post.el); Time.date = Time.parse(node.textContent); node.textContent = Time.funk(Time); return node.dataset.time = Time.date.toISOString(); diff --git a/script.coffee b/script.coffee index affc84de4..5485ee469 100644 --- a/script.coffee +++ b/script.coffee @@ -2247,8 +2247,7 @@ Time = Main.callbacks.push @node node: (post) -> return if post.class is 'inline' - # .posttime exists on every board except /f/ - node = $ '.dateTime', post.el + node = $ '.postInfo > .dateTime', post.el Time.date = Time.parse node.textContent node.textContent = Time.funk(Time) # Set the datetime attribute, ISO'd. From 0313b094ce9a16c09777e01d2f05d3920084b49d Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 15:20:47 +0200 Subject: [PATCH 10/52] QR fixes. --- 4chan_x.user.js | 15 ++++++++------- script.coffee | 13 +++++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 22bf9f56d..ab54d6346 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1360,7 +1360,7 @@ return $.on(d, 'dragstart dragend', QR.drag); }, node: function(post) { - return $.on($('.quotejs + .quotejs', post.el), 'click', QR.quote); + return $.on($('.postInfo > .postNum > a:last-child', post.el), 'click', QR.quote); }, open: function() { if (QR.el) { @@ -1479,12 +1479,12 @@ } QR.open(); if (!g.REPLY) { - $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', this).firstChild.id; + $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', this).id.slice(1); } - id = this.previousElementSibling.hash.slice(1); + id = this.hash.slice(2); text = ">>" + id + "\n"; sel = window.getSelection(); - if ((s = sel.toString()) && id === ((_ref = $.x('ancestor-or-self::blockquote/preceding-sibling::input', sel.anchorNode)) != null ? _ref.name : void 0)) { + if ((s = sel.toString()) && id === ((_ref = $.x('ancestor-or-self::blockquote', sel.anchorNode)) != null ? _ref.id.slice(1) : void 0)) { s = s.replace(/\n/g, '\n>'); text += ">" + s + "\n"; } @@ -1814,7 +1814,7 @@ } }, dialog: function() { - var e, fileInput, mimeTypes, name, spoiler, ta, thread, threads, _i, _j, _len, _len1, _ref, _ref1; + var e, fileInput, id, mimeTypes, name, spoiler, ta, thread, threads, _i, _j, _len, _len1, _ref, _ref1; QR.el = UI.dialog('qr', 'top:0;right:0;', '\
\ Quick Reply \ @@ -1856,10 +1856,11 @@ spoiler.hidden = !QR.spoiler; if (!g.REPLY) { threads = ''; - _ref = $$('.op'); + _ref = $$('.thread'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { thread = _ref[_i]; - threads += ""; + id = thread.id.slice(1); + threads += ""; } $.prepend($('.move > span', QR.el), $.el('select', { innerHTML: threads, diff --git a/script.coffee b/script.coffee index 5485ee469..829cfc422 100644 --- a/script.coffee +++ b/script.coffee @@ -1030,7 +1030,7 @@ QR = $.on d, 'dragstart dragend', QR.drag node: (post) -> - $.on $('.quotejs + .quotejs', post.el), 'click', QR.quote + $.on $('.postInfo > .postNum > a:last-child', post.el), 'click', QR.quote open: -> if QR.el @@ -1113,14 +1113,14 @@ QR = e?.preventDefault() QR.open() unless g.REPLY - $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', @).firstChild.id + $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', @).id[1..] # Make sure we get the correct number, even with XXX censors - id = @previousElementSibling.hash[1..] + id = @hash[2..] text = ">>#{id}\n" sel = window.getSelection() - if (s = sel.toString()) and id is $.x('ancestor-or-self::blockquote/preceding-sibling::input', sel.anchorNode)?.name + if (s = sel.toString()) and id is $.x('ancestor-or-self::blockquote', sel.anchorNode)?.id[1..] s = s.replace /\n/g, '\n>' text += ">#{s}\n" @@ -1425,8 +1425,9 @@ QR = unless g.REPLY # Make a list with visible threads and an option to create a new one. threads = '' - for thread in $$ '.op' - threads += "" + for thread in $$ '.thread' + id = thread.id[1..] + threads += "" $.prepend $('.move > span', QR.el), $.el 'select' innerHTML: threads title: 'Create a new thread / Reply to a thread' From 52687b5ea6c957eeeb431502c7a35d8044c1cbfa Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 29 Apr 2012 15:39:12 +0200 Subject: [PATCH 11/52] Quote Backlinks fixes. --- 4chan_x.user.js | 15 ++++++--------- script.coffee | 13 +++++-------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index ab54d6346..3ad45d0b4 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3058,7 +3058,7 @@ return Main.callbacks.push(this.node); }, node: function(post) { - var a, container, el, link, qid, quote, quotes, root, _i, _len, _ref; + var a, container, el, link, qid, quote, quotes, _i, _len, _ref; if (post.isInlined) { return; } @@ -3066,17 +3066,17 @@ _ref = post.quotes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { quote = _ref[_i]; - if (qid = quote.hash.slice(1)) { + if (qid = quote.hash.slice(2)) { quotes[qid] = true; } } a = $.el('a', { - href: "#" + post.id, + href: "#p" + post.id, className: post.root.hidden ? 'filtered backlink' : 'backlink', textContent: QuoteBacklink.funk(post.id) }); for (qid in quotes) { - if (!(el = $.id(qid)) || el.className === 'op' && !Conf['OP Backlinks']) { + if (!(el = $.id("pi" + qid)) || /\bop\b/.test(el.parentNode.className) && !Conf['OP Backlinks']) { continue; } link = a.cloneNode(true); @@ -3092,12 +3092,9 @@ container = $.el('span', { className: 'container' }); - $.add(container, [$.tn(' '), link]); - root = $('.reportbutton', el) || $('span[id]', el); - $.after(root, container); - } else { - $.add(container, [$.tn(' '), link]); + $.add(el, container); } + $.add(container, [$.tn(' '), link]); } } }; diff --git a/script.coffee b/script.coffee index 829cfc422..ae58701ef 100644 --- a/script.coffee +++ b/script.coffee @@ -2391,16 +2391,16 @@ QuoteBacklink = quotes = {} for quote in post.quotes # Don't process >>>/b/. - if qid = quote.hash[1..] + if qid = quote.hash[2..] # Duplicate quotes get overwritten. quotes[qid] = true a = $.el 'a', - href: "##{post.id}" + href: "#p#{post.id}" className: if post.root.hidden then 'filtered backlink' else 'backlink' textContent: QuoteBacklink.funk post.id for qid of quotes # Don't backlink the OP. - continue if !(el = $.id qid) or el.className is 'op' and !Conf['OP Backlinks'] + continue if !(el = $.id "pi#{qid}") or /\bop\b/.test(el.parentNode.className) and !Conf['OP Backlinks'] link = a.cloneNode true if Conf['Quote Preview'] $.on link, 'mouseover', QuotePreview.mouseover @@ -2410,11 +2410,8 @@ QuoteBacklink = link.setAttribute 'onclick', "replyhl('#{post.id}');" unless (container = $ '.container', el) and container.parentNode is el container = $.el 'span', className: 'container' - $.add container, [$.tn(' '), link] - root = $('.reportbutton', el) or $('span[id]', el) - $.after root, container - else - $.add container, [$.tn(' '), link] + $.add el, container + $.add container, [$.tn(' '), link] return QuoteInline = From 425b95a1e2cacd19cd2298c135aa370e6f15f4bf Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 04:29:20 +0200 Subject: [PATCH 12/52] Quote Previewing and QR fixes. Quote previewing works, but UI doesn't so you won't see anything. --- 4chan_x.user.js | 19 +++++++++---------- script.coffee | 21 ++++++++------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 3ad45d0b4..1475c7552 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1360,7 +1360,7 @@ return $.on(d, 'dragstart dragend', QR.drag); }, node: function(post) { - return $.on($('.postInfo > .postNum > a:last-child', post.el), 'click', QR.quote); + return $.on($('.postInfo > .postNum > a[title="Quote this post"]', post.el), 'click', QR.quote); }, open: function() { if (QR.el) { @@ -1481,7 +1481,7 @@ if (!g.REPLY) { $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', this).id.slice(1); } - id = this.hash.slice(2); + id = this.parentNode.parentNode.id.slice(2); text = ">>" + id + "\n"; sel = window.getSelection(); if ((s = sel.toString()) && id === ((_ref = $.x('ancestor-or-self::blockquote', sel.anchorNode)) != null ? _ref.id.slice(1) : void 0)) { @@ -3249,7 +3249,7 @@ } }, mouseover: function(e) { - var el, id, node, qp, quote, replyID, threadID, _i, _len, _ref; + var el, id, qp, quote, replyID, threadID, _i, _len, _ref; if (/\binlined\b/.test(this.className)) { return; } @@ -3258,14 +3258,13 @@ className: 'reply dialog' }); $.add(d.body, qp); - id = this.hash.slice(1); - if (el = $.id(id)) { + id = this.hash.slice(2); + if (el = $.id("p" + id)) { qp.innerHTML = el.innerHTML; if (Conf['Quote Highlighting']) { $.addClass(el, 'qphl'); } - node = /\bbacklink\b/.test(this.className) ? this.parentNode : $.x('ancestor::blockquote', this); - replyID = $.x('preceding-sibling::input', node).name; + replyID = $.x('ancestor::div[contains(@class,"post")]', this).id; _ref = $$('.quotelink, .backlink', qp); for (_i = 0, _len = _ref.length; _i < _len; _i++) { quote = _ref[_i]; @@ -3275,7 +3274,7 @@ } } else { qp.textContent = "Loading " + id + "..."; - threadID = this.pathname.split('/').pop() || $.x('ancestor::div[@class="thread"]', this).firstChild.id; + threadID = this.pathname.split('/').pop(); $.cache(this.pathname, (function() { return QuotePreview.parse(this, id, threadID); })); @@ -3304,10 +3303,10 @@ } doc = d.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = req.response; - node = doc.getElementById(id); + node = doc.getElementById("p" + id); qp.innerHTML = node.innerHTML; post = { - root: qp, + el: qp, filesize: $('.filesize', qp), img: $('img[data-md5]', qp) }; diff --git a/script.coffee b/script.coffee index ae58701ef..d15e27bcc 100644 --- a/script.coffee +++ b/script.coffee @@ -1030,7 +1030,7 @@ QR = $.on d, 'dragstart dragend', QR.drag node: (post) -> - $.on $('.postInfo > .postNum > a:last-child', post.el), 'click', QR.quote + $.on $('.postInfo > .postNum > a[title="Quote this post"]', post.el), 'click', QR.quote open: -> if QR.el @@ -1116,7 +1116,7 @@ QR = $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', @).id[1..] # Make sure we get the correct number, even with XXX censors - id = @hash[2..] + id = @parentNode.parentNode.id[2..] text = ">>#{id}\n" sel = window.getSelection() @@ -2518,22 +2518,17 @@ QuotePreview = className: 'reply dialog' $.add d.body, qp - id = @hash[1..] - if el = $.id id + id = @hash[2..] + if el = $.id "p#{id}" qp.innerHTML = el.innerHTML $.addClass el, 'qphl' if Conf['Quote Highlighting'] - node = - if /\bbacklink\b/.test @className - @parentNode - else - $.x 'ancestor::blockquote', @ - replyID = $.x('preceding-sibling::input', node).name + replyID = $.x('ancestor::div[contains(@class,"post")]', @).id for quote in $$ '.quotelink, .backlink', qp if quote.hash[1..] is replyID $.addClass quote, 'forwardlink' else qp.textContent = "Loading #{id}..." - threadID = @pathname.split('/').pop() or $.x('ancestor::div[@class="thread"]', @).firstChild.id + threadID = @pathname.split('/').pop() $.cache @pathname, (-> QuotePreview.parse @, id, threadID) UI.hover e $.on @, 'mousemove', UI.hover @@ -2554,10 +2549,10 @@ QuotePreview = doc = d.implementation.createHTMLDocument '' doc.documentElement.innerHTML = req.response - node = doc.getElementById id + node = doc.getElementById "p#{id}" qp.innerHTML = node.innerHTML post = - root: qp + el: qp filesize: $ '.filesize', qp img: $ 'img[data-md5]', qp if Conf['Image Auto-Gif'] From 7b6cedd0052f038e0c63c09888d91ce3445df0c9 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 05:02:00 +0200 Subject: [PATCH 13/52] Close #400 --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1475c7552..3623f8d83 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1836,7 +1836,7 @@ }); ta.style.cssText = $.get('QR.size', ''); } - mimeTypes = $('ul.rules').firstElementChild.textContent.match(/: (.+) /)[1].toLowerCase().replace(/\w+/g, function(type) { + mimeTypes = $('ul.rules').firstElementChild.textContent.match(/: (.+)/)[1].toLowerCase().replace(/\w+/g, function(type) { switch (type) { case 'jpg': return 'image/jpeg'; diff --git a/script.coffee b/script.coffee index d15e27bcc..2d8f49d5d 100644 --- a/script.coffee +++ b/script.coffee @@ -1403,7 +1403,7 @@ QR = ta.style.cssText = $.get 'QR.size', '' # Allow only this board's supported files. - mimeTypes = $('ul.rules').firstElementChild.textContent.match(/: (.+) /)[1].toLowerCase().replace /\w+/g, (type) -> + mimeTypes = $('ul.rules').firstElementChild.textContent.match(/: (.+)/)[1].toLowerCase().replace /\w+/g, (type) -> switch type when 'jpg' 'image/jpeg' From e52ee68c97017b261e3e3d0b3c79d023a162a9cc Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 10:02:40 +0200 Subject: [PATCH 14/52] This should fix Comment Expansion. --- 4chan_x.user.js | 11 +++++------ script.coffee | 14 ++++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1bda89a86..a5b3cec7f 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -762,18 +762,17 @@ ExpandComment = { init: function() { var a, _i, _len, _ref; - _ref = $$('.abbr > a'); + _ref = $$('.abbr'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { a = _ref[_i]; - $.on(a, 'click', ExpandComment.expand); + $.on(a.firstElementChild, 'click', ExpandComment.expand); } }, expand: function(e) { var a, replyID, threadID, _, _ref; e.preventDefault(); - _ref = this.href.match(/(\d+)#(\d+)/), _ = _ref[0], threadID = _ref[1], replyID = _ref[2]; + _ref = this.href.match(/(\d+)#p(\d+)/), _ = _ref[0], threadID = _ref[1], replyID = _ref[2]; this.textContent = "Loading " + replyID + "..."; - threadID = this.pathname.split('/').pop() || $.x('ancestor::div[@class="thread"]/div', this).id; a = this; return $.cache(this.pathname, (function() { return ExpandComment.parse(this, a, threadID, replyID); @@ -787,7 +786,7 @@ } doc = d.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = req.response; - node = d.importNode(doc.getElementById(replyID)); + node = d.importNode(doc.getElementById("m" + replyID)); quotes = node.getElementsByClassName('quotelink'); for (_i = 0, _len = quotes.length; _i < _len; _i++) { quote = quotes[_i]; @@ -818,7 +817,7 @@ if (Conf['Indicate Cross-thread Quotes']) { QuoteCT.node(post); } - return $.replace(a.parentNode.parentNode, node.lastChild); + return $.replace(a.parentNode.parentNode, node); } }; diff --git a/script.coffee b/script.coffee index 6cf60faa3..e28bbb90e 100644 --- a/script.coffee +++ b/script.coffee @@ -609,14 +609,13 @@ StrikethroughQuotes = ExpandComment = init: -> - for a in $$ '.abbr > a' - $.on a, 'click', ExpandComment.expand + for a in $$ '.abbr' + $.on a.firstElementChild, 'click', ExpandComment.expand return expand: (e) -> e.preventDefault() - [_, threadID, replyID] = @href.match /(\d+)#(\d+)/ + [_, threadID, replyID] = @href.match /(\d+)#p(\d+)/ @textContent = "Loading #{replyID}..." - threadID = @pathname.split('/').pop() or $.x('ancestor::div[@class="thread"]/div', @).id a = @ $.cache @pathname, (-> ExpandComment.parse @, a, threadID, replyID) parse: (req, a, threadID, replyID) -> @@ -629,12 +628,15 @@ ExpandComment = # Import the node to fix quote.hashes # as they're empty when in a different document. - node = d.importNode doc.getElementById replyID + node = d.importNode doc.getElementById "m#{replyID}" quotes = node.getElementsByClassName 'quotelink' for quote in quotes if quote.hash is href = quote.getAttribute 'href' # Add pathname to in-thread quotes quote.pathname = "/#{g.BOARD}/res/#{threadID}" + # NEW HTML ??? + # OP quotes have different href attribute than normal quotes. + # Waiting for a reply from moot. else if href isnt quote.href # Fix cross-thread links, not cross-board ones quote.href = "res/#{href}" post = @@ -652,7 +654,7 @@ ExpandComment = QuoteOP.node post if Conf['Indicate Cross-thread Quotes'] QuoteCT.node post - $.replace a.parentNode.parentNode, node.lastChild + $.replace a.parentNode.parentNode, node ExpandThread = init: -> From 18c9642b5269444192b7ea151e39eb1341cc4c5d Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 10:28:44 +0200 Subject: [PATCH 15/52] Fix filter highlight styling. --- 4chan_x.user.js | 12 ++++-------- script.coffee | 11 ++++------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index a5b3cec7f..5b9b1e16c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -621,7 +621,7 @@ if (post.isInlined) { return; } - isOP = post["class"] === 'op'; + isOP = /\bop\b/.test(post["class"]); el = post.el; for (key in Filter.filters) { value = Filter[key](post); @@ -646,11 +646,7 @@ } return; } - if (isOP) { - $.addClass(el.parentNode, result[0]); - } else { - $.addClass(el, result[0]); - } + $.addClass((isOP ? post.root.parentNode : post.root), result[0]); if (isOP && result[1] && !g.REPLY) { thisThread = el.parentNode.parentNode; if (firstThread = $('div[class="postContainer opContainer"]')) { @@ -4574,8 +4570,8 @@ input ~ a > img[data-md5] {\ .filetitle, .replytitle, .postername, .commentpostername, .postertrip {\ background: none;\ }\ -.filter_highlight.op,\ -.filter_highlight > td[id] {\ +.filter_highlight.thread,\ +.filter_highlight > .reply {\ box-shadow: -5px 0 rgba(255,0,0,0.5);\ }\ .filtered {\ diff --git a/script.coffee b/script.coffee index e28bbb90e..57dc06936 100644 --- a/script.coffee +++ b/script.coffee @@ -513,7 +513,7 @@ Filter = node: (post) -> return if post.isInlined - isOP = post.class is 'op' + isOP = /\bop\b/.test post.class {el} = post for key of Filter.filters value = Filter[key] post @@ -536,10 +536,7 @@ Filter = return # Highlight - if isOP - $.addClass el.parentNode, result[0] - else - $.addClass el, result[0] + $.addClass (if isOP then post.root.parentNode else post.root), result[0] if isOP and result[1] and not g.REPLY # Put the highlighted OPs' threads on top of the board pages... thisThread = el.parentNode.parentNode @@ -3595,8 +3592,8 @@ input ~ a > img[data-md5] { .filetitle, .replytitle, .postername, .commentpostername, .postertrip { background: none; } -.filter_highlight.op, -.filter_highlight > td[id] { +.filter_highlight.thread, +.filter_highlight > .reply { box-shadow: -5px 0 rgba(255,0,0,0.5); } .filtered { From 59c879b59ccb076a2b75897a051496be61398d09 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 11:00:52 +0200 Subject: [PATCH 16/52] Filter fixes. --- 4chan_x.user.js | 6 +++--- script.coffee | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 5b9b1e16c..07aafcfc2 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -649,7 +649,7 @@ $.addClass((isOP ? post.root.parentNode : post.root), result[0]); if (isOP && result[1] && !g.REPLY) { thisThread = el.parentNode.parentNode; - if (firstThread = $('div[class="postContainer opContainer"]')) { + if (firstThread = $('div[class=thread]')) { $.before(firstThread.parentNode, [thisThread, thisThread.nextElementSibling]); } } @@ -657,7 +657,7 @@ } }, name: function(post) { - return $('.name', post.el).textContent || false; + return $('.name', post.el).textContent; }, uniqueid: function(post) { var uid; @@ -702,7 +702,7 @@ filename: function(post) { var file, fileInfo; fileInfo = post.fileInfo; - if (fileInfo && (file = $('span', fileInfo))) { + if (fileInfo && (file = $('.fileText > span', fileInfo))) { return file.title; } return false; diff --git a/script.coffee b/script.coffee index 57dc06936..b5c1af466 100644 --- a/script.coffee +++ b/script.coffee @@ -541,11 +541,11 @@ Filter = # Put the highlighted OPs' threads on top of the board pages... thisThread = el.parentNode.parentNode # ...before the first non highlighted thread. - if firstThread = $ 'div[class="postContainer opContainer"]' + if firstThread = $ 'div[class=thread]' $.before firstThread.parentNode, [thisThread, thisThread.nextElementSibling] name: (post) -> - $('.name', post.el).textContent or false + $('.name', post.el).textContent uniqueid: (post) -> # NEW HTML ??? if uid = $ '.posteruid', post.el @@ -574,7 +574,7 @@ Filter = text.join '' filename: (post) -> {fileInfo} = post - if fileInfo and file = $ 'span', fileInfo + if fileInfo and file = $ '.fileText > span', fileInfo return file.title false dimensions: (post) -> From a3c00a57924e11f343244a4216e917c8a35b9035 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 11:50:03 +0200 Subject: [PATCH 17/52] Fix Thread Hiding. --- 4chan_x.user.js | 68 +++++++++++++++++++++++-------------------------- script.coffee | 65 ++++++++++++++++++++++------------------------ 2 files changed, 63 insertions(+), 70 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 07aafcfc2..08fa1c699 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -637,7 +637,7 @@ if (result === true) { if (isOP) { if (!g.REPLY) { - ThreadHiding.hide(post.el.parentNode); + ThreadHiding.hide(post.root.parentNode); } else { continue; } @@ -2369,31 +2369,31 @@ ThreadHiding = { init: function() { - var a, hiddenThreads, op, thread, _i, _len, _ref; + var a, hiddenThreads, thread, _i, _len, _ref; hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); _ref = $$('.thread'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { thread = _ref[_i]; - op = $('.op', thread); a = $.el('a', { - textContent: '[ - ]', + className: 'hide_thread_button', + innerHTML: '[ - ]', href: 'javascript:;' }); $.on(a, 'click', ThreadHiding.cb); - $.prepend(op, a); - if (op.id in hiddenThreads) { + $.prepend(thread, a); + if (thread.id.slice(1) in hiddenThreads) { ThreadHiding.hide(thread); } } }, cb: function() { - return ThreadHiding.toggle(this.parentNode.parentNode); + return ThreadHiding.toggle(this.parentNode); }, toggle: function(thread) { var hiddenThreads, id; hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); - id = $('.op', thread).id; - if (thread.hidden || thread.firstChild.className === 'block') { + id = thread.id.slice(1); + if (thread.hidden || /\bhidden_thread\b/.test(thread.firstChild.className)) { ThreadHiding.show(thread); delete hiddenThreads[id]; } else { @@ -2403,40 +2403,34 @@ return $.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); }, hide: function(thread) { - var a, div, name, num, op, span, text, trip, uid, _ref, _ref1; + var a, num, opInfo, span, text; if (!Conf['Show Stubs']) { thread.hidden = true; - thread.nextSibling.hidden = true; + thread.nextElementSibling.hidden = true; return; } if (thread.firstChild.className === 'block') { return; } num = 0; - if (span = $('.omittedposts', thread)) { - num = Number(span.textContent.match(/\d+/)[0]); + if (span = $('.summary', thread)) { + num = Number(span.textContent.match(/\d+/)); } - num += $$('.op ~ table', thread).length; + num += $$('.opContainer ~ .replyContainer', thread).length; text = num === 1 ? '1 reply' : "" + num + " replies"; - op = $('.op', thread); - name = $('.postername', op).textContent; - uid = ((_ref = $('.posteruid', op)) != null ? _ref.textContent : void 0) || ''; - trip = ((_ref1 = $('.postertrip', op)) != null ? _ref1.textContent : void 0) || ''; - a = $.el('a', { - innerHTML: "[ + ] " + name + " " + uid + " " + trip + " (" + text + ")", - href: 'javascript:;' - }); - $.on(a, 'click', ThreadHiding.cb); - div = $.el('div', { - className: 'block' - }); - $.add(div, a); - return $.prepend(thread, div); + opInfo = $('.op > .postInfo > .nameBlock', thread).textContent; + a = $('.hide_thread_button', thread); + $.addClass(a, 'hidden_thread'); + a.firstChild.textContent = '[ + ]'; + return $.add(a, $.tn(" " + opInfo + " (" + text + ")")); }, - show: function(thread, id) { - $.rm($('.block', thread)); + show: function(thread) { + var a; + a = $('.hide_thread_button', thread); + $.removeClass(a, 'hidden_thread'); + a.innerHTML = '[ - ]'; thread.hidden = false; - return thread.nextSibling.hidden = false; + return thread.nextElementSibling.hidden = false; } }; @@ -4066,9 +4060,7 @@ } } else { if (Conf['Thread Hiding']) { - setTimeout(function() { - return ThreadHiding.init(); - }); + ThreadHiding.init(); } if (Conf['Thread Expansion']) { setTimeout(function() { @@ -4215,11 +4207,15 @@ a[href="javascript:;"] {\ text-decoration: none;\ }\ \ -.block ~ *,\ +.hide_thread_button {\ + float: left;\ +}\ +\ +.hidden_thread ~ *,\ #content > [name=tab]:not(:checked) + div,\ #updater:not(:hover) > :not(.move),\ #qp > input, #qp .inline, .forwarded {\ - display: none;\ + display: none !important;\ }\ \ h1 {\ diff --git a/script.coffee b/script.coffee index b5c1af466..86aeb0dfc 100644 --- a/script.coffee +++ b/script.coffee @@ -528,7 +528,7 @@ Filter = if result is true if isOP unless g.REPLY - ThreadHiding.hide post.el.parentNode + ThreadHiding.hide post.root.parentNode else continue else @@ -1879,24 +1879,24 @@ ThreadHiding = init: -> hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} for thread in $$ '.thread' - op = $ '.op', thread a = $.el 'a', - textContent: '[ - ]' + className: 'hide_thread_button' + innerHTML: '[ - ]' href: 'javascript:;' $.on a, 'click', ThreadHiding.cb - $.prepend op, a + $.prepend thread, a - if op.id of hiddenThreads + if thread.id[1..] of hiddenThreads ThreadHiding.hide thread return cb: -> - ThreadHiding.toggle @parentNode.parentNode + ThreadHiding.toggle @parentNode toggle: (thread) -> hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} - id = $('.op', thread).id - if thread.hidden or thread.firstChild.className is 'block' + id = thread.id[1..] + if thread.hidden or /\bhidden_thread\b/.test thread.firstChild.className ThreadHiding.show thread delete hiddenThreads[id] else @@ -1907,36 +1907,29 @@ ThreadHiding = hide: (thread) -> unless Conf['Show Stubs'] thread.hidden = true - thread.nextSibling.hidden = true + thread.nextElementSibling.hidden = true return return if thread.firstChild.className is 'block' # already hidden by filter - num = 0 - if span = $ '.omittedposts', thread - num = Number span.textContent.match(/\d+/)[0] - num += $$('.op ~ table', thread).length - text = if num is 1 then '1 reply' else "#{num} replies" - op = $ '.op', thread - name = $('.postername', op).textContent - uid = $('.posteruid', op)?.textContent or '' - trip = $('.postertrip', op)?.textContent or '' + num = 0 + if span = $ '.summary', thread + num = Number span.textContent.match /\d+/ + num += $$('.opContainer ~ .replyContainer', thread).length + text = if num is 1 then '1 reply' else "#{num} replies" + opInfo = $('.op > .postInfo > .nameBlock', thread).textContent - a = $.el 'a', - innerHTML: "[ + ] #{name} #{uid} #{trip} (#{text})" - href: 'javascript:;' - $.on a, 'click', ThreadHiding.cb + a = $ '.hide_thread_button', thread + $.addClass a, 'hidden_thread' + a.firstChild.textContent = '[ + ]' + $.add a, $.tn " #{opInfo} (#{text})" - div = $.el 'div', - className: 'block' - - $.add div, a - $.prepend thread, div - - show: (thread, id) -> - $.rm $ '.block', thread + show: (thread) -> + a = $ '.hide_thread_button', thread + $.removeClass a, 'hidden_thread' + a.innerHTML = '[ - ]' thread.hidden = false - thread.nextSibling.hidden = false + thread.nextElementSibling.hidden = false Updater = init: -> @@ -3134,7 +3127,7 @@ Main = else #not reply if Conf['Thread Hiding'] - setTimeout -> ThreadHiding.init() + ThreadHiding.init() if Conf['Thread Expansion'] setTimeout -> ExpandThread.init() @@ -3237,11 +3230,15 @@ a[href="javascript:;"] { text-decoration: none; } -.block ~ *, +.hide_thread_button { + float: left; +} + +.hidden_thread ~ *, #content > [name=tab]:not(:checked) + div, #updater:not(:hover) > :not(.move), #qp > input, #qp .inline, .forwarded { - display: none; + display: none !important; } h1 { From b72083552ce833b9aa0e467c29039d3ec214362f Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 14:21:25 +0200 Subject: [PATCH 18/52] Fix Reply Hiding. --- 4chan_x.user.js | 82 +++++++++++++++++++++++-------------------------- script.coffee | 69 +++++++++++++++++++++-------------------- 2 files changed, 74 insertions(+), 77 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 08fa1c699..328463c9d 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -923,69 +923,61 @@ ReplyHiding = { init: function() { - this.td = $.el('td', { - noWrap: true, - className: 'replyhider', - innerHTML: '[ - ]' - }); return Main.callbacks.push(this.node); }, node: function(post) { - var td; - if (post["class"]) { + var button; + if (post.isInlined || /\bop\b/.test(post["class"])) { return; } - td = ReplyHiding.td.cloneNode(true); - $.on(td.firstChild, 'click', ReplyHiding.toggle); - $.replace(post.el.previousSibling, td); + button = post.el.previousElementSibling; + button.innerHTML = '[ - ]'; + $.addClass(button, 'hide_reply_button'); + $.on(button.firstChild, 'click', ReplyHiding.toggle); if (post.id in g.hiddenReplies) { - return ReplyHiding.hide(post.root); + return ReplyHiding.hide(post.root.firstElementChild); } }, toggle: function() { - var id, parent, quote, table, _i, _j, _len, _len1, _ref, _ref1; - parent = this.parentNode; - if (parent.className === 'replyhider') { - ReplyHiding.hide(parent.parentNode.parentNode.parentNode); - id = parent.nextSibling.id; - _ref = $$(".quotelink[href='#" + id + "'], .backlink[href='#" + id + "']"); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - $.addClass(quote, 'filtered'); - } - g.hiddenReplies[id] = Date.now(); - } else { - table = parent.nextSibling; - table.hidden = false; - $.rm(parent); - id = table.firstChild.firstChild.lastChild.id; - _ref1 = $$(".quotelink[href$='#" + id + "'], .backlink[href='#" + id + "']"); - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - quote = _ref1[_j]; + var button, id, quote, quotes, _i, _j, _len, _len1; + button = this.parentNode; + id = button.id.slice(2); + quotes = $$(".quotelink[href$='#p" + id + "'], .backlink[href='#p" + id + "']"); + if (/\bhidden_reply\b/.test(button.className)) { + ReplyHiding.show(button); + for (_i = 0, _len = quotes.length; _i < _len; _i++) { + quote = quotes[_i]; $.removeClass(quote, 'filtered'); } delete g.hiddenReplies[id]; + } else { + ReplyHiding.hide(button); + for (_j = 0, _len1 = quotes.length; _j < _len1; _j++) { + quote = quotes[_j]; + $.addClass(quote, 'filtered'); + } + g.hiddenReplies[id] = Date.now(); } return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); }, - hide: function(table) { - var div, name, trip, uid, _ref, _ref1; - if (table.hidden) { + hide: function(button) { + if (/\bhidden_reply\b/.test(button.className)) { return; } - table.hidden = true; + $.addClass(button, 'hidden_reply'); if (!Conf['Show Stubs']) { + button.hidden = true; return; } - name = $('.commentpostername', table).textContent; - uid = ((_ref = $('.posteruid', table)) != null ? _ref.textContent : void 0) || ''; - trip = ((_ref1 = $('.postertrip', table)) != null ? _ref1.textContent : void 0) || ''; - div = $.el('div', { - className: 'stub', - innerHTML: "[ + ] " + name + " " + uid + " " + trip + "" - }); - $.on(div.firstChild, 'click', ReplyHiding.toggle); - return $.before(table, div); + return button.firstChild.textContent = "[ + ] " + ($('.nameBlock', button.nextElementSibling).textContent); + }, + show: function(button) { + $.removeClass(button, 'hidden_reply'); + if (!Conf['Show Stubs']) { + button.hidden = false; + return; + } + return button.firstChild.textContent = '[ - ]'; } }; @@ -4210,8 +4202,12 @@ a[href="javascript:;"] {\ .hide_thread_button {\ float: left;\ }\ +.hide_reply_button.hidden_reply {\ + float: none;\ +}\ \ .hidden_thread ~ *,\ +.hidden_reply + .reply,\ #content > [name=tab]:not(:checked) + div,\ #updater:not(:hover) > :not(.move),\ #qp > input, #qp .inline, .forwarded {\ diff --git a/script.coffee b/script.coffee index 86aeb0dfc..87de1ef6f 100644 --- a/script.coffee +++ b/script.coffee @@ -730,55 +730,52 @@ ExpandThread = ReplyHiding = init: -> - @td = $.el 'td', - noWrap: true - className: 'replyhider' - innerHTML: '[ - ]' Main.callbacks.push @node node: (post) -> - return if post.class - td = ReplyHiding.td.cloneNode true - $.on td.firstChild, 'click', ReplyHiding.toggle - $.replace post.el.previousSibling, td + return if post.isInlined or /\bop\b/.test post.class + button = post.el.previousElementSibling + button.innerHTML = '[ - ]' + $.addClass button, 'hide_reply_button' + $.on button.firstChild, 'click', ReplyHiding.toggle if post.id of g.hiddenReplies - ReplyHiding.hide post.root + ReplyHiding.hide post.root.firstElementChild toggle: -> - parent = @parentNode - if parent.className is 'replyhider' - ReplyHiding.hide parent.parentNode.parentNode.parentNode - id = parent.nextSibling.id - for quote in $$ ".quotelink[href='##{id}'], .backlink[href='##{id}']" - $.addClass quote, 'filtered' - g.hiddenReplies[id] = Date.now() - else - table = parent.nextSibling - table.hidden = false - $.rm parent - id = table.firstChild.firstChild.lastChild.id - for quote in $$ ".quotelink[href$='##{id}'], .backlink[href='##{id}']" + button = @parentNode + id = button.id[2..] + quotes = $$ ".quotelink[href$='#p#{id}'], .backlink[href='#p#{id}']" + if /\bhidden_reply\b/.test button.className + ReplyHiding.show button + for quote in quotes $.removeClass quote, 'filtered' delete g.hiddenReplies[id] + else + ReplyHiding.hide button + for quote in quotes + $.addClass quote, 'filtered' + g.hiddenReplies[id] = Date.now() $.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies - hide: (table) -> - return if table.hidden # already hidden by filter + hide: (button) -> + return if /\bhidden_reply\b/.test button.className # already hidden once by filter + $.addClass button, 'hidden_reply' - table.hidden = true + unless Conf['Show Stubs'] + button.hidden = true + return - return unless Conf['Show Stubs'] + button.firstChild.textContent = "[ + ] #{$('.nameBlock', button.nextElementSibling).textContent}" - name = $('.commentpostername', table).textContent - uid = $('.posteruid', table)?.textContent or '' - trip = $('.postertrip', table)?.textContent or '' + show: (button) -> + $.removeClass button, 'hidden_reply' - div = $.el 'div', - className: 'stub' - innerHTML: "[ + ] #{name} #{uid} #{trip}" - $.on div.firstChild, 'click', ReplyHiding.toggle - $.before table, div + unless Conf['Show Stubs'] + button.hidden = false + return + + button.firstChild.textContent = '[ - ]' Keybinds = init: -> @@ -3233,8 +3230,12 @@ a[href="javascript:;"] { .hide_thread_button { float: left; } +.hide_reply_button.hidden_reply { + float: none; +} .hidden_thread ~ *, +.hidden_reply + .reply, #content > [name=tab]:not(:checked) + div, #updater:not(:hover) > :not(.move), #qp > input, #qp .inline, .forwarded { From 7b20be3a913b1a9e597456d8805aa6f804121093 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 30 Apr 2012 14:55:43 +0200 Subject: [PATCH 19/52] Fix preParsing of inserted posts. Ha ha, back to Tera. --- 4chan_x.user.js | 19 ++++++++++--------- script.coffee | 17 +++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 328463c9d..d0aeb4da8 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -4072,7 +4072,7 @@ } board = $('.board'); nodes = []; - _ref1 = $$('.post', board); + _ref1 = $$('.postContainer', board); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { node = _ref1[_j]; nodes.push(Main.preParse(node)); @@ -4117,21 +4117,22 @@ } }, preParse: function(node) { - var fileInfo, img, klass, post; - klass = node.className; + var el, fileInfo, img, klass, post; + el = $('.post', node); + klass = el.className; post = { - root: node.parentNode, - el: node, + root: node, + el: el, "class": klass, - id: node.id.slice(1), + id: el.id.slice(1), threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).id.slice(1), isInlined: /\binline\b/.test(klass), - quotes: node.getElementsByClassName('quotelink'), - backlinks: node.getElementsByClassName('backlink'), + quotes: el.getElementsByClassName('quotelink'), + backlinks: el.getElementsByClassName('backlink'), fileInfo: false, img: false }; - if (fileInfo = $('.fileInfo', node)) { + if (fileInfo = $('.fileInfo', el)) { img = fileInfo.nextElementSibling.firstElementChild; if (img.alt !== 'File deleted.') { post.fileInfo = fileInfo; diff --git a/script.coffee b/script.coffee index 87de1ef6f..0ae63ce9f 100644 --- a/script.coffee +++ b/script.coffee @@ -3137,7 +3137,7 @@ Main = board = $ '.board' nodes = [] - for node in $$ '.post', board + for node in $$ '.postContainer', board nodes.push Main.preParse node Main.node nodes, true @@ -3172,19 +3172,20 @@ Main = window.location = "https://raw.github.com/mayhemydg/4chan-x/#{version}/4chan_x.user.js" preParse: (node) -> - klass = node.className + el = $ '.post', node + klass = el.className post = - root: node.parentNode - el: node + root: node + el: el class: klass - id: node.id[1..] + id: el.id[1..] threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).id[1..] isInlined: /\binline\b/.test klass - quotes: node.getElementsByClassName 'quotelink' - backlinks: node.getElementsByClassName 'backlink' + quotes: el.getElementsByClassName 'quotelink' + backlinks: el.getElementsByClassName 'backlink' fileInfo: false img: false - if fileInfo = $ '.fileInfo', node + if fileInfo = $ '.fileInfo', el img = fileInfo.nextElementSibling.firstElementChild if img.alt isnt 'File deleted.' post.fileInfo = fileInfo From fabd8873175f7ffd84f4516c98ca0568a99f6494 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 15:52:28 +0200 Subject: [PATCH 20/52] Add a span in the reply hider. --- 4chan_x.user.js | 7 ++++--- script.coffee | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index d0aeb4da8..d31cb09ad 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -931,8 +931,8 @@ return; } button = post.el.previousElementSibling; - button.innerHTML = '[ - ]'; $.addClass(button, 'hide_reply_button'); + button.innerHTML = '[ - ]'; $.on(button.firstChild, 'click', ReplyHiding.toggle); if (post.id in g.hiddenReplies) { return ReplyHiding.hide(post.root.firstElementChild); @@ -969,7 +969,8 @@ button.hidden = true; return; } - return button.firstChild.textContent = "[ + ] " + ($('.nameBlock', button.nextElementSibling).textContent); + button.firstChild.firstChild.textContent = '[ + ]'; + return $.add(button.firstChild, $.tn(" " + ($('.nameBlock', button.nextElementSibling).textContent))); }, show: function(button) { $.removeClass(button, 'hidden_reply'); @@ -977,7 +978,7 @@ button.hidden = false; return; } - return button.firstChild.textContent = '[ - ]'; + return button.firstChild.innerHTML = '[ - ]'; } }; diff --git a/script.coffee b/script.coffee index 0ae63ce9f..7de768fdc 100644 --- a/script.coffee +++ b/script.coffee @@ -735,8 +735,8 @@ ReplyHiding = node: (post) -> return if post.isInlined or /\bop\b/.test post.class button = post.el.previousElementSibling - button.innerHTML = '[ - ]' $.addClass button, 'hide_reply_button' + button.innerHTML = '[ - ]' $.on button.firstChild, 'click', ReplyHiding.toggle if post.id of g.hiddenReplies @@ -766,7 +766,8 @@ ReplyHiding = button.hidden = true return - button.firstChild.textContent = "[ + ] #{$('.nameBlock', button.nextElementSibling).textContent}" + button.firstChild.firstChild.textContent = '[ + ]' + $.add button.firstChild, $.tn " #{$('.nameBlock', button.nextElementSibling).textContent}" show: (button) -> $.removeClass button, 'hidden_reply' @@ -775,7 +776,7 @@ ReplyHiding = button.hidden = false return - button.firstChild.textContent = '[ - ]' + button.firstChild.innerHTML = '[ - ]' Keybinds = init: -> From 145a6ef58172e5b453dbb46477d8fc6a6e64bfdd Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 16:38:55 +0200 Subject: [PATCH 21/52] Use [hidden] as this is easier to work with. --- 4chan_x.user.js | 8 +++++--- script.coffee | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index d31cb09ad..1c5760817 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -943,7 +943,7 @@ button = this.parentNode; id = button.id.slice(2); quotes = $$(".quotelink[href$='#p" + id + "'], .backlink[href='#p" + id + "']"); - if (/\bhidden_reply\b/.test(button.className)) { + if (button.nextElementSibling.hidden) { ReplyHiding.show(button); for (_i = 0, _len = quotes.length; _i < _len; _i++) { quote = quotes[_i]; @@ -961,9 +961,10 @@ return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); }, hide: function(button) { - if (/\bhidden_reply\b/.test(button.className)) { + if (button.nextElementSibling.hidden) { return; } + button.nextElementSibling.hidden = true; $.addClass(button, 'hidden_reply'); if (!Conf['Show Stubs']) { button.hidden = true; @@ -973,6 +974,7 @@ return $.add(button.firstChild, $.tn(" " + ($('.nameBlock', button.nextElementSibling).textContent))); }, show: function(button) { + button.nextElementSibling.hidden = false; $.removeClass(button, 'hidden_reply'); if (!Conf['Show Stubs']) { button.hidden = false; @@ -4209,7 +4211,7 @@ a[href="javascript:;"] {\ }\ \ .hidden_thread ~ *,\ -.hidden_reply + .reply,\ +.reply[hidden],\ #content > [name=tab]:not(:checked) + div,\ #updater:not(:hover) > :not(.move),\ #qp > input, #qp .inline, .forwarded {\ diff --git a/script.coffee b/script.coffee index 7de768fdc..020c4f4e8 100644 --- a/script.coffee +++ b/script.coffee @@ -746,7 +746,7 @@ ReplyHiding = button = @parentNode id = button.id[2..] quotes = $$ ".quotelink[href$='#p#{id}'], .backlink[href='#p#{id}']" - if /\bhidden_reply\b/.test button.className + if button.nextElementSibling.hidden ReplyHiding.show button for quote in quotes $.removeClass quote, 'filtered' @@ -759,7 +759,8 @@ ReplyHiding = $.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies hide: (button) -> - return if /\bhidden_reply\b/.test button.className # already hidden once by filter + return if button.nextElementSibling.hidden # already hidden once by filter + button.nextElementSibling.hidden = true $.addClass button, 'hidden_reply' unless Conf['Show Stubs'] @@ -770,6 +771,7 @@ ReplyHiding = $.add button.firstChild, $.tn " #{$('.nameBlock', button.nextElementSibling).textContent}" show: (button) -> + button.nextElementSibling.hidden = false $.removeClass button, 'hidden_reply' unless Conf['Show Stubs'] @@ -3237,7 +3239,7 @@ a[href="javascript:;"] { } .hidden_thread ~ *, -.hidden_reply + .reply, +.reply[hidden], #content > [name=tab]:not(:checked) + div, #updater:not(:hover) > :not(.move), #qp > input, #qp .inline, .forwarded { From bce07659a0842e8c26b1a20daee15a731cf5063f Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 16:54:55 +0200 Subject: [PATCH 22/52] Fix Recursive Filtering and strikethroughing quotes. --- 4chan_x.user.js | 4 ++-- script.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1c5760817..12b8edfd3 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -745,10 +745,10 @@ _ref = post.quotes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { quote = _ref[_i]; - if ((el = $.id(quote.hash.slice(1))) && el.parentNode.parentNode.parentNode.hidden) { + if ((el = $.id(quote.hash.slice(1))) && el.hidden) { $.addClass(quote, 'filtered'); if (Conf['Recursive Filtering']) { - ReplyHiding.hide(post.root); + ReplyHiding.hide(post.root.firstElementChild); } } } diff --git a/script.coffee b/script.coffee index 020c4f4e8..cb1b14feb 100644 --- a/script.coffee +++ b/script.coffee @@ -599,9 +599,9 @@ StrikethroughQuotes = node: (post) -> return if post.isInlined for quote in post.quotes - if (el = $.id quote.hash[1..]) and el.parentNode.parentNode.parentNode.hidden + if (el = $.id quote.hash[1..]) and el.hidden $.addClass quote, 'filtered' - ReplyHiding.hide post.root if Conf['Recursive Filtering'] + ReplyHiding.hide post.root.firstElementChild if Conf['Recursive Filtering'] return ExpandComment = From b8e953d4ae502ed104d6b1182e11fc6921da5382 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 17:11:43 +0200 Subject: [PATCH 23/52] Update Thread and Comment Expansion. --- 4chan_x.user.js | 23 +++++++++++------------ script.coffee | 23 +++++++---------------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 12b8edfd3..a81386caa 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -770,9 +770,9 @@ _ref = this.href.match(/(\d+)#p(\d+)/), _ = _ref[0], threadID = _ref[1], replyID = _ref[2]; this.textContent = "Loading " + replyID + "..."; a = this; - return $.cache(this.pathname, (function() { + return $.cache(this.pathname, function() { return ExpandComment.parse(this, a, threadID, replyID); - })); + }); }, parse: function(req, a, threadID, replyID) { var doc, href, node, post, quote, quotes, _i, _len; @@ -786,11 +786,11 @@ quotes = node.getElementsByClassName('quotelink'); for (_i = 0, _len = quotes.length; _i < _len; _i++) { quote = quotes[_i]; - if (quote.hash === (href = quote.getAttribute('href'))) { - quote.pathname = "/" + g.BOARD + "/res/" + threadID; - } else if (href !== quote.href) { - quote.href = "res/" + href; + href = quote.getAttribute('href'); + if (href[0] === '/') { + continue; } + quote.href = "res/" + href; } post = { el: node, @@ -846,9 +846,9 @@ $.rm(container); } a.textContent = a.textContent.replace('+', '\u00d7 Loading...'); - return $.cache(pathname, (function() { + return $.cache(pathname, function() { return ExpandThread.parse(this, pathname, thread, a); - })); + }); case '\u00d7': a.textContent = a.textContent.replace('\u00d7 Loading...', '+'); return $.cache.requests[pathname].abort(); @@ -902,11 +902,10 @@ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { quote = _ref1[_j]; href = quote.getAttribute('href'); - if (quote.hash === href) { - quote.pathname = pathname; - } else if (href !== quote.href) { - quote.href = "res/" + href; + if (href[0] === '/') { + continue; } + quote.href = "res/" + href; } id = reply.firstElementChild.id.slice(2); link = $('.postNum.desktop', reply).firstElementChild; diff --git a/script.coffee b/script.coffee index cb1b14feb..176c1bb76 100644 --- a/script.coffee +++ b/script.coffee @@ -614,7 +614,7 @@ ExpandComment = [_, threadID, replyID] = @href.match /(\d+)#p(\d+)/ @textContent = "Loading #{replyID}..." a = @ - $.cache @pathname, (-> ExpandComment.parse @, a, threadID, replyID) + $.cache @pathname, -> ExpandComment.parse @, a, threadID, replyID parse: (req, a, threadID, replyID) -> if req.status isnt 200 a.textContent = "#{req.status} #{req.statusText}" @@ -629,13 +629,9 @@ ExpandComment = quotes = node.getElementsByClassName 'quotelink' for quote in quotes - if quote.hash is href = quote.getAttribute 'href' # Add pathname to in-thread quotes - quote.pathname = "/#{g.BOARD}/res/#{threadID}" - # NEW HTML ??? - # OP quotes have different href attribute than normal quotes. - # Waiting for a reply from moot. - else if href isnt quote.href # Fix cross-thread links, not cross-board ones - quote.href = "res/#{href}" + href = quote.getAttribute 'href' + continue if href[0] is '/' # Cross-board quote + quote.href = "res/#{href}" # Fix pathnames post = el: node threadId: threadID @@ -674,7 +670,7 @@ ExpandThread = if container = $ '.container', thread.firstElementChild $.rm container a.textContent = a.textContent.replace '+', '\u00d7 Loading...' - $.cache pathname, (-> ExpandThread.parse @, pathname, thread, a) + $.cache pathname, -> ExpandThread.parse @, pathname, thread, a when '\u00d7' a.textContent = a.textContent.replace '\u00d7 Loading...', '+' @@ -711,13 +707,8 @@ ExpandThread = reply = d.importNode reply for quote in $$ '.quotelink', reply href = quote.getAttribute 'href' - if quote.hash is href # Add pathname to in-thread quotes - quote.pathname = pathname - # NEW HTML ??? - # OP quotes have different href attribute than normal quotes. - # Waiting for a reply from moot. - else if href isnt quote.href # Fix cross-thread links, not cross-board ones - quote.href = "res/#{href}" + continue if href[0] is '/' # Cross-board quote + quote.href = "res/#{href}" # Fix pathnames id = reply.firstElementChild.id[2..] link = $('.postNum.desktop', reply).firstElementChild link.href = "res/#{threadID}#p#{id}" From 6038e06ef69f37901e91a7ba0fcdd7a5e29bde71 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 17:13:21 +0200 Subject: [PATCH 24/52] Add a p to hashes of quotified links. --- script.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.coffee b/script.coffee index 176c1bb76..e57705950 100644 --- a/script.coffee +++ b/script.coffee @@ -2612,7 +2612,7 @@ Quotify = textContent: "#{quote}\u00A0(Dead)" if board is g.BOARD and $.id id - a.href = "##{id}" + a.href = "#p#{id}" a.className = 'quotelink' a.setAttribute 'onclick', "replyhl('#{id}');" else From 359d508c309b220303ffe51cdf51522470168473 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 17:17:41 +0200 Subject: [PATCH 25/52] Fix class of filtered backlinks. --- 4chan_x.user.js | 4 ++-- script.coffee | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index a81386caa..dd9334a61 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3052,7 +3052,7 @@ } a = $.el('a', { href: "#p" + post.id, - className: post.root.hidden ? 'filtered backlink' : 'backlink', + className: post.el.hidden ? 'filtered backlink' : 'backlink', textContent: QuoteBacklink.funk(post.id) }); for (qid in quotes) { @@ -3373,7 +3373,7 @@ textContent: "" + quote + "\u00A0(Dead)" })); if (board === g.BOARD && $.id(id)) { - a.href = "#" + id; + a.href = "#p" + id; a.className = 'quotelink'; a.setAttribute('onclick', "replyhl('" + id + "');"); } else { diff --git a/script.coffee b/script.coffee index e57705950..a2d74d442 100644 --- a/script.coffee +++ b/script.coffee @@ -2380,7 +2380,7 @@ QuoteBacklink = quotes[qid] = true a = $.el 'a', href: "#p#{post.id}" - className: if post.root.hidden then 'filtered backlink' else 'backlink' + className: if post.el.hidden then 'filtered backlink' else 'backlink' textContent: QuoteBacklink.funk post.id for qid of quotes # Don't backlink the OP. From 6ffa33bd6778e7fc80a913a11858766b78a3b890 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 18:18:41 +0200 Subject: [PATCH 26/52] Final fix for Show Stubs, Reply Hiding and Filtering. These should be independant. --- 4chan_x.user.js | 66 ++++++++++++++++++++++++++++--------------------- script.coffee | 65 ++++++++++++++++++++++++++---------------------- 2 files changed, 73 insertions(+), 58 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index dd9334a61..cf4194cf8 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -617,12 +617,12 @@ }; }, node: function(post) { - var el, filter, firstThread, isOP, key, result, thisThread, value, _i, _len, _ref; + var filter, firstThread, isOP, key, result, root, thisThread, value, _i, _len, _ref; if (post.isInlined) { return; } isOP = /\bop\b/.test(post["class"]); - el = post.el; + root = post.root; for (key in Filter.filters) { value = Filter[key](post); if (value === false) { @@ -637,18 +637,18 @@ if (result === true) { if (isOP) { if (!g.REPLY) { - ThreadHiding.hide(post.root.parentNode); + ThreadHiding.hide(root.parentNode); } else { continue; } } else { - ReplyHiding.hide(post.root); + ReplyHiding.hide(root); } return; } - $.addClass((isOP ? post.root.parentNode : post.root), result[0]); + $.addClass((isOP ? root.parentNode : root), result[0]); if (isOP && result[1] && !g.REPLY) { - thisThread = el.parentNode.parentNode; + thisThread = root.parentNode; if (firstThread = $('div[class=thread]')) { $.before(firstThread.parentNode, [thisThread, thisThread.nextElementSibling]); } @@ -748,7 +748,7 @@ if ((el = $.id(quote.hash.slice(1))) && el.hidden) { $.addClass(quote, 'filtered'); if (Conf['Recursive Filtering']) { - ReplyHiding.hide(post.root.firstElementChild); + ReplyHiding.hide(post.root); } } } @@ -929,28 +929,29 @@ if (post.isInlined || /\bop\b/.test(post["class"])) { return; } - button = post.el.previousElementSibling; + button = post.root.firstElementChild; $.addClass(button, 'hide_reply_button'); button.innerHTML = '[ - ]'; $.on(button.firstChild, 'click', ReplyHiding.toggle); if (post.id in g.hiddenReplies) { - return ReplyHiding.hide(post.root.firstElementChild); + return ReplyHiding.hide(post.root); } }, toggle: function() { - var button, id, quote, quotes, _i, _j, _len, _len1; + var button, id, quote, quotes, root, _i, _j, _len, _len1; button = this.parentNode; - id = button.id.slice(2); + root = button.parentNode; + id = root.id.slice(2); quotes = $$(".quotelink[href$='#p" + id + "'], .backlink[href='#p" + id + "']"); - if (button.nextElementSibling.hidden) { - ReplyHiding.show(button); + if (/\bstub\b/.test(button.className)) { + ReplyHiding.show(root); for (_i = 0, _len = quotes.length; _i < _len; _i++) { quote = quotes[_i]; $.removeClass(quote, 'filtered'); } delete g.hiddenReplies[id]; } else { - ReplyHiding.hide(button); + ReplyHiding.hide(root); for (_j = 0, _len1 = quotes.length; _j < _len1; _j++) { quote = quotes[_j]; $.addClass(quote, 'filtered'); @@ -959,27 +960,36 @@ } return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); }, - hide: function(button) { - if (button.nextElementSibling.hidden) { + hide: function(root) { + var button, el, stub; + button = root.firstElementChild; + if (button.hidden) { return; } - button.nextElementSibling.hidden = true; - $.addClass(button, 'hidden_reply'); + button.hidden = true; + el = root.lastElementChild; + el.hidden = true; if (!Conf['Show Stubs']) { - button.hidden = true; return; } - button.firstChild.firstChild.textContent = '[ + ]'; - return $.add(button.firstChild, $.tn(" " + ($('.nameBlock', button.nextElementSibling).textContent))); + stub = $.el('div', { + className: 'hide_reply_button stub', + innerHTML: '[ + ] ' + }); + $.add(stub.firstChild, $.tn($('.nameBlock', el).textContent)); + $.on(stub.firstChild, 'click', ReplyHiding.toggle); + return $.after(button, stub); }, - show: function(button) { - button.nextElementSibling.hidden = false; - $.removeClass(button, 'hidden_reply'); + show: function(root) { + var button, el; + el = root.lastElementChild; + button = root.firstElementChild; + el.hidden = false; + button.hidden = false; if (!Conf['Show Stubs']) { - button.hidden = false; return; } - return button.firstChild.innerHTML = '[ - ]'; + return $.rm(button.nextElementSibling); } }; @@ -2783,7 +2793,7 @@ node: function(post) { var img; img = post.img; - if (!(img && /\bimgspoiler\b/.test(img.parentNode.className)) || post["class"] === 'inline') { + if (!(img && /^Spoiler/.test(img.alt)) || post["class"] === 'inline') { return; } img.removeAttribute('style'); @@ -4120,7 +4130,7 @@ }, preParse: function(node) { var el, fileInfo, img, klass, post; - el = $('.post', node); + el = node.lastElementChild; klass = el.className; post = { root: node, diff --git a/script.coffee b/script.coffee index a2d74d442..8e0251ea2 100644 --- a/script.coffee +++ b/script.coffee @@ -514,7 +514,7 @@ Filter = node: (post) -> return if post.isInlined isOP = /\bop\b/.test post.class - {el} = post + {root} = post for key of Filter.filters value = Filter[key] post if value is false @@ -528,18 +528,18 @@ Filter = if result is true if isOP unless g.REPLY - ThreadHiding.hide post.root.parentNode + ThreadHiding.hide root.parentNode else continue else - ReplyHiding.hide post.root + ReplyHiding.hide root return # Highlight - $.addClass (if isOP then post.root.parentNode else post.root), result[0] + $.addClass (if isOP then root.parentNode else root), result[0] if isOP and result[1] and not g.REPLY # Put the highlighted OPs' threads on top of the board pages... - thisThread = el.parentNode.parentNode + thisThread = root.parentNode # ...before the first non highlighted thread. if firstThread = $ 'div[class=thread]' $.before firstThread.parentNode, [thisThread, thisThread.nextElementSibling] @@ -601,7 +601,7 @@ StrikethroughQuotes = for quote in post.quotes if (el = $.id quote.hash[1..]) and el.hidden $.addClass quote, 'filtered' - ReplyHiding.hide post.root.firstElementChild if Conf['Recursive Filtering'] + ReplyHiding.hide post.root if Conf['Recursive Filtering'] return ExpandComment = @@ -725,51 +725,56 @@ ReplyHiding = node: (post) -> return if post.isInlined or /\bop\b/.test post.class - button = post.el.previousElementSibling + button = post.root.firstElementChild $.addClass button, 'hide_reply_button' button.innerHTML = '[ - ]' $.on button.firstChild, 'click', ReplyHiding.toggle if post.id of g.hiddenReplies - ReplyHiding.hide post.root.firstElementChild + ReplyHiding.hide post.root toggle: -> button = @parentNode - id = button.id[2..] + root = button.parentNode + id = root.id[2..] quotes = $$ ".quotelink[href$='#p#{id}'], .backlink[href='#p#{id}']" - if button.nextElementSibling.hidden - ReplyHiding.show button + if /\bstub\b/.test button.className + ReplyHiding.show root for quote in quotes $.removeClass quote, 'filtered' delete g.hiddenReplies[id] else - ReplyHiding.hide button + ReplyHiding.hide root for quote in quotes $.addClass quote, 'filtered' g.hiddenReplies[id] = Date.now() $.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies - hide: (button) -> - return if button.nextElementSibling.hidden # already hidden once by filter - button.nextElementSibling.hidden = true - $.addClass button, 'hidden_reply' + hide: (root) -> + button = root.firstElementChild + return if button.hidden # already hidden once by filter + button.hidden = true + el = root.lastElementChild + el.hidden = true - unless Conf['Show Stubs'] - button.hidden = true - return + return unless Conf['Show Stubs'] - button.firstChild.firstChild.textContent = '[ + ]' - $.add button.firstChild, $.tn " #{$('.nameBlock', button.nextElementSibling).textContent}" + stub = $.el 'div', + className: 'hide_reply_button stub' + innerHTML: '[ + ] ' + $.add stub.firstChild, $.tn $('.nameBlock', el).textContent + $.on stub.firstChild, 'click', ReplyHiding.toggle + $.after button, stub - show: (button) -> - button.nextElementSibling.hidden = false - $.removeClass button, 'hidden_reply' + show: (root) -> + el = root.lastElementChild + button = root.firstElementChild + el.hidden = false + button.hidden = false - unless Conf['Show Stubs'] - button.hidden = false - return + return unless Conf['Show Stubs'] - button.firstChild.innerHTML = '[ - ]' + $.rm button.nextElementSibling Keybinds = init: -> @@ -2203,7 +2208,7 @@ RevealSpoilers = Main.callbacks.push @node node: (post) -> {img} = post - if not (img and /\bimgspoiler\b/.test img.parentNode.className) or post.class is 'inline' + if not (img and /^Spoiler/.test img.alt) or post.class is 'inline' return img.removeAttribute 'style' img.src = "//thumbs.4chan.org#{img.parentNode.pathname.replace(/src(\/\d+).+$/, 'thumb$1s.jpg')}" @@ -3166,7 +3171,7 @@ Main = window.location = "https://raw.github.com/mayhemydg/4chan-x/#{version}/4chan_x.user.js" preParse: (node) -> - el = $ '.post', node + el = node.lastElementChild klass = el.className post = root: node From 7751f7abd1f815e4158113c0c8d419a9d24f12c0 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 18:41:44 +0200 Subject: [PATCH 27/52] Thread Expansions fix and improvement. --- 4chan_x.user.js | 18 ++++++++++-------- script.coffee | 12 ++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index cf4194cf8..706534d10 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -837,12 +837,12 @@ return _results; }, toggle: function(thread) { - var a, backlink, container, div, next, num, pathname, _i, _len, _ref, _results; + var a, backlink, container, num, pathname, replies, reply, _i, _j, _len, _len1, _ref, _results; pathname = "/" + g.BOARD + "/res/" + thread.id.slice(1); a = $('.summary', thread); switch (a.textContent[0]) { case '+': - if (container = $('.container', thread.firstElementChild)) { + if (container = $('.container', a.previousElementSibling)) { $.rm(container); } a.textContent = a.textContent.replace('+', '\u00d7 Loading...'); @@ -865,14 +865,16 @@ return 5; } })(); - div = $.x("following-sibling::div[last()]/preceding-sibling::div[" + (num - 1) + "]", a); - while ((next = a.nextSibling) && next !== div) { - $.rm(next); + replies = $$('.replyContainer', thread); + replies.splice(replies.length - num, num); + for (_i = 0, _len = replies.length; _i < _len; _i++) { + reply = replies[_i]; + $.rm(reply); } _ref = $$('.backlink', a.previousElementSibling); _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - backlink = _ref[_i]; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + backlink = _ref[_j]; if (!$.id(backlink.hash.slice(1))) { _results.push($.rm(backlink)); } else { @@ -4130,7 +4132,7 @@ }, preParse: function(node) { var el, fileInfo, img, klass, post; - el = node.lastElementChild; + el = $('.post', node); klass = el.className; post = { root: node, diff --git a/script.coffee b/script.coffee index 8e0251ea2..5e5094628 100644 --- a/script.coffee +++ b/script.coffee @@ -667,7 +667,7 @@ ExpandThread = switch a.textContent[0] when '+' - if container = $ '.container', thread.firstElementChild + if container = $ '.container', a.previousElementSibling $.rm container a.textContent = a.textContent.replace '+', '\u00d7 Loading...' $.cache pathname, -> ExpandThread.parse @, pathname, thread, a @@ -683,13 +683,13 @@ ExpandThread = when 'b', 'vg' then 3 when 't' then 1 else 5 - div = $.x "following-sibling::div[last()]/preceding-sibling::div[#{num - 1}]", a - while (next = a.nextSibling) and next isnt div - $.rm next + replies = $$ '.replyContainer', thread + replies.splice replies.length - num, num + for reply in replies + $.rm reply for backlink in $$ '.backlink', a.previousElementSibling $.rm backlink unless $.id backlink.hash[1..] - parse: (req, pathname, thread, a) -> if req.status isnt 200 a.textContent = "#{req.status} #{req.statusText}" @@ -3171,7 +3171,7 @@ Main = window.location = "https://raw.github.com/mayhemydg/4chan-x/#{version}/4chan_x.user.js" preParse: (node) -> - el = node.lastElementChild + el = $ '.post', node klass = el.className post = root: node From 7f6782778f18e5f1b08408047925e1ea347985e1 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 18:48:55 +0200 Subject: [PATCH 28/52] Move Thread Hiding code before Reply Hiding. --- 4chan_x.user.js | 134 ++++++++++++++++++++++++------------------------ script.coffee | 112 ++++++++++++++++++++-------------------- 2 files changed, 123 insertions(+), 123 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 706534d10..9f1cc18ff 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -922,6 +922,73 @@ } }; + ThreadHiding = { + init: function() { + var a, hiddenThreads, thread, _i, _len, _ref; + hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); + _ref = $$('.thread'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + thread = _ref[_i]; + a = $.el('a', { + className: 'hide_thread_button', + innerHTML: '[ - ]', + href: 'javascript:;' + }); + $.on(a, 'click', ThreadHiding.cb); + $.prepend(thread, a); + if (thread.id.slice(1) in hiddenThreads) { + ThreadHiding.hide(thread); + } + } + }, + cb: function() { + return ThreadHiding.toggle(this.parentNode); + }, + toggle: function(thread) { + var hiddenThreads, id; + hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); + id = thread.id.slice(1); + if (thread.hidden || /\bhidden_thread\b/.test(thread.firstChild.className)) { + ThreadHiding.show(thread); + delete hiddenThreads[id]; + } else { + ThreadHiding.hide(thread); + hiddenThreads[id] = Date.now(); + } + return $.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); + }, + hide: function(thread) { + var a, num, opInfo, span, text; + if (!Conf['Show Stubs']) { + thread.hidden = true; + thread.nextElementSibling.hidden = true; + return; + } + if (thread.firstChild.className === 'block') { + return; + } + num = 0; + if (span = $('.summary', thread)) { + num = Number(span.textContent.match(/\d+/)); + } + num += $$('.opContainer ~ .replyContainer', thread).length; + text = num === 1 ? '1 reply' : "" + num + " replies"; + opInfo = $('.op > .postInfo > .nameBlock', thread).textContent; + a = $('.hide_thread_button', thread); + $.addClass(a, 'hidden_thread'); + a.firstChild.textContent = '[ + ]'; + return $.add(a, $.tn(" " + opInfo + " (" + text + ")")); + }, + show: function(thread) { + var a; + a = $('.hide_thread_button', thread); + $.removeClass(a, 'hidden_thread'); + a.innerHTML = '[ - ]'; + thread.hidden = false; + return thread.nextElementSibling.hidden = false; + } + }; + ReplyHiding = { init: function() { return Main.callbacks.push(this.node); @@ -2373,73 +2440,6 @@ } }; - ThreadHiding = { - init: function() { - var a, hiddenThreads, thread, _i, _len, _ref; - hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); - _ref = $$('.thread'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - thread = _ref[_i]; - a = $.el('a', { - className: 'hide_thread_button', - innerHTML: '[ - ]', - href: 'javascript:;' - }); - $.on(a, 'click', ThreadHiding.cb); - $.prepend(thread, a); - if (thread.id.slice(1) in hiddenThreads) { - ThreadHiding.hide(thread); - } - } - }, - cb: function() { - return ThreadHiding.toggle(this.parentNode); - }, - toggle: function(thread) { - var hiddenThreads, id; - hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); - id = thread.id.slice(1); - if (thread.hidden || /\bhidden_thread\b/.test(thread.firstChild.className)) { - ThreadHiding.show(thread); - delete hiddenThreads[id]; - } else { - ThreadHiding.hide(thread); - hiddenThreads[id] = Date.now(); - } - return $.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); - }, - hide: function(thread) { - var a, num, opInfo, span, text; - if (!Conf['Show Stubs']) { - thread.hidden = true; - thread.nextElementSibling.hidden = true; - return; - } - if (thread.firstChild.className === 'block') { - return; - } - num = 0; - if (span = $('.summary', thread)) { - num = Number(span.textContent.match(/\d+/)); - } - num += $$('.opContainer ~ .replyContainer', thread).length; - text = num === 1 ? '1 reply' : "" + num + " replies"; - opInfo = $('.op > .postInfo > .nameBlock', thread).textContent; - a = $('.hide_thread_button', thread); - $.addClass(a, 'hidden_thread'); - a.firstChild.textContent = '[ + ]'; - return $.add(a, $.tn(" " + opInfo + " (" + text + ")")); - }, - show: function(thread) { - var a; - a = $('.hide_thread_button', thread); - $.removeClass(a, 'hidden_thread'); - a.innerHTML = '[ - ]'; - thread.hidden = false; - return thread.nextElementSibling.hidden = false; - } - }; - Updater = { init: function() { var checkbox, checked, dialog, html, input, name, title, _i, _len, _ref; diff --git a/script.coffee b/script.coffee index 5e5094628..f4a18e807 100644 --- a/script.coffee +++ b/script.coffee @@ -719,6 +719,62 @@ ExpandThread = $.rm next $.after a, nodes +ThreadHiding = + init: -> + hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} + for thread in $$ '.thread' + a = $.el 'a', + className: 'hide_thread_button' + innerHTML: '[ - ]' + href: 'javascript:;' + $.on a, 'click', ThreadHiding.cb + $.prepend thread, a + + if thread.id[1..] of hiddenThreads + ThreadHiding.hide thread + return + + cb: -> + ThreadHiding.toggle @parentNode + + toggle: (thread) -> + hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} + id = thread.id[1..] + if thread.hidden or /\bhidden_thread\b/.test thread.firstChild.className + ThreadHiding.show thread + delete hiddenThreads[id] + else + ThreadHiding.hide thread + hiddenThreads[id] = Date.now() + $.set "hiddenThreads/#{g.BOARD}/", hiddenThreads + + hide: (thread) -> + unless Conf['Show Stubs'] + thread.hidden = true + thread.nextElementSibling.hidden = true + return + + return if thread.firstChild.className is 'block' # already hidden by filter + + num = 0 + if span = $ '.summary', thread + num = Number span.textContent.match /\d+/ + num += $$('.opContainer ~ .replyContainer', thread).length + text = if num is 1 then '1 reply' else "#{num} replies" + opInfo = $('.op > .postInfo > .nameBlock', thread).textContent + + a = $ '.hide_thread_button', thread + $.addClass a, 'hidden_thread' + a.firstChild.textContent = '[ + ]' + $.add a, $.tn " #{opInfo} (#{text})" + + show: (thread) -> + a = $ '.hide_thread_button', thread + $.removeClass a, 'hidden_thread' + a.innerHTML = '[ - ]' + thread.hidden = false + thread.nextElementSibling.hidden = false + ReplyHiding = init: -> Main.callbacks.push @node @@ -1871,62 +1927,6 @@ Options = Unread.update true @nextElementSibling.innerHTML = " " -ThreadHiding = - init: -> - hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} - for thread in $$ '.thread' - a = $.el 'a', - className: 'hide_thread_button' - innerHTML: '[ - ]' - href: 'javascript:;' - $.on a, 'click', ThreadHiding.cb - $.prepend thread, a - - if thread.id[1..] of hiddenThreads - ThreadHiding.hide thread - return - - cb: -> - ThreadHiding.toggle @parentNode - - toggle: (thread) -> - hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} - id = thread.id[1..] - if thread.hidden or /\bhidden_thread\b/.test thread.firstChild.className - ThreadHiding.show thread - delete hiddenThreads[id] - else - ThreadHiding.hide thread - hiddenThreads[id] = Date.now() - $.set "hiddenThreads/#{g.BOARD}/", hiddenThreads - - hide: (thread) -> - unless Conf['Show Stubs'] - thread.hidden = true - thread.nextElementSibling.hidden = true - return - - return if thread.firstChild.className is 'block' # already hidden by filter - - num = 0 - if span = $ '.summary', thread - num = Number span.textContent.match /\d+/ - num += $$('.opContainer ~ .replyContainer', thread).length - text = if num is 1 then '1 reply' else "#{num} replies" - opInfo = $('.op > .postInfo > .nameBlock', thread).textContent - - a = $ '.hide_thread_button', thread - $.addClass a, 'hidden_thread' - a.firstChild.textContent = '[ + ]' - $.add a, $.tn " #{opInfo} (#{text})" - - show: (thread) -> - a = $ '.hide_thread_button', thread - $.removeClass a, 'hidden_thread' - a.innerHTML = '[ - ]' - thread.hidden = false - thread.nextElementSibling.hidden = false - Updater = init: -> html = "
-#{Conf['Interval']}
" From ce1086ac60f4cf385457c1949d36f46819cffc78 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 1 May 2012 19:16:21 +0200 Subject: [PATCH 29/52] This should fix the updater. --- 4chan_x.user.js | 27 ++++++++++++++------------- script.coffee | 33 +++++++++++++++++---------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 9f1cc18ff..22eebf26c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2455,7 +2455,7 @@ dialog = UI.dialog('updater', 'bottom: 0; right: 0;', html); this.count = $('#count', dialog); this.timer = $('#timer', dialog); - this.br = $('br[clear]'); + this.thread = $('.thread'); _ref = $$('input', dialog); for (_i = 0, _len = _ref.length; _i < _len; _i++) { input = _ref[_i]; @@ -2514,7 +2514,7 @@ }; }, update: function() { - var doc, id, newPosts, nodes, reply, scroll, _i, _len, _ref; + var count, doc, id, lastPost, nodes, reply, scroll, _i, _len, _ref; if (this.status === 404) { Updater.timer.textContent = ''; Updater.count.textContent = 404; @@ -2531,7 +2531,7 @@ return; } Updater.retryCoef = 10; - Updater.timer.textContent = '-' + Conf['Interval']; + Updater.timer.textContent = "-" + Conf['Interval']; /* Status Code 304: Not modified By sending the `If-Modified-Since` header we get a proper status code, and no response. @@ -2549,25 +2549,26 @@ Updater.lastModified = this.getResponseHeader('Last-Modified'); doc = d.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = this.response; - id = $('input', Updater.br.previousElementSibling).name; + lastPost = Updater.thread.lastElementChild; + id = lastPost.id.slice(2); nodes = []; - _ref = $$('.reply', doc).reverse(); + _ref = $$('.replyContainer', doc).reverse(); for (_i = 0, _len = _ref.length; _i < _len; _i++) { reply = _ref[_i]; - if (reply.id <= id) { + if (reply.id.slice(2) <= id) { break; } - nodes.push(reply.parentNode.parentNode.parentNode); + nodes.push(reply); } - newPosts = nodes.length; - scroll = Conf['Scrolling'] && Updater.scrollBG() && newPosts && Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25; + count = nodes.length; + scroll = Conf['Scrolling'] && Updater.scrollBG() && count && lastPost.getBoundingClientRect().bottom - d.body.clientHeight < 25; if (Conf['Verbose']) { - Updater.count.textContent = "+" + newPosts; - Updater.count.className = newPosts ? 'new' : null; + Updater.count.textContent = "+" + count; + Updater.count.className = count ? 'new' : null; } - $.before(Updater.br, nodes.reverse()); + $.add(Updater.thread, nodes.reverse()); if (scroll) { - return Updater.br.previousSibling.scrollIntoView(); + return nodes[0].scrollIntoView(); } } }, diff --git a/script.coffee b/script.coffee index f4a18e807..9cb4c471e 100644 --- a/script.coffee +++ b/script.coffee @@ -1944,9 +1944,9 @@ Updater = dialog = UI.dialog 'updater', 'bottom: 0; right: 0;', html - @count = $ '#count', dialog - @timer = $ '#timer', dialog - @br = $ 'br[clear]' + @count = $ '#count', dialog + @timer = $ '#timer', dialog + @thread = $ '.thread' for input in $$ 'input', dialog if input.type is 'checkbox' @@ -2010,7 +2010,7 @@ Updater = return Updater.retryCoef = 10 - Updater.timer.textContent = '-' + Conf['Interval'] + Updater.timer.textContent = "-#{Conf['Interval']}" ### Status Code 304: Not modified @@ -2021,29 +2021,30 @@ Updater = if @status is 304 if Conf['Verbose'] Updater.count.textContent = '+0' - Updater.count.className = null + Updater.count.className = null return Updater.lastModified = @getResponseHeader 'Last-Modified' doc = d.implementation.createHTMLDocument '' doc.documentElement.innerHTML = @response - id = $('input', Updater.br.previousElementSibling).name + lastPost = Updater.thread.lastElementChild + id = lastPost.id[2..] nodes = [] - for reply in $$('.reply', doc).reverse() - break if reply.id <= id #make sure to not insert older posts - nodes.push reply.parentNode.parentNode.parentNode #table + for reply in $$('.replyContainer', doc).reverse() + break if reply.id[2..] <= id #make sure to not insert older posts + nodes.push reply - newPosts = nodes.length - scroll = Conf['Scrolling'] && Updater.scrollBG() && newPosts && - Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25 + count = nodes.length + scroll = Conf['Scrolling'] && Updater.scrollBG() && count && + lastPost.getBoundingClientRect().bottom - d.body.clientHeight < 25 if Conf['Verbose'] - Updater.count.textContent = "+#{newPosts}" - Updater.count.className = if newPosts then 'new' else null + Updater.count.textContent = "+#{count}" + Updater.count.className = if count then 'new' else null - $.before Updater.br, nodes.reverse() + $.add Updater.thread, nodes.reverse() if scroll - Updater.br.previousSibling.scrollIntoView() + nodes[0].scrollIntoView() timeout: -> Updater.timeoutID = setTimeout Updater.timeout, 1000 From f2631c9de1d2ef4912bc45a10fceab022c8b40d4 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 2 May 2012 02:12:51 +0200 Subject: [PATCH 30/52] Fix Unread notifiers. --- 4chan_x.user.js | 9 +++++---- script.coffee | 8 +++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 22eebf26c..1844119b8 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3478,20 +3478,21 @@ replies: [], foresee: [], node: function(post) { - var count, index; + var count, el, index; if ((index = Unread.foresee.indexOf(post.id)) !== -1) { Unread.foresee.splice(index, 1); return; } - if (post.root.hidden || post["class"]) { + el = post.el; + if (el.hidden) { return; } - count = Unread.replies.push(post.el); + count = Unread.replies.push(el); return Unread.update(count === 1); }, scroll: function() { var bottom, height, i, reply, _i, _len, _ref; - height = d.body.clientHeight; + height = d.documentElement.clientHeight; _ref = Unread.replies; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { reply = _ref[i]; diff --git a/script.coffee b/script.coffee index 9cb4c471e..74d6074c6 100644 --- a/script.coffee +++ b/script.coffee @@ -2691,12 +2691,14 @@ Unread = if (index = Unread.foresee.indexOf post.id) isnt -1 Unread.foresee.splice index, 1 return - return if post.root.hidden or post.class - count = Unread.replies.push post.el + {el} = post + # new HTML ??? + return if el.hidden # or inlined/OP + count = Unread.replies.push el Unread.update count is 1 scroll: -> - height = d.body.clientHeight + height = d.documentElement.clientHeight for reply, i in Unread.replies {bottom} = reply.getBoundingClientRect() if bottom > height #post is not completely read From 8bbddc262ebe99c6300f2f8c9519e4bd123aea0c Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 2 May 2012 03:04:17 +0200 Subject: [PATCH 31/52] Fix UI and other document visible dimension values. --- 4chan_x.user.js | 44 ++++++++++++++++++-------------------- script.coffee | 57 +++++++++++++++++++++++-------------------------- 2 files changed, 48 insertions(+), 53 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1844119b8..fda862808 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -217,22 +217,21 @@ rect = el.getBoundingClientRect(); UI.dx = e.clientX - rect.left; UI.dy = e.clientY - rect.top; - UI.width = d.body.clientWidth - el.offsetWidth; - return UI.height = d.body.clientHeight - el.offsetHeight; + UI.width = d.documentElement.clientWidth - rect.width; + return UI.height = d.documentElement.clientHeight - rect.height; }, drag: function(e) { - var bottom, left, right, style, top; + var left, style, top; left = e.clientX - UI.dx; top = e.clientY - UI.dy; - left = left < 10 ? 0 : UI.width - left < 10 ? null : left; - top = top < 10 ? 0 : UI.height - top < 10 ? null : top; - right = left === null ? 0 : null; - bottom = top === null ? 0 : null; + left = left < 10 ? '0px' : UI.width - left < 10 ? null : left + 'px'; + top = top < 10 ? '0px' : UI.height - top < 10 ? null : top + 'px'; style = UI.el.style; + $.log(left, top); + style.left = left; style.top = top; - style.right = right; - style.bottom = bottom; - return style.left = left; + style.right = left === null ? '0px' : null; + return style.bottom = top === null ? '0px' : null; }, dragend: function() { var el; @@ -242,20 +241,19 @@ return d.removeEventListener('mouseup', UI.dragend, false); }, hover: function(e) { - var clientHeight, clientWidth, clientX, clientY, el, height, style, top, _ref; + var clientHeight, clientWidth, clientX, clientY, height, style, top, _ref; clientX = e.clientX, clientY = e.clientY; - el = UI.el; - style = el.style; - _ref = d.body, clientHeight = _ref.clientHeight, clientWidth = _ref.clientWidth; - height = el.offsetHeight; + style = UI.el.style; + _ref = d.documentElement, clientHeight = _ref.clientHeight, clientWidth = _ref.clientWidth; + height = UI.el.offsetHeight; top = clientY - 120; - style.top = clientHeight <= height || top <= 0 ? 0 : top + height >= clientHeight ? clientHeight - height : top; + style.top = clientHeight <= height || top <= 0 ? '0px' : top + height >= clientHeight ? clientHeight - height + 'px' : top + 'px'; if (clientX <= clientWidth - 400) { - style.left = clientX + 45; + style.left = clientX + 45 + 'px'; return style.right = null; } else { style.left = null; - return style.right = clientWidth - clientX + 45; + return style.right = clientWidth - clientX + 45 + 'px'; } }, hoverend: function() { @@ -1286,7 +1284,7 @@ td.className = 'reply'; td.removeAttribute('tabindex'); rect = td.getBoundingClientRect(); - if (rect.bottom >= 0 && rect.top <= d.body.clientHeight) { + if (rect.bottom >= 0 && rect.top <= d.documentElement.clientHeight) { next = delta === +1 ? $.x('following::td[@class="reply"]', td) : $.x('preceding::td[@class="reply"]', td); if (!next) { td.className = 'replyhl'; @@ -1298,7 +1296,7 @@ return; } rect = next.getBoundingClientRect(); - if (rect.top < 0 || rect.bottom > d.body.clientHeight) { + if (rect.top < 0 || rect.bottom > d.documentElement.clientHeight) { next.scrollIntoView(delta === -1); } next.className = 'replyhl'; @@ -1314,7 +1312,7 @@ for (_i = 0, _len = replies.length; _i < _len; _i++) { reply = replies[_i]; rect = reply.getBoundingClientRect(); - if (delta === +1 && rect.top >= 0 || delta === -1 && rect.bottom <= d.body.clientHeight) { + if (delta === +1 && rect.top >= 0 || delta === -1 && rect.bottom <= d.documentElement.clientHeight) { reply.className = 'replyhl'; reply.tabIndex = 0; reply.focus(); @@ -2561,7 +2559,7 @@ nodes.push(reply); } count = nodes.length; - scroll = Conf['Scrolling'] && Updater.scrollBG() && count && lastPost.getBoundingClientRect().bottom - d.body.clientHeight < 25; + scroll = Conf['Scrolling'] && Updater.scrollBG() && count && lastPost.getBoundingClientRect().bottom - d.documentElement.clientHeight < 25; if (Conf['Verbose']) { Updater.count.textContent = "+" + count; Updater.count.className = count ? 'new' : null; @@ -3883,7 +3881,7 @@ return $.prepend($.id('delform'), controls); }, resize: function() { - return ImageExpand.style.textContent = ".fitheight img[data-md5] + img {max-height:" + d.body.clientHeight + "px;}"; + return ImageExpand.style.textContent = ".fitheight img[data-md5] + img {max-height:" + d.documentElement.clientHeight + "px;}"; } }; diff --git a/script.coffee b/script.coffee index 74d6074c6..95aaf8f6d 100644 --- a/script.coffee +++ b/script.coffee @@ -175,32 +175,30 @@ UI = d.addEventListener 'mouseup', UI.dragend, false #distance from pointer to el edge is constant; calculate it here. # XXX opera reports el.offsetLeft / el.offsetTop as 0 - rect = el.getBoundingClientRect() - UI.dx = e.clientX - rect.left - UI.dy = e.clientY - rect.top - #factor out el from document dimensions - UI.width = d.body.clientWidth - el.offsetWidth - UI.height = d.body.clientHeight - el.offsetHeight + rect = el.getBoundingClientRect() + UI.dx = e.clientX - rect.left + UI.dy = e.clientY - rect.top + UI.width = d.documentElement.clientWidth - rect.width + UI.height = d.documentElement.clientHeight - rect.height drag: (e) -> left = e.clientX - UI.dx - top = e.clientY - UI.dy + top = e.clientY - UI.dy left = - if left < 10 then 0 + if left < 10 then '0px' else if UI.width - left < 10 then null - else left + else left + 'px' top = - if top < 10 then 0 + if top < 10 then '0px' else if UI.height - top < 10 then null - else top - right = if left is null then 0 else null - bottom = if top is null then 0 else null + else top + 'px' #using null instead of '' is 4% faster #these 4 statements are 40% faster than 1 style.cssText {style} = UI.el - style.top = top - style.right = right - style.bottom = bottom + $.log left, top style.left = left + style.top = top + style.right = if left is null then '0px' else null + style.bottom = if top is null then '0px' else null dragend: -> #$ coffee -bpe '{a} = {b} = c' #var a, b; @@ -211,26 +209,25 @@ UI = d.removeEventListener 'mouseup', UI.dragend, false hover: (e) -> {clientX, clientY} = e - {el} = UI - {style} = el - {clientHeight, clientWidth} = d.body - height = el.offsetHeight + {style} = UI.el + {clientHeight, clientWidth} = d.documentElement + height = UI.el.offsetHeight top = clientY - 120 style.top = if clientHeight <= height or top <= 0 - 0 + '0px' else if top + height >= clientHeight - clientHeight - height + clientHeight - height + 'px' else - top + top + 'px' if clientX <= clientWidth - 400 - style.left = clientX + 45 + style.left = clientX + 45 + 'px' style.right = null else style.left = null - style.right = clientWidth - clientX + 45 + style.right = clientWidth - clientX + 45 + 'px' hoverend: -> $.rm UI.el @@ -969,7 +966,7 @@ Keybinds = td.className = 'reply' td.removeAttribute 'tabindex' rect = td.getBoundingClientRect() - if rect.bottom >= 0 and rect.top <= d.body.clientHeight # We're at least partially visible + if rect.bottom >= 0 and rect.top <= d.documentElement.clientHeight # We're at least partially visible next = if delta is +1 $.x 'following::td[@class="reply"]', td @@ -982,7 +979,7 @@ Keybinds = return return unless g.REPLY or $.x('ancestor::div[@class="thread"]', next) is thread rect = next.getBoundingClientRect() - if rect.top < 0 or rect.bottom > d.body.clientHeight + if rect.top < 0 or rect.bottom > d.documentElement.clientHeight next.scrollIntoView delta is -1 next.className = 'replyhl' next.tabIndex = 0 @@ -993,7 +990,7 @@ Keybinds = replies.reverse() if delta is -1 for reply in replies rect = reply.getBoundingClientRect() - if delta is +1 and rect.top >= 0 or delta is -1 and rect.bottom <= d.body.clientHeight + if delta is +1 and rect.top >= 0 or delta is -1 and rect.bottom <= d.documentElement.clientHeight reply.className = 'replyhl' reply.tabIndex = 0 reply.focus() @@ -2037,7 +2034,7 @@ Updater = count = nodes.length scroll = Conf['Scrolling'] && Updater.scrollBG() && count && - lastPost.getBoundingClientRect().bottom - d.body.clientHeight < 25 + lastPost.getBoundingClientRect().bottom - d.documentElement.clientHeight < 25 if Conf['Verbose'] Updater.count.textContent = "+#{count}" Updater.count.className = if count then 'new' else null @@ -2967,7 +2964,7 @@ ImageExpand = $.prepend $.id('delform'), controls resize: -> - ImageExpand.style.textContent = ".fitheight img[data-md5] + img {max-height:#{d.body.clientHeight}px;}" + ImageExpand.style.textContent = ".fitheight img[data-md5] + img {max-height:#{d.documentElement.clientHeight}px;}" Main = init: -> From e6954fd254343a42ab274721652dc002bbe29b77 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 2 May 2012 11:14:43 +0200 Subject: [PATCH 32/52] Update Next/Previous board page navigation. --- 4chan_x.user.js | 10 +++++----- script.coffee | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index fda862808..9716b4420 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1071,7 +1071,7 @@ return $.on(d, 'keydown', Keybinds.keydown); }, keydown: function(e) { - var key, o, range, selEnd, selStart, ta, thread, value, _ref, _ref1; + var key, link, o, range, selEnd, selStart, ta, thread, value; if (!(key = Keybinds.keyCode(e)) || /TEXTAREA|INPUT/.test(e.target.nodeName) && !(e.altKey || e.ctrlKey || e.keyCode === 27)) { return; } @@ -1132,13 +1132,13 @@ window.location = "/" + g.BOARD + "/0#0"; break; case Conf.nextPage: - if ((_ref = $('input[value=Next]')) != null) { - _ref.click(); + if (link = $('link[rel=next]', d.head)) { + window.location = link.href; } break; case Conf.previousPage: - if ((_ref1 = $('input[value=Previous]')) != null) { - _ref1.click(); + if (link = $('link[rel=prev]', d.head)) { + window.location.href = link.href; } break; case Conf.nextThread: diff --git a/script.coffee b/script.coffee index 95aaf8f6d..9b2cae76f 100644 --- a/script.coffee +++ b/script.coffee @@ -888,9 +888,11 @@ Keybinds = when Conf.zero window.location = "/#{g.BOARD}/0#0" when Conf.nextPage - $('input[value=Next]')?.click() + if link = $ 'link[rel=next]', d.head + window.location = link.href when Conf.previousPage - $('input[value=Previous]')?.click() + if link = $ 'link[rel=prev]', d.head + window.location.href = link.href # Thread Navigation when Conf.nextThread return if g.REPLY From c6a72d9faee1e5120554facbe57abc83a3a5ca17 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 2 May 2012 11:24:03 +0200 Subject: [PATCH 33/52] post.img -> img in auto-gif. --- 4chan_x.user.js | 17 +++++++++-------- script.coffee | 15 ++++++++------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 9716b4420..d5489ceb1 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3710,17 +3710,18 @@ return Main.callbacks.push(this.node); }, node: function(post) { - var img, src; - if (post.root.hidden || !post.img) { + var gif, img, src; + img = post.img; + if (post.root.hidden || !img) { return; } - src = post.img.parentNode.href; - if (/gif$/.test(src) && !/spoiler/.test(post.img.src)) { - img = $.el('img'); - $.on(img, 'load', function() { - return post.img.src = src; + src = img.parentNode.href; + if (/gif$/.test(src) && !/spoiler/.test(img.src)) { + gif = $.el('img'); + $.on(gif, 'load', function() { + return img.src = src; }); - return img.src = src; + return gif.src = src; } } }; diff --git a/script.coffee b/script.coffee index 9b2cae76f..fb0cf70bb 100644 --- a/script.coffee +++ b/script.coffee @@ -2845,14 +2845,15 @@ AutoGif = return if g.BOARD is 'gif' Main.callbacks.push @node node: (post) -> - return if post.root.hidden or not post.img - src = post.img.parentNode.href - if /gif$/.test(src) and !/spoiler/.test post.img.src - img = $.el 'img' - $.on img, 'load', -> + {img} = post + return if post.root.hidden or not img + src = img.parentNode.href + if /gif$/.test(src) and !/spoiler/.test img.src + gif = $.el 'img' + $.on gif, 'load', -> # Replace the thumbnail once the GIF has finished loading. - post.img.src = src - img.src = src + img.src = src + gif.src = src ImageExpand = init: -> From 1433baacfdcc050912d3aaf6896b1f1f3f6361c9 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 2 May 2012 11:59:14 +0200 Subject: [PATCH 34/52] Fix some post hidden checking. --- 4chan_x.user.js | 4 ++-- script.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index d5489ceb1..c63b4d499 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3712,7 +3712,7 @@ node: function(post) { var gif, img, src; img = post.img; - if (post.root.hidden || !img) { + if (post.el.hidden || !img) { return; } src = img.parentNode.href; @@ -3738,7 +3738,7 @@ } a = post.img.parentNode; $.on(a, 'click', ImageExpand.cb.toggle); - if (ImageExpand.on && !post.root.hidden && post["class"] !== 'inline') { + if (ImageExpand.on && !post.el.hidden && post["class"] !== 'inline') { return ImageExpand.expand(post.img); } }, diff --git a/script.coffee b/script.coffee index fb0cf70bb..44ca9c4b0 100644 --- a/script.coffee +++ b/script.coffee @@ -2846,7 +2846,7 @@ AutoGif = Main.callbacks.push @node node: (post) -> {img} = post - return if post.root.hidden or not img + return if post.el.hidden or not img src = img.parentNode.href if /gif$/.test(src) and !/spoiler/.test img.src gif = $.el 'img' @@ -2864,7 +2864,7 @@ ImageExpand = return unless post.img a = post.img.parentNode $.on a, 'click', ImageExpand.cb.toggle - if ImageExpand.on and !post.root.hidden and post.class isnt 'inline' + if ImageExpand.on and !post.el.hidden and post.class isnt 'inline' ImageExpand.expand post.img cb: toggle: (e) -> From 1e5056852064dd33fa2e7062f4fcc9b376406714 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 3 May 2012 10:10:44 +0200 Subject: [PATCH 35/52] Fix Quote Inlining. ohboyherewego.diff --- 4chan_x.user.js | 127 +++++++++++++++++++++++++----------------------- script.coffee | 105 ++++++++++++++++++++------------------- 2 files changed, 120 insertions(+), 112 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index c63b4d499..2669e119e 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3117,11 +3117,11 @@ return; } e.preventDefault(); - id = this.hash.slice(1); + id = this.hash.slice(2); if (/\binlined\b/.test(this.className)) { QuoteInline.rm(this, id); } else { - if ($.x("ancestor::*[@id='" + id + "']", this)) { + if ($.x("ancestor::div[contains(@id,'p" + id + "')]", this)) { return; } QuoteInline.add(this, id); @@ -3129,61 +3129,60 @@ return this.classList.toggle('inlined'); }, add: function(q, id) { - var el, i, inline, pathname, root, table, threadID; - root = q.parentNode.nodeName === 'FONT' ? q.parentNode : q.nextSibling ? q.nextSibling : q; - if (el = $.id(id)) { - inline = QuoteInline.table(id, el.innerHTML); - if ((i = Unread.replies.indexOf(el.parentNode.parentNode.parentNode)) !== -1) { + var clonePost, el, i, inline, pathname, root; + root = $.x('ancestor::*[parent::blockquote]', q); + if (el = $.id("p" + id)) { + $.removeClass(el, 'qphl'); + clonePost = QuoteInline.clone(id, el); + if (/\bbacklink\b/.test(q.className)) { + $.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); } - if (/\bbacklink\b/.test(q.className)) { - $.after(q.parentNode, inline); - if (Conf['Forward Hiding']) { - table = $.x('ancestor::table', el); - $.addClass(table, 'forwarded'); - ++table.title || (table.title = 1); - } - return; - } - return $.after(root, inline); - } else { - inline = $.el('td', { - className: 'reply inline', - id: "i" + id, - innerHTML: "Loading " + id + "..." - }); - $.after(root, inline); - pathname = q.pathname; - threadID = pathname.split('/').pop(); - return $.cache(pathname, (function() { - return QuoteInline.parse(this, pathname, id, threadID, inline); - })); + 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); + }); }, rm: function(q, id) { - var inlined, table, _i, _len, _ref; - table = $.x("following::*[@id='i" + id + "']", q); - $.rm(table); + var div, inlined, _i, _len, _ref; + div = $.x("following::div[@id='i_pc" + id + "']", q); + $.rm(div); if (!Conf['Forward Hiding']) { return; } - _ref = $$('.backlink.inlined', table); + _ref = $$('.backlink.inlined', div); for (_i = 0, _len = _ref.length; _i < _len; _i++) { inlined = _ref[_i]; - table = $.x('ancestor::table', $.id(inlined.hash.slice(1))); - if (!--table.title) { - $.removeClass(table, 'forwarded'); + div = $.id(inlined.hash.slice(1)); + if (!--div.dataset.forwarded) { + $.removeClass(div.parentNode, 'forwarded'); } } if (/\bbacklink\b/.test(q.className)) { - table = $.x('ancestor::table', $.id(id)); - if (!--table.title) { - return $.removeClass(table, 'forwarded'); + div = $.id("p" + id); + if (!--div.dataset.forwarded) { + return $.removeClass(div.parentNode, 'forwarded'); } } }, - parse: function(req, pathname, id, threadID, inline) { + parse: function(req, pathname, id, inline) { var doc, href, link, newInline, node, quote, _i, _len, _ref; if (!inline.parentNode) { return; @@ -3194,29 +3193,36 @@ } doc = d.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = req.response; - node = doc.getElementById(id); - newInline = QuoteInline.table(id, node.innerHTML); + 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]; - if ((href = quote.getAttribute('href')) === quote.hash) { - quote.pathname = pathname; - } else if (!g.REPLY && href !== quote.href) { - quote.href = "res/" + href; + href = quote.getAttribute('href'); + if (href[0] === '/') { + continue; } + quote.href = "res/" + href; } - link = $('.quotejs', newInline); - link.href = "" + pathname + "#" + id; + link = $('.postInfo > .postNum > a:first-child', newInline); + link.href = "" + pathname + "#p" + id; link.nextSibling.href = "" + pathname + "#q" + id; $.addClass(newInline, 'crossquote'); return $.replace(inline, newInline); }, - table: function(id, html) { - return $.el('table', { - className: 'inline', - id: "i" + id, - innerHTML: "" + html + "" + clone: function(id, el) { + var clone, node, _i, _len, _ref; + clone = $.el('div', { + className: 'postContainer inline', + id: "i_pc" + id }); + $.add(clone, el.cloneNode(true)); + _ref = $$('[id]', clone); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + node.id = "i_" + node.id; + } + return clone; } }; @@ -3240,7 +3246,7 @@ } }, mouseover: function(e) { - var el, id, qp, quote, replyID, threadID, _i, _len, _ref; + var el, id, qp, quote, replyID, _i, _len, _ref; if (/\binlined\b/.test(this.className)) { return; } @@ -3265,10 +3271,9 @@ } } else { qp.textContent = "Loading " + id + "..."; - threadID = this.pathname.split('/').pop(); - $.cache(this.pathname, (function() { - return QuotePreview.parse(this, id, threadID); - })); + $.cache(this.pathname, function() { + return QuotePreview.parse(this, id); + }); UI.hover(e); } $.on(this, 'mousemove', UI.hover); @@ -3276,14 +3281,14 @@ }, mouseout: function() { var el; + UI.hoverend(); if (el = $.id(this.hash.slice(1))) { $.removeClass(el, 'qphl'); } - UI.hoverend(); $.off(this, 'mousemove', UI.hover); return $.off(this, 'mouseout click', QuotePreview.mouseout); }, - parse: function(req, id, threadID) { + parse: function(req, id) { var doc, node, post, qp; if (!((qp = UI.el) && qp.textContent === ("Loading " + id + "..."))) { return; @@ -3405,7 +3410,7 @@ ReportButton = { init: function() { this.a = $.el('a', { - className: 'reportbutton', + className: 'report_button', innerHTML: '[ ! ]', href: 'javascript:;' }); diff --git a/script.coffee b/script.coffee index 44ca9c4b0..301c296ca 100644 --- a/script.coffee +++ b/script.coffee @@ -2417,53 +2417,53 @@ QuoteInline = toggle: (e) -> return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0 e.preventDefault() - id = @hash[1..] + id = @hash[2..] if /\binlined\b/.test @className QuoteInline.rm @, id else - return if $.x "ancestor::*[@id='#{id}']", @ + return if $.x "ancestor::div[contains(@id,'p#{id}')]", @ QuoteInline.add @, id @classList.toggle 'inlined' add: (q, id) -> - root = if q.parentNode.nodeName is 'FONT' then q.parentNode else if q.nextSibling then q.nextSibling else q - if el = $.id id - inline = QuoteInline.table id, el.innerHTML - if (i = Unread.replies.indexOf el.parentNode.parentNode.parentNode) isnt -1 + root = $.x 'ancestor::*[parent::blockquote]', q + if el = $.id "p#{id}" + $.removeClass el, 'qphl' + clonePost = QuoteInline.clone id, el + if /\bbacklink\b/.test q.className + $.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 - if /\bbacklink\b/.test q.className - $.after q.parentNode, inline - if Conf['Forward Hiding'] - table = $.x 'ancestor::table', el - $.addClass table, 'forwarded' - # Will only unhide if there's no inlined backlinks of it anymore. - ++table.title or table.title = 1 - return - $.after root, inline - else - inline = $.el 'td', - className: 'reply inline' - id: "i#{id}" - innerHTML: "Loading #{id}..." - $.after root, inline - {pathname} = q - threadID = pathname.split('/').pop() - $.cache pathname, (-> QuoteInline.parse @, pathname, id, threadID, inline) + return + + inline = $.el 'div', + className: 'inline' + id: "i#{id}" + textContent: "Loading #{id}..." + $.after root, inline + {pathname} = q + $.cache pathname, -> QuoteInline.parse @, pathname, id, inline rm: (q, id) -> - #select the corresponding table or loading td - table = $.x "following::*[@id='i#{id}']", q - $.rm table + # select the corresponding inlined quote or loading quote + div = $.x "following::div[@id='i_pc#{id}']", q + $.rm div return unless Conf['Forward Hiding'] - for inlined in $$ '.backlink.inlined', table - table = $.x 'ancestor::table', $.id inlined.hash[1..] - $.removeClass table, 'forwarded' unless --table.title + for inlined in $$ '.backlink.inlined', div + div = $.id inlined.hash[1..] + $.removeClass div.parentNode, 'forwarded' unless --div.dataset.forwarded if /\bbacklink\b/.test q.className - table = $.x 'ancestor::table', $.id id - $.removeClass table, 'forwarded' unless --table.title + div = $.id "p#{id}" + $.removeClass div.parentNode, 'forwarded' unless --div.dataset.forwarded - parse: (req, pathname, id, threadID, inline) -> + parse: (req, pathname, id, inline) -> return unless inline.parentNode if req.status isnt 200 @@ -2473,23 +2473,27 @@ QuoteInline = doc = d.implementation.createHTMLDocument '' doc.documentElement.innerHTML = req.response - node = doc.getElementById id - newInline = QuoteInline.table id, node.innerHTML + node = doc.getElementById "p#{id}" + newInline = QuoteInline.clone id, node for quote in $$ '.quotelink', newInline - if (href = quote.getAttribute 'href') is quote.hash #add pathname to normal quotes - quote.pathname = pathname - else if !g.REPLY and href isnt quote.href #fix x-thread links, not x-board ones - quote.href = "res/#{href}" - link = $ '.quotejs', newInline - link.href = "#{pathname}##{id}" + 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, 'crossquote' $.replace inline, newInline - table: (id, html) -> - $.el 'table', - className: 'inline' - id: "i#{id}" - innerHTML: "#{html}" + + clone: (id, el) -> + clone = $.el 'div', + className: 'postContainer inline' + id: "i_pc#{id}" + $.add clone, el.cloneNode true + for node in $$ '[id]', clone + # Don't mess with other features + node.id = "i_#{node.id}" + clone QuotePreview = init: -> @@ -2517,18 +2521,17 @@ QuotePreview = $.addClass quote, 'forwardlink' else qp.textContent = "Loading #{id}..." - threadID = @pathname.split('/').pop() - $.cache @pathname, (-> QuotePreview.parse @, id, threadID) + $.cache @pathname, -> QuotePreview.parse @, id UI.hover e $.on @, 'mousemove', UI.hover $.on @, 'mouseout click', QuotePreview.mouseout mouseout: -> + UI.hoverend() if el = $.id @hash[1..] $.removeClass el, 'qphl' - UI.hoverend() $.off @, 'mousemove', UI.hover $.off @, 'mouseout click', QuotePreview.mouseout - parse: (req, id, threadID) -> + parse: (req, id) -> return unless (qp = UI.el) and qp.textContent is "Loading #{id}..." if req.status isnt 200 @@ -2637,7 +2640,7 @@ Quotify = ReportButton = init: -> @a = $.el 'a', - className: 'reportbutton' + className: 'report_button' innerHTML: '[ ! ]' href: 'javascript:;' Main.callbacks.push @node From e516eed4ebda33c09b492077233498dcfdd8254d Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 3 May 2012 11:03:15 +0200 Subject: [PATCH 36/52] Fix support of inlined posts in other features. --- 4chan_x.user.js | 34 +++++++++++++++--------------- script.coffee | 56 ++++++++++++++++++++++++------------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 2669e119e..c4b9986dc 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -227,7 +227,6 @@ left = left < 10 ? '0px' : UI.width - left < 10 ? null : left + 'px'; top = top < 10 ? '0px' : UI.height - top < 10 ? null : top + 'px'; style = UI.el.style; - $.log(left, top); style.left = left; style.top = top; style.right = left === null ? '0px' : null; @@ -619,7 +618,7 @@ if (post.isInlined) { return; } - isOP = /\bop\b/.test(post["class"]); + isOP = post.id === post.threadId; root = post.root; for (key in Filter.filters) { value = Filter[key](post); @@ -907,8 +906,8 @@ } quote.href = "res/" + href; } - id = reply.firstElementChild.id.slice(2); - link = $('.postNum.desktop', reply).firstElementChild; + id = reply.id.slice(2); + link = $('.postInfo > .postNum > a:first-child', reply); link.href = "res/" + threadID + "#p" + id; link.nextSibling.href = "res/" + threadID + "#q" + id; nodes.push(reply); @@ -2453,7 +2452,7 @@ dialog = UI.dialog('updater', 'bottom: 0; right: 0;', html); this.count = $('#count', dialog); this.timer = $('#timer', dialog); - this.thread = $('.thread'); + this.thread = $.id("t" + g.THREAD_ID); _ref = $$('input', dialog); for (_i = 0, _len = _ref.length; _i < _len; _i++) { input = _ref[_i]; @@ -2712,7 +2711,7 @@ }, node: function(post) { var name, node; - if (post["class"] === 'inline') { + if (post.isInlined && !post.isCrosspost) { return; } name = $('.name', post.el); @@ -2773,7 +2772,7 @@ node: function(post) { var img, link, nodes, _i, _len, _ref; img = post.img; - if (post["class"] === 'inline' || !img) { + if (post.isInlined && !post.isCrosspost || !img) { return; } img = img.parentNode; @@ -2794,7 +2793,7 @@ node: function(post) { var img; img = post.img; - if (!(img && /^Spoiler/.test(img.alt)) || post["class"] === 'inline') { + if (!(img && /^Spoiler/.test(img.alt)) || post.isInlined && !post.isCrosspost) { return; } img.removeAttribute('style'); @@ -2824,7 +2823,7 @@ }, node: function(post) { var node; - if (post["class"] === 'inline') { + if (post.isInlined && !post.isCrosspost) { return; } node = $('.postInfo > .dateTime', post.el); @@ -2919,7 +2918,7 @@ }, node: function(post) { var data, link, node, regexp, resolution, size, span, unit, _, _ref; - if (post["class"] === 'inline' || !(node = post.filesize)) { + if (post.isInlined && !post.isCrosspost || !(node = post.filesize)) { return; } regexp = /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/; @@ -3207,7 +3206,7 @@ link = $('.postInfo > .postNum > a:first-child', newInline); link.href = "" + pathname + "#p" + id; link.nextSibling.href = "" + pathname + "#q" + id; - $.addClass(newInline, 'crossquote'); + $.addClass(newInline, 'crosspost'); return $.replace(inline, newInline); }, clone: function(id, el) { @@ -3324,7 +3323,7 @@ }, node: function(post) { var quote, _i, _len, _ref; - if (post["class"] === 'inline') { + if (post.isInlined && !post.isCrosspost) { return; } _ref = post.quotes; @@ -3343,7 +3342,7 @@ }, node: function(post) { var path, quote, _i, _len, _ref; - if (post["class"] === 'inline') { + if (post.isInlined && !post.isCrosspost) { return; } _ref = post.quotes; @@ -3366,7 +3365,7 @@ }, node: function(post) { var a, board, data, i, id, index, m, node, nodes, quote, quotes, snapshot, text, _i, _j, _len, _ref; - if (post["class"] === 'inline') { + if (post.isInlined && !post.isCrosspost) { return; } snapshot = d.evaluate('.//text()[not(parent::a)]', post.el.lastElementChild, null, 6, null); @@ -3384,7 +3383,7 @@ nodes.push($.tn(text)); } id = quote.match(/\d+$/)[0]; - board = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : $('.postNum.desktop', post.el).firstElementChild.pathname.split('/')[1]; + board = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : $('.postInfo > .postNum > a:first-child', post.el).pathname.split('/')[1]; nodes.push(a = $.el('a', { textContent: "" + quote + "\u00A0(Dead)" })); @@ -3487,7 +3486,7 @@ return; } el = post.el; - if (el.hidden) { + if (el.hidden || /\bop\b/.test(post["class"]) || post.isInlined) { return; } count = Unread.replies.push(el); @@ -3743,7 +3742,7 @@ } a = post.img.parentNode; $.on(a, 'click', ImageExpand.cb.toggle); - if (ImageExpand.on && !post.el.hidden && post["class"] !== 'inline') { + if (ImageExpand.on && !post.el.hidden) { return ImageExpand.expand(post.img); } }, @@ -4147,6 +4146,7 @@ id: el.id.slice(1), threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).id.slice(1), isInlined: /\binline\b/.test(klass), + isCrosspost: /\bcrosspost\b/.test(klass), quotes: el.getElementsByClassName('quotelink'), backlinks: el.getElementsByClassName('backlink'), fileInfo: false, diff --git a/script.coffee b/script.coffee index 301c296ca..fa2003243 100644 --- a/script.coffee +++ b/script.coffee @@ -194,7 +194,6 @@ UI = #using null instead of '' is 4% faster #these 4 statements are 40% faster than 1 style.cssText {style} = UI.el - $.log left, top style.left = left style.top = top style.right = if left is null then '0px' else null @@ -510,7 +509,7 @@ Filter = node: (post) -> return if post.isInlined - isOP = /\bop\b/.test post.class + isOP = post.id is post.threadId {root} = post for key of Filter.filters value = Filter[key] post @@ -706,8 +705,8 @@ ExpandThread = href = quote.getAttribute 'href' continue if href[0] is '/' # Cross-board quote quote.href = "res/#{href}" # Fix pathnames - id = reply.firstElementChild.id[2..] - link = $('.postNum.desktop', reply).firstElementChild + id = reply.id[2..] + link = $ '.postInfo > .postNum > a:first-child', reply link.href = "res/#{threadID}#p#{id}" link.nextSibling.href = "res/#{threadID}#q#{id}" nodes.push reply @@ -1945,7 +1944,7 @@ Updater = @count = $ '#count', dialog @timer = $ '#timer', dialog - @thread = $ '.thread' + @thread = $.id "t#{g.THREAD_ID}" for input in $$ 'input', dialog if input.type is 'checkbox' @@ -2156,7 +2155,7 @@ Anonymize = init: -> Main.callbacks.push @node node: (post) -> - return if post.class is 'inline' + return if post.isInlined and not post.isCrosspost name = $ '.name', post.el name.textContent = 'Anonymous' if node = name.nextElementSibling @@ -2195,7 +2194,7 @@ Sauce = node: (post) -> {img} = post - return if post.class is 'inline' or not img + return if post.isInlined and not post.isCrosspost or not img img = img.parentNode nodes = [] for link in Sauce.links @@ -2208,10 +2207,10 @@ RevealSpoilers = Main.callbacks.push @node node: (post) -> {img} = post - if not (img and /^Spoiler/.test img.alt) or post.class is 'inline' + if not (img and /^Spoiler/.test img.alt) or post.isInlined and not post.isCrosspost return img.removeAttribute 'style' - img.src = "//thumbs.4chan.org#{img.parentNode.pathname.replace(/src(\/\d+).+$/, 'thumb$1s.jpg')}" + img.src = "//thumbs.4chan.org#{img.parentNode.pathname.replace /src(\/\d+).+$/, 'thumb$1s.jpg'}" Time = init: -> @@ -2236,7 +2235,7 @@ Time = Main.callbacks.push @node node: (post) -> - return if post.class is 'inline' + return if post.isInlined and not post.isCrosspost node = $ '.postInfo > .dateTime', post.el Time.date = Time.parse node.textContent node.textContent = Time.funk(Time) @@ -2296,7 +2295,7 @@ FileInfo = @setFormats() Main.callbacks.push @node node: (post) -> - return if post.class is 'inline' or not node = post.filesize + return if post.isInlined and not post.isCrosspost or not node = post.filesize regexp = /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/ [_, link, size, unit, resolution] = node.innerHTML.match regexp @@ -2482,7 +2481,7 @@ QuoteInline = link = $ '.postInfo > .postNum > a:first-child', newInline link.href = "#{pathname}#p#{id}" link.nextSibling.href = "#{pathname}#q#{id}" - $.addClass newInline, 'crossquote' + $.addClass newInline, 'crosspost' $.replace inline, newInline clone: (id, el) -> @@ -2558,7 +2557,7 @@ QuoteOP = init: -> Main.callbacks.push @node node: (post) -> - return if post.class is 'inline' + return if post.isInlined and not post.isCrosspost for quote in post.quotes if quote.hash[2..] is post.threadId # \u00A0 is nbsp @@ -2569,7 +2568,7 @@ QuoteCT = init: -> Main.callbacks.push @node node: (post) -> - return if post.class is 'inline' + return if post.isInlined and not post.isCrosspost for quote in post.quotes unless quote.hash # Make sure this isn't a link to the board we're on. @@ -2585,7 +2584,7 @@ Quotify = init: -> Main.callbacks.push @node node: (post) -> - return if post.class is 'inline' + return if post.isInlined and not post.isCrosspost # XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE is 6 # Get all the text nodes that are not inside an anchor. @@ -2613,7 +2612,7 @@ Quotify = m[1] else # Get the post's board, whether it's inlined or not. - $('.postNum.desktop', post.el).firstElementChild.pathname.split('/')[1] + $('.postInfo > .postNum > a:first-child', post.el).pathname.split('/')[1] nodes.push a = $.el 'a', # \u00A0 is nbsp @@ -2695,7 +2694,7 @@ Unread = return {el} = post # new HTML ??? - return if el.hidden # or inlined/OP + return if el.hidden or /\bop\b/.test(post.class) or post.isInlined count = Unread.replies.push el Unread.update count is 1 @@ -2867,7 +2866,7 @@ ImageExpand = return unless post.img a = post.img.parentNode $.on a, 'click', ImageExpand.cb.toggle - if ImageExpand.on and !post.el.hidden and post.class isnt 'inline' + if ImageExpand.on and !post.el.hidden ImageExpand.expand post.img cb: toggle: (e) -> @@ -3180,16 +3179,17 @@ Main = el = $ '.post', node klass = el.className post = - root: node - el: el - class: klass - id: el.id[1..] - threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).id[1..] - isInlined: /\binline\b/.test klass - quotes: el.getElementsByClassName 'quotelink' - backlinks: el.getElementsByClassName 'backlink' - fileInfo: false - img: false + root: node + el: el + class: klass + id: el.id[1..] + threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).id[1..] + isInlined: /\binline\b/.test klass + isCrosspost: /\bcrosspost\b/.test klass + quotes: el.getElementsByClassName 'quotelink' + backlinks: el.getElementsByClassName 'backlink' + fileInfo: false + img: false if fileInfo = $ '.fileInfo', el img = fileInfo.nextElementSibling.firstElementChild if img.alt isnt 'File deleted.' From dc3f6b93a4186bbe1b89a605c6f83577d25c70f0 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 3 May 2012 12:08:31 +0200 Subject: [PATCH 37/52] Fix File Info Formatting. --- 4chan_x.user.js | 121 +++++++++++++++++++++--------------------------- changelog | 2 + script.coffee | 107 ++++++++++++++++++------------------------ 3 files changed, 99 insertions(+), 131 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index c4b9986dc..54c681f56 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -153,8 +153,7 @@ sauces: ['http://iqdb.org/?url=$1', 'http://www.google.com/searchbyimage?image_url=$1', '#http://tineye.com/search?url=$1', '#http://saucenao.com/search.php?db=999&url=$1', '#http://3d.iqdb.org/?url=$1', '#http://regex.info/exif.cgi?imgurl=$2', '# uploaders:', '#http://imgur.com/upload?url=$2', '#http://omploader.org/upload?url1=$2', '# "View Same" in archives:', '#http://archive.foolz.us/$4/image/$3/', '#https://archive.installgentoo.net/$4/image/$3'].join('\n'), time: '%m/%d/%y(%a)%H:%M', backlink: '>>%id', - fileInfoR: '%l (%s, %r)', - fileInfoT: '%l (%s, %r)', + fileInfo: '%l (%p%s, %r)', favicon: 'ferongr', hotkeys: { openQR: ['i', 'Open QR with post number inserted'], @@ -2190,7 +2189,7 @@ } }, dialog: function() { - var arr, back, checked, description, dialog, favicon, fileInfoR, fileInfoT, hiddenNum, hiddenThreads, indicator, indicators, input, key, li, obj, overlay, ta, time, tr, ul, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3; + var arr, back, checked, description, dialog, favicon, fileInfo, hiddenNum, hiddenThreads, indicator, indicators, input, key, li, obj, overlay, ta, time, tr, ul, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3; dialog = $.el('div', { id: 'options', className: 'reply dialog', @@ -2268,16 +2267,13 @@ \
File Info Formatting is disabled.
\
    \ - Thread File Info Formatting\ -
  • :
  • \ -
  • Link: %l (lowercase L)
  • \ + File Info Formatting\ +
  • :
  • \ +
  • Link (with original file name): %l (lowercase L, truncated), %L (untruncated)
  • \ +
  • Original file name: %n (Truncated), %N (Untruncated)
  • \ +
  • Spoiler indicator: %p
  • \
  • Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
  • \
  • Resolution: %r (Displays PDF on /po/, for PDFs)
  • \ - Reply File Info Formatting\ -
  • :
  • \ -
  • All thread formatters also work for reply formatting.
  • \ -
  • Link (with original file name): %l (lowercase L)(Truncated), %L (Untruncated)
  • \ -
  • Original file name: %n (Truncated), %N (Untruncated)
  • \
\
Unread Favicon is disabled.
\ Unread favicons
\ @@ -2332,16 +2328,13 @@ } (back = $('[name=backlink]', dialog)).value = Conf['backlink']; (time = $('[name=time]', dialog)).value = Conf['time']; - (fileInfoR = $('[name=fileInfoR]', dialog)).value = Conf['fileInfoR']; - (fileInfoT = $('[name=fileInfoT]', dialog)).value = Conf['fileInfoT']; + (fileInfo = $('[name=fileInfo]', dialog)).value = Conf['fileInfo']; $.on(back, 'keyup', $.cb.value); $.on(back, 'keyup', Options.backlink); $.on(time, 'keyup', $.cb.value); $.on(time, 'keyup', Options.time); - $.on(fileInfoR, 'keyup', $.cb.value); - $.on(fileInfoR, 'keyup', Options.fileInfo); - $.on(fileInfoT, 'keyup', $.cb.value); - $.on(fileInfoT, 'keyup', Options.fileInfo); + $.on(fileInfo, 'keyup', $.cb.value); + $.on(fileInfo, 'keyup', Options.fileInfo); favicon = $('select', dialog); favicon.value = Conf['favicon']; $.on(favicon, 'change', $.cb.value); @@ -2380,8 +2373,7 @@ d.body.style.setProperty('overflow', 'hidden', null); Options.backlink.call(back); Options.time.call(time); - Options.fileInfo.call(fileInfoR); - Options.fileInfo.call(fileInfoT); + Options.fileInfo.call(fileInfo); return Options.favicon.call(favicon); }, close: function() { @@ -2416,19 +2408,17 @@ return $.id('backlinkPreview').textContent = Conf['backlink'].replace(/%id/, '123456789'); }, fileInfo: function() { - var type; - type = this.name === 'fileInfoR' ? 0 : 1; FileInfo.data = { - link: '1329791824.png', - size: 996, + link: 'javascript:;', + spoiler: true, + size: '276', unit: 'KB', - resolution: '1366x768', - fullname: '[a.f.k.] Sayonara Zetsubou Sensei - 09.avi_snapshot_03.34_[2011.02.20_06.58.00].jpg', - shortname: '[a.f.k.] Sayonara Zetsubou Sen(...).jpg', - type: type + resolution: '1280x720', + fullname: 'd9bb2efc98dd0df141a94399ff5880b7.jpg', + shortname: 'd9bb2efc98dd0df141a94399ff5880(...).jpg' }; FileInfo.setFormats(); - return $.id("" + this.name + "Preview").innerHTML = FileInfo.funks[type](FileInfo); + return $.id('fileInfoPreview').innerHTML = FileInfo.funk(FileInfo); }, favicon: function() { Favicon["switch"](); @@ -2917,42 +2907,34 @@ return Main.callbacks.push(this.node); }, node: function(post) { - var data, link, node, regexp, resolution, size, span, unit, _, _ref; - if (post.isInlined && !post.isCrosspost || !(node = post.filesize)) { + var alt, node, span; + if (post.isInlined && !post.isCrosspost || !post.fileInfo) { return; } - regexp = /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/; - _ref = node.innerHTML.match(regexp), _ = _ref[0], link = _ref[1], size = _ref[2], unit = _ref[3], resolution = _ref[4]; - data = { - link: link, - size: size, - unit: unit, - resolution: resolution + node = post.fileInfo.firstElementChild; + alt = post.img.alt; + span = $('span', node); + FileInfo.data = { + link: post.img.parentNode.href, + spoiler: /^Spoiler/.test(alt), + size: alt.match(/\d+/)[0], + unit: alt.match(/\w+$/)[0], + resolution: span.previousSibling.textContent.match(/\d+x\d+|PDF/)[0], + fullname: span.title, + shortname: span.textContent }; - if (span = $('span', node)) { - data.fullname = span.title; - data.shortname = span.textContent; - } - data.type = +(!span); - FileInfo.data = data; - return node.innerHTML = FileInfo.funks[data.type](FileInfo); + return node.innerHTML = FileInfo.funk(FileInfo); }, setFormats: function() { - var code, format, funks, i, param, _i; - funks = []; - for (i = _i = 0; _i <= 1; i = ++_i) { - format = i ? Conf['fileInfoT'] : Conf['fileInfoR']; - param = i ? /%([BKlMrs])/g : /%([BKlLMnNrs])/g; - code = format.replace(param, function(s, c) { - if (c in FileInfo.formatters) { - return "' + f.formatters." + c + "() + '"; - } else { - return s; - } - }); - funks.push(Function('f', "return '" + code + "'")); - } - return this.funks = funks; + var code; + code = Conf['fileInfo'].replace(/%([BKlLMnNprs])/g, function(s, c) { + if (c in FileInfo.formatters) { + return "' + f.formatters." + c + "() + '"; + } else { + return s; + } + }); + return this.funk = Function('f', "return '" + code + "'"); }, convertUnit: function(unitT) { var i, size, unitF, units; @@ -2981,25 +2963,28 @@ }, formatters: { l: function() { - if (FileInfo.data.type === 0) { - return FileInfo.data.link.replace(/>\d+\.\w+" + (this.n()) + "<"); - } else { - return FileInfo.data.link; - } + return "" + (this.n()) + ""; }, L: function() { - return FileInfo.data.link.replace(/>\d+\.\w+" + FileInfo.data.fullname + "<"); + return "" + (this.N()) + ""; }, n: function() { if (FileInfo.data.fullname === FileInfo.data.shortname) { return FileInfo.data.fullname; } else { - return "" + FileInfo.data.fullname + "" + FileInfo.data.shortname + ""; + return "" + FileInfo.data.shortname + "" + FileInfo.data.fullname + ""; } }, N: function() { return FileInfo.data.fullname; }, + p: function() { + if (FileInfo.data.spoiler) { + return 'Spoiler, '; + } else { + return ''; + } + }, s: function() { return "" + FileInfo.data.size + " " + FileInfo.data.unit; }, @@ -4440,8 +4425,8 @@ textarea.field {\ float: left;\ pointer-events: none;\ }\ -.filename:hover > .fntrunc,\ -.filename:not(:hover) > .fnfull {\ +.fileText:hover .fntrunc,\ +.fileText:not(:hover) .fnfull {\ display: none;\ }\ img[data-md5], img[data-md5] + img {\ diff --git a/changelog b/changelog index 11067256f..544e8c44e 100644 --- a/changelog +++ b/changelog @@ -1,4 +1,6 @@ master +- Mayhem + Add Spoiler indicator option in File Info Formatting 2.29.4 - Mayhem diff --git a/script.coffee b/script.coffee index fa2003243..683201d54 100644 --- a/script.coffee +++ b/script.coffee @@ -114,8 +114,7 @@ Config = ].join '\n' time: '%m/%d/%y(%a)%H:%M' backlink: '>>%id' - fileInfoR: '%l (%s, %r)' - fileInfoT: '%l (%s, %r)' + fileInfo: '%l (%p%s, %r)' favicon: 'ferongr' hotkeys: # QR & Options @@ -1779,16 +1778,13 @@ Options =
File Info Formatting is disabled.
    - Thread File Info Formatting -
  • :
  • -
  • Link: %l (lowercase L)
  • + File Info Formatting +
  • :
  • +
  • Link (with original file name): %l (lowercase L, truncated), %L (untruncated)
  • +
  • Original file name: %n (Truncated), %N (Untruncated)
  • +
  • Spoiler indicator: %p
  • Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
  • Resolution: %r (Displays PDF on /po/, for PDFs)
  • - Reply File Info Formatting -
  • :
  • -
  • All thread formatters also work for reply formatting.
  • -
  • Link (with original file name): %l (lowercase L)(Truncated), %L (Untruncated)
  • -
  • Original file name: %n (Truncated), %N (Untruncated)
Unread Favicon is disabled.
Unread favicons
@@ -1836,18 +1832,15 @@ Options = $.on ta, 'change', $.cb.value #rice - (back = $ '[name=backlink]', dialog).value = Conf['backlink'] - (time = $ '[name=time]', dialog).value = Conf['time'] - (fileInfoR = $ '[name=fileInfoR]', dialog).value = Conf['fileInfoR'] - (fileInfoT = $ '[name=fileInfoT]', dialog).value = Conf['fileInfoT'] + (back = $ '[name=backlink]', dialog).value = Conf['backlink'] + (time = $ '[name=time]', dialog).value = Conf['time'] + (fileInfo = $ '[name=fileInfo]', dialog).value = Conf['fileInfo'] $.on back, 'keyup', $.cb.value $.on back, 'keyup', Options.backlink $.on time, 'keyup', $.cb.value $.on time, 'keyup', Options.time - $.on fileInfoR, 'keyup', $.cb.value - $.on fileInfoR, 'keyup', Options.fileInfo - $.on fileInfoT, 'keyup', $.cb.value - $.on fileInfoT, 'keyup', Options.fileInfo + $.on fileInfo, 'keyup', $.cb.value + $.on fileInfo, 'keyup', Options.fileInfo favicon = $ 'select', dialog favicon.value = Conf['favicon'] $.on favicon, 'change', $.cb.value @@ -1880,8 +1873,7 @@ Options = Options.backlink.call back Options.time.call time - Options.fileInfo.call fileInfoR - Options.fileInfo.call fileInfoT + Options.fileInfo.call fileInfo Options.favicon.call favicon close: -> @@ -1909,17 +1901,16 @@ Options = backlink: -> $.id('backlinkPreview').textContent = Conf['backlink'].replace /%id/, '123456789' fileInfo: -> - type = if @name is 'fileInfoR' then 0 else 1 FileInfo.data = - link: '1329791824.png' - size: 996 + link: 'javascript:;' + spoiler: true + size: '276' unit: 'KB' - resolution: '1366x768' - fullname: '[a.f.k.] Sayonara Zetsubou Sensei - 09.avi_snapshot_03.34_[2011.02.20_06.58.00].jpg' - shortname: '[a.f.k.] Sayonara Zetsubou Sen(...).jpg' - type: type + resolution: '1280x720' + fullname: 'd9bb2efc98dd0df141a94399ff5880b7.jpg' + shortname: 'd9bb2efc98dd0df141a94399ff5880(...).jpg' FileInfo.setFormats() - $.id("#{@name}Preview").innerHTML = FileInfo.funks[type] FileInfo + $.id('fileInfoPreview').innerHTML = FileInfo.funk FileInfo favicon: -> Favicon.switch() Unread.update true @@ -2295,33 +2286,26 @@ FileInfo = @setFormats() Main.callbacks.push @node node: (post) -> - return if post.isInlined and not post.isCrosspost or not node = post.filesize - regexp = /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/ - [_, link, size, unit, resolution] = - node.innerHTML.match regexp - data = - link: link - size: size - unit: unit - resolution: resolution - if span = $ 'span', node - data.fullname = span.title - data.shortname = span.textContent - data.type = +!span - FileInfo.data = data - node.innerHTML = FileInfo.funks[data.type] FileInfo + return if post.isInlined and not post.isCrosspost or not post.fileInfo + node = post.fileInfo.firstElementChild + alt = post.img.alt + span = $ 'span', node + FileInfo.data = + link: post.img.parentNode.href + spoiler: /^Spoiler/.test alt + size: alt.match(/\d+/)[0] + unit: alt.match(/\w+$/)[0] + resolution: span.previousSibling.textContent.match(/\d+x\d+|PDF/)[0] + fullname: span.title + shortname: span.textContent + node.innerHTML = FileInfo.funk FileInfo setFormats: -> - funks = [] - for i in [0..1] - format = if i then Conf['fileInfoT'] else Conf['fileInfoR'] - param = if i then /%([BKlMrs])/g else /%([BKlLMnNrs])/g - code = format.replace param, (s, c) -> - if c of FileInfo.formatters - "' + f.formatters.#{c}() + '" - else - s - funks.push Function 'f', "return '#{code}'" - @funks = funks + code = Conf['fileInfo'].replace /%([BKlLMnNprs])/g, (s, c) -> + if c of FileInfo.formatters + "' + f.formatters.#{c}() + '" + else + s + @funk = Function 'f', "return '#{code}'" convertUnit: (unitT) -> size = @data.size unitF = @data.unit @@ -2337,18 +2321,15 @@ FileInfo = size = size.toFixed 2 "#{size} #{unitT}" formatters: - l: -> - if FileInfo.data.type is 0 - FileInfo.data.link.replace />\d+\.\w+#{@n()}<" - else - FileInfo.data.link - L: -> FileInfo.data.link.replace />\d+\.\w+#{FileInfo.data.fullname}<" + l: -> "#{@n()}" + L: -> "#{@N()}" n: -> if FileInfo.data.fullname is FileInfo.data.shortname FileInfo.data.fullname else - "#{FileInfo.data.fullname}#{FileInfo.data.shortname}" + "#{FileInfo.data.shortname}#{FileInfo.data.fullname}" N: -> FileInfo.data.fullname + p: -> if FileInfo.data.spoiler then 'Spoiler, ' else '' s: -> "#{FileInfo.data.size} #{FileInfo.data.unit}" B: -> FileInfo.convertUnit 'B' K: -> FileInfo.convertUnit 'KB' @@ -3453,8 +3434,8 @@ textarea.field { float: left; pointer-events: none; } -.filename:hover > .fntrunc, -.filename:not(:hover) > .fnfull { +.fileText:hover .fntrunc, +.fileText:not(:hover) .fnfull { display: none; } img[data-md5], img[data-md5] + img { From 43ecd1c761428a5599f11d5ccdaea90de790194f Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 3 May 2012 13:42:46 +0200 Subject: [PATCH 38/52] Fix isInlined and isCrosspost. Derp. --- 4chan_x.user.js | 12 ++++++------ script.coffee | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 54c681f56..7ab20c8e7 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3402,7 +3402,7 @@ }, node: function(post) { var a; - if (!(a = $('.reportbutton', post.el))) { + if (!(a = $('.report_button', post.el))) { a = ReportButton.a.cloneNode(true); $.add($('.postInfo', post.el), a); } @@ -4121,17 +4121,17 @@ } }, preParse: function(node) { - var el, fileInfo, img, klass, post; + var el, fileInfo, img, post, rootClass; + rootClass = node.className; el = $('.post', node); - klass = el.className; post = { root: node, el: el, - "class": klass, + "class": el.className, id: el.id.slice(1), threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).id.slice(1), - isInlined: /\binline\b/.test(klass), - isCrosspost: /\bcrosspost\b/.test(klass), + isInlined: /\binline\b/.test(rootClass), + isCrosspost: /\bcrosspost\b/.test(rootClass), quotes: el.getElementsByClassName('quotelink'), backlinks: el.getElementsByClassName('backlink'), fileInfo: false, diff --git a/script.coffee b/script.coffee index 683201d54..4882f0af5 100644 --- a/script.coffee +++ b/script.coffee @@ -2625,7 +2625,7 @@ ReportButton = href: 'javascript:;' Main.callbacks.push @node node: (post) -> - unless a = $ '.reportbutton', post.el + unless a = $ '.report_button', post.el a = ReportButton.a.cloneNode true $.add $('.postInfo', post.el), a $.on a, 'click', ReportButton.report @@ -3157,16 +3157,16 @@ Main = window.location = "https://raw.github.com/mayhemydg/4chan-x/#{version}/4chan_x.user.js" preParse: (node) -> - el = $ '.post', node - klass = el.className - post = + rootClass = node.className + el = $ '.post', node + post = root: node el: el - class: klass + class: el.className id: el.id[1..] threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).id[1..] - isInlined: /\binline\b/.test klass - isCrosspost: /\bcrosspost\b/.test klass + isInlined: /\binline\b/.test rootClass + isCrosspost: /\bcrosspost\b/.test rootClass quotes: el.getElementsByClassName 'quotelink' backlinks: el.getElementsByClassName 'backlink' fileInfo: false From 8c839754fde4cb8282e13145e6264d5fa225c685 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 3 May 2012 16:51:01 +0200 Subject: [PATCH 39/52] Styling fixes. --- 4chan_x.user.js | 95 ++++++++++++++++++++++--------------------------- script.coffee | 91 ++++++++++++++++++++-------------------------- 2 files changed, 81 insertions(+), 105 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 7ab20c8e7..f8fdd330f 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3236,7 +3236,7 @@ } qp = UI.el = $.el('div', { id: 'qp', - className: 'reply dialog' + className: 'reply dialog post' }); $.add(d.body, qp); id = this.hash.slice(2); @@ -3245,11 +3245,11 @@ if (Conf['Quote Highlighting']) { $.addClass(el, 'qphl'); } - replyID = $.x('ancestor::div[contains(@class,"post")]', this).id; + replyID = $.x('ancestor::div[contains(@class,"postContainer")]', this).id.slice(2); _ref = $$('.quotelink, .backlink', qp); for (_i = 0, _len = _ref.length; _i < _len; _i++) { quote = _ref[_i]; - if (quote.hash.slice(1) === replyID) { + if (quote.hash.slice(2) === replyID) { $.addClass(quote, 'forwardlink'); } } @@ -3273,7 +3273,7 @@ return $.off(this, 'mouseout click', QuotePreview.mouseout); }, parse: function(req, id) { - var doc, node, post, qp; + var doc, fileInfo, img, node, post, qp; if (!((qp = UI.el) && qp.textContent === ("Loading " + id + "..."))) { return; } @@ -3286,10 +3286,15 @@ node = doc.getElementById("p" + id); qp.innerHTML = node.innerHTML; post = { - el: qp, - filesize: $('.filesize', qp), - img: $('img[data-md5]', qp) + 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); } @@ -3780,7 +3785,7 @@ case 'fit screen': klass = 'fitwidth fitheight'; } - $('body > form').className = klass; + $.id('delform').className = klass; if (/\bfitheight\b/.test(klass)) { $.on(window, 'resize', ImageExpand.resize); if (!ImageExpand.style) { @@ -4192,8 +4197,9 @@ callbacks: [], css: '\ /* dialog styling */\ -.dialog {\ +.dialog.reply {\ border: 1px solid rgba(0,0,0,.25);\ + padding: 0;\ }\ .move {\ cursor: move;\ @@ -4204,28 +4210,26 @@ label, .favicon {\ a[href="javascript:;"] {\ text-decoration: none;\ }\ +.warning {\ + color: red;\ +}\ \ .hide_thread_button {\ float: left;\ }\ -.hide_reply_button.hidden_reply {\ - float: none;\ -}\ \ .hidden_thread ~ *,\ -.reply[hidden],\ +[hidden],\ #content > [name=tab]:not(:checked) + div,\ #updater:not(:hover) > :not(.move),\ -#qp > input, #qp .inline, .forwarded {\ +.autohide:not(:hover) > form,\ +#qp input, #qp .inline, .forwarded {\ display: none !important;\ }\ \ h1 {\ text-align: center;\ }\ -.autohide:not(:hover) > form {\ - display: none;\ -}\ #qr > .move {\ min-width: 300px;\ overflow: hidden;\ @@ -4365,6 +4369,8 @@ h1 {\ }\ .field {\ border: 1px solid #CCC;\ + box-sizing: border-box;\ + -moz-box-sizing: border-box;\ color: #333;\ font: 13px sans-serif;\ margin: 0;\ @@ -4388,6 +4394,7 @@ textarea.field {\ min-height: 120px;\ }\ .field:only-child {\ + display: block;\ min-width: 100%;\ }\ .captcha {\ @@ -4397,6 +4404,7 @@ textarea.field {\ text-align: center;\ }\ .captcha > img {\ + display: block;\ height: 57px;\ width: 300px;\ }\ @@ -4411,41 +4419,21 @@ textarea.field {\ width: 30%;\ }\ \ -.new {\ - background: lime;\ -}\ -.warning {\ - color: red;\ -}\ -.replyhider {\ - vertical-align: top;\ -}\ -\ -.filesize + br + a {\ - float: left;\ - pointer-events: none;\ -}\ .fileText:hover .fntrunc,\ .fileText:not(:hover) .fnfull {\ display: none;\ }\ -img[data-md5], img[data-md5] + img {\ - pointer-events: all;\ -}\ .fitwidth img[data-md5] + img {\ max-width: 100%;\ }\ -.gecko > .fitwidth img[data-md5] + img,\ -.presto > .fitwidth img[data-md5] + img {\ - width: 100%;\ -}\ +\ /* revealed spoilers do not have height/width,\ this fixes "expanded" auto-gifs */\ -img[data-md5] {\ +.op > div > a > img[data-md5] {\ max-height: 252px;\ max-width: 252px;\ }\ -input ~ a > img[data-md5] {\ +.reply > div > a > img[data-md5] {\ max-height: 127px;\ max-width: 127px;\ }\ @@ -4498,18 +4486,20 @@ input ~ a > img[data-md5] {\ #options label {\ text-decoration: underline;\ }\ -#content > div {\ +#content {\ height: 450px;\ overflow: auto;\ }\ #content textarea {\ + box-sizing: border-box;\ + -moz-box-sizing: border-box;\ margin: 0;\ min-height: 100px;\ resize: vertical;\ width: 100%;\ }\ #sauces {\ - height: 320px;\ + height: 300px;\ }\ \ #updater {\ @@ -4522,9 +4512,8 @@ input ~ a > img[data-md5] {\ border: none;\ background: transparent;\ }\ -\ -#stats {\ - border: none;\ +.new {\ + background: lime;\ }\ \ #watcher {\ @@ -4548,10 +4537,7 @@ input ~ a > img[data-md5] {\ text-decoration: underline;\ }\ \ -#qp {\ - padding-bottom: 5px;\ -}\ -#qp > a > img {\ +#qp img {\ max-height: 300px;\ max-width: 500px;\ }\ @@ -4561,23 +4547,26 @@ input ~ a > img[data-md5] {\ .inlined {\ opacity: .5;\ }\ -.inline .reply {\ +.inline {\ + overflow: hidden;\ background-color: rgba(255, 255, 255, 0.15);\ border: 1px solid rgba(128, 128, 128, 0.5);\ }\ -.filetitle, .replytitle, .postername, .commentpostername, .postertrip {\ +.inline .post {\ background: none;\ + border: none;\ }\ .filter_highlight.thread,\ .filter_highlight > .reply {\ box-shadow: -5px 0 rgba(255,0,0,0.5);\ }\ .filtered {\ - text-decoration: line-through;\ + text-decoration: underline line-through;\ }\ .quotelink.forwardlink,\ .backlink.forwardlink {\ - color: #4C4CA9;\ + text-decoration: none;\ + border-bottom: 1px dashed;\ }\ ' }; diff --git a/script.coffee b/script.coffee index 4882f0af5..aed9e563e 100644 --- a/script.coffee +++ b/script.coffee @@ -2488,16 +2488,16 @@ QuotePreview = return if /\binlined\b/.test @className qp = UI.el = $.el 'div', id: 'qp' - className: 'reply dialog' + className: 'reply dialog post' $.add d.body, qp id = @hash[2..] if el = $.id "p#{id}" qp.innerHTML = el.innerHTML $.addClass el, 'qphl' if Conf['Quote Highlighting'] - replyID = $.x('ancestor::div[contains(@class,"post")]', @).id + replyID = $.x('ancestor::div[contains(@class,"postContainer")]', @).id[2..] for quote in $$ '.quotelink, .backlink', qp - if quote.hash[1..] is replyID + if quote.hash[2..] is replyID $.addClass quote, 'forwardlink' else qp.textContent = "Loading #{id}..." @@ -2524,9 +2524,12 @@ QuotePreview = node = doc.getElementById "p#{id}" qp.innerHTML = node.innerHTML post = - el: qp - filesize: $ '.filesize', qp - img: $ 'img[data-md5]', qp + 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'] @@ -2879,7 +2882,7 @@ ImageExpand = klass = 'fitheight' when 'fit screen' klass = 'fitwidth fitheight' - $('body > form').className = klass + $.id('delform').className = klass if /\bfitheight\b/.test klass $.on window, 'resize', ImageExpand.resize unless ImageExpand.style @@ -3201,8 +3204,9 @@ Main = callbacks: [] css: ' /* dialog styling */ -.dialog { +.dialog.reply { border: 1px solid rgba(0,0,0,.25); + padding: 0; } .move { cursor: move; @@ -3213,28 +3217,26 @@ label, .favicon { a[href="javascript:;"] { text-decoration: none; } +.warning { + color: red; +} .hide_thread_button { float: left; } -.hide_reply_button.hidden_reply { - float: none; -} .hidden_thread ~ *, -.reply[hidden], +[hidden], #content > [name=tab]:not(:checked) + div, #updater:not(:hover) > :not(.move), -#qp > input, #qp .inline, .forwarded { +.autohide:not(:hover) > form, +#qp input, #qp .inline, .forwarded { display: none !important; } h1 { text-align: center; } -.autohide:not(:hover) > form { - display: none; -} #qr > .move { min-width: 300px; overflow: hidden; @@ -3374,6 +3376,8 @@ h1 { } .field { border: 1px solid #CCC; + box-sizing: border-box; + -moz-box-sizing: border-box; color: #333; font: 13px sans-serif; margin: 0; @@ -3397,6 +3401,7 @@ textarea.field { min-height: 120px; } .field:only-child { + display: block; min-width: 100%; } .captcha { @@ -3406,6 +3411,7 @@ textarea.field { text-align: center; } .captcha > img { + display: block; height: 57px; width: 300px; } @@ -3420,41 +3426,21 @@ textarea.field { width: 30%; } -.new { - background: lime; -} -.warning { - color: red; -} -.replyhider { - vertical-align: top; -} - -.filesize + br + a { - float: left; - pointer-events: none; -} .fileText:hover .fntrunc, .fileText:not(:hover) .fnfull { display: none; } -img[data-md5], img[data-md5] + img { - pointer-events: all; -} .fitwidth img[data-md5] + img { max-width: 100%; } -.gecko > .fitwidth img[data-md5] + img, -.presto > .fitwidth img[data-md5] + img { - width: 100%; -} + /* revealed spoilers do not have height/width, this fixes "expanded" auto-gifs */ -img[data-md5] { +.op > div > a > img[data-md5] { max-height: 252px; max-width: 252px; } -input ~ a > img[data-md5] { +.reply > div > a > img[data-md5] { max-height: 127px; max-width: 127px; } @@ -3507,18 +3493,20 @@ input ~ a > img[data-md5] { #options label { text-decoration: underline; } -#content > div { +#content { height: 450px; overflow: auto; } #content textarea { + box-sizing: border-box; + -moz-box-sizing: border-box; margin: 0; min-height: 100px; resize: vertical; width: 100%; } #sauces { - height: 320px; + height: 300px; } #updater { @@ -3531,9 +3519,8 @@ input ~ a > img[data-md5] { border: none; background: transparent; } - -#stats { - border: none; +.new { + background: lime; } #watcher { @@ -3557,10 +3544,7 @@ input ~ a > img[data-md5] { text-decoration: underline; } -#qp { - padding-bottom: 5px; -} -#qp > a > img { +#qp img { max-height: 300px; max-width: 500px; } @@ -3570,23 +3554,26 @@ input ~ a > img[data-md5] { .inlined { opacity: .5; } -.inline .reply { +.inline { + overflow: hidden; background-color: rgba(255, 255, 255, 0.15); border: 1px solid rgba(128, 128, 128, 0.5); } -.filetitle, .replytitle, .postername, .commentpostername, .postertrip { +.inline .post { background: none; + border: none; } .filter_highlight.thread, .filter_highlight > .reply { box-shadow: -5px 0 rgba(255,0,0,0.5); } .filtered { - text-decoration: line-through; + text-decoration: underline line-through; } .quotelink.forwardlink, .backlink.forwardlink { - color: #4C4CA9; + text-decoration: none; + border-bottom: 1px dashed; } ' From d8f5ad1eaddaa19b622a7e3aa88f90625e488e03 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 3 May 2012 17:59:07 +0200 Subject: [PATCH 40/52] Missing class. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index f8fdd330f..795cd2c4c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2268,7 +2268,7 @@
File Info Formatting is disabled.
\
    \ File Info Formatting\ -
  • :
  • \ +
  • :
  • \
  • Link (with original file name): %l (lowercase L, truncated), %L (untruncated)
  • \
  • Original file name: %n (Truncated), %N (Untruncated)
  • \
  • Spoiler indicator: %p
  • \ diff --git a/script.coffee b/script.coffee index aed9e563e..bd286c202 100644 --- a/script.coffee +++ b/script.coffee @@ -1779,7 +1779,7 @@ Options =
    File Info Formatting is disabled.
      File Info Formatting -
    • :
    • +
    • :
    • Link (with original file name): %l (lowercase L, truncated), %L (untruncated)
    • Original file name: %n (Truncated), %N (Untruncated)
    • Spoiler indicator: %p
    • From baab56b52689c1ce051f84292476e803d84b97fe Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Fri, 4 May 2012 10:14:54 +0200 Subject: [PATCH 41/52] Anonumizer: Remove trips, not user IDs or whatever's after the name. Remove the mail only if it's not sage. --- 4chan_x.user.js | 9 ++++++--- script.coffee | 7 ++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 795cd2c4c..d6c6e9641 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2700,14 +2700,17 @@ return Main.callbacks.push(this.node); }, node: function(post) { - var name, node; + var name, parent, trip; if (post.isInlined && !post.isCrosspost) { return; } name = $('.name', post.el); name.textContent = 'Anonymous'; - if (node = name.nextElementSibling) { - return $.rm(node); + if ((trip = name.nextElementSibling) && trip.className === 'postertrip') { + $.rm(trip); + } + if ((parent = name.parentNode).className === 'useremail' && !/^sage$/i.test(parent.pathname)) { + return $.replace(parent, name); } } }; diff --git a/script.coffee b/script.coffee index bd286c202..c2e59ae43 100644 --- a/script.coffee +++ b/script.coffee @@ -2149,8 +2149,10 @@ Anonymize = return if post.isInlined and not post.isCrosspost name = $ '.name', post.el name.textContent = 'Anonymous' - if node = name.nextElementSibling - $.rm node + 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 + $.replace parent, name Sauce = init: -> @@ -2677,7 +2679,6 @@ Unread = Unread.foresee.splice index, 1 return {el} = post - # new HTML ??? return if el.hidden or /\bop\b/.test(post.class) or post.isInlined count = Unread.replies.push el Unread.update count is 1 From fec14cfb16f3f047431581f287021dcd8bd8ee2f Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Fri, 4 May 2012 10:16:28 +0200 Subject: [PATCH 42/52] Don't use 'mailto:' from email strings when filtering. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index d6c6e9641..a94d79213 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -679,7 +679,7 @@ email: function(post) { var mail; if (mail = $('.useremail', post.el)) { - return mail.href; + return mail.pathname; } return false; }, diff --git a/script.coffee b/script.coffee index c2e59ae43..ee885d19e 100644 --- a/script.coffee +++ b/script.coffee @@ -556,7 +556,7 @@ Filter = false email: (post) -> if mail = $ '.useremail', post.el - return mail.href + return mail.pathname false subject: (post) -> $('.subject', post.el).textContent or false From f6bb81cfcddddbc50b8a5ab046caf3554953fea8 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 7 May 2012 09:46:15 +0200 Subject: [PATCH 43/52] Random fixes and tweaks. --- 4chan_x.user.js | 70 ++++++++++++++++++++++++++----------------------- script.coffee | 45 ++++++++++++++++--------------- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index a94d79213..02353bd4b 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -646,7 +646,7 @@ if (isOP && result[1] && !g.REPLY) { thisThread = root.parentNode; if (firstThread = $('div[class=thread]')) { - $.before(firstThread.parentNode, [thisThread, thisThread.nextElementSibling]); + $.before(firstThread, [thisThread, thisThread.nextElementSibling]); } } } @@ -833,21 +833,20 @@ return _results; }, toggle: function(thread) { - var a, backlink, container, num, pathname, replies, reply, _i, _j, _len, _len1, _ref, _results; + var a, backlink, num, pathname, replies, reply, _i, _j, _len, _len1, _ref; pathname = "/" + g.BOARD + "/res/" + thread.id.slice(1); a = $('.summary', thread); switch (a.textContent[0]) { case '+': - if (container = $('.container', a.previousElementSibling)) { - $.rm(container); - } a.textContent = a.textContent.replace('+', '\u00d7 Loading...'); - return $.cache(pathname, function() { - return ExpandThread.parse(this, pathname, thread, a); + $.cache(pathname, function() { + return ExpandThread.parse(this, thread, a); }); + break; case '\u00d7': a.textContent = a.textContent.replace('\u00d7 Loading...', '+'); - return $.cache.requests[pathname].abort(); + $.cache.requests[pathname].abort(); + break; case '-': a.textContent = a.textContent.replace('-', '+'); num = (function() { @@ -868,20 +867,16 @@ $.rm(reply); } _ref = $$('.backlink', a.previousElementSibling); - _results = []; for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { backlink = _ref[_j]; if (!$.id(backlink.hash.slice(1))) { - _results.push($.rm(backlink)); - } else { - _results.push(void 0); + $.rm(backlink); } } - return _results; } }, - parse: function(req, pathname, thread, a) { - var doc, href, id, link, next, nodes, quote, reply, threadID, _i, _j, _len, _len1, _ref, _ref1; + parse: function(req, thread, a) { + var backlink, doc, href, id, link, nodes, post, quote, reply, threadID, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3; if (req.status !== 200) { a.textContent = "" + req.status + " " + req.statusText; $.off(a, 'click', ExpandThread.cb.toggle); @@ -911,8 +906,17 @@ link.nextSibling.href = "res/" + threadID + "#q" + id; nodes.push(reply); } - while (next = a.nextSibling) { - $.rm(next); + _ref2 = $$('.summary ~ .replyContainer', a.parentNode); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + post = _ref2[_k]; + $.rm(post); + } + _ref3 = $$('.backlink', a.previousElementSibling); + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + backlink = _ref3[_l]; + if (!$.id(backlink.hash.slice(1))) { + $.rm(backlink); + } } return $.after(a, nodes); } @@ -1485,15 +1489,15 @@ if (data == null) { data = {}; } + if (!QR.el) { + return; + } if (g.dead) { value = 404; disabled = true; QR.cooldown.auto = false; } value = QR.cooldown.seconds || data.progress || value; - if (!QR.el) { - return; - } input = QR.status.input; input.value = QR.cooldown.auto && Conf['Cooldown'] ? value ? "Auto " + value : 'Auto' : value || 'Submit'; return input.disabled = disabled || false; @@ -1542,10 +1546,10 @@ if (!g.REPLY) { $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', this).id.slice(1); } - id = this.parentNode.parentNode.id.slice(2); + id = this.previousSibling.hash.slice(2); text = ">>" + id + "\n"; sel = window.getSelection(); - if ((s = sel.toString()) && id === ((_ref = $.x('ancestor-or-self::blockquote', sel.anchorNode)) != null ? _ref.id.slice(1) : void 0)) { + if ((s = sel.toString()) && id === ((_ref = $.x('ancestor-or-self::blockquote', sel.anchorNode)) != null ? _ref.id.match(/\d+$/)[0] : void 0)) { s = s.replace(/\n/g, '\n>'); text += ">" + s + "\n"; } @@ -1553,7 +1557,6 @@ caretPos = ta.selectionStart; QR.selected.el.lastChild.textContent = QR.selected.com = ta.value = ta.value.slice(0, caretPos) + text + ta.value.slice(ta.selectionEnd); ta.focus(); - ta.selectionEnd = ta.selectionStart = caretPos + text.length; range = caretPos + text.length; return ta.setSelectionRange(range, range); }, @@ -1839,7 +1842,7 @@ this.timeout = Date.now() + 26 * $.MINUTE; challenge = this.challenge.firstChild.value; this.img.alt = challenge; - this.img.src = "http://www.google.com/recaptcha/api/image?c=" + challenge; + this.img.src = "//www.google.com/recaptcha/api/image?c=" + challenge; return this.input.value = null; }, count: function(count) { @@ -1909,10 +1912,10 @@ }); QR.mimeTypes = mimeTypes.split(', '); QR.mimeTypes.push(''); - fileInput = $('[type=file]', QR.el); - fileInput.max = $('[name=MAX_FILE_SIZE]').value; + fileInput = $('input[type=file]', QR.el); + fileInput.max = $('input[name=MAX_FILE_SIZE]').value; fileInput.accept = mimeTypes; - QR.spoiler = !!$('#com_submit + label'); + QR.spoiler = !!$('input[name=spoiler]'); spoiler = $('#spoilerLabel', QR.el); spoiler.hidden = !QR.spoiler; if (!g.REPLY) { @@ -1958,8 +1961,9 @@ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { name = _ref1[_j]; $.on($("[name=" + name + "]", QR.el), 'input keyup change paste', function() { + var _ref2; QR.selected[this.name] = this.value; - if (QR.cooldown.auto && QR.selected === QR.replies[0] && parseInt(QR.status.input.value.match(/\d+/)) < 6) { + if (QR.cooldown.auto && QR.selected === QR.replies[0] && (0 < (_ref2 = QR.cooldown.seconds) && _ref2 < 6)) { return QR.cooldown.auto = false; } }); @@ -1977,7 +1981,7 @@ } return _results; }); - QR.status.input = $('[type=submit]', QR.el); + QR.status.input = $('input[type=submit]', QR.el); QR.status(); QR.cooldown.init(); QR.captcha.init(); @@ -2050,7 +2054,7 @@ upfile: reply.file, spoiler: reply.spoiler, mode: 'regist', - pwd: (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : $('[name=pwd]').value, + pwd: (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : $('input[name=pwd]').value, recaptcha_challenge_field: challenge, recaptcha_response_field: response + ' ' }; @@ -2089,7 +2093,7 @@ } } }; - return QR.ajax = $.ajax($('form[name=post]').action, callbacks, opts); + return QR.ajax = $.ajax($.id('postForm').parentNode.action, callbacks, opts); }, response: function(html) { var b, doc, err, node, persona, postNumber, reply, thread, _, _ref; @@ -4179,7 +4183,7 @@ _ref = mutation.addedNodes; for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { addedNode = _ref[_j]; - if (addedNode.nodeName === 'DIV' && /\bpostContainer\b/.test(addedNode.className)) { + if (/\bpostContainer\b/.test(addedNode.className)) { nodes.push(Main.preParse(addedNode)); } } @@ -4191,7 +4195,7 @@ listener: function(e) { var target; target = e.target; - if (target.nodeName === 'DIV' && /\bpostContainer\b/.test(addedNode.className)) { + if (/\bpostContainer\b/.test(addedNode.className)) { return Main.node([Main.preParse(target)]); } }, diff --git a/script.coffee b/script.coffee index ee885d19e..86709ada5 100644 --- a/script.coffee +++ b/script.coffee @@ -533,11 +533,11 @@ Filter = # Highlight $.addClass (if isOP then root.parentNode else root), result[0] if isOP and result[1] and not g.REPLY - # Put the highlighted OPs' threads on top of the board pages... + # Put the highlighted OPs' thread on top of the board page... thisThread = root.parentNode # ...before the first non highlighted thread. if firstThread = $ 'div[class=thread]' - $.before firstThread.parentNode, [thisThread, thisThread.nextElementSibling] + $.before firstThread, [thisThread, thisThread.nextElementSibling] name: (post) -> $('.name', post.el).textContent @@ -662,10 +662,8 @@ ExpandThread = switch a.textContent[0] when '+' - if container = $ '.container', a.previousElementSibling - $.rm container a.textContent = a.textContent.replace '+', '\u00d7 Loading...' - $.cache pathname, -> ExpandThread.parse @, pathname, thread, a + $.cache pathname, -> ExpandThread.parse @, thread, a when '\u00d7' a.textContent = a.textContent.replace '\u00d7 Loading...', '+' @@ -684,8 +682,9 @@ ExpandThread = $.rm reply for backlink in $$ '.backlink', a.previousElementSibling $.rm backlink unless $.id backlink.hash[1..] + return - parse: (req, pathname, thread, a) -> + parse: (req, thread, a) -> if req.status isnt 200 a.textContent = "#{req.status} #{req.statusText}" $.off a, 'click', ExpandThread.cb.toggle @@ -710,8 +709,10 @@ ExpandThread = link.nextSibling.href = "res/#{threadID}#q#{id}" nodes.push reply # eat everything, then replace with fresh full posts - while next = a.nextSibling - $.rm next + for post in $$ '.summary ~ .replyContainer', a.parentNode + $.rm post + for backlink in $$ '.backlink', a.previousElementSibling + $.rm backlink unless $.id backlink.hash[1..] $.after a, nodes ThreadHiding = @@ -1123,12 +1124,12 @@ QR = $('.warning', QR.el).textContent = null status: (data={}) -> + return unless QR.el if g.dead value = 404 disabled = true QR.cooldown.auto = false value = QR.cooldown.seconds or data.progress or value - return unless QR.el {input} = QR.status input.value = if QR.cooldown.auto and Conf['Cooldown'] @@ -1163,13 +1164,12 @@ QR = QR.open() unless g.REPLY $('select', QR.el).value = $.x('ancestor::div[@class="thread"]', @).id[1..] - # Make sure we get the correct number, even with XXX censors - id = @parentNode.parentNode.id[2..] + id = @previousSibling.hash[2..] text = ">>#{id}\n" sel = window.getSelection() - if (s = sel.toString()) and id is $.x('ancestor-or-self::blockquote', sel.anchorNode)?.id[1..] + if (s = sel.toString()) and id is $.x('ancestor-or-self::blockquote', sel.anchorNode)?.id.match(/\d+$/)[0] s = s.replace /\n/g, '\n>' text += ">#{s}\n" @@ -1183,7 +1183,6 @@ QR = ta.value[...caretPos] + text + ta.value[ta.selectionEnd..] ta.focus() # Move the caret to the end of the new quote. - ta.selectionEnd = ta.selectionStart = caretPos + text.length range = caretPos + text.length ta.setSelectionRange range, range @@ -1404,7 +1403,7 @@ QR = @timeout = Date.now() + 26*$.MINUTE challenge = @challenge.firstChild.value @img.alt = challenge - @img.src = "http://www.google.com/recaptcha/api/image?c=#{challenge}" + @img.src = "//www.google.com/recaptcha/api/image?c=#{challenge}" @input.value = null count: (count) -> @input.placeholder = switch count @@ -1463,11 +1462,11 @@ QR = QR.mimeTypes = mimeTypes.split ', ' # Add empty mimeType to avoid errors with URLs selected in Window's file dialog. QR.mimeTypes.push '' - fileInput = $ '[type=file]', QR.el - fileInput.max = $('[name=MAX_FILE_SIZE]').value + fileInput = $ 'input[type=file]', QR.el + fileInput.max = $('input[name=MAX_FILE_SIZE]').value fileInput.accept = mimeTypes - QR.spoiler = !!$ '#com_submit + label' + QR.spoiler = !!$ 'input[name=spoiler]' spoiler = $ '#spoilerLabel', QR.el spoiler.hidden = !QR.spoiler @@ -1502,7 +1501,7 @@ QR = QR.selected[@name] = @value # Disable auto-posting if you're typing in the first reply # during the last 5 seconds of the cooldown. - if QR.cooldown.auto and QR.selected is QR.replies[0] and parseInt(QR.status.input.value.match /\d+/) < 6 + if QR.cooldown.auto and QR.selected is QR.replies[0] and 0 < QR.cooldown.seconds < 6 QR.cooldown.auto = false # sync between tabs $.sync 'QR.persona', (persona) -> @@ -1511,7 +1510,7 @@ QR = QR.selected[key] = val $("[name=#{key}]", QR.el).value = val - QR.status.input = $ '[type=submit]', QR.el + QR.status.input = $ 'input[type=submit]', QR.el QR.status() QR.cooldown.init() QR.captcha.init() @@ -1585,7 +1584,7 @@ QR = upfile: reply.file spoiler: reply.spoiler mode: 'regist' - pwd: if m = d.cookie.match(/4chan_pass=([^;]+)/) then decodeURIComponent m[1] else $('[name=pwd]').value + pwd: if m = d.cookie.match(/4chan_pass=([^;]+)/) then decodeURIComponent m[1] else $('input[name=pwd]').value recaptcha_challenge_field: challenge recaptcha_response_field: response + ' ' @@ -1614,7 +1613,7 @@ QR = # Uploading... QR.status progress: "#{Math.round e.loaded / e.total * 100}%" - QR.ajax = $.ajax $('form[name=post]').action, callbacks, opts + QR.ajax = $.ajax $.id('postForm').parentNode.action, callbacks, opts response: (html) -> doc = d.implementation.createHTMLDocument '' @@ -3192,12 +3191,12 @@ Main = nodes = [] for mutation in mutations for addedNode in mutation.addedNodes - if addedNode.nodeName is 'DIV' and /\bpostContainer\b/.test addedNode.className + if /\bpostContainer\b/.test addedNode.className nodes.push Main.preParse addedNode Main.node nodes if nodes.length listener: (e) -> {target} = e - if target.nodeName is 'DIV' and /\bpostContainer\b/.test addedNode.className + if /\bpostContainer\b/.test addedNode.className Main.node [Main.preParse target] namespace: '4chan_x.' From a5912734f3fdf8b249b7091f17c96bb62f97f08b Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 7 May 2012 10:03:22 +0200 Subject: [PATCH 44/52] Use IDs for backlink containers. --- 4chan_x.user.js | 7 ++++--- script.coffee | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 02353bd4b..3bc070944 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3058,7 +3058,7 @@ textContent: QuoteBacklink.funk(post.id) }); for (qid in quotes) { - if (!(el = $.id("pi" + qid)) || /\bop\b/.test(el.parentNode.className) && !Conf['OP Backlinks']) { + if (!(el = $.id("pi" + qid)) || !Conf['OP Backlinks'] && /\bop\b/.test(el.parentNode.className)) { continue; } link = a.cloneNode(true); @@ -3070,9 +3070,10 @@ } else { link.setAttribute('onclick', "replyhl('" + post.id + "');"); } - if (!((container = $('.container', el)) && container.parentNode === el)) { + if (!(container = $.id("blc" + qid))) { container = $.el('span', { - className: 'container' + className: 'container', + id: "blc" + qid }); $.add(el, container); } diff --git a/script.coffee b/script.coffee index 86709ada5..d17f69f19 100644 --- a/script.coffee +++ b/script.coffee @@ -2370,7 +2370,7 @@ QuoteBacklink = textContent: QuoteBacklink.funk post.id for qid of quotes # Don't backlink the OP. - continue if !(el = $.id "pi#{qid}") or /\bop\b/.test(el.parentNode.className) and !Conf['OP Backlinks'] + continue if !(el = $.id "pi#{qid}") or !Conf['OP Backlinks'] and /\bop\b/.test el.parentNode.className link = a.cloneNode true if Conf['Quote Preview'] $.on link, 'mouseover', QuotePreview.mouseover @@ -2378,8 +2378,10 @@ QuoteBacklink = $.on link, 'click', QuoteInline.toggle else link.setAttribute 'onclick', "replyhl('#{post.id}');" - unless (container = $ '.container', el) and container.parentNode is el - container = $.el 'span', className: 'container' + unless container = $.id "blc#{qid}" + container = $.el 'span', + className: 'container' + id: "blc#{qid}" $.add el, container $.add container, [$.tn(' '), link] return From d1a699162196e85069cda7aec127cabcb1785e52 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 7 May 2012 10:09:14 +0200 Subject: [PATCH 45/52] Use $.addClass in Thread Stats. --- 4chan_x.user.js | 4 ++-- script.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 3bc070944..61c5203a2 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2578,7 +2578,7 @@ }, retry: function() { this.count.textContent = 'Retry'; - this.count.className = ''; + this.count.className = null; return this.update(); }, update: function() { @@ -3463,7 +3463,7 @@ imgcount = $.id('imagecount'); imgcount.textContent = ++ThreadStats.images; if (ThreadStats.images > ThreadStats.imgLimit) { - return imgcount.className = 'warning'; + return $.addClass(imgcount, 'warning'); } } }; diff --git a/script.coffee b/script.coffee index d17f69f19..a7a853392 100644 --- a/script.coffee +++ b/script.coffee @@ -2048,7 +2048,7 @@ Updater = retry: -> @count.textContent = 'Retry' - @count.className = '' + @count.className = null @update() update: -> @@ -2663,7 +2663,7 @@ ThreadStats = imgcount = $.id 'imagecount' imgcount.textContent = ++ThreadStats.images if ThreadStats.images > ThreadStats.imgLimit - imgcount.className = 'warning' + $.addClass imgcount, 'warning' Unread = init: -> From 2af993300cde5b1812c4dae6979accdcfacc4e3b Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 9 May 2012 09:40:54 +0200 Subject: [PATCH 46/52] Keybinds and navigation fixes. --- 4chan_x.user.js | 37 ++++++++++++++++++------------------- script.coffee | 37 ++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index e03ece502..126e2ed10 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1258,13 +1258,13 @@ if (all) { return $.id('imageExpand').click(); } else { - thumb = $('img[data-md5]', $('.replyhl', thread) || thread); + thumb = $('img[data-md5]', $('.post.highlight', thread) || thread); return ImageExpand.toggle(thumb.parentNode); } }, qr: function(thread, quote) { if (quote) { - QR.quote.call($('.quotejs + .quotejs', $('.replyhl', thread) || thread)); + QR.quote.call($('.postInfo > .postNum > a[title="Quote this post"]', $('.post.highlight', thread) || thread)); } else { QR.open(); } @@ -1272,7 +1272,7 @@ }, open: function(thread, tab) { var id, url; - id = thread.firstChild.id; + id = thread.id.slice(1); url = "//boards.4chan.org/" + g.BOARD + "/res/" + id; if (tab) { return $.open(url); @@ -1281,17 +1281,15 @@ } }, hl: function(delta, thread) { - var next, rect, replies, reply, td, _i, _len; - if (td = $('.replyhl', thread)) { - td.className = 'reply'; - td.removeAttribute('tabindex'); - rect = td.getBoundingClientRect(); + var next, post, rect, replies, reply, _i, _len; + if (post = $('.reply.highlight', thread)) { + $.removeClass(post, 'highlight'); + post.removeAttribute('tabindex'); + rect = post.getBoundingClientRect(); if (rect.bottom >= 0 && rect.top <= d.documentElement.clientHeight) { - next = delta === +1 ? $.x('following::td[@class="reply"]', td) : $.x('preceding::td[@class="reply"]', td); + next = delta === +1 ? $.x('parent::div/following-sibling::div/div[contains(@class,"reply")]', post) : $.x('parent::div/preceding-sibling::div/div[contains(@class,"reply")]', post); if (!next) { - td.className = 'replyhl'; - td.tabIndex = 0; - td.focus(); + this.focus(post); return; } if (!(g.REPLY || $.x('ancestor::div[@class="thread"]', next) === thread)) { @@ -1301,9 +1299,7 @@ if (rect.top < 0 || rect.bottom > d.documentElement.clientHeight) { next.scrollIntoView(delta === -1); } - next.className = 'replyhl'; - next.tabIndex = 0; - next.focus(); + this.focus(next); return; } } @@ -1315,12 +1311,15 @@ reply = replies[_i]; rect = reply.getBoundingClientRect(); if (delta === +1 && rect.top >= 0 || delta === -1 && rect.bottom <= d.documentElement.clientHeight) { - reply.className = 'replyhl'; - reply.tabIndex = 0; - reply.focus(); + this.focus(reply); return; } } + }, + focus: function(post) { + $.addClass(post, 'highlight'); + post.tabIndex = 0; + return post.focus(); } }; @@ -1372,7 +1371,7 @@ return thread; } } - return $('form[name=delform]'); + return $('.board'); }, scroll: function(delta) { var i, rect, thread, top, _ref, _ref1; diff --git a/script.coffee b/script.coffee index d4b3d814d..f85b1f463 100644 --- a/script.coffee +++ b/script.coffee @@ -944,18 +944,18 @@ Keybinds = if all $.id('imageExpand').click() else - thumb = $ 'img[data-md5]', $('.replyhl', thread) or thread + thumb = $ 'img[data-md5]', $('.post.highlight', thread) or thread ImageExpand.toggle thumb.parentNode qr: (thread, quote) -> if quote - QR.quote.call $ '.quotejs + .quotejs', $('.replyhl', thread) or thread + QR.quote.call $ '.postInfo > .postNum > a[title="Quote this post"]', $('.post.highlight', thread) or thread else QR.open() $('textarea', QR.el).focus() open: (thread, tab) -> - id = thread.firstChild.id + id = thread.id[1..] url = "//boards.4chan.org/#{g.BOARD}/res/#{id}" if tab $.open url @@ -963,28 +963,24 @@ Keybinds = location.href = url hl: (delta, thread) -> - if td = $ '.replyhl', thread - td.className = 'reply' - td.removeAttribute 'tabindex' - rect = td.getBoundingClientRect() + if post = $ '.reply.highlight', thread + $.removeClass post, 'highlight' + post.removeAttribute 'tabindex' + rect = post.getBoundingClientRect() if rect.bottom >= 0 and rect.top <= d.documentElement.clientHeight # We're at least partially visible next = if delta is +1 - $.x 'following::td[@class="reply"]', td + $.x 'parent::div/following-sibling::div/div[contains(@class,"reply")]', post else - $.x 'preceding::td[@class="reply"]', td + $.x 'parent::div/preceding-sibling::div/div[contains(@class,"reply")]', post unless next - td.className = 'replyhl' - td.tabIndex = 0 - td.focus() + @focus post return return unless g.REPLY or $.x('ancestor::div[@class="thread"]', next) is thread rect = next.getBoundingClientRect() if rect.top < 0 or rect.bottom > d.documentElement.clientHeight next.scrollIntoView delta is -1 - next.className = 'replyhl' - next.tabIndex = 0 - next.focus() + @focus next return replies = $$ '.reply', thread @@ -992,11 +988,14 @@ Keybinds = for reply in replies rect = reply.getBoundingClientRect() if delta is +1 and rect.top >= 0 or delta is -1 and rect.bottom <= d.documentElement.clientHeight - reply.className = 'replyhl' - reply.tabIndex = 0 - reply.focus() + @focus reply return + focus: (post) -> + $.addClass post, 'highlight' + post.tabIndex = 0 + post.focus() + Nav = # ◀ ▶ init: -> @@ -1036,7 +1035,7 @@ Nav = if full return [thread, i, rect] return thread - return $ 'form[name=delform]' + return $ '.board' scroll: (delta) -> [thread, i, rect] = Nav.getThread true From 8e651ff102c31e64f6f799a3e1c30a797f898640 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 9 May 2012 10:00:36 +0200 Subject: [PATCH 47/52] Fix #411. I always forget that Firefox is shit and doesn't let you select nodes in a logical order. --- 4chan_x.user.js | 2 +- script.coffee | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 126e2ed10..ff2557f03 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1287,7 +1287,7 @@ post.removeAttribute('tabindex'); rect = post.getBoundingClientRect(); if (rect.bottom >= 0 && rect.top <= d.documentElement.clientHeight) { - next = delta === +1 ? $.x('parent::div/following-sibling::div/div[contains(@class,"reply")]', post) : $.x('parent::div/preceding-sibling::div/div[contains(@class,"reply")]', post); + next = $.x('child::div[contains(@class,"post reply")]', delta === +1 ? post.parentNode.nextElementSibling : post.parentNode.previousElementSibling); if (!next) { this.focus(post); return; diff --git a/script.coffee b/script.coffee index f85b1f463..c6c061e85 100644 --- a/script.coffee +++ b/script.coffee @@ -968,11 +968,8 @@ Keybinds = post.removeAttribute 'tabindex' rect = post.getBoundingClientRect() if rect.bottom >= 0 and rect.top <= d.documentElement.clientHeight # We're at least partially visible - next = - if delta is +1 - $.x 'parent::div/following-sibling::div/div[contains(@class,"reply")]', post - else - $.x 'parent::div/preceding-sibling::div/div[contains(@class,"reply")]', post + next = $.x 'child::div[contains(@class,"post reply")]', + if delta is +1 then post.parentNode.nextElementSibling else post.parentNode.previousElementSibling unless next @focus post return From 4a2ba910db04013af14efc14f6666aa0e3016bfc Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 9 May 2012 12:11:42 +0200 Subject: [PATCH 48/52] Fix #423 --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 51f38b2d3..a324a820d 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1131,7 +1131,7 @@ Keybinds.img(thread, true); break; case Conf.zero: - window.location = "/" + g.BOARD + "/0#0"; + window.location = "/" + g.BOARD + "/0#delform"; break; case Conf.nextPage: if (link = $('link[rel=next]', d.head)) { diff --git a/script.coffee b/script.coffee index dabf3887d..dae8bb705 100644 --- a/script.coffee +++ b/script.coffee @@ -885,7 +885,7 @@ Keybinds = Keybinds.img thread, true # Board Navigation when Conf.zero - window.location = "/#{g.BOARD}/0#0" + window.location = "/#{g.BOARD}/0#delform" when Conf.nextPage if link = $ 'link[rel=next]', d.head window.location = link.href From 070816de06c331729b97bf8175604aa086f534a7 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 13 May 2012 15:04:36 +0200 Subject: [PATCH 49/52] Fix user id filtering. --- 4chan_x.user.js | 2 +- script.coffee | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index a324a820d..292cdaa1c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -658,7 +658,7 @@ uniqueid: function(post) { var uid; if (uid = $('.posteruid', post.el)) { - return uid.textContent; + return uid.textContent.slice(5, -1); } return false; }, diff --git a/script.coffee b/script.coffee index dae8bb705..bea06f060 100644 --- a/script.coffee +++ b/script.coffee @@ -542,9 +542,8 @@ Filter = name: (post) -> $('.name', post.el).textContent uniqueid: (post) -> - # NEW HTML ??? if uid = $ '.posteruid', post.el - return uid.textContent + return uid.textContent[5...-1] false tripcode: (post) -> if trip = $ '.postertrip', post.el From 1d517d6becc57a287956586def2fdb1e3a85bd59 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 13 May 2012 16:21:16 +0200 Subject: [PATCH 50/52] Ugh. Fix OP Quote Highlighting. --- 4chan_x.user.js | 24 +++++++++++++++++++++--- script.coffee | 22 +++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 292cdaa1c..90f91b5eb 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3123,7 +3123,11 @@ var clonePost, el, i, inline, pathname, root; root = $.x('ancestor::*[parent::blockquote]', q); if (el = $.id("p" + id)) { - $.removeClass(el, 'qphl'); + if (/\bop\b/.test(el.className)) { + $.removeClass(el.parentNode, 'qphl'); + } else { + $.removeClass(el, 'qphl'); + } clonePost = QuoteInline.clone(id, el); if (/\bbacklink\b/.test(q.className)) { $.after(q.parentNode, clonePost); @@ -3250,7 +3254,11 @@ if (el = $.id("p" + id)) { qp.innerHTML = el.innerHTML; if (Conf['Quote Highlighting']) { - $.addClass(el, 'qphl'); + if (/\bop\b/.test(el.className)) { + $.addClass(el.parentNode, 'qphl'); + } else { + $.addClass(el, 'qphl'); + } } replyID = $.x('ancestor::div[contains(@class,"postContainer")]', this).id.slice(2); _ref = $$('.quotelink, .backlink', qp); @@ -3274,7 +3282,11 @@ var el; UI.hoverend(); if (el = $.id(this.hash.slice(1))) { - $.removeClass(el, 'qphl'); + if (/\bop\b/.test(el.className)) { + $.removeClass(el.parentNode, 'qphl'); + } else { + $.removeClass(el, 'qphl'); + } } $.off(this, 'mousemove', UI.hover); return $.off(this, 'mouseout click', QuotePreview.mouseout); @@ -4538,6 +4550,12 @@ textarea.field {\ .qphl {\ outline: 2px solid rgba(216, 94, 49, .7);\ }\ +.qphl.opContainer {\ + outline-offset: -2px;\ +}\ +div.opContainer {\ + display: block !important;\ +}\ .inlined {\ opacity: .5;\ }\ diff --git a/script.coffee b/script.coffee index bea06f060..2864447e8 100644 --- a/script.coffee +++ b/script.coffee @@ -2406,7 +2406,10 @@ QuoteInline = add: (q, id) -> root = $.x 'ancestor::*[parent::blockquote]', q if el = $.id "p#{id}" - $.removeClass el, 'qphl' + if /\bop\b/.test el.className + $.removeClass el.parentNode, 'qphl' + else + $.removeClass el, 'qphl' clonePost = QuoteInline.clone id, el if /\bbacklink\b/.test q.className $.after q.parentNode, clonePost @@ -2492,7 +2495,11 @@ QuotePreview = id = @hash[2..] if el = $.id "p#{id}" qp.innerHTML = el.innerHTML - $.addClass el, 'qphl' if Conf['Quote Highlighting'] + 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[2..] for quote in $$ '.quotelink, .backlink', qp if quote.hash[2..] is replyID @@ -2506,7 +2513,10 @@ QuotePreview = mouseout: -> UI.hoverend() if el = $.id @hash[1..] - $.removeClass el, 'qphl' + if /\bop\b/.test el.className + $.removeClass el.parentNode, 'qphl' + else + $.removeClass el, 'qphl' $.off @, 'mousemove', UI.hover $.off @, 'mouseout click', QuotePreview.mouseout parse: (req, id) -> @@ -3555,6 +3565,12 @@ textarea.field { .qphl { outline: 2px solid rgba(216, 94, 49, .7); } +.qphl.opContainer { + outline-offset: -2px; +} +div.opContainer { + display: block !important; +} .inlined { opacity: .5; } From 4bfab3c3b9a9ef354d709701772738c58d90f05c Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 13 May 2012 16:26:19 +0200 Subject: [PATCH 51/52] Ugh, better thread filter highlighting. --- 4chan_x.user.js | 4 +++- script.coffee | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 90f91b5eb..ca2359418 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -4568,7 +4568,9 @@ div.opContainer {\ background: none;\ border: none;\ }\ -.filter_highlight.thread,\ +.filter_highlight.thread > .opContainer {\ + box-shadow: inset 5px 0 rgba(255,0,0,0.5);\ +}\ .filter_highlight > .reply {\ box-shadow: -5px 0 rgba(255,0,0,0.5);\ }\ diff --git a/script.coffee b/script.coffee index 2864447e8..81c3f3038 100644 --- a/script.coffee +++ b/script.coffee @@ -3583,7 +3583,9 @@ div.opContainer { background: none; border: none; } -.filter_highlight.thread, +.filter_highlight.thread > .opContainer { + box-shadow: inset 5px 0 rgba(255,0,0,0.5); +} .filter_highlight > .reply { box-shadow: -5px 0 rgba(255,0,0,0.5); } From 1d0f5a3d24a569d7d4a910f59bc3737dc8a97350 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 13 May 2012 16:51:01 +0200 Subject: [PATCH 52/52] Don't set ISO'd time on the time element, 4chan will give the timestamps. --- 4chan_x.user.js | 3 +-- script.coffee | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index ca2359418..f668de93c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2824,8 +2824,7 @@ } node = $('.postInfo > .dateTime', post.el); Time.date = Time.parse(node.textContent); - node.textContent = Time.funk(Time); - return node.dataset.time = Time.date.toISOString(); + return node.textContent = Time.funk(Time); }, foo: function() { var code; diff --git a/script.coffee b/script.coffee index 81c3f3038..cbccbde19 100644 --- a/script.coffee +++ b/script.coffee @@ -2226,8 +2226,6 @@ Time = node = $ '.postInfo > .dateTime', post.el Time.date = Time.parse node.textContent node.textContent = Time.funk(Time) - # Set the datetime attribute, ISO'd. - node.dataset.time = Time.date.toISOString() foo: -> code = Conf['time'].replace /%([A-Za-z])/g, (s, c) -> if c of Time.formatters