diff --git a/LICENSE b/LICENSE index 633bc8ac7..43b9ec419 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.2.25 - 2013-08-05 +* 4chan X - Version 1.2.25 - 2013-08-06 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 44df79589..497294377 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -19,7 +19,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.2.25 - 2013-08-05 +* 4chan X - Version 1.2.25 - 2013-08-06 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -8612,34 +8612,42 @@ }); }, node: function() { - var a, span; + var a, files, posts, span, _ref; - if (!(span = $('.summary', this.OP.nodes.root.parentNode))) { + if (!(span = $.x('following-sibling::span[contains(@class,"summary")][1]', this.OP.nodes.root))) { return; } + _ref = span.textContent.match(/\d+/g), posts = _ref[0], files = _ref[1]; a = $.el('a', { - textContent: "+ " + span.textContent, + textContent: ExpandThread.text('+', posts, files), className: 'summary', href: 'javascript:;' }); $.on(a, 'click', ExpandThread.cbToggle); return $.replace(span, a); }, - cbToggle: function() { - var op; + text: function(status, posts, files) { + var text; - op = Get.postFromRoot(this.previousElementSibling); - return ExpandThread.toggle(op.thread); + text = [status]; + text.push("" + posts + " post" + (posts > 1 ? 's' : '')); + if (+files) { + text.push("and " + files + " image repl" + (files > 1 ? 'ies' : 'y')); + } + text.push(status === '-' ? 'shown' : 'omitted'); + return text.join(' ') + '.'; + }, + cbToggle: function() { + return ExpandThread.toggle(Get.threadFromRoot(this.parentNode)); }, toggle: function(thread) { - var a, inlined, num, post, replies, reply, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + var a, files, filesCount, inlined, num, post, posts, postsCount, reply, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3, _ref4; threadRoot = thread.OP.nodes.root.parentNode; a = $('.summary', threadRoot); switch (thread.isExpanded) { case false: case void 0: - thread.isExpanded = 'loading'; _ref = $$('.thread > .postContainer', threadRoot); for (_i = 0, _len = _ref.length; _i < _len; _i++) { post = _ref[_i]; @@ -8650,7 +8658,8 @@ return; } thread.isExpanded = 'loading'; - a.textContent = a.textContent.replace('+', '...'); + _ref1 = a.textContent.match(/\d+/g), posts = _ref1[0], files = _ref1[1]; + a.textContent = ExpandThread.text('...', posts, files); $.cache("//api.4chan.org/" + thread.board + "/res/" + thread + ".json", function() { return ExpandThread.parse(this, thread, a); }); @@ -8660,84 +8669,99 @@ if (!a) { return; } - a.textContent = a.textContent.replace('...', '+'); + _ref2 = a.textContent.match(/\d+/g), posts = _ref2[0], files = _ref2[1]; + a.textContent = ExpandThread.text('+', posts, files); break; case true: thread.isExpanded = false; - if (a) { - a.textContent = a.textContent.replace('-', '+').replace('hide', 'view').replace('expanded', 'omitted'); - num = (function() { - if (thread.isSticky) { - return 1; - } else { - switch (g.BOARD.ID) { - case 'b': - case 'vg': - case 'q': - return 3; - case 't': - return 1; - default: - return 5; - } + num = (function() { + if (thread.isSticky) { + return 1; + } else { + switch (g.BOARD.ID) { + case 'b': + case 'vg': + case 'q': + return 3; + case 't': + return 1; + default: + return 5; } - })(); - replies = $$('.thread > .replyContainer', threadRoot).slice(0, -num); - for (_j = 0, _len1 = replies.length; _j < _len1; _j++) { - reply = replies[_j]; - if (Conf['Quote Inlining']) { - while (inlined = $('.inlined', reply)) { - inlined.click(); - } - } - $.rm(reply); } - } - _ref1 = $$('.thread > .postContainer', threadRoot); - for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { - post = _ref1[_k]; + })(); + posts = $$(".thread > .replyContainer", threadRoot); + _ref3 = [thread.OP.nodes.root].concat(posts.slice(-num)); + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + post = _ref3[_j]; ExpandComment.contract(Get.postFromRoot(post)); } + if (!a) { + return; + } + postsCount = 0; + filesCount = 0; + _ref4 = posts.slice(0, -num); + for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { + reply = _ref4[_k]; + if (Conf['Quote Inlining']) { + while (inlined = $('.inlined', reply)) { + inlined.click(); + } + } + postsCount++; + if ('file' in Get.postFromRoot(reply)) { + filesCount++; + } + $.rm(reply); + } + a.textContent = ExpandThread.text('+', postsCount, filesCount); } }, parse: function(req, thread, a) { - var link, node, nodes, post, posts, replies, reply, spoilerRange, status, _i, _len; + var filesCount, link, post, posts, postsCount, postsObj, postsRoot, reply, root, spoilerRange, _i, _len; if (a.textContent[0] === '+') { return; } - status = req.status; - if (![200, 304].contains(status)) { - a.textContent = "Error " + req.statusText + " (" + status + ")"; - $.off(a, 'click', ExpandThread.cb.toggle); + if (![200, 304].contains(req.status)) { + a.textContent = "Error " + req.statusText + " (" + req.status + ")"; + $.off(a, 'click', ExpandThread.cbToggle); return; } thread.isExpanded = true; - a.textContent = a.textContent.replace('...', '-').replace('view', 'hide').replace('omitted', 'expanded'); posts = JSON.parse(req.response).posts; - if (spoilerRange = posts[0].custom_spoiler) { - Build.spoilerRange[g.BOARD] = spoilerRange; + if (spoilerRange = posts.shift().custom_spoiler) { + Build.spoilerRange[thread.board] = spoilerRange; } - replies = posts.slice(1); - posts = []; - nodes = []; - for (_i = 0, _len = replies.length; _i < _len; _i++) { - reply = replies[_i]; + postsObj = []; + postsRoot = []; + filesCount = 0; + for (_i = 0, _len = posts.length; _i < _len; _i++) { + reply = posts[_i]; if (post = thread.posts[reply.no]) { - nodes.push(post.nodes.root); + if ('file' in post) { + filesCount++; + } + postsRoot.push(post.nodes.root); continue; } - node = Build.postFromObject(reply, thread.board.ID); - post = new Post(node, thread, thread.board); - link = $('a[title="Highlight this post"]', node); + root = Build.postFromObject(reply, thread.board.ID); + post = new Post(root, thread, thread.board); + link = $('a[title="Highlight this post"]', root); link.href = "res/" + thread + "#p" + post; link.nextSibling.href = "res/" + thread + "#q" + post; - posts.push(post); - nodes.push(node); + if ('file' in post) { + filesCount++; + } + postsObj.push(post); + postsRoot.push(root); } - Main.callbackNodes(Post, posts); - $.after(a, nodes); - return Fourchan.parseThread(thread.ID, 1, nodes.length); + Main.callbackNodes(Post, postsObj); + $.after(a, postsRoot); + postsCount = postsRoot.length; + a.textContent = ExpandThread.text('-', postsCount, filesCount); + return Fourchan.parseThread(thread.ID, 1, postsCount); } }; diff --git a/builds/crx/script.js b/builds/crx/script.js index ddab4bd0b..4816da6d1 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.2.25 - 2013-08-05 +* 4chan X - Version 1.2.25 - 2013-08-06 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -8597,34 +8597,42 @@ }); }, node: function() { - var a, span; + var a, files, posts, span, _ref; - if (!(span = $('.summary', this.OP.nodes.root.parentNode))) { + if (!(span = $.x('following-sibling::span[contains(@class,"summary")][1]', this.OP.nodes.root))) { return; } + _ref = span.textContent.match(/\d+/g), posts = _ref[0], files = _ref[1]; a = $.el('a', { - textContent: "+ " + span.textContent, + textContent: ExpandThread.text('+', posts, files), className: 'summary', href: 'javascript:;' }); $.on(a, 'click', ExpandThread.cbToggle); return $.replace(span, a); }, - cbToggle: function() { - var op; + text: function(status, posts, files) { + var text; - op = Get.postFromRoot(this.previousElementSibling); - return ExpandThread.toggle(op.thread); + text = [status]; + text.push("" + posts + " post" + (posts > 1 ? 's' : '')); + if (+files) { + text.push("and " + files + " image repl" + (files > 1 ? 'ies' : 'y')); + } + text.push(status === '-' ? 'shown' : 'omitted'); + return text.join(' ') + '.'; + }, + cbToggle: function() { + return ExpandThread.toggle(Get.threadFromRoot(this.parentNode)); }, toggle: function(thread) { - var a, inlined, num, post, replies, reply, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + var a, files, filesCount, inlined, num, post, posts, postsCount, reply, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3, _ref4; threadRoot = thread.OP.nodes.root.parentNode; a = $('.summary', threadRoot); switch (thread.isExpanded) { case false: case void 0: - thread.isExpanded = 'loading'; _ref = $$('.thread > .postContainer', threadRoot); for (_i = 0, _len = _ref.length; _i < _len; _i++) { post = _ref[_i]; @@ -8635,7 +8643,8 @@ return; } thread.isExpanded = 'loading'; - a.textContent = a.textContent.replace('+', '...'); + _ref1 = a.textContent.match(/\d+/g), posts = _ref1[0], files = _ref1[1]; + a.textContent = ExpandThread.text('...', posts, files); $.cache("//api.4chan.org/" + thread.board + "/res/" + thread + ".json", function() { return ExpandThread.parse(this, thread, a); }); @@ -8645,84 +8654,99 @@ if (!a) { return; } - a.textContent = a.textContent.replace('...', '+'); + _ref2 = a.textContent.match(/\d+/g), posts = _ref2[0], files = _ref2[1]; + a.textContent = ExpandThread.text('+', posts, files); break; case true: thread.isExpanded = false; - if (a) { - a.textContent = a.textContent.replace('-', '+').replace('hide', 'view').replace('expanded', 'omitted'); - num = (function() { - if (thread.isSticky) { - return 1; - } else { - switch (g.BOARD.ID) { - case 'b': - case 'vg': - case 'q': - return 3; - case 't': - return 1; - default: - return 5; - } + num = (function() { + if (thread.isSticky) { + return 1; + } else { + switch (g.BOARD.ID) { + case 'b': + case 'vg': + case 'q': + return 3; + case 't': + return 1; + default: + return 5; } - })(); - replies = $$('.thread > .replyContainer', threadRoot).slice(0, -num); - for (_j = 0, _len1 = replies.length; _j < _len1; _j++) { - reply = replies[_j]; - if (Conf['Quote Inlining']) { - while (inlined = $('.inlined', reply)) { - inlined.click(); - } - } - $.rm(reply); } - } - _ref1 = $$('.thread > .postContainer', threadRoot); - for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { - post = _ref1[_k]; + })(); + posts = $$(".thread > .replyContainer", threadRoot); + _ref3 = [thread.OP.nodes.root].concat(posts.slice(-num)); + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + post = _ref3[_j]; ExpandComment.contract(Get.postFromRoot(post)); } + if (!a) { + return; + } + postsCount = 0; + filesCount = 0; + _ref4 = posts.slice(0, -num); + for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { + reply = _ref4[_k]; + if (Conf['Quote Inlining']) { + while (inlined = $('.inlined', reply)) { + inlined.click(); + } + } + postsCount++; + if ('file' in Get.postFromRoot(reply)) { + filesCount++; + } + $.rm(reply); + } + a.textContent = ExpandThread.text('+', postsCount, filesCount); } }, parse: function(req, thread, a) { - var link, node, nodes, post, posts, replies, reply, spoilerRange, status, _i, _len; + var filesCount, link, post, posts, postsCount, postsObj, postsRoot, reply, root, spoilerRange, _i, _len; if (a.textContent[0] === '+') { return; } - status = req.status; - if (![200, 304].contains(status)) { - a.textContent = "Error " + req.statusText + " (" + status + ")"; - $.off(a, 'click', ExpandThread.cb.toggle); + if (![200, 304].contains(req.status)) { + a.textContent = "Error " + req.statusText + " (" + req.status + ")"; + $.off(a, 'click', ExpandThread.cbToggle); return; } thread.isExpanded = true; - a.textContent = a.textContent.replace('...', '-').replace('view', 'hide').replace('omitted', 'expanded'); posts = JSON.parse(req.response).posts; - if (spoilerRange = posts[0].custom_spoiler) { - Build.spoilerRange[g.BOARD] = spoilerRange; + if (spoilerRange = posts.shift().custom_spoiler) { + Build.spoilerRange[thread.board] = spoilerRange; } - replies = posts.slice(1); - posts = []; - nodes = []; - for (_i = 0, _len = replies.length; _i < _len; _i++) { - reply = replies[_i]; + postsObj = []; + postsRoot = []; + filesCount = 0; + for (_i = 0, _len = posts.length; _i < _len; _i++) { + reply = posts[_i]; if (post = thread.posts[reply.no]) { - nodes.push(post.nodes.root); + if ('file' in post) { + filesCount++; + } + postsRoot.push(post.nodes.root); continue; } - node = Build.postFromObject(reply, thread.board.ID); - post = new Post(node, thread, thread.board); - link = $('a[title="Highlight this post"]', node); + root = Build.postFromObject(reply, thread.board.ID); + post = new Post(root, thread, thread.board); + link = $('a[title="Highlight this post"]', root); link.href = "res/" + thread + "#p" + post; link.nextSibling.href = "res/" + thread + "#q" + post; - posts.push(post); - nodes.push(node); + if ('file' in post) { + filesCount++; + } + postsObj.push(post); + postsRoot.push(root); } - Main.callbackNodes(Post, posts); - $.after(a, nodes); - return Fourchan.parseThread(thread.ID, 1, nodes.length); + Main.callbackNodes(Post, postsObj); + $.after(a, postsRoot); + postsCount = postsRoot.length; + a.textContent = ExpandThread.text('-', postsCount, filesCount); + return Fourchan.parseThread(thread.ID, 1, postsCount); } }; diff --git a/src/Miscellaneous/ExpandThread.coffee b/src/Miscellaneous/ExpandThread.coffee index 764d201ab..4d63a2989 100644 --- a/src/Miscellaneous/ExpandThread.coffee +++ b/src/Miscellaneous/ExpandThread.coffee @@ -6,17 +6,24 @@ ExpandThread = name: 'Thread Expansion' cb: @node node: -> - return unless span = $ '.summary', @OP.nodes.root.parentNode + return unless span = $.x 'following-sibling::span[contains(@class,"summary")][1]', @OP.nodes.root + [posts, files] = span.textContent.match /\d+/g a = $.el 'a', - textContent: "+ #{span.textContent}" + textContent: ExpandThread.text '+', posts, files className: 'summary' href: 'javascript:;' $.on a, 'click', ExpandThread.cbToggle $.replace span, a + text: (status, posts, files) -> + text = [status] + text.push "#{posts} post#{if posts > 1 then 's' else ''}" + text.push "and #{files} image repl#{if files > 1 then 'ies' else 'y'}" if +files + text.push if status is '-' then 'shown' else 'omitted' + text.join(' ') + '.' + cbToggle: -> - op = Get.postFromRoot @previousElementSibling - ExpandThread.toggle op.thread + ExpandThread.toggle Get.threadFromRoot @parentNode toggle: (thread) -> threadRoot = thread.OP.nodes.root.parentNode @@ -24,74 +31,82 @@ ExpandThread = switch thread.isExpanded when false, undefined - thread.isExpanded = 'loading' for post in $$ '.thread > .postContainer', threadRoot ExpandComment.expand Get.postFromRoot post unless a thread.isExpanded = true return thread.isExpanded = 'loading' - a.textContent = a.textContent.replace '+', '...' + [posts, files] = a.textContent.match /\d+/g + a.textContent = ExpandThread.text '...', posts, files $.cache "//api.4chan.org/#{thread.board}/res/#{thread}.json", -> ExpandThread.parse @, thread, a when 'loading' thread.isExpanded = false return unless a - a.textContent = a.textContent.replace '...', '+' + [posts, files] = a.textContent.match /\d+/g + a.textContent = ExpandThread.text '+', posts, files when true thread.isExpanded = false - if a - a.textContent = a.textContent.replace('-', '+').replace('hide', 'view').replace('expanded', 'omitted') - #goddamit moot - num = if thread.isSticky - 1 - else switch g.BOARD.ID - # XXX boards config - when 'b', 'vg', 'q' then 3 - when 't' then 1 - else 5 - replies = $$('.thread > .replyContainer', threadRoot)[...-num] - for reply in replies - if Conf['Quote Inlining'] - # rm clones - inlined.click() while inlined = $ '.inlined', reply - $.rm reply - for post in $$ '.thread > .postContainer', threadRoot + #goddamit moot + num = if thread.isSticky + 1 + else switch g.BOARD.ID + # XXX boards config + when 'b', 'vg', 'q' then 3 + when 't' then 1 + else 5 + posts = $$ ".thread > .replyContainer", threadRoot + for post in [thread.OP.nodes.root].concat posts[-num..] ExpandComment.contract Get.postFromRoot post + return unless a + postsCount = 0 + filesCount = 0 + for reply in posts[...-num] + if Conf['Quote Inlining'] + # rm clones + inlined.click() while inlined = $ '.inlined', reply + postsCount++ + filesCount++ if 'file' of Get.postFromRoot reply + $.rm reply + a.textContent = ExpandThread.text '+', postsCount, filesCount return parse: (req, thread, a) -> return if a.textContent[0] is '+' - {status} = req - unless [200, 304].contains status - a.textContent = "Error #{req.statusText} (#{status})" - $.off a, 'click', ExpandThread.cb.toggle + unless [200, 304].contains req.status + a.textContent = "Error #{req.statusText} (#{req.status})" + $.off a, 'click', ExpandThread.cbToggle return thread.isExpanded = true - a.textContent = a.textContent.replace('...', '-').replace('view', 'hide').replace('omitted', 'expanded') - posts = JSON.parse(req.response).posts - if spoilerRange = posts[0].custom_spoiler - Build.spoilerRange[g.BOARD] = spoilerRange + {posts} = JSON.parse req.response + if spoilerRange = posts.shift().custom_spoiler + Build.spoilerRange[thread.board] = spoilerRange - replies = posts[1..] - posts = [] - nodes = [] - for reply in replies + postsObj = [] + postsRoot = [] + filesCount = 0 + for reply in posts if post = thread.posts[reply.no] - nodes.push post.nodes.root + filesCount++ if 'file' of post + postsRoot.push post.nodes.root continue - node = Build.postFromObject reply, thread.board.ID - post = new Post node, thread, thread.board - link = $ 'a[title="Highlight this post"]', node + root = Build.postFromObject reply, thread.board.ID + post = new Post root, thread, thread.board + link = $ 'a[title="Highlight this post"]', root link.href = "res/#{thread}#p#{post}" link.nextSibling.href = "res/#{thread}#q#{post}" - posts.push post - nodes.push node - Main.callbackNodes Post, posts - $.after a, nodes + filesCount++ if 'file' of post + postsObj.push post + postsRoot.push root + Main.callbackNodes Post, postsObj + $.after a, postsRoot - Fourchan.parseThread thread.ID, 1, nodes.length + postsCount = postsRoot.length + a.textContent = ExpandThread.text '-', postsCount, filesCount + + Fourchan.parseThread thread.ID, 1, postsCount