diff --git a/4chan_x.user.js b/4chan_x.user.js index 2eb1d304f..fb4ffa8b1 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -511,7 +511,7 @@ Filter = { filters: {}, init: function() { - var boards, filter, hl, key, op, regexp, top, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4; + var boards, filter, hl, key, op, regexp, stub, top, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; for (key in Config.filter) { this.filters[key] = []; _ref = Conf[key].split('\n'); @@ -538,13 +538,15 @@ alert(e.message); continue; } - op = ((_ref2 = filter.match(/[^t]op:(yes|no|only)/)) != null ? _ref2[1].toLowerCase() : void 0) || 'no'; + op = ((_ref2 = filter.match(/[^t]op:(yes|no|only)/)) != null ? _ref2[1] : void 0) || 'no'; + stub = (_ref3 = filter.match(/stub:(yes|no)/)) != null ? _ref3[1] : void 0; + stub = stub === 'yes' && !Conf['Show Stubs'] || stub === 'no' && Conf['Show Stubs']; if (hl = /highlight/.test(filter)) { - hl = ((_ref3 = filter.match(/highlight:(\w+)/)) != null ? _ref3[1].toLowerCase() : void 0) || 'filter_highlight'; - top = ((_ref4 = filter.match(/top:(yes|no)/)) != null ? _ref4[1].toLowerCase() : void 0) || 'yes'; + hl = ((_ref4 = filter.match(/highlight:(\w+)/)) != null ? _ref4[1] : void 0) || 'filter_highlight'; + top = ((_ref5 = filter.match(/top:(yes|no)/)) != null ? _ref5[1] : void 0) || 'yes'; top = top === 'yes'; } - this.filters[key].push(this.createFilter(regexp, op, hl, top)); + this.filters[key].push(this.createFilter(regexp, op, stub, hl, top)); } if (!this.filters[key].length) { delete this.filters[key]; @@ -554,13 +556,19 @@ return Main.callbacks.push(this.node); } }, - createFilter: function(regexp, op, hl, top) { - var test; + createFilter: function(regexp, op, stub, hl, top) { + var settings, test; test = typeof regexp === 'string' ? function(value) { return regexp === value; } : function(value) { return regexp.test(value); }; + settings = { + hide: !hl, + stub: stub, + "class": hl, + top: top + }; return function(value, isOP) { if (isOP && op === 'no' || !isOP && op === 'only') { return false; @@ -568,10 +576,7 @@ if (!test(value)) { return false; } - if (hl) { - return [hl, top]; - } - return true; + return settings; }; }, node: function(post) { @@ -592,20 +597,20 @@ if (!(result = filter(value, isOP))) { continue; } - if (result === true) { + if (result.hide) { if (isOP) { if (!g.REPLY) { - ThreadHiding.hide(root.parentNode); + ThreadHiding.hide(root.parentNode, result.stub); } else { continue; } } else { - ReplyHiding.hide(root); + ReplyHiding.hide(root, result.stub); } return; } - $.addClass(root, result[0]); - if (isOP && result[1] && !g.REPLY) { + $.addClass(root, result["class"]); + if (isOP && result.top && !g.REPLY) { thisThread = root.parentNode; if (firstThread = $('div[class="postContainer opContainer"]').parentNode) { $.before(firstThread, [thisThread, thisThread.nextElementSibling]); @@ -920,14 +925,14 @@ } return $.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); }, - hide: function(thread) { + hide: function(thread, invert_stub_conf) { var a, num, opInfo, span, text; - if (!Conf['Show Stubs']) { + if (Conf['Show Stubs'] === invert_stub_conf) { thread.hidden = true; thread.nextElementSibling.hidden = true; return; } - if (thread.firstChild.className === 'hide_thread_button hidden_thread') { + if (/\bhidden_thread\b/.test(thread.firstChild.className)) { return; } num = 0; @@ -937,16 +942,20 @@ 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 + ")")); + a = $.el('a', { + className: 'hide_thread_button hidden_thread', + innerHTML: '[ + ]', + href: 'javascript:;' + }); + $.add(a, $.tn(" " + opInfo + " (" + text + ")")); + $.on(a, 'click', ThreadHiding.cb); + return $.prepend(thread, a); }, show: function(thread) { var a; - a = $('.hide_thread_button', thread); - $.removeClass(a, 'hidden_thread'); - a.innerHTML = '[ - ]'; + if (a = $('.hidden_thread', thread)) { + $.rm(a); + } thread.hidden = false; return thread.nextElementSibling.hidden = false; } @@ -957,14 +966,14 @@ return Main.callbacks.push(this.node); }, node: function(post) { - var button; + var side; if (post.isInlined || /\bop\b/.test(post["class"])) { return; } - button = post.root.firstElementChild; - $.addClass(button, 'hide_reply_button'); - button.innerHTML = '[ - ]'; - $.on(button.firstChild, 'click', ReplyHiding.toggle); + side = $('.sideArrows', post.root); + $.addClass(side, 'hide_reply_button'); + side.innerHTML = '[ - ]'; + $.on(side.firstChild, 'click', ReplyHiding.toggle); if (post.id in g.hiddenReplies) { return ReplyHiding.hide(post.root); } @@ -992,36 +1001,34 @@ } return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); }, - hide: function(root) { - var button, el, stub; - button = root.firstElementChild; - if (button.hidden) { + hide: function(root, invert_stub_conf) { + var a, el, side, stub; + side = $('.sideArrows', root); + if (side.hidden) { return; } - button.hidden = true; - el = root.lastElementChild; + side.hidden = true; + el = side.nextElementSibling; el.hidden = true; - if (!Conf['Show Stubs']) { + if (Conf['Show Stubs'] === invert_stub_conf) { return; } 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); + a = stub.firstChild; + $.add(a, $.tn($('.nameBlock', el).textContent)); + $.on(a, 'click', ReplyHiding.toggle); + return $.prepend(root, stub); }, show: function(root) { - var button, el; - el = root.lastElementChild; - button = root.firstElementChild; - el.hidden = false; - button.hidden = false; - if (!Conf['Show Stubs']) { - return; + var stub; + if (stub = $('.stub', root)) { + $.rm(stub); } - return $.rm(button.nextElementSibling); + $('.sideArrows', root).hidden = false; + return $('.post', root).hidden = false; } }; @@ -2205,6 +2212,7 @@ \ diff --git a/changelog b/changelog index 53ba3939d..6fb00dd04 100644 --- a/changelog +++ b/changelog @@ -1,4 +1,6 @@ master +- Mayhem + Add a per filter stub setting. 2.30.8 - Mayhem diff --git a/script.coffee b/script.coffee index 6de792096..9bee54a20 100644 --- a/script.coffee +++ b/script.coffee @@ -419,19 +419,24 @@ Filter = # Filter OPs along with their threads, replies only, or both. # Defaults to replies only. - op = filter.match(/[^t]op:(yes|no|only)/)?[1].toLowerCase() or 'no' + op = filter.match(/[^t]op:(yes|no|only)/)?[1] or 'no' + + # Overrule the `Show Stubs` setting. + # Defaults to stub showing. + stub = filter.match(/stub:(yes|no)/)?[1] + stub = stub is 'yes' and !Conf['Show Stubs'] or stub is 'no' and Conf['Show Stubs'] # Highlight the post, or hide it. # If not specified, the highlight class will be filter_highlight. # Defaults to post hiding. if hl = /highlight/.test filter - hl = filter.match(/highlight:(\w+)/)?[1].toLowerCase() or 'filter_highlight' + hl = filter.match(/highlight:(\w+)/)?[1] or 'filter_highlight' # Put highlighted OP's thread on top of the board page or not. # Defaults to on top. - top = filter.match(/top:(yes|no)/)?[1].toLowerCase() or 'yes' + top = filter.match(/top:(yes|no)/)?[1] or 'yes' top = top is 'yes' # Turn it into a boolean - @filters[key].push @createFilter regexp, op, hl, top + @filters[key].push @createFilter regexp, op, stub, hl, top # Only execute filter types that contain valid filters. unless @filters[key].length @@ -440,21 +445,24 @@ Filter = if Object.keys(@filters).length Main.callbacks.push @node - createFilter: (regexp, op, hl, top) -> + createFilter: (regexp, op, stub, hl, top) -> test = if typeof regexp is 'string' # MD5 checking (value) -> regexp is value else (value) -> regexp.test value + settings = + hide: !hl + stub: stub + class: hl + top: top (value, isOP) -> if isOP and op is 'no' or !isOP and op is 'only' return false unless test value return false - if hl - return [hl, top] - true + settings node: (post) -> return if post.isInlined @@ -470,19 +478,19 @@ Filter = continue # Hide - if result is true + if result.hide if isOP unless g.REPLY - ThreadHiding.hide root.parentNode + ThreadHiding.hide root.parentNode, result.stub else continue else - ReplyHiding.hide root + ReplyHiding.hide root, result.stub return # Highlight - $.addClass root, result[0] - if isOP and result[1] and not g.REPLY + $.addClass root, result.class + if isOP and result.top and not g.REPLY # Put the highlighted OPs' thread on top of the board page... thisThread = root.parentNode # ...before the first non highlighted thread. @@ -670,7 +678,7 @@ ThreadHiding = init: -> hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} for thread in $$ '.thread' - a = $.el 'a', + a = $.el 'a', className: 'hide_thread_button' innerHTML: '[ - ]' href: 'javascript:;' @@ -695,13 +703,13 @@ ThreadHiding = hiddenThreads[id] = Date.now() $.set "hiddenThreads/#{g.BOARD}/", hiddenThreads - hide: (thread) -> - unless Conf['Show Stubs'] + hide: (thread, invert_stub_conf) -> + unless Conf['Show Stubs'] isnt invert_stub_conf thread.hidden = true thread.nextElementSibling.hidden = true return - return if thread.firstChild.className is 'hide_thread_button hidden_thread' # already hidden by filter + return if /\bhidden_thread\b/.test thread.firstChild.className # already hidden once by the filter num = 0 if span = $ '.summary', thread @@ -710,15 +718,17 @@ ThreadHiding = 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 = '[ + ]' + a = $.el 'a', + className: 'hide_thread_button hidden_thread' + innerHTML: '[ + ]' + href: 'javascript:;' $.add a, $.tn " #{opInfo} (#{text})" + $.on a, 'click', ThreadHiding.cb + $.prepend thread, a show: (thread) -> - a = $ '.hide_thread_button', thread - $.removeClass a, 'hidden_thread' - a.innerHTML = '[ - ]' + if a = $ '.hidden_thread', thread + $.rm a thread.hidden = false thread.nextElementSibling.hidden = false @@ -728,10 +738,10 @@ ReplyHiding = node: (post) -> return if post.isInlined or /\bop\b/.test post.class - button = post.root.firstElementChild - $.addClass button, 'hide_reply_button' - button.innerHTML = '[ - ]' - $.on button.firstChild, 'click', ReplyHiding.toggle + side = $ '.sideArrows', post.root + $.addClass side, 'hide_reply_button' + side.innerHTML = '[ - ]' + $.on side.firstChild, 'click', ReplyHiding.toggle if post.id of g.hiddenReplies ReplyHiding.hide post.root @@ -753,31 +763,28 @@ ReplyHiding = g.hiddenReplies[id] = Date.now() $.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies - hide: (root) -> - button = root.firstElementChild - return if button.hidden # already hidden once by filter - button.hidden = true - el = root.lastElementChild + hide: (root, invert_stub_conf) -> + side = $ '.sideArrows', root + return if side.hidden # already hidden once by the filter + side.hidden = true + el = side.nextElementSibling el.hidden = true - return unless Conf['Show Stubs'] + return unless Conf['Show Stubs'] isnt invert_stub_conf 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 + a = stub.firstChild + $.add a, $.tn $('.nameBlock', el).textContent + $.on a, 'click', ReplyHiding.toggle + $.prepend root, stub show: (root) -> - el = root.lastElementChild - button = root.firstElementChild - el.hidden = false - button.hidden = false - - return unless Conf['Show Stubs'] - - $.rm button.nextElementSibling + if stub = $ '.stub', root + $.rm stub + $('.sideArrows', root).hidden = false + $('.post', root).hidden = false Keybinds = init: -> @@ -1692,6 +1699,7 @@ Options =