diff --git a/4chan_x.user.js b/4chan_x.user.js index 676813cf5..3e0a0d565 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan x -// @version 2.24.3 +// @version 2.24.5 // @namespace aeosynth // @description Adds various features. // @copyright 2009-2011 James Campos @@ -18,7 +18,7 @@ * Copyright (c) 2009-2011 James Campos * Copyright (c) 2012 Nicolas Stepien * http://mayhemydg.github.com/4chan-x/ - * 4chan X 2.24.3 + * 4chan X 2.24.5 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -49,6 +49,9 @@ * * CONTRIBUTORS * + * seaweed - bottom padding for image hover + * e000 - cooldown sanity check + * ahokadesuka - scroll back when unexpanding images * Shou- - pentadactyl fixes * ferongr - new favicons * xat- - new favicons @@ -200,7 +203,7 @@ NAMESPACE = '4chan_x.'; - VERSION = '2.24.3'; + VERSION = '2.24.5'; SECOND = 1000; @@ -309,7 +312,7 @@ $.extend($, { ready: function(fc) { var cb; - if (/interactive|complete/.test(d.readyState)) return fc(); + if (/interactive|complete/.test(d.readyState)) return setTimeout(fc); cb = function() { $.off(d, 'DOMContentLoaded', cb); return fc(); @@ -849,7 +852,7 @@ name = $('.commentpostername', reply).textContent; trip = ((_ref = $('.postertrip', reply)) != null ? _ref.textContent : void 0) || ''; a = $.el('a', { - textContent: "[ + ] " + name + " " + trip, + innerHTML: "[ + ] " + name + " " + trip, href: 'javascript:;' }); $.on(a, 'click', replyHiding.cb.show); @@ -943,13 +946,15 @@ keybinds.img(thread); break; case conf.nextThread: - nav.next(); + if (g.REPLY) return; + nav.scroll(+1); break; case conf.openThreadTab: keybinds.open(thread, true); break; case conf.previousThread: - nav.prev(); + if (g.REPLY) return; + nav.scroll(-1); break; case conf.update: updater.update(); @@ -1156,10 +1161,18 @@ return $.add(d.body, span); }, prev: function() { - return nav.scroll(-1); + if (g.REPLY) { + return window.scrollTo(0, 0); + } else { + return nav.scroll(-1); + } }, next: function() { - return nav.scroll(+1); + if (g.REPLY) { + return window.scrollTo(0, d.body.scrollHeight); + } else { + return nav.scroll(+1); + } }, threads: [], getThread: function(full) { @@ -1178,37 +1191,13 @@ return null; }, scroll: function(delta) { - var i, rect, thread, top, _ref; - if (g.REPLY) { - if (delta === -1) { - window.scrollTo(0, 0); - } else { - window.scrollTo(0, d.body.scrollHeight); - } - return; - } + var i, rect, thread, top, _ref, _ref2; _ref = nav.getThread(true), thread = _ref[0], i = _ref[1], rect = _ref[2]; top = rect.top; if (!((delta === -1 && Math.ceil(top) < 0) || (delta === +1 && top > 1))) { i += delta; } - if (i === -1) { - if (g.PAGENUM === 0) { - window.scrollTo(0, 0); - } else { - window.location = "" + (g.PAGENUM - 1) + "#0"; - } - return; - } - if (delta === +1) { - if (i === nav.threads.length || (innerHeight + pageYOffset === d.body.scrollHeight)) { - if ($('table.pages input[value="Next"]')) { - window.location = "" + (g.PAGENUM + 1) + "#0"; - return; - } - } - } - top = nav.threads[i].getBoundingClientRect().top; + top = (_ref2 = nav.threads[i]) != null ? _ref2.getBoundingClientRect().top : void 0; return window.scrollBy(0, top); } }; @@ -1454,12 +1443,12 @@ if (g.REPLY) return $('.postarea form').action += '?cooldown'; }, start: function() { - var submit, _i, _len, _ref; + var submit, _i, _len, _ref, _ref2; cooldown.duration = Math.ceil(($.get(g.BOARD + '/cooldown', 0) - Date.now()) / 1000); - if (!(cooldown.duration > 0)) return; - _ref = $$('#com_submit'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - submit = _ref[_i]; + if (!((60 >= (_ref = cooldown.duration) && _ref > 0))) return; + _ref2 = $$('#com_submit'); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + submit = _ref2[_i]; submit.value = cooldown.duration; submit.disabled = true; } @@ -1901,7 +1890,7 @@ name = $('.postername', thread).textContent; trip = ((_ref = $('.postername + .postertrip', thread)) != null ? _ref.textContent : void 0) || ''; a = $.el('a', { - textContent: "[ + ] " + name + trip + " (" + text + ")", + innerHTML: "[ + ] " + name + trip + " (" + text + ")", href: 'javascript:;' }); $.on(a, 'click', threadHiding.cb.show); @@ -2988,9 +2977,12 @@ } }, toggle: function(a) { - var thumb; + var rect, thumb; thumb = a.firstChild; if (thumb.hidden) { + rect = a.parentNode.getBoundingClientRect(); + if (rect.top < 0) d.body.scrollTop += rect.top; + if (rect.left < 0) d.body.scrollLeft += rect.left; return imgExpand.contract(thumb); } else { return imgExpand.expand(thumb); @@ -3002,9 +2994,10 @@ }, expand: function(thumb, url) { var a, filesize, img, max; + if (thumb.hidden) return; a = thumb.parentNode; img = $.el('img', { - src: url ? url : a.href + src: url || a.href }); if (engine === 'gecko' && a.parentNode.className !== 'op') { filesize = $.x('preceding-sibling::span[@class="filesize"]', a).textContent; @@ -3016,28 +3009,29 @@ return $.add(a, img); }, error: function() { - var req, src, thumb, url; + var href, req, src, thumb, url; + href = this.parentNode.href; thumb = this.previousSibling; imgExpand.contract(thumb); - src = this.src.split('/'); - if (url = redirect.image(src[3], src[5])) { - return imgExpand.expand(thumb, url); - } else if (engine === 'webkit') { + src = href.split('/'); + if (this.src.split('/')[2] === 'images.4chan.org' && (url = redirect.image(src[3], src[5]))) { + setTimeout(imgExpand.expand, 10000, thumb, url); + return; + } + url = href + '?' + Date.now(); + if (engine === 'webkit') { return req = $.ajax(this.src, (function() { if (this.status !== 404) { - return setTimeout(imgExpand.retry, 10000, thumb); + return setTimeout(imgExpand.expand, 10000, thumb, url); } }), { type: 'head', event: 'onreadystatechange' }); } else if (!g.dead) { - return setTimeout(imgExpand.retry, 10000, thumb); + return setTimeout(imgExpand.expand, 10000, thumb, url); } }, - retry: function(thumb) { - if (!thumb.hidden) return imgExpand.expand(thumb); - }, dialog: function() { var controls, form, imageType, select; controls = $.el('div', { @@ -3268,6 +3262,7 @@ #ihover {\ max-height: 100%;\ max-width: 75%;\ + padding-bottom: 18px;\ }\ \ #navlinks {\ diff --git a/Cakefile b/Cakefile index b95e2b2c5..140d5d3cb 100644 --- a/Cakefile +++ b/Cakefile @@ -2,7 +2,7 @@ {exec} = require 'child_process' fs = require 'fs' -VERSION = '2.24.3' +VERSION = '2.24.5' HEADER = """ // ==UserScript== @@ -56,6 +56,9 @@ HEADER = """ * * CONTRIBUTORS * + * seaweed - bottom padding for image hover + * e000 - cooldown sanity check + * ahokadesuka - scroll back when unexpanding images * Shou- - pentadactyl fixes * ferongr - new favicons * xat- - new favicons diff --git a/changelog b/changelog index 4af786053..83fb8f7e9 100644 --- a/changelog +++ b/changelog @@ -1,5 +1,22 @@ master +2.24.5 +- Mayhem + Index Navigation and the See next/previous thread keybinds will not cycle through board pages anymore. + Fix archive redirection in Opera. + Opera support will now be temporarily on hold. + see https://github.com/MayhemYDG/4chan-x/issues/136 + +2.24.4 +- ahokadesuka + Scroll back up when unexpanding images. +- e000 + Prevent absurd cooldown durations. +- Mayhem + Better image expanding reload, should fool CloudFlare's cache. +- seaweed + Prevent the hover image to be partially masked by the url preview/status bar. + 2.24.3 - Mayhem Set image limit in Thread Stats to 252 for /a/ and /v/, default to 152. diff --git a/latest.js b/latest.js index 219917673..150273f8c 100644 --- a/latest.js +++ b/latest.js @@ -1 +1 @@ -postMessage({version:'2.24.3'},'*'); +postMessage({version:'2.24.5'},'*'); diff --git a/script.coffee b/script.coffee index 9f728add5..54094885e 100644 --- a/script.coffee +++ b/script.coffee @@ -121,7 +121,7 @@ conf = {} ) null, config NAMESPACE = '4chan_x.' -VERSION = '2.24.3' +VERSION = '2.24.5' SECOND = 1000 MINUTE = 60*SECOND HOUR = 60*MINUTE @@ -223,7 +223,9 @@ $.extend = (object, properties) -> $.extend $, ready: (fc) -> if /interactive|complete/.test d.readyState - return fc() + # Execute the functions in parallel. + # If one fails, do not stop the others. + return setTimeout fc cb = -> $.off d, 'DOMContentLoaded', cb fc() @@ -619,7 +621,7 @@ replyHiding = name = $('.commentpostername', reply).textContent trip = $('.postertrip', reply)?.textContent or '' a = $.el 'a', - textContent: "[ + ] #{name} #{trip}" + innerHTML: "[ + ] #{name} #{trip}" href: 'javascript:;' $.on a, 'click', replyHiding.cb.show @@ -691,11 +693,13 @@ keybinds = when conf.expandImages keybinds.img thread when conf.nextThread - nav.next() + return if g.REPLY + nav.scroll +1 when conf.openThreadTab keybinds.open thread, true when conf.previousThread - nav.prev() + return if g.REPLY + nav.scroll -1 when conf.update updater.update() when conf.watch @@ -827,10 +831,16 @@ nav = $.add d.body, span prev: -> - nav.scroll -1 + if g.REPLY + window.scrollTo 0, 0 + else + nav.scroll -1 next: -> - nav.scroll +1 + if g.REPLY + window.scrollTo 0, d.body.scrollHeight + else + nav.scroll +1 threads: [] @@ -846,13 +856,6 @@ nav = return null scroll: (delta) -> - if g.REPLY - if delta is -1 - window.scrollTo 0,0 - else - window.scrollTo 0, d.body.scrollHeight - return - [thread, i, rect] = nav.getThread true {top} = rect @@ -862,22 +865,7 @@ nav = unless (delta is -1 and Math.ceil(top) < 0) or (delta is +1 and top > 1) i += delta - if i is -1 - if g.PAGENUM is 0 - window.scrollTo 0, 0 - else - window.location = "#{g.PAGENUM - 1}#0" - return - if delta is +1 - # if we're at the last thread, or we're at the bottom of the page. - # kind of hackish, what we really need to do is make nav.getThread smarter. - if i is nav.threads.length or (innerHeight + pageYOffset == d.body.scrollHeight) - if $ 'table.pages input[value="Next"]' - window.location = "#{g.PAGENUM + 1}#0" - return - #TODO sfx - - {top} = nav.threads[i].getBoundingClientRect() + {top} = nav.threads[i]?.getBoundingClientRect() window.scrollBy 0, top options = @@ -1095,7 +1083,7 @@ cooldown = start: -> cooldown.duration = Math.ceil ($.get(g.BOARD+'/cooldown', 0) - Date.now()) / 1000 - return unless cooldown.duration > 0 + return unless 60 >= cooldown.duration > 0 for submit in $$ '#com_submit' submit.value = cooldown.duration submit.disabled = true @@ -1518,7 +1506,7 @@ threadHiding = trip = $('.postername + .postertrip', thread)?.textContent or '' a = $.el 'a', - textContent: "[ + ] #{name}#{trip} (#{text})" + innerHTML: "[ + ] #{name}#{trip} (#{text})" href: 'javascript:;' $.on a, 'click', threadHiding.cb.show @@ -2318,6 +2306,9 @@ imgExpand = toggle: (a) -> thumb = a.firstChild if thumb.hidden + rect = a.parentNode.getBoundingClientRect() + d.body.scrollTop += rect.top if rect.top < 0 + d.body.scrollLeft += rect.left if rect.left < 0 imgExpand.contract thumb else imgExpand.expand thumb @@ -2327,9 +2318,10 @@ imgExpand = $.rm thumb.nextSibling expand: (thumb, url) -> + return if thumb.hidden a = thumb.parentNode img = $.el 'img', - src: if url then url else a.href + src: url or a.href if engine is 'gecko' and a.parentNode.className isnt 'op' filesize = $.x('preceding-sibling::span[@class="filesize"]', a).textContent max = filesize.match /(\d+)x/ @@ -2339,22 +2331,23 @@ imgExpand = $.add a, img error: -> + href = @parentNode.href thumb = @previousSibling imgExpand.contract thumb - src = @src.split '/' - if url = redirect.image src[3], src[5] - imgExpand.expand thumb, url + src = href.split '/' + if @src.split('/')[2] is 'images.4chan.org' and url = redirect.image src[3], src[5] + setTimeout imgExpand.expand, 10000, thumb, url + return + url = href + '?' + Date.now() #navigator.online is not x-browser/os yet - else if engine is 'webkit' + if engine is 'webkit' req = $.ajax @src, (-> - setTimeout imgExpand.retry, 10000, thumb if @status isnt 404 + setTimeout imgExpand.expand, 10000, thumb, url if @status isnt 404 ), type: 'head', event: 'onreadystatechange' #Firefox returns a status code of 0 because of the same origin policy #Oprah doesn't send any request else unless g.dead - setTimeout imgExpand.retry, 10000, thumb - retry: (thumb) -> - imgExpand.expand thumb unless thumb.hidden + setTimeout imgExpand.expand, 10000, thumb, url dialog: -> controls = $.el 'div', @@ -2626,6 +2619,7 @@ Main = #ihover { max-height: 100%; max-width: 75%; + padding-bottom: 18px; } #navlinks {