From 3f438d55ff28e802d74ad8a84e99aad5d61ee697 Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Tue, 11 Mar 2014 11:57:30 -0700 Subject: [PATCH 1/4] Tighten up Get.threadFromRoom, Get.contextFromNode --- LICENSE | 2 +- builds/4chan-X.user.js | 9 ++++----- builds/crx/script.js | 9 ++++----- src/General/Get.coffee | 5 ++--- src/General/lib/post.class | 1 + 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/LICENSE b/LICENSE index 466133539..d45e0ed08 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.4.1 - 2014-03-10 +* 4chan X - Version 1.4.1 - 2014-03-11 * * Licensed under the MIT license. * https://github.com/Spittie/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 8da0d8c27..bba046fd7 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.4.1 - 2014-03-10 +* 4chan X - Version 1.4.1 - 2014-03-11 * * Licensed under the MIT license. * https://github.com/Spittie/4chan-x/blob/master/LICENSE @@ -1087,6 +1087,7 @@ this.thread.OP = this; this.thread.isSticky = !!$('.stickyIcon', info); this.thread.isClosed = !!$('.closedIcon', info); + root.parentElement.dataset.fullID = this.fullID; } this.info = {}; if (subject = $('.subject', info)) { @@ -3844,7 +3845,7 @@ return "/" + thread.board + "/ - " + excerpt; }, threadFromRoot: function(root) { - return g.threads["" + g.BOARD + "." + root.id.slice(1)]; + return g.threads[root.dataset.fullID]; }, threadFromNode: function(node) { return Get.threadFromRoot($.x('ancestor::div[@class="thread"]', node)); @@ -3862,9 +3863,7 @@ return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', node)); }, contextFromNode: function(node) { - var snapshot; - snapshot = $.X('ancestor::div[contains(@class,"postContainer")]', node); - return Get.postFromRoot(snapshot.snapshotItem(snapshot.length - 1)); + return Get.postFromRoot($.x('ancestor::div[@class="thread"]', node).firstElementChild); }, postDataFromLink: function(link) { var boardID, path, postID, threadID, _ref; diff --git a/builds/crx/script.js b/builds/crx/script.js index 9a6aa427e..bbf52aa44 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.4.1 - 2014-03-10 +* 4chan X - Version 1.4.1 - 2014-03-11 * * Licensed under the MIT license. * https://github.com/Spittie/4chan-x/blob/master/LICENSE @@ -1141,6 +1141,7 @@ this.thread.OP = this; this.thread.isSticky = !!$('.stickyIcon', info); this.thread.isClosed = !!$('.closedIcon', info); + root.parentElement.dataset.fullID = this.fullID; } this.info = {}; if (subject = $('.subject', info)) { @@ -3903,7 +3904,7 @@ return "/" + thread.board + "/ - " + excerpt; }, threadFromRoot: function(root) { - return g.threads["" + g.BOARD + "." + root.id.slice(1)]; + return g.threads[root.dataset.fullID]; }, threadFromNode: function(node) { return Get.threadFromRoot($.x('ancestor::div[@class="thread"]', node)); @@ -3921,9 +3922,7 @@ return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', node)); }, contextFromNode: function(node) { - var snapshot; - snapshot = $.X('ancestor::div[contains(@class,"postContainer")]', node); - return Get.postFromRoot(snapshot.snapshotItem(snapshot.length - 1)); + return Get.postFromRoot($.x('ancestor::div[@class="thread"]', node).firstElementChild); }, postDataFromLink: function(link) { var boardID, path, postID, threadID, _ref; diff --git a/src/General/Get.coffee b/src/General/Get.coffee index 11ea71b6b..f042fde45 100755 --- a/src/General/Get.coffee +++ b/src/General/Get.coffee @@ -8,7 +8,7 @@ Get = excerpt = "#{excerpt[...67]}..." "/#{thread.board}/ - #{excerpt}" threadFromRoot: (root) -> - g.threads["#{g.BOARD}.#{root.id[1..]}"] + g.threads[root.dataset.fullID] threadFromNode: (node) -> Get.threadFromRoot $.x 'ancestor::div[@class="thread"]', node postFromRoot: (root) -> @@ -17,8 +17,7 @@ Get = postFromNode: (node) -> Get.postFromRoot $.x 'ancestor::div[contains(@class,"postContainer")][1]', node contextFromNode: (node) -> - snapshot = $.X 'ancestor::div[contains(@class,"postContainer")]', node - Get.postFromRoot snapshot.snapshotItem(snapshot.length - 1) + Get.postFromRoot $.x('ancestor::div[@class="thread"]', node).firstElementChild postDataFromLink: (link) -> if link.hostname is 'boards.4chan.org' path = link.pathname.split '/' diff --git a/src/General/lib/post.class b/src/General/lib/post.class index 54c8dcf5d..7f4c778e4 100755 --- a/src/General/lib/post.class +++ b/src/General/lib/post.class @@ -23,6 +23,7 @@ class Post @thread.OP = @ @thread.isSticky = !!$ '.stickyIcon', info @thread.isClosed = !!$ '.closedIcon', info + root.parentElement.dataset.fullID = @fullID @info = {} if subject = $ '.subject', info From 08241a213faddbf11961353eb960f2943ffba340 Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Tue, 11 Mar 2014 12:48:23 -0700 Subject: [PATCH 2/4] Reflow Navigate.node, allow navigation from backlinks and their hashes --- builds/4chan-X.user.js | 43 +++++++++++++++++++---------- builds/crx/script.js | 43 +++++++++++++++++++---------- src/General/Navigate.coffee | 33 +++++++++++++++------- src/Quotelinks/QuoteBacklink.coffee | 7 ++++- 4 files changed, 85 insertions(+), 41 deletions(-) diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index bba046fd7..f327a160d 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -5251,7 +5251,7 @@ return $.add(this.nodes.info, container); }, buildBacklink: function(quoted, quoter) { - var a, frag, text; + var a, frag, hash, text; frag = QuoteBacklink.frag.cloneNode(true); a = frag.lastElementChild; a.href = "/" + quoter.board + "/res/" + quoter.thread + "#p" + quoter; @@ -5269,7 +5269,14 @@ if (Conf['Quote Inlining']) { $.on(a, 'click', QuoteInline.toggle); if (Conf['Quote Hash Navigation']) { - QuoteInline.qiQuote(a, quoter.isHidden); + hash = QuoteInline.qiQuote(a, quoter.isHidden); + } + } + if (Conf['JSON Navigation']) { + if (hash) { + Navigate.singleQuoteLink(hash); + } else if (!Conf['Quote Inlining']) { + Navigate.singleQuoteLink(a); } } return frag; @@ -12598,22 +12605,28 @@ return $.on(replyLink, 'click', Navigate.navigate); }, post: function() { - var boardID, hashlink, postID, postlink, threadID, _i, _len, _ref, _ref1; - if (Conf['Quote Hash Navigation']) { - _ref = $$('.hashlink', this.nodes.comment); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - hashlink = _ref[_i]; - _ref1 = Get.postDataFromLink(hashlink), boardID = _ref1.boardID, threadID = _ref1.threadID, postID = _ref1.postID; - if (boardID !== g.BOARD.ID || (threadID !== g.THREADID)) { - $.on(hashlink, 'click', Navigate.navigate); - } - } + var linktype; + if (!(g.VIEW === 'thread' && this.thread.ID === g.THREADID)) { + $.on($('a[title="Highlight this post"]', this.nodes.info), 'click', Navigate.navigate); } - if (g.VIEW === 'thread' && this.thread.ID === g.THREADID) { + if (!(linktype = Conf['Quote Inlining'] && Conf['Quote Hash Navigation'] ? '.hashlink' : !Conf['Quote Inlining'] ? '.quotelink' : null)) { return; } - postlink = $('a[title="Highlight this post"]', this.nodes.info); - return $.on(postlink, 'click', Navigate.navigate); + return Navigate.quoteLink($$(linktype, this.nodes.comment)); + }, + quoteLink: function(links) { + var link, _i, _len; + for (_i = 0, _len = links.length; _i < _len; _i++) { + link = links[_i]; + Navigate.singleQuoteLink(link); + } + }, + singleQuoteLink: function(link) { + var boardID, threadID, _ref; + _ref = Get.postDataFromLink(link), boardID = _ref.boardID, threadID = _ref.threadID; + if (g.VIEW === 'index' || boardID !== g.BOARD.ID || threadID !== g.THREADID) { + return $.on(link, 'click', Navigate.navigate); + } }, clean: function() { g.threads.forEach(function(thread) { diff --git a/builds/crx/script.js b/builds/crx/script.js index bbf52aa44..ddd862b08 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -5303,7 +5303,7 @@ return $.add(this.nodes.info, container); }, buildBacklink: function(quoted, quoter) { - var a, frag, text; + var a, frag, hash, text; frag = QuoteBacklink.frag.cloneNode(true); a = frag.lastElementChild; a.href = "/" + quoter.board + "/res/" + quoter.thread + "#p" + quoter; @@ -5321,7 +5321,14 @@ if (Conf['Quote Inlining']) { $.on(a, 'click', QuoteInline.toggle); if (Conf['Quote Hash Navigation']) { - QuoteInline.qiQuote(a, quoter.isHidden); + hash = QuoteInline.qiQuote(a, quoter.isHidden); + } + } + if (Conf['JSON Navigation']) { + if (hash) { + Navigate.singleQuoteLink(hash); + } else if (!Conf['Quote Inlining']) { + Navigate.singleQuoteLink(a); } } return frag; @@ -12612,22 +12619,28 @@ return $.on(replyLink, 'click', Navigate.navigate); }, post: function() { - var boardID, hashlink, postID, postlink, threadID, _i, _len, _ref, _ref1; - if (Conf['Quote Hash Navigation']) { - _ref = $$('.hashlink', this.nodes.comment); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - hashlink = _ref[_i]; - _ref1 = Get.postDataFromLink(hashlink), boardID = _ref1.boardID, threadID = _ref1.threadID, postID = _ref1.postID; - if (boardID !== g.BOARD.ID || (threadID !== g.THREADID)) { - $.on(hashlink, 'click', Navigate.navigate); - } - } + var linktype; + if (!(g.VIEW === 'thread' && this.thread.ID === g.THREADID)) { + $.on($('a[title="Highlight this post"]', this.nodes.info), 'click', Navigate.navigate); } - if (g.VIEW === 'thread' && this.thread.ID === g.THREADID) { + if (!(linktype = Conf['Quote Inlining'] && Conf['Quote Hash Navigation'] ? '.hashlink' : !Conf['Quote Inlining'] ? '.quotelink' : null)) { return; } - postlink = $('a[title="Highlight this post"]', this.nodes.info); - return $.on(postlink, 'click', Navigate.navigate); + return Navigate.quoteLink($$(linktype, this.nodes.comment)); + }, + quoteLink: function(links) { + var link, _i, _len; + for (_i = 0, _len = links.length; _i < _len; _i++) { + link = links[_i]; + Navigate.singleQuoteLink(link); + } + }, + singleQuoteLink: function(link) { + var boardID, threadID, _ref; + _ref = Get.postDataFromLink(link), boardID = _ref.boardID, threadID = _ref.threadID; + if (g.VIEW === 'index' || boardID !== g.BOARD.ID || threadID !== g.THREADID) { + return $.on(link, 'click', Navigate.navigate); + } }, clean: function() { g.threads.forEach(function(thread) { diff --git a/src/General/Navigate.coffee b/src/General/Navigate.coffee index 410abf5e7..9f837d366 100644 --- a/src/General/Navigate.coffee +++ b/src/General/Navigate.coffee @@ -10,7 +10,7 @@ Navigate = $.add Index.navLinks, Navigate.el @title = -> return - + @el = $.el 'div', id: 'breadCrumb' @@ -28,16 +28,29 @@ Navigate = $.on replyLink, 'click', Navigate.navigate post: -> # Allows us to navigate via JSON from thread to thread by hashes and quote highlights. - if Conf['Quote Hash Navigation'] - for hashlink in $$ '.hashlink', @nodes.comment - {boardID, threadID, postID} = Get.postDataFromLink hashlink - if boardID isnt g.BOARD.ID or (threadID isnt g.THREADID) - $.on hashlink, 'click', Navigate.navigate - # We don't need to reload the thread inside the thread - return if g.VIEW is 'thread' and @thread.ID is g.THREADID - postlink = $ 'a[title="Highlight this post"]', @nodes.info - $.on postlink, 'click', Navigate.navigate + unless g.VIEW is 'thread' and @thread.ID is g.THREADID + $.on $('a[title="Highlight this post"]', @nodes.info), 'click', Navigate.navigate + + return unless (linktype = if Conf['Quote Inlining'] and Conf['Quote Hash Navigation'] + '.hashlink' + else if !Conf['Quote Inlining'] + '.quotelink' + else + null + ) + + Navigate.quoteLink $$ linktype, @nodes.comment + + quoteLink: (links) -> + for link in links + Navigate.singleQuoteLink link + return + + singleQuoteLink: (link) -> + {boardID, threadID} = Get.postDataFromLink link + if g.VIEW is 'index' or boardID isnt g.BOARD.ID or threadID isnt g.THREADID + $.on link, 'click', Navigate.navigate clean: -> # Garbage collection diff --git a/src/Quotelinks/QuoteBacklink.coffee b/src/Quotelinks/QuoteBacklink.coffee index 6ffa9cfba..bb9d66367 100755 --- a/src/Quotelinks/QuoteBacklink.coffee +++ b/src/Quotelinks/QuoteBacklink.coffee @@ -68,5 +68,10 @@ QuoteBacklink = if Conf['Quote Inlining'] $.on a, 'click', QuoteInline.toggle if Conf['Quote Hash Navigation'] - QuoteInline.qiQuote a, quoter.isHidden + hash = QuoteInline.qiQuote a, quoter.isHidden + if Conf['JSON Navigation'] + if hash + Navigate.singleQuoteLink hash + else unless Conf['Quote Inlining'] + Navigate.singleQuoteLink a frag From dec9775f806dc1d02aee9fa2548be31b4eda69ca Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Tue, 11 Mar 2014 13:43:23 -0700 Subject: [PATCH 3/4] Less Array::map, more manual loops. Map is slow. http://jsperf.com/arraymap --- builds/4chan-X.user.js | 104 ++++++++++++++++++++++++--------------- builds/crx/script.js | 104 ++++++++++++++++++++++++--------------- src/General/Index.coffee | 50 ++++++++++++------- 3 files changed, 157 insertions(+), 101 deletions(-) diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index f327a160d..0b74da538 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -3310,12 +3310,11 @@ return $.event('IndexRefresh'); }, buildHRs: function(threadRoots) { - var node, nodes, _i, _len; + var i, node, nodes; nodes = []; - for (_i = 0, _len = threadRoots.length; _i < _len; _i++) { - node = threadRoots[_i]; - nodes.push(node); - nodes.push($.el('hr')); + i = 0; + while (node = threadRoots[i++]) { + nodes.push(node, $.el('hr')); } return nodes; }, @@ -3360,7 +3359,7 @@ return Main.callbackNodes(Post, posts); }, buildCatalogViews: function() { - var catalogThreads, thread, _i, _len, _ref; + var catalogThreads, nodes, thread, _i, _j, _len, _len1, _ref, _ref1; catalogThreads = []; _ref = Index.sortedThreads; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -3370,9 +3369,13 @@ } } Main.callbackNodes(CatalogThread, catalogThreads); - return Index.sortedThreads.map(function(thread) { - return thread.catalogView.nodes.root; - }); + nodes = []; + _ref1 = Index.sortedThreads; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + thread = _ref1[_j]; + nodes.push(thread.catalogView.nodes.root); + } + return nodes; }, sizeCatalogViews: function(nodes) { var height, node, ratio, size, thumb, width, _i, _len, _ref; @@ -3390,13 +3393,16 @@ } }, sort: function() { - var sortedThreadIDs; - switch (Conf['Index Sort']) { - case 'bump': - sortedThreadIDs = Index.liveThreadIDs; - break; - case 'lastreply': - sortedThreadIDs = __slice.call(Index.liveThreadData).sort(function(a, b) { + var sortedThreadIDs, sortedThreads, threadID, _i, _len; + sortedThreads = []; + sortedThreadIDs = []; + ({ + 'bump': function() { + return sortedThreadIDs = Index.liveThreadIDs; + }, + 'lastreply': function() { + var data, liveData, _i, _len; + liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { var _ref, _ref1; if ('last_replies' in a) { _ref = a.last_replies, a = _ref[_ref.length - 1]; @@ -3405,32 +3411,43 @@ _ref1 = b.last_replies, b = _ref1[_ref1.length - 1]; } return b.no - a.no; - }).map(function(data) { - return data.no; }); - break; - case 'birth': - sortedThreadIDs = __slice.call(Index.liveThreadIDs).sort(function(a, b) { + for (_i = 0, _len = liveData.length; _i < _len; _i++) { + data = liveData[_i]; + sortedThreadIDs.push(data.no); + } + }, + 'birth': function() { + return sortedThreadIDs = __slice.call(Index.liveThreadIDs).sort(function(a, b) { return b - a; }); - break; - case 'replycount': - sortedThreadIDs = __slice.call(Index.liveThreadData).sort(function(a, b) { + }, + 'replycount': function() { + var data, liveData, _i, _len; + liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.replies - a.replies; - }).map(function(data) { - return data.no; }); - break; - case 'filecount': - sortedThreadIDs = __slice.call(Index.liveThreadData).sort(function(a, b) { + for (_i = 0, _len = liveData.length; _i < _len; _i++) { + data = liveData[_i]; + sortedThreadIDs.push(data.no); + } + }, + 'filecount': function() { + var data, liveData, _i, _len; + liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.images - a.images; - }).map(function(data) { - return data.no; }); + for (_i = 0, _len = liveData.length; _i < _len; _i++) { + data = liveData[_i]; + sortedThreadIDs.push(data.no); + } + } + })[Conf['Index Sort']](); + for (_i = 0, _len = sortedThreadIDs.length; _i < _len; _i++) { + threadID = sortedThreadIDs[_i]; + sortedThreads.push(g.BOARD.threads[threadID]); } - Index.sortedThreads = sortedThreadIDs.map(function(threadID) { - return g.BOARD.threads[threadID]; - }).filter(function(thread) { + Index.sortedThreads = sortedThreads.filter(function(thread) { return thread.isHidden === Index.showHiddenThreads; }); if (Index.isSearching) { @@ -3455,7 +3472,7 @@ } }, buildIndex: function(infinite) { - var nodes, pageNum, threads, threadsPerPage; + var nodes, pageNum, thread, threads, threadsPerPage, _i, _j, _len, _len1, _ref; switch (Conf['Index Mode']) { case 'paged': case 'infinite': @@ -3466,9 +3483,11 @@ } threadsPerPage = Index.getThreadsNumPerPage(); threads = Index.sortedThreads.slice(threadsPerPage * pageNum, threadsPerPage * (pageNum + 1)); - nodes = threads.map(function(thread) { - return thread.OP.nodes.root.parentNode; - }); + nodes = []; + for (_i = 0, _len = threads.length; _i < _len; _i++) { + thread = threads[_i]; + nodes.push(thread.OP.nodes.root.parentNode); + } Index.buildReplies(threads); nodes = Index.buildHRs(nodes); Index.buildPagelist(); @@ -3479,9 +3498,12 @@ Index.sizeCatalogViews(nodes); break; default: - nodes = Index.sortedThreads.map(function(thread) { - return thread.OP.nodes.root.parentNode; - }); + nodes = []; + _ref = Index.sortedThreads; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + thread = _ref[_j]; + nodes.push(thread.OP.nodes.root.parentNode); + } Index.buildReplies(Index.sortedThreads); nodes = Index.buildHRs(nodes); } diff --git a/builds/crx/script.js b/builds/crx/script.js index ddd862b08..9d7c2e7f0 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -3369,12 +3369,11 @@ return $.event('IndexRefresh'); }, buildHRs: function(threadRoots) { - var node, nodes, _i, _len; + var i, node, nodes; nodes = []; - for (_i = 0, _len = threadRoots.length; _i < _len; _i++) { - node = threadRoots[_i]; - nodes.push(node); - nodes.push($.el('hr')); + i = 0; + while (node = threadRoots[i++]) { + nodes.push(node, $.el('hr')); } return nodes; }, @@ -3419,7 +3418,7 @@ return Main.callbackNodes(Post, posts); }, buildCatalogViews: function() { - var catalogThreads, thread, _i, _len, _ref; + var catalogThreads, nodes, thread, _i, _j, _len, _len1, _ref, _ref1; catalogThreads = []; _ref = Index.sortedThreads; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -3429,9 +3428,13 @@ } } Main.callbackNodes(CatalogThread, catalogThreads); - return Index.sortedThreads.map(function(thread) { - return thread.catalogView.nodes.root; - }); + nodes = []; + _ref1 = Index.sortedThreads; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + thread = _ref1[_j]; + nodes.push(thread.catalogView.nodes.root); + } + return nodes; }, sizeCatalogViews: function(nodes) { var height, node, ratio, size, thumb, width, _i, _len, _ref; @@ -3449,13 +3452,16 @@ } }, sort: function() { - var sortedThreadIDs; - switch (Conf['Index Sort']) { - case 'bump': - sortedThreadIDs = Index.liveThreadIDs; - break; - case 'lastreply': - sortedThreadIDs = __slice.call(Index.liveThreadData).sort(function(a, b) { + var sortedThreadIDs, sortedThreads, threadID, _i, _len; + sortedThreads = []; + sortedThreadIDs = []; + ({ + 'bump': function() { + return sortedThreadIDs = Index.liveThreadIDs; + }, + 'lastreply': function() { + var data, liveData, _i, _len; + liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { var _ref, _ref1; if ('last_replies' in a) { _ref = a.last_replies, a = _ref[_ref.length - 1]; @@ -3464,32 +3470,43 @@ _ref1 = b.last_replies, b = _ref1[_ref1.length - 1]; } return b.no - a.no; - }).map(function(data) { - return data.no; }); - break; - case 'birth': - sortedThreadIDs = __slice.call(Index.liveThreadIDs).sort(function(a, b) { + for (_i = 0, _len = liveData.length; _i < _len; _i++) { + data = liveData[_i]; + sortedThreadIDs.push(data.no); + } + }, + 'birth': function() { + return sortedThreadIDs = __slice.call(Index.liveThreadIDs).sort(function(a, b) { return b - a; }); - break; - case 'replycount': - sortedThreadIDs = __slice.call(Index.liveThreadData).sort(function(a, b) { + }, + 'replycount': function() { + var data, liveData, _i, _len; + liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.replies - a.replies; - }).map(function(data) { - return data.no; }); - break; - case 'filecount': - sortedThreadIDs = __slice.call(Index.liveThreadData).sort(function(a, b) { + for (_i = 0, _len = liveData.length; _i < _len; _i++) { + data = liveData[_i]; + sortedThreadIDs.push(data.no); + } + }, + 'filecount': function() { + var data, liveData, _i, _len; + liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.images - a.images; - }).map(function(data) { - return data.no; }); + for (_i = 0, _len = liveData.length; _i < _len; _i++) { + data = liveData[_i]; + sortedThreadIDs.push(data.no); + } + } + })[Conf['Index Sort']](); + for (_i = 0, _len = sortedThreadIDs.length; _i < _len; _i++) { + threadID = sortedThreadIDs[_i]; + sortedThreads.push(g.BOARD.threads[threadID]); } - Index.sortedThreads = sortedThreadIDs.map(function(threadID) { - return g.BOARD.threads[threadID]; - }).filter(function(thread) { + Index.sortedThreads = sortedThreads.filter(function(thread) { return thread.isHidden === Index.showHiddenThreads; }); if (Index.isSearching) { @@ -3514,7 +3531,7 @@ } }, buildIndex: function(infinite) { - var nodes, pageNum, threads, threadsPerPage; + var nodes, pageNum, thread, threads, threadsPerPage, _i, _j, _len, _len1, _ref; switch (Conf['Index Mode']) { case 'paged': case 'infinite': @@ -3525,9 +3542,11 @@ } threadsPerPage = Index.getThreadsNumPerPage(); threads = Index.sortedThreads.slice(threadsPerPage * pageNum, threadsPerPage * (pageNum + 1)); - nodes = threads.map(function(thread) { - return thread.OP.nodes.root.parentNode; - }); + nodes = []; + for (_i = 0, _len = threads.length; _i < _len; _i++) { + thread = threads[_i]; + nodes.push(thread.OP.nodes.root.parentNode); + } Index.buildReplies(threads); nodes = Index.buildHRs(nodes); Index.buildPagelist(); @@ -3538,9 +3557,12 @@ Index.sizeCatalogViews(nodes); break; default: - nodes = Index.sortedThreads.map(function(thread) { - return thread.OP.nodes.root.parentNode; - }); + nodes = []; + _ref = Index.sortedThreads; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + thread = _ref[_j]; + nodes.push(thread.OP.nodes.root.parentNode); + } Index.buildReplies(Index.sortedThreads); nodes = Index.buildHRs(nodes); } diff --git a/src/General/Index.coffee b/src/General/Index.coffee index 657f08f03..6a4139e3a 100644 --- a/src/General/Index.coffee +++ b/src/General/Index.coffee @@ -616,9 +616,9 @@ Index = buildHRs: (threadRoots) -> nodes = [] - for node in threadRoots - nodes.push node - nodes.push $.el 'hr' + i = 0 + while node = threadRoots[i++] + nodes.push node, $.el 'hr' nodes buildReplies: (threads) -> @@ -651,7 +651,9 @@ Index = for thread in Index.sortedThreads when !thread.catalogView catalogThreads.push new CatalogThread Build.catalogThread(thread), thread Main.callbackNodes CatalogThread, catalogThreads - Index.sortedThreads.map (thread) -> thread.catalogView.nodes.root + nodes = [] + nodes.push thread.catalogView.nodes.root for thread in Index.sortedThreads + return nodes sizeCatalogViews: (nodes) -> # XXX When browsers support CSS3 attr(), use it instead. @@ -666,24 +668,32 @@ Index = return sort: -> - switch Conf['Index Sort'] - when 'bump' + sortedThreads = [] + sortedThreadIDs = [] + + { + 'bump': -> sortedThreadIDs = Index.liveThreadIDs - when 'lastreply' - sortedThreadIDs = [Index.liveThreadData...].sort (a, b) -> + 'lastreply': -> + liveData = [Index.liveThreadData...].sort (a, b) -> [..., a] = a.last_replies if 'last_replies' of a [..., b] = b.last_replies if 'last_replies' of b b.no - a.no - .map (data) -> data.no - when 'birth' + sortedThreadIDs.push data.no for data in liveData + return + 'birth': -> sortedThreadIDs = [Index.liveThreadIDs...].sort (a, b) -> b - a - when 'replycount' - sortedThreadIDs = [Index.liveThreadData...].sort((a, b) -> b.replies - a.replies).map (data) -> data.no - when 'filecount' - sortedThreadIDs = [Index.liveThreadData...].sort((a, b) -> b.images - a.images).map (data) -> data.no - Index.sortedThreads = sortedThreadIDs - .map (threadID) -> g.BOARD.threads[threadID] - .filter (thread) -> thread.isHidden is Index.showHiddenThreads + 'replycount': -> + liveData = [Index.liveThreadData...].sort((a, b) -> b.replies - a.replies) + sortedThreadIDs.push data.no for data in liveData + return + 'filecount': -> + liveData = [Index.liveThreadData...].sort((a, b) -> b.images - a.images) + sortedThreadIDs.push data.no for data in liveData + return + }[Conf['Index Sort']]() + sortedThreads.push g.BOARD.threads[threadID] for threadID in sortedThreadIDs + Index.sortedThreads = sortedThreads.filter (thread) -> thread.isHidden is Index.showHiddenThreads if Index.isSearching Index.sortedThreads = Index.querySearch(Index.searchInput.value) or Index.sortedThreads # Sticky threads @@ -707,7 +717,8 @@ Index = return threadsPerPage = Index.getThreadsNumPerPage() threads = Index.sortedThreads[threadsPerPage * pageNum ... threadsPerPage * (pageNum + 1)] - nodes = threads.map (thread) -> thread.OP.nodes.root.parentNode + nodes = [] + nodes.push thread.OP.nodes.root.parentNode for thread in threads Index.buildReplies threads nodes = Index.buildHRs nodes Index.buildPagelist() @@ -716,7 +727,8 @@ Index = nodes = Index.buildCatalogViews() Index.sizeCatalogViews nodes else - nodes = Index.sortedThreads.map (thread) -> thread.OP.nodes.root.parentNode + nodes = [] + nodes.push thread.OP.nodes.root.parentNode for thread in Index.sortedThreads Index.buildReplies Index.sortedThreads nodes = Index.buildHRs nodes $.rmAll Index.root unless infinite From 5cbe5753e8e4510dbe70408bd400c24f5ed3be2e Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Tue, 11 Mar 2014 14:14:24 -0700 Subject: [PATCH 4/4] Use while loops for consistency and also get rid of Array::filter --- builds/4chan-X.user.js | 96 +++++++++++++++++++++++----------------- builds/crx/script.js | 96 +++++++++++++++++++++++----------------- src/General/Index.coffee | 55 ++++++++++++++++------- 3 files changed, 150 insertions(+), 97 deletions(-) diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 0b74da538..0e7fc6af5 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -2832,10 +2832,14 @@ return $.event('change', null, Index.selectMode); }, cycleSortType: function() { - var i, type, types, _i, _len; - types = __slice.call(Index.selectSort.options).filter(function(option) { - return !option.disabled; - }); + var i, option, type, types, _i, _len; + types = []; + i = 0; + while (option = Index.selectSort.options[i++]) { + if (!option.disabled) { + types.push(option); + } + } for (i = _i = 0, _len = types.length; _i < _len; i = ++_i) { type = types[i]; if (type.selected) { @@ -2846,13 +2850,15 @@ return $.event('change', null, Index.selectSort); }, catalogSwitch: function() { - var hash; - if (!Conf['JSON Navigation']) { - return; - } - $.set('Index Mode', 'catalog'); - hash = window.location.hash; - return window.location = './' + hash; + return $.get('JSON Navigation', true, function(items) { + var hash; + if (!items['JSON Navigation']) { + return; + } + $.set('Index Mode', 'catalog'); + hash = window.location.hash; + return window.location = './' + hash; + }); }, searchTest: function() { var hash, match; @@ -2942,20 +2948,18 @@ return Index.buildIndex(); }, target: function() { - var thread, threadID, thumb, _ref; - _ref = g.BOARD.threads; - for (threadID in _ref) { - thread = _ref[threadID]; + return g.BOARD.threads.forEach(function(thread) { + var thumb; if (!thread.catalogView) { - continue; + return; } thumb = thread.catalogView.nodes.thumb; if (Conf['Open threads in a new tab']) { - thumb.target = '_blank'; + return thumb.target = '_blank'; } else { - thumb.removeAttribute('target'); + return thumb.removeAttribute('target'); } - } + }); }, replies: function() { Index.buildThreads(); @@ -3359,7 +3363,7 @@ return Main.callbackNodes(Post, posts); }, buildCatalogViews: function() { - var catalogThreads, nodes, thread, _i, _j, _len, _len1, _ref, _ref1; + var catalogThreads, i, nodes, thread, _i, _len, _ref; catalogThreads = []; _ref = Index.sortedThreads; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -3370,9 +3374,8 @@ } Main.callbackNodes(CatalogThread, catalogThreads); nodes = []; - _ref1 = Index.sortedThreads; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - thread = _ref1[_j]; + i = 0; + while (thread = Index.sortedThreads[i++]) { nodes.push(thread.catalogView.nodes.root); } return nodes; @@ -3393,7 +3396,7 @@ } }, sort: function() { - var sortedThreadIDs, sortedThreads, threadID, _i, _len; + var i, sortedThreadIDs, sortedThreads, thread, threadID; sortedThreads = []; sortedThreadIDs = []; ({ @@ -3401,7 +3404,7 @@ return sortedThreadIDs = Index.liveThreadIDs; }, 'lastreply': function() { - var data, liveData, _i, _len; + var data, i, liveData; liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { var _ref, _ref1; if ('last_replies' in a) { @@ -3412,8 +3415,8 @@ } return b.no - a.no; }); - for (_i = 0, _len = liveData.length; _i < _len; _i++) { - data = liveData[_i]; + i = 0; + while (data = liveData[i++]) { sortedThreadIDs.push(data.no); } }, @@ -3423,33 +3426,37 @@ }); }, 'replycount': function() { - var data, liveData, _i, _len; + var data, i, liveData; liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.replies - a.replies; }); - for (_i = 0, _len = liveData.length; _i < _len; _i++) { - data = liveData[_i]; + i = 0; + while (data = liveData[i++]) { sortedThreadIDs.push(data.no); } }, 'filecount': function() { - var data, liveData, _i, _len; + var data, i, liveData; liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.images - a.images; }); - for (_i = 0, _len = liveData.length; _i < _len; _i++) { - data = liveData[_i]; + i = 0; + while (data = liveData[i++]) { sortedThreadIDs.push(data.no); } } })[Conf['Index Sort']](); - for (_i = 0, _len = sortedThreadIDs.length; _i < _len; _i++) { - threadID = sortedThreadIDs[_i]; + i = 0; + while (threadID = sortedThreadIDs[i++]) { sortedThreads.push(g.BOARD.threads[threadID]); } - Index.sortedThreads = sortedThreads.filter(function(thread) { - return thread.isHidden === Index.showHiddenThreads; - }); + Index.sortedThreads = []; + i = 0; + while (thread = sortedThreads[i++]) { + if (thread.isHidden === Index.showHiddenThreads) { + Index.sortedThreads.push(thread); + } + } if (Index.isSearching) { Index.sortedThreads = Index.querySearch(Index.searchInput.value) || Index.sortedThreads; } @@ -3553,9 +3560,16 @@ return Index.search(keywords); }, search: function(keywords) { - return Index.sortedThreads.filter(function(thread) { - return Index.searchMatch(thread, keywords); - }); + var filtered, i, sortedThreads, thread; + filtered = []; + i = 0; + sortedThreads = Index.sortedThreads; + while (thread = sortedThreads[i++]) { + if (Index.searchMatch(thread, keywords)) { + filtered.push(thread); + } + } + return Index.sortedThreads = filtered; }, searchMatch: function(thread, keywords) { var file, info, key, keyword, text, _i, _j, _len, _len1, _ref, _ref1; diff --git a/builds/crx/script.js b/builds/crx/script.js index 9d7c2e7f0..fa91a6218 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -2891,10 +2891,14 @@ return $.event('change', null, Index.selectMode); }, cycleSortType: function() { - var i, type, types, _i, _len; - types = __slice.call(Index.selectSort.options).filter(function(option) { - return !option.disabled; - }); + var i, option, type, types, _i, _len; + types = []; + i = 0; + while (option = Index.selectSort.options[i++]) { + if (!option.disabled) { + types.push(option); + } + } for (i = _i = 0, _len = types.length; _i < _len; i = ++_i) { type = types[i]; if (type.selected) { @@ -2905,13 +2909,15 @@ return $.event('change', null, Index.selectSort); }, catalogSwitch: function() { - var hash; - if (!Conf['JSON Navigation']) { - return; - } - $.set('Index Mode', 'catalog'); - hash = window.location.hash; - return window.location = './' + hash; + return $.get('JSON Navigation', true, function(items) { + var hash; + if (!items['JSON Navigation']) { + return; + } + $.set('Index Mode', 'catalog'); + hash = window.location.hash; + return window.location = './' + hash; + }); }, searchTest: function() { var hash, match; @@ -3001,20 +3007,18 @@ return Index.buildIndex(); }, target: function() { - var thread, threadID, thumb, _ref; - _ref = g.BOARD.threads; - for (threadID in _ref) { - thread = _ref[threadID]; + return g.BOARD.threads.forEach(function(thread) { + var thumb; if (!thread.catalogView) { - continue; + return; } thumb = thread.catalogView.nodes.thumb; if (Conf['Open threads in a new tab']) { - thumb.target = '_blank'; + return thumb.target = '_blank'; } else { - thumb.removeAttribute('target'); + return thumb.removeAttribute('target'); } - } + }); }, replies: function() { Index.buildThreads(); @@ -3418,7 +3422,7 @@ return Main.callbackNodes(Post, posts); }, buildCatalogViews: function() { - var catalogThreads, nodes, thread, _i, _j, _len, _len1, _ref, _ref1; + var catalogThreads, i, nodes, thread, _i, _len, _ref; catalogThreads = []; _ref = Index.sortedThreads; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -3429,9 +3433,8 @@ } Main.callbackNodes(CatalogThread, catalogThreads); nodes = []; - _ref1 = Index.sortedThreads; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - thread = _ref1[_j]; + i = 0; + while (thread = Index.sortedThreads[i++]) { nodes.push(thread.catalogView.nodes.root); } return nodes; @@ -3452,7 +3455,7 @@ } }, sort: function() { - var sortedThreadIDs, sortedThreads, threadID, _i, _len; + var i, sortedThreadIDs, sortedThreads, thread, threadID; sortedThreads = []; sortedThreadIDs = []; ({ @@ -3460,7 +3463,7 @@ return sortedThreadIDs = Index.liveThreadIDs; }, 'lastreply': function() { - var data, liveData, _i, _len; + var data, i, liveData; liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { var _ref, _ref1; if ('last_replies' in a) { @@ -3471,8 +3474,8 @@ } return b.no - a.no; }); - for (_i = 0, _len = liveData.length; _i < _len; _i++) { - data = liveData[_i]; + i = 0; + while (data = liveData[i++]) { sortedThreadIDs.push(data.no); } }, @@ -3482,33 +3485,37 @@ }); }, 'replycount': function() { - var data, liveData, _i, _len; + var data, i, liveData; liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.replies - a.replies; }); - for (_i = 0, _len = liveData.length; _i < _len; _i++) { - data = liveData[_i]; + i = 0; + while (data = liveData[i++]) { sortedThreadIDs.push(data.no); } }, 'filecount': function() { - var data, liveData, _i, _len; + var data, i, liveData; liveData = __slice.call(Index.liveThreadData).sort(function(a, b) { return b.images - a.images; }); - for (_i = 0, _len = liveData.length; _i < _len; _i++) { - data = liveData[_i]; + i = 0; + while (data = liveData[i++]) { sortedThreadIDs.push(data.no); } } })[Conf['Index Sort']](); - for (_i = 0, _len = sortedThreadIDs.length; _i < _len; _i++) { - threadID = sortedThreadIDs[_i]; + i = 0; + while (threadID = sortedThreadIDs[i++]) { sortedThreads.push(g.BOARD.threads[threadID]); } - Index.sortedThreads = sortedThreads.filter(function(thread) { - return thread.isHidden === Index.showHiddenThreads; - }); + Index.sortedThreads = []; + i = 0; + while (thread = sortedThreads[i++]) { + if (thread.isHidden === Index.showHiddenThreads) { + Index.sortedThreads.push(thread); + } + } if (Index.isSearching) { Index.sortedThreads = Index.querySearch(Index.searchInput.value) || Index.sortedThreads; } @@ -3612,9 +3619,16 @@ return Index.search(keywords); }, search: function(keywords) { - return Index.sortedThreads.filter(function(thread) { - return Index.searchMatch(thread, keywords); - }); + var filtered, i, sortedThreads, thread; + filtered = []; + i = 0; + sortedThreads = Index.sortedThreads; + while (thread = sortedThreads[i++]) { + if (Index.searchMatch(thread, keywords)) { + filtered.push(thread); + } + } + return Index.sortedThreads = filtered; }, searchMatch: function(thread, keywords) { var file, info, key, keyword, text, _i, _j, _len, _len1, _ref, _ref1; diff --git a/src/General/Index.coffee b/src/General/Index.coffee index 6a4139e3a..7db9ae027 100644 --- a/src/General/Index.coffee +++ b/src/General/Index.coffee @@ -252,17 +252,21 @@ Index = $.event 'change', null, Index.selectMode cycleSortType: -> - types = [Index.selectSort.options...].filter (option) -> !option.disabled + types = [] + i = 0 + while option = Index.selectSort.options[i++] + types.push option if !option.disabled for type, i in types break if type.selected types[(i + 1) % types.length].selected = true $.event 'change', null, Index.selectSort catalogSwitch: -> - return if !Conf['JSON Navigation'] - $.set 'Index Mode', 'catalog' - {hash} = window.location - window.location = './' + hash + $.get 'JSON Navigation', true, (items) -> + return if !items['JSON Navigation'] + $.set 'Index Mode', 'catalog' + {hash} = window.location + window.location = './' + hash searchTest: -> return unless hash = window.location.hash @@ -331,13 +335,13 @@ Index = Index.buildIndex() target: -> - for threadID, thread of g.BOARD.threads when thread.catalogView + g.BOARD.threads.forEach (thread) -> + return if !thread.catalogView {thumb} = thread.catalogView.nodes if Conf['Open threads in a new tab'] thumb.target = '_blank' else thumb.removeAttribute 'target' - return replies: -> Index.buildThreads() @@ -652,7 +656,9 @@ Index = catalogThreads.push new CatalogThread Build.catalogThread(thread), thread Main.callbackNodes CatalogThread, catalogThreads nodes = [] - nodes.push thread.catalogView.nodes.root for thread in Index.sortedThreads + i = 0 + while thread = Index.sortedThreads[i++] + nodes.push thread.catalogView.nodes.root return nodes sizeCatalogViews: (nodes) -> @@ -679,21 +685,35 @@ Index = [..., a] = a.last_replies if 'last_replies' of a [..., b] = b.last_replies if 'last_replies' of b b.no - a.no - sortedThreadIDs.push data.no for data in liveData + i = 0 + while data = liveData[i++] + sortedThreadIDs.push data.no return 'birth': -> sortedThreadIDs = [Index.liveThreadIDs...].sort (a, b) -> b - a 'replycount': -> liveData = [Index.liveThreadData...].sort((a, b) -> b.replies - a.replies) - sortedThreadIDs.push data.no for data in liveData + i = 0 + while data = liveData[i++] + sortedThreadIDs.push data.no return 'filecount': -> liveData = [Index.liveThreadData...].sort((a, b) -> b.images - a.images) - sortedThreadIDs.push data.no for data in liveData + i = 0 + while data = liveData[i++] + sortedThreadIDs.push data.no return }[Conf['Index Sort']]() - sortedThreads.push g.BOARD.threads[threadID] for threadID in sortedThreadIDs - Index.sortedThreads = sortedThreads.filter (thread) -> thread.isHidden is Index.showHiddenThreads + + i = 0 + while threadID = sortedThreadIDs[i++] + sortedThreads.push g.BOARD.threads[threadID] + + Index.sortedThreads = [] + i = 0 + while thread = sortedThreads[i++] + Index.sortedThreads.push thread if thread.isHidden is Index.showHiddenThreads + if Index.isSearching Index.sortedThreads = Index.querySearch(Index.searchInput.value) or Index.sortedThreads # Sticky threads @@ -773,8 +793,13 @@ Index = Index.search keywords search: (keywords) -> - Index.sortedThreads.filter (thread) -> - Index.searchMatch thread, keywords + filtered = [] + i = 0 + {sortedThreads} = Index + while thread = sortedThreads[i++] + filtered.push thread if Index.searchMatch thread, keywords + Index.sortedThreads = filtered + searchMatch: (thread, keywords) -> {info, file} = thread.OP