diff --git a/4chan_x.js b/4chan_x.js index 4cd0578a8..616d9a7b8 100644 --- a/4chan_x.js +++ b/4chan_x.js @@ -59,7 +59,7 @@ */ (function() { - var $, $$, NAMESPACE, a, as, autoWatch, callback, changeCheckbox, changeValue, config, d, delform, el, expand, expandComment, expandThread, g, imageClick, imageExpand, imageExpandClick, imageHover, imageResize, imageThumb, imageToggle, imageType, imageTypeChange, keyModeNormal, keybinds, log, nav, navtopr, nodeInserted, omitted, onloadComment, onloadThread, option, options, parseResponse, pathname, qr, recaptcha, recaptchaListener, recaptchaReload, redirect, replyHiding, replyNav, report, request, scroll, scrollThread, span, temp, text, threadHiding, tzOffset, ui, updateAuto, updateCallback, updateFavicon, updateInterval, updateNow, updateTime, updateTitle, updateVerbose, updater, updaterMake, watcher, _config, _i, _j, _k, _l, _len, _len2, _len3, _len4, _len5, _m, _ref, _ref2, _ref3, _ref4; + var $, $$, NAMESPACE, a, as, autoWatch, callback, changeCheckbox, changeValue, config, d, delform, el, expand, expandComment, expandThread, g, imageClick, imageExpand, imageExpandClick, imageHover, imageResize, imageThumb, imageToggle, imageType, imageTypeChange, keyModeNormal, keybinds, log, nav, navtopr, nodeInserted, omitted, onloadComment, onloadThread, option, options, parseResponse, pathname, qr, recaptcha, recaptchaListener, recaptchaReload, redirect, replyHiding, replyNav, report, scroll, scrollThread, span, temp, text, threadHiding, tzOffset, ui, updateCallback, updateFavicon, updateTime, updateTitle, updater, watcher, _config, _i, _j, _k, _l, _len, _len2, _len3, _len4, _len5, _m, _ref, _ref2, _ref3, _ref4; var __slice = Array.prototype.slice; if (typeof console != "undefined" && console !== null) { log = console.log; @@ -253,12 +253,20 @@ return object; }; $.extend($, { + get: function(url, cb) { + var r; + r = new XMLHttpRequest(); + r.onload = cb; + r.open('get', url, true); + r.send(); + return r; + }, cb: { checked: function() { return $.getValue(this.name, this.checked); }, value: function() { - return $.setValue(this.name, this.checked); + return $.setValue(this.name, this.value); } }, deleteValue: function(name) { @@ -1536,13 +1544,51 @@ } } }; - request = function(url, callback) { - var r; - r = new XMLHttpRequest(); - r.onload = callback; - r.open('get', url, true); - r.send(); - return r; + updateFavicon = function() { + var clone, favicon, href, len; + len = g.replies.length; + if (g.dead) { + if (len > 0) { + href = g.favDeadHalo; + } else { + href = g.favDead; + } + } else { + if (len > 0) { + href = g.favHalo; + } else { + href = g.favDefault; + } + } + favicon = $('link[rel="shortcut icon"]', d); + clone = favicon.cloneNode(true); + clone.href = href; + return $.replace(favicon, clone); + }; + updateTime = function() { + var count, span, time; + span = $('#updater #timer'); + time = Number(span.textContent); + if (++time === 0) { + return updateNow(); + } else if (time > 10) { + time = 0; + g.req.abort(); + updateNow(); + if (g.verbose) { + count = $('#updater #count'); + count.textContent = 'retry'; + return count.className = ''; + } + } else { + return span.textContent = time; + } + }; + updateTitle = function() { + var len; + len = g.replies.length; + d.title = d.title.replace(/\d+/, len); + return updateFavicon(); }; updateCallback = function() { var arr, body, count, id, input, l, replies, reply, root, s, table, timer, _i, _len, _ref; @@ -1594,95 +1640,9 @@ } return timer.textContent = -1 * GM_getValue('Interval', 10); }; - updateFavicon = function() { - var clone, favicon, href, len; - len = g.replies.length; - if (g.dead) { - if (len > 0) { - href = g.favDeadHalo; - } else { - href = g.favDead; - } - } else { - if (len > 0) { - href = g.favHalo; - } else { - href = g.favDefault; - } - } - favicon = $('link[rel="shortcut icon"]', d); - clone = favicon.cloneNode(true); - clone.href = href; - return $.replace(favicon, clone); - }; - updateTime = function() { - var count, span, time; - span = $('#updater #timer'); - time = Number(span.textContent); - if (++time === 0) { - return updateNow(); - } else if (time > 10) { - time = 0; - g.req.abort(); - updateNow(); - if (g.verbose) { - count = $('#updater #count'); - count.textContent = 'retry'; - return count.className = ''; - } - } else { - return span.textContent = time; - } - }; - updateTitle = function() { - var len; - len = g.replies.length; - d.title = d.title.replace(/\d+/, len); - return updateFavicon(); - }; - updateAuto = function() { - var span; - span = $('#updater #timer'); - if (this.checked) { - span.textContent = -1 * GM_getValue('Interval', 10); - return g.interval = window.setInterval(updateTime, 1000); - } else { - span.textContent = 'Thread Updater'; - return clearInterval(g.interval); - } - }; - updateInterval = function() { - var num, span; - if (!(num = Number(this.value))) { - num = 10; - } - this.value = num; - GM_setValue('Interval', num); - span = $('#updater #timer'); - if (0 > Number(span.textContent)) { - return span.textContent = -1 * num; - } - }; - updateNow = function() { - var url; - url = location.href + '?' + Date.now(); - g.req = request(url, updateCallback); - return $("#updater #timer").textContent = 0; - }; - updateVerbose = function() { - var timer; - g.verbose = this.checked; - timer = $('#updater #timer'); - if (this.checked) { - return timer.hidden = false; - } else { - timer.hidden = true; - return $("#updater #count").textContent = 'Thread Updater'; - } - }; updater = { init: function() { - var autoUpT, box, checked, conf, dialog, html, name, title, verbose, _i, _len, _ref; + var autoUpT, checked, conf, dialog, html, input, interva, name, title, updNow, verbose, _i, _len, _ref; html = "
"; conf = config.updater.checkbox; for (name in conf) { @@ -1694,21 +1654,28 @@ title = 'Controls whether *this* thread auotmatically updates or not'; checked = $.config('Auto Update') ? 'checked' : ''; html += "
"; + html += "
"; + html += "
"; dialog = ui.dialog('updater', { bottom: '0px', right: '0px' }, html); _ref = $$('input[type=checkbox]', dialog); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - box = _ref[_i]; - $.bind(box, 'click', $.cb.checked); + input = _ref[_i]; + $.bind(input, 'click', $.cb.checked); } + $.bind($('input[type=text]', dialog), 'change', $.cb.value); verbose = $('input[name=\"Verbose\"]', dialog); autoUpT = $('input[name=\"Auto Update This\"]', dialog); + interva = $('input[name=\"Interval\"]', dialog); + updNow = $('input[type=button]', dialog); $.bind(verbose, 'click', updater.cb.verbose); $.bind(autoUpT, 'click', updater.cb.autoUpdate); + $.bind(updNow, 'click', updater.update); $.append(d.body, dialog); - return updater.cb.verbose.call(verbose); + updater.cb.verbose.call(verbose); + return updater.cb.autoUpdate.call(autoUpT); }, cb: { verbose: function(e) { @@ -1722,52 +1689,54 @@ } }, autoUpdate: function(e) { + var timer; + timer = $('#timer'); if (this.checked) { - updater.timer = $.config('Interval'); - return $('#timer').textContent = updater.timer; + timer.textContent = '-' + $.config('Interval'); + return updater.intervalID = window.setInterval(updater.timeout, 1000); } else { - return updater.timer = null; + timer.textContent = 'Thread Updater'; + return window.clearInterval(updater.intervalID); } + }, + update: function(e) { + var arr, body, br, id, replies, reply; + br = $('br[clear]'); + id = Number($('td[id]', br.previousElementSibling).id); + body = $.el('body', { + innerHTML: this.responseText + }); + arr = []; + replies = $$('td[id]', body); + log(replies.length); + while ((reply = replies.pop()) && (reply.id > id)) { + arr.push(reply.parentNode.parentNode.parentNode); + } + log(arr.length); + while (reply = arr.pop()) { + $.before(br, reply); + } + return log('end'); } - } - }; - updaterMake = function() { - var div, html, input, interval, name, _i, _len, _ref; - html = "
Thread Updater
"; - html += "
"; - html += "
"; - html += "
"; - html += "
"; - html += "
"; - div = ui.dialog('updater', 'bottomright', html); - _ref = $$('input[type=checkbox]', div); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - input = _ref[_i]; - $.bind(input, 'click', changeCheckbox); - name = input.name; - if (name === 'autoL') { - input.checked = GM_getValue('autoG', true); - } else { - input.checked = GM_getValue(name, true); + }, + timeout: function() { + var n, timer; + timer = $('#timer'); + n = Number(timer.textContent); + n += 1; + timer.textContent = n; + if (n === 0 || n === 10) { + return updater.update(); } - switch (name) { - case 'autoL': - $.bind(input, 'click', updateAuto); - break; - case 'verbose': - $.bind(input, 'click', updateVerbose); + }, + update: function() { + var cb, url, _ref; + if ((_ref = updater.request) != null) { + _ref.abort(); } - } - if (!(g.verbose = GM_getValue('verbose', true))) { - $("#timer", div).hidden = true; - } - interval = $('input[name=interval]', div); - interval.value = GM_getValue('Interval', 10); - $.bind(interval, 'change', updateInterval); - $.bind($('input[type=button]', div), 'click', updateNow); - d.body.appendChild(div); - if (GM_getValue('autoG', true)) { - return updateAuto.call($("input[name=autoL]", div)); + url = location.href; + cb = updater.cb.update; + return updater.request = $.get(url, cb); } }; watcher = { diff --git a/script.coffee b/script.coffee index d680b4f7f..9439e91c5 100644 --- a/script.coffee +++ b/script.coffee @@ -35,7 +35,7 @@ config = 'Unread Count': [true, 'Show unread post count in tab title'] updater: checkbox: - 'Verbose': [true, 'Show countdown timer, new post count'] + 'Verbose': [true, 'Show countdown timer, new post count'] 'Auto Update': [false, 'Automatically fetch new posts'] 'Interval': 30 @@ -152,11 +152,17 @@ $.extend = (object, properties) -> object $.extend $, + get: (url, cb) -> + r = new XMLHttpRequest() + r.onload = cb + r.open 'get', url, true + r.send() + r cb: checked: -> $.getValue @name, @checked value: -> - $.setValue @name, @checked + $.setValue @name, @value deleteValue: (name) -> name = NAMESPACE + name delete localStorage[name] @@ -1190,12 +1196,43 @@ threadHiding = unless node.nodeName is 'CENTER' threadHiding.thread node -request = (url, callback) -> - r = new XMLHttpRequest() - r.onload = callback - r.open 'get', url, true - r.send() - r +updateFavicon = -> + len = g.replies.length + if g.dead + if len > 0 + href = g.favDeadHalo + else + href = g.favDead + else + if len > 0 + href = g.favHalo + else + href = g.favDefault + favicon = $ 'link[rel="shortcut icon"]', d + clone = favicon.cloneNode true + clone.href = href + $.replace favicon, clone + +updateTime = -> + span = $ '#updater #timer' + time = Number span.textContent + if ++time is 0 + updateNow() + else if time > 10 + time = 0 + g.req.abort() + updateNow() + if g.verbose + count = $ '#updater #count' + count.textContent = 'retry' + count.className = '' + else + span.textContent = time + +updateTitle = -> + len = g.replies.length + d.title = d.title.replace /\d+/, len + updateFavicon() updateCallback = -> count = $ '#updater #count' @@ -1240,77 +1277,6 @@ updateCallback = -> timer.textContent = -1 * GM_getValue 'Interval', 10 -updateFavicon = -> - len = g.replies.length - if g.dead - if len > 0 - href = g.favDeadHalo - else - href = g.favDead - else - if len > 0 - href = g.favHalo - else - href = g.favDefault - favicon = $ 'link[rel="shortcut icon"]', d - clone = favicon.cloneNode true - clone.href = href - $.replace favicon, clone - -updateTime = -> - span = $ '#updater #timer' - time = Number span.textContent - if ++time is 0 - updateNow() - else if time > 10 - time = 0 - g.req.abort() - updateNow() - if g.verbose - count = $ '#updater #count' - count.textContent = 'retry' - count.className = '' - else - span.textContent = time - -updateTitle = -> - len = g.replies.length - d.title = d.title.replace /\d+/, len - updateFavicon() - -updateAuto = -> - span = $ '#updater #timer' - if @checked - span.textContent = -1 * GM_getValue 'Interval', 10 - g.interval = window.setInterval updateTime, 1000 - else - span.textContent = 'Thread Updater' - clearInterval g.interval - -updateInterval = -> - unless num = Number @value - num = 10 - @value = num - GM_setValue 'Interval', num - - span = $ '#updater #timer' - if 0 > Number span.textContent - span.textContent = -1 * num - -updateNow = -> - url = location.href + '?' + Date.now() # fool the cache - g.req = request url, updateCallback - $("#updater #timer").textContent = 0 - -updateVerbose = -> - g.verbose = @checked - timer = $ '#updater #timer' - if @checked - timer.hidden = false - else - timer.hidden = true - $("#updater #count").textContent = 'Thread Updater' - updater = init: -> html = "
" @@ -1325,20 +1291,27 @@ updater = checked = if $.config 'Auto Update' then 'checked' else '' html += "
" + html += "
" + html += "
" + dialog = ui.dialog 'updater', bottom: '0px', right: '0px', html - for box in $$ 'input[type=checkbox]', dialog - $.bind box, 'click', $.cb.checked + for input in $$ 'input[type=checkbox]', dialog + $.bind input, 'click', $.cb.checked + $.bind $('input[type=text]', dialog), 'change', $.cb.value verbose = $ 'input[name=\"Verbose\"]', dialog autoUpT = $ 'input[name=\"Auto Update This\"]', dialog + interva = $ 'input[name=\"Interval\"]', dialog + updNow = $ 'input[type=button]', dialog $.bind verbose, 'click', updater.cb.verbose $.bind autoUpT, 'click', updater.cb.autoUpdate + $.bind updNow, 'click', updater.update $.append d.body, dialog updater.cb.verbose.call verbose - #updater.cb.autoUpdate.call autoUpT + updater.cb.autoUpdate.call autoUpT cb: verbose: (e) -> @@ -1349,46 +1322,48 @@ updater = $.hide $ '#count' $('#timer').textContent = 'Thread Updater' autoUpdate: (e) -> + timer = $ '#timer' if @checked - updater.timer = $.config 'Interval' - $('#timer').textContent = updater.timer + timer.textContent = '-' + $.config 'Interval' + updater.intervalID = window.setInterval updater.timeout, 1000 else - updater.timer = null + timer.textContent = 'Thread Updater' + window.clearInterval updater.intervalID + update: (e) -> + br = $ 'br[clear]' -updaterMake = -> - html = "
Thread Updater
" - html += "
" - html += "
" - html += "
" - html += "
" - html += "
" - div = ui.dialog 'updater', 'bottomright', html + id = Number $('td[id]', br.previousElementSibling).id - for input in $$ 'input[type=checkbox]', div - $.bind input, 'click', changeCheckbox - name = input.name - if name is 'autoL' - input.checked = GM_getValue 'autoG', true - else - input.checked = GM_getValue name, true - switch name - when 'autoL' - $.bind input, 'click', updateAuto - when 'verbose' - $.bind input, 'click', updateVerbose + body = $.el 'body', + innerHTML: @responseText - unless g.verbose = GM_getValue 'verbose', true - $("#timer", div).hidden = true + arr = [] + replies = $$ 'td[id]', body + log replies.length + while (reply = replies.pop()) and (reply.id > id) + arr.push reply.parentNode.parentNode.parentNode #table - interval = $ 'input[name=interval]', div - interval.value = GM_getValue 'Interval', 10 - $.bind interval, 'change', updateInterval + log arr.length + #XXX add replies in correct order so /b/acklinks resolve + while reply = arr.pop() + $.before br, reply - $.bind $('input[type=button]', div), 'click', updateNow + log 'end' - d.body.appendChild div + timeout: -> + timer = $ '#timer' + n = Number timer.textContent + n += 1 + timer.textContent = n - if GM_getValue 'autoG', true then updateAuto.call $("input[name=autoL]", div) + if n == 0 or n == 10 #retry + updater.update() + + update: -> + updater.request?.abort() + url = location.href #+ '?' + Date.now() # fool the cache + cb = updater.cb.update + updater.request = $.get url, cb watcher = init: ->