From 034648a5df2222c4cc09816b61893503ed366d2f Mon Sep 17 00:00:00 2001 From: James Campos Date: Thu, 2 Feb 2012 02:28:11 -0800 Subject: [PATCH 01/28] fix #161 --- 4chan_x.user.js | 15 ++++++++++++--- changelog | 2 ++ script.coffee | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index cd8480063..72f457cf7 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1202,7 +1202,6 @@ init: function() { var h1, iframe; if (!$.id('recaptcha_challenge_field_holder')) return; - $('form[name=post]').hidden = true; h1 = $.el('h1', { innerHTML: 'Open the Quick Reply' }); @@ -3483,6 +3482,8 @@ if (conf['Quote Backlinks']) quoteBacklink.init(); if (conf['Indicate OP quote']) quoteOP.init(); if (conf['Indicate Cross-thread Quotes']) quoteDR.init(); + if (conf['Quick Reply']) Main.css += 'form[name=post] { display: none; }'; + Main.addStyle(); return $.ready(Main.ready); }, ready: function() { @@ -3493,7 +3494,6 @@ } if (!$.id('navtopr')) return; $.addClass(d.body, engine); - $.addStyle(Main.css); threading.init(); Favicon.init(); if (conf['Quick Reply']) qr.init(); @@ -3528,6 +3528,14 @@ } return $.on(form, 'DOMNodeInserted', Main.node); }, + addStyle: function() { + $.off(d, 'DOMNodeInserted', Main.addStyle); + if (d.head) { + return $.addStyle(Main.css); + } else { + return $.on(d, 'DOMNodeInserted', Main.addStyle); + } + }, message: function(e) { var data, version; data = e.data; @@ -3881,7 +3889,8 @@ img[md5], img[md5] + img {\ }\ .filtered {\ text-decoration: line-through;\ -}' +}\ +' }; Main.init(); diff --git a/changelog b/changelog index 462108b6a..a9fdab8ec 100644 --- a/changelog +++ b/changelog @@ -1,4 +1,6 @@ master +- aeosynth + prevent post form flicker 2.25.3 - Mayhem diff --git a/script.coffee b/script.coffee index 2e236083c..4b06573ef 100644 --- a/script.coffee +++ b/script.coffee @@ -862,7 +862,6 @@ nav = qr = init: -> return unless $.id 'recaptcha_challenge_field_holder' - $('form[name=post]').hidden = true h1 = $.el 'h1' innerHTML: 'Open the Quick Reply' $.on $('a', h1), 'click', qr.open @@ -2711,6 +2710,10 @@ Main = if conf['Indicate Cross-thread Quotes'] quoteDR.init() + if conf['Quick Reply'] + Main.css += 'form[name=post] { display: none; }' + + Main.addStyle() $.ready Main.ready @@ -2721,7 +2724,6 @@ Main = if not $.id 'navtopr' return $.addClass d.body, engine - $.addStyle Main.css threading.init() Favicon.init() @@ -2778,6 +2780,13 @@ Main = alert err $.on form, 'DOMNodeInserted', Main.node + addStyle: -> + $.off d, 'DOMNodeInserted', Main.addStyle + if d.head + $.addStyle Main.css + else # XXX fox + $.on d, 'DOMNodeInserted', Main.addStyle + message: (e) -> {data} = e {version} = data @@ -3122,6 +3131,7 @@ img[md5], img[md5] + img { } .filtered { text-decoration: line-through; -}' +} +' Main.init() From 5d3daaf72ea3113b3ba42979e43a016ee3b8c721 Mon Sep 17 00:00:00 2001 From: James Campos Date: Sun, 5 Feb 2012 01:49:28 -0800 Subject: [PATCH 02/28] work with new setting --- 4chan_x.user.js | 4 +++- script.coffee | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 8b9bd0056..ac68029b1 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3494,7 +3494,9 @@ if (conf['Quote Backlinks']) quoteBacklink.init(); if (conf['Indicate OP quote']) quoteOP.init(); if (conf['Indicate Cross-thread Quotes']) quoteDR.init(); - if (conf['Quick Reply']) Main.css += 'form[name=post] { display: none; }'; + if (conf['Quick Reply'] && conf['Hide Original Post Form']) { + Main.css += 'form[name=post] { display: none; }'; + } Main.addStyle(); return $.ready(Main.ready); }, diff --git a/script.coffee b/script.coffee index 45b5d1d82..a356822b3 100644 --- a/script.coffee +++ b/script.coffee @@ -2730,7 +2730,7 @@ Main = if conf['Indicate Cross-thread Quotes'] quoteDR.init() - if conf['Quick Reply'] + if conf['Quick Reply'] and conf['Hide Original Post Form'] Main.css += 'form[name=post] { display: none; }' Main.addStyle() From 11f6dcfd24c28c26cb59db0981962dafc8878ce8 Mon Sep 17 00:00:00 2001 From: James Campos Date: Sun, 5 Feb 2012 01:55:27 -0800 Subject: [PATCH 03/28] don't hide form twice --- 4chan_x.user.js | 1 - script.coffee | 1 - 2 files changed, 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index ac68029b1..8fca7d626 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1204,7 +1204,6 @@ }); $.on($('a', link), 'click', qr.open); form = d.forms[0]; - form.hidden = true; $.before(form, link); } g.callbacks.push(function(root) { diff --git a/script.coffee b/script.coffee index a356822b3..6d7a7f3ef 100644 --- a/script.coffee +++ b/script.coffee @@ -871,7 +871,6 @@ qr = link = $.el 'h1', innerHTML: "#{if g.REPLY then 'Open the Quick Reply' else 'Create a New Thread'}" $.on $('a', link), 'click', qr.open form = d.forms[0] - form.hidden = true $.before form, link g.callbacks.push (root) -> $.on $('.quotejs + .quotejs', root), 'click', qr.quote From aa40ca01df9ed030fa73ad607a617bed7d712373 Mon Sep 17 00:00:00 2001 From: James Campos Date: Sun, 5 Feb 2012 02:13:05 -0800 Subject: [PATCH 04/28] instanceof Array --- 4chan_x.user.js | 18 ++++++++---------- script.coffee | 10 ++++------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 58309cfd8..bf21e352c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -186,17 +186,15 @@ (flatten = function(parent, obj) { var key, val, _results; - if (typeof obj === 'object') { - if (obj.length) { - return conf[parent] = obj[0]; - } else { - _results = []; - for (key in obj) { - val = obj[key]; - _results.push(flatten(key, val)); - } - return _results; + if (obj instanceof Array) { + return conf[parent] = obj[0]; + } else if (typeof obj === 'object') { + _results = []; + for (key in obj) { + val = obj[key]; + _results.push(flatten(key, val)); } + return _results; } else { return conf[parent] = obj; } diff --git a/script.coffee b/script.coffee index 8994a342f..7a6318d5f 100644 --- a/script.coffee +++ b/script.coffee @@ -112,12 +112,10 @@ log = console.log.bind? console # flatten the config conf = {} (flatten = (parent, obj) -> - if typeof obj is 'object' - # array - if obj.length - conf[parent] = obj[0] - # object - else for key, val of obj + if obj instanceof Array + conf[parent] = obj[0] + else if typeof obj is 'object' + for key, val of obj flatten key, val else # string or number conf[parent] = obj From e269182e8d02cbb5a74c7aeda17aeaa9ecd39f74 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 5 Feb 2012 14:17:19 +0100 Subject: [PATCH 05/28] Prevent the page from being scrolled with opened options. --- 4chan_x.user.js | 2 ++ script.coffee | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 8f0152165..b1334e93f 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2113,6 +2113,7 @@ id: 'overlay' }); $.on(overlay, 'click', function() { + d.body.style.removeProperty('overflow'); return $.rm(overlay); }); $.on(dialog, 'click', function(e) { @@ -2120,6 +2121,7 @@ }); $.add(overlay, dialog); $.add(d.body, overlay); + d.body.style.setProperty('overflow', 'hidden', 'important'); options.backlink.call(back); options.time.call(time); return options.favicon.call(favicon); diff --git a/script.coffee b/script.coffee index 329c28c48..4ebedb04c 100644 --- a/script.coffee +++ b/script.coffee @@ -1647,10 +1647,13 @@ options = indicators[@name].hidden = @checked overlay = $.el 'div', id: 'overlay' - $.on overlay, 'click', -> $.rm overlay + $.on overlay, 'click', -> + d.body.style.removeProperty 'overflow' + $.rm overlay $.on dialog, 'click', (e) -> e.stopPropagation() $.add overlay, dialog $.add d.body, overlay + d.body.style.setProperty 'overflow', 'hidden', 'important' options.backlink.call back options.time.call time From c73d0e17f2bd8712a57a1f34f260f0b99150ca9a Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 5 Feb 2012 14:56:50 +0100 Subject: [PATCH 06/28] Add a version class to the body for userstyles to use. Close #164 --- 4chan_x.user.js | 1 + script.coffee | 1 + 2 files changed, 2 insertions(+) diff --git a/4chan_x.user.js b/4chan_x.user.js index b1334e93f..e0b554b08 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3506,6 +3506,7 @@ return; } if (!$.id('navtopr')) return; + $.addClass(d.body, "chanx_" + (VERSION.match(/\.(\d+)/)[1])); $.addClass(d.body, engine); threading.init(); Favicon.init(); diff --git a/script.coffee b/script.coffee index 4ebedb04c..d6902e78c 100644 --- a/script.coffee +++ b/script.coffee @@ -2743,6 +2743,7 @@ Main = return if not $.id 'navtopr' return + $.addClass d.body, "chanx_#{VERSION.match(/\.(\d+)/)[1]}" $.addClass d.body, engine threading.init() Favicon.init() From 5291ef5ac1e65e1df69139681f4623bc98cad5e1 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 5 Feb 2012 17:38:28 +0100 Subject: [PATCH 07/28] Make Unread Favicon option, independant of Unread Favicon. Remove the 'None' favicon choice. Refactor. Close #100 --- 4chan_x.user.js | 66 ++++++++++++++++----------------- changelog | 1 + script.coffee | 97 ++++++++++++++++++++++++------------------------- 3 files changed, 80 insertions(+), 84 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index e0b554b08..7df2221ed 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -105,6 +105,7 @@ Monitoring: { 'Thread Updater': [true, 'Update threads. Has more options in its own dialog.'], 'Unread Count': [true, 'Show unread post count in tab title'], + 'Unread Favicon': [true, 'Show a different favicon when there are unread posts'], 'Post in Title': [true, 'Show the op\'s post in the tab title'], 'Thread Stats': [true, 'Display reply and image count'], 'Thread Watcher': [true, 'Bookmark threads'], @@ -167,7 +168,7 @@ expandImages: ['m', 'Expand selected image'], expandAllImages: ['M', 'Expand all images'], update: ['u', 'Update now'], - unreadCountTo0: ['z', 'Reset unread count to 0'] + unreadCountTo0: ['z', 'Reset unread status'] }, updater: { checkbox: { @@ -971,8 +972,7 @@ break; case conf.unreadCountTo0: unread.replies = []; - unread.updateTitle(); - Favicon.update(); + unread.update(); break; default: return; @@ -2025,14 +2025,13 @@
  • Hour: %k, %H, %l (lowercase L), %I (uppercase i), %p, %P
  • \
  • Minutes: %M
  • \ \ -
    Unread Count is disabled.
    \ +
    Unread Favicon is disabled.
    \ Unread favicons
    \ \ \ \ @@ -2150,7 +2149,7 @@ }, favicon: function() { Favicon["switch"](); - if (g.REPLY && conf['Unread Count']) Favicon.update(); + unread.update(true); return this.nextElementSibling.innerHTML = " "; } }; @@ -2366,8 +2365,13 @@ updater.count.textContent = 404; updater.count.className = 'warning'; clearTimeout(updater.timeoutID); - d.title = d.title.match(/^.+-/)[0] + ' 404'; g.dead = true; + if (conf['Unread Count']) { + unread.title = unread.title.match(/^.+-/)[0] + ' 404'; + } else { + d.title = d.title.match(/^.+-/)[0] + ' 404'; + } + unread.update(true); qr.message.send({ req: 'abort' }); @@ -2831,10 +2835,9 @@ root = q.parentNode.nodeName === 'FONT' ? q.parentNode : q.nextSibling ? q.nextSibling : q; if (el = $.id(id)) { inline = quoteInline.table(id, el.innerHTML); - if (g.REPLY && conf['Unread Count'] && (i = unread.replies.indexOf(el.parentNode.parentNode.parentNode)) !== -1) { + if ((i = unread.replies.indexOf(el.parentNode.parentNode.parentNode)) !== -1) { unread.replies.splice(i, 1); - unread.updateTitle(); - Favicon.update(); + unread.update(); } if (/\bbacklink\b/.test(q.className)) { $.after(q.parentNode, inline); @@ -3104,7 +3107,8 @@ unread = { init: function() { - d.title = '(0) ' + d.title; + this.title = d.title; + unread.update(); $.on(window, 'scroll', unread.scroll); return g.callbacks.push(unread.node); }, @@ -3112,8 +3116,7 @@ node: function(root) { if (root.hidden || root.className) return; unread.replies.push(root); - unread.updateTitle(); - if (unread.replies.length === 1) return Favicon.update(); + return unread.update(); }, scroll: function() { var bottom, height, i, reply, _len, _ref; @@ -3126,20 +3129,25 @@ } if (i === 0) return; unread.replies = unread.replies.slice(i); - unread.updateTitle(); - if (unread.replies.length === 0) return Favicon.update(); + return unread.update(); }, - updateTitle: function() { - return d.title = d.title.replace(/\d+/, unread.replies.length); + update: function(forceUpdate) { + var count; + if (!g.REPLY) return; + count = unread.replies.length; + if (conf['Unread Count']) d.title = "(" + count + ") " + unread.title; + if (!(conf['Unread Favicon'] && count < 2 || forceUpdate)) return; + Favicon.el.href = g.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"]; + if (engine !== 'webkit') return $.add(d.head, $.rm(Favicon.el)); } }; Favicon = { init: function() { - var favicon, href; - favicon = $('link[rel="shortcut icon"]', d.head); - favicon.type = 'image/x-icon'; - href = favicon.href; + var href; + this.el = $('link[rel="shortcut icon"]', d.head); + this.el.type = 'image/x-icon'; + href = this.el.href; this.SFW = /ws.ico$/.test(href); this["default"] = href; return this["switch"](); @@ -3165,23 +3173,11 @@ this.unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='; this.unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAKECAAAAAC6Xw////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='; this.unreadNSFW = 'data:unreadNSFW;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='; - break; - case 'None': - this.unreadDead = this.dead; - this.unreadSFW = 'http://static.4chan.org/image/favicon-ws.ico'; - this.unreadNSFW = 'http://static.4chan.org/image/favicon.ico'; } return this.unread = this.SFW ? this.unreadSFW : this.unreadNSFW; }, empty: 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///9vb2////yH5BAEAAAMALAAAAAAQABAAAAIvnI+pq+D9DBAUoFkPFnbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==', - dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==', - update: function() { - var favicon, l; - l = unread.replies.length; - favicon = $('link[rel="shortcut icon"]', d.head); - favicon.href = g.dead ? l ? this.unreadDead : this.dead : l ? this.unread : this["default"]; - if (engine !== 'webkit') return $.add(d.head, $.rm(favicon)); - } + dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==' }; redirect = { @@ -3519,7 +3515,7 @@ if (conf['Thread Stats']) threadStats.init(); if (conf['Reply Navigation']) nav.init(); if (conf['Post in Title']) titlePost.init(); - if (conf['Unread Count']) unread.init(); + if (conf['Unread Count'] || conf['Unread Favicon']) unread.init(); } else { if (conf['Thread Hiding']) threadHiding.init(); if (conf['Thread Expansion']) expandThread.init(); diff --git a/changelog b/changelog index 73932bdff..2a1d87707 100644 --- a/changelog +++ b/changelog @@ -4,6 +4,7 @@ master - Mayhem Increase Sauce linking possibilites: Thumbnails, full images, MD5 hashes. + Unread Favicon is now optional, independent of Unread Count. 2.25.5 - Mayhem diff --git a/script.coffee b/script.coffee index d6902e78c..c7da7ffd8 100644 --- a/script.coffee +++ b/script.coffee @@ -26,6 +26,7 @@ config = Monitoring: 'Thread Updater': [true, 'Update threads. Has more options in its own dialog.'] 'Unread Count': [true, 'Show unread post count in tab title'] + 'Unread Favicon': [true, 'Show a different favicon when there are unread posts'] 'Post in Title': [true, 'Show the op\'s post in the tab title'] 'Thread Stats': [true, 'Display reply and image count'] 'Thread Watcher': [true, 'Bookmark threads'] @@ -96,7 +97,7 @@ config = expandImages: ['m', 'Expand selected image'] expandAllImages: ['M', 'Expand all images'] update: ['u', 'Update now'] - unreadCountTo0: ['z', 'Reset unread count to 0'] + unreadCountTo0: ['z', 'Reset unread status'] updater: checkbox: 'Scrolling': [false, 'Scroll updated posts into view. Only enabled at bottom of page.'] @@ -713,8 +714,7 @@ keybinds = qr.submit() if qr.el and !qr.status() when conf.unreadCountTo0 unread.replies = [] - unread.updateTitle() - Favicon.update() + unread.update() else return e.preventDefault() @@ -1570,14 +1570,13 @@ options =
  • Hour: %k, %H, %l (lowercase L), %I (uppercase i), %p, %P
  • Minutes: %M
  • -
    Unread Count is disabled.
    +
    Unread Favicon is disabled.
    Unread favicons
    @@ -1681,7 +1680,7 @@ options = $.id('backlinkPreview').textContent = conf['backlink'].replace /%id/, '123456789' favicon: -> Favicon.switch() - Favicon.update() if g.REPLY and conf['Unread Count'] + unread.update true @nextElementSibling.innerHTML = " " threading = @@ -1865,8 +1864,12 @@ updater = updater.count.textContent = 404 updater.count.className = 'warning' clearTimeout updater.timeoutID - d.title = d.title.match(/^.+-/)[0] + ' 404' g.dead = true + if conf['Unread Count'] + unread.title = unread.title.match(/^.+-/)[0] + ' 404' + else + d.title = d.title.match(/^.+-/)[0] + ' 404' + unread.update true qr.message.send req: 'abort' qr.status() Favicon.update() @@ -2217,10 +2220,9 @@ quoteInline = root = if q.parentNode.nodeName is 'FONT' then q.parentNode else if q.nextSibling then q.nextSibling else q if el = $.id id inline = quoteInline.table id, el.innerHTML - if g.REPLY and conf['Unread Count'] and (i = unread.replies.indexOf el.parentNode.parentNode.parentNode) isnt -1 + if (i = unread.replies.indexOf el.parentNode.parentNode.parentNode) isnt -1 unread.replies.splice i, 1 - unread.updateTitle() - Favicon.update() + unread.update() if /\bbacklink\b/.test q.className $.after q.parentNode, inline $.addClass $.x('ancestor::table', el), 'forwarded' if conf['Forward Hiding'] @@ -2392,7 +2394,8 @@ threadStats = unread = init: -> - d.title = '(0) ' + d.title + @title = d.title + unread.update() $.on window, 'scroll', unread.scroll g.callbacks.push unread.node @@ -2401,9 +2404,7 @@ unread = node: (root) -> return if root.hidden or root.className unread.replies.push root - unread.updateTitle() - if unread.replies.length is 1 - Favicon.update() + unread.update() scroll: -> height = d.body.clientHeight @@ -2414,18 +2415,42 @@ unread = return if i is 0 unread.replies = unread.replies[i..] - unread.updateTitle() - if unread.replies.length is 0 - Favicon.update() + unread.update() - updateTitle: -> - d.title = d.title.replace /\d+/, unread.replies.length + update: (forceUpdate) -> + return unless g.REPLY + + count = unread.replies.length + + if conf['Unread Count'] + d.title = "(#{count}) #{unread.title}" + + unless conf['Unread Favicon'] and count < 2 or forceUpdate + return + + Favicon.el.href = + if g.dead + if count + Favicon.unreadDead + else + Favicon.dead + else + if count + Favicon.unread + else + Favicon.default + + #`favicon.href = href` doesn't work on Firefox + #`favicon.href = href` isn't enough on Opera + #Opera won't always update the favicon if the href didn't not change + if engine isnt 'webkit' + $.add d.head, $.rm Favicon.el Favicon = init: -> - favicon = $ 'link[rel="shortcut icon"]', d.head - favicon.type = 'image/x-icon' - {href} = favicon + @el = $ 'link[rel="shortcut icon"]', d.head + @el.type = 'image/x-icon' + {href} = @el @SFW = /ws.ico$/.test href @default = href @switch() @@ -2448,37 +2473,11 @@ Favicon = @unreadDead = 'data:unreadDead;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=' @unreadSFW = 'data:unreadSFW;base64,R0lGODlhEAAQAKECAAAAAC6Xw////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=' @unreadNSFW = 'data:unreadNSFW;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs=' - when 'None' - @unreadDead = @dead - @unreadSFW = 'http://static.4chan.org/image/favicon-ws.ico' - @unreadNSFW = 'http://static.4chan.org/image/favicon.ico' @unread = if @SFW then @unreadSFW else @unreadNSFW empty: 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///9vb2////yH5BAEAAAMALAAAAAAQABAAAAIvnI+pq+D9DBAUoFkPFnbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==' dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==' - update: -> - l = unread.replies.length - - favicon = $ 'link[rel="shortcut icon"]', d.head - favicon.href = - if g.dead - if l - @unreadDead - else - @dead - else - if l - @unread - else - @default - - #`favicon.href = href` doesn't work on Firefox - #`favicon.href = href` isn't enough on Opera - #Opera won't always update the favicon if the href do not change - if engine isnt 'webkit' - $.add d.head, $.rm favicon - redirect = init: -> url = @@ -2774,7 +2773,7 @@ Main = if conf['Post in Title'] titlePost.init() - if conf['Unread Count'] + if conf['Unread Count'] or conf['Unread Favicon'] unread.init() else #not reply From aa5cb8007bdfb893c4a61f5818eeaaf49419ca23 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 5 Feb 2012 17:42:43 +0100 Subject: [PATCH 08/28] Don't set body's overflow to '!important'. Fix overflow reset on Chrome. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 7df2221ed..518403e65 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2120,7 +2120,7 @@ }); $.add(overlay, dialog); $.add(d.body, overlay); - d.body.style.setProperty('overflow', 'hidden', 'important'); + d.body.style.setProperty('overflow', 'hidden', null); options.backlink.call(back); options.time.call(time); return options.favicon.call(favicon); diff --git a/script.coffee b/script.coffee index c7da7ffd8..4caf717f9 100644 --- a/script.coffee +++ b/script.coffee @@ -1652,7 +1652,7 @@ options = $.on dialog, 'click', (e) -> e.stopPropagation() $.add overlay, dialog $.add d.body, overlay - d.body.style.setProperty 'overflow', 'hidden', 'important' + d.body.style.setProperty 'overflow', 'hidden', null options.backlink.call back options.time.call time From 86f0bd6193e5fae5fd2de0a70443cfd2b76d79b7 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 5 Feb 2012 21:49:22 +0100 Subject: [PATCH 09/28] Fix some compatibility issues with file drag'n'drop. Close #181. --- 4chan_x.user.js | 31 +++++++++++++++++++------------ changelog | 1 + script.coffee | 27 +++++++++++++++++---------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 518403e65..8ff06921d 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1231,8 +1231,10 @@ qr.dialog(); if (conf['Auto Hide QR']) qr.hide(); } - $.on(d, 'dragover', qr.fileDrop); - $.on(d, 'drop', qr.fileDrop); + $.on(d, 'dragover', qr.dragOver); + $.on(d, 'drop', qr.dropFile); + $.on(d, 'dragstart', qr.drag); + $.on(d, 'dragend', qr.drag); return window.location = 'javascript:void(Recaptcha.focus_response_field=function(){})'; }, open: function() { @@ -1355,17 +1357,22 @@ ta.focus(); return ta.selectionEnd = ta.selectionStart = caretPos + text.length; }, - fileDrop: function(e) { - if (/TEXTAREA|INPUT/.test(e.target.nodeName)) return; + drag: function(e) { + var i; + i = e.type === 'dragstart' ? 'off' : 'on'; + $[i](d, 'dragover', qr.dragOver); + return $[i](d, 'drop', qr.dropFile); + }, + dragOver: function(e) { e.preventDefault(); - e.stopPropagation(); - e.dataTransfer.dropEffect = 'copy'; - if (e.type === 'drop') { - if (!e.dataTransfer.files.length) return; - qr.open(); - qr.fileInput.call(e.dataTransfer); - return $.addClass(qr.el, 'dump'); - } + return e.dataTransfer.dropEffect = 'copy'; + }, + dropFile: function(e) { + if (!e.dataTransfer.files.length) return; + e.preventDefault(); + qr.open(); + qr.fileInput.call(e.dataTransfer); + return $.addClass(qr.el, 'dump'); }, fileInput: function() { var file, _i, _len, _ref; diff --git a/changelog b/changelog index 2a1d87707..4cff966b8 100644 --- a/changelog +++ b/changelog @@ -5,6 +5,7 @@ master Increase Sauce linking possibilites: Thumbnails, full images, MD5 hashes. Unread Favicon is now optional, independent of Unread Count. + Fix some compatibility issues with file drag and drop, notably with QuickDrag extension. 2.25.5 - Mayhem diff --git a/script.coffee b/script.coffee index 4caf717f9..edf308c21 100644 --- a/script.coffee +++ b/script.coffee @@ -889,8 +889,10 @@ qr = if conf['Persistent QR'] qr.dialog() qr.hide() if conf['Auto Hide QR'] - $.on d, 'dragover', qr.fileDrop - $.on d, 'drop', qr.fileDrop + $.on d, 'dragover', qr.dragOver + $.on d, 'drop', qr.dropFile + $.on d, 'dragstart', qr.drag + $.on d, 'dragend', qr.drag # prevent original captcha input from being focused on reload window.location = 'javascript:void(Recaptcha.focus_response_field=function(){})' @@ -1000,16 +1002,21 @@ qr = # Move the caret to the end of the new quote. ta.selectionEnd = ta.selectionStart = caretPos + text.length - fileDrop: (e) -> - return if /TEXTAREA|INPUT/.test e.target.nodeName + drag: (e) -> + # Let it drag anything from the page. + i = if e.type is 'dragstart' then 'off' else 'on' + $[i] d, 'dragover', qr.dragOver + $[i] d, 'drop', qr.dropFile + dragOver: (e) -> e.preventDefault() - e.stopPropagation() e.dataTransfer.dropEffect = 'copy' # cursor feedback - if e.type is 'drop' - return unless e.dataTransfer.files.length # let it only drop files - qr.open() - qr.fileInput.call e.dataTransfer - $.addClass qr.el, 'dump' + dropFile: (e) -> + # Let it only handle files from the desktop. + return unless e.dataTransfer.files.length + e.preventDefault() + qr.open() + qr.fileInput.call e.dataTransfer + $.addClass qr.el, 'dump' fileInput: -> qr.cleanError() # Set or change current reply's file. From 2008d6d7737626884b5b9142fc8e85fdb2f8ff1f Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 6 Feb 2012 11:01:17 +0100 Subject: [PATCH 10/28] Fix #188 --- 4chan_x.user.js | 1 + script.coffee | 1 + 2 files changed, 2 insertions(+) diff --git a/4chan_x.user.js b/4chan_x.user.js index 8ff06921d..36bbb6df5 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3763,6 +3763,7 @@ textarea.field {\ }\ #qr [type=submit] {\ margin: 1px 0;\ + padding: 1px; /* not Gecko */\ padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */\ width: 30%;\ }\ diff --git a/script.coffee b/script.coffee index edf308c21..fc433cde4 100644 --- a/script.coffee +++ b/script.coffee @@ -3015,6 +3015,7 @@ textarea.field { } #qr [type=submit] { margin: 1px 0; + padding: 1px; /* not Gecko */ padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */ width: 30%; } From 31badbae9dac271e9c70e58351a03151a05bc71d Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 6 Feb 2012 11:04:29 +0100 Subject: [PATCH 11/28] Fix #185. --- 4chan_x.user.js | 5 ++++- script.coffee | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 36bbb6df5..a444bf560 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1200,7 +1200,10 @@ link = $.el('h1', { innerHTML: "" + (g.REPLY ? 'Open the Quick Reply' : 'Create a New Thread') + "" }); - $.on($('a', link), 'click', qr.open); + $.on($('a', link), 'click', function() { + qr.open(); + return $('textarea', qr.el).focus(); + }); form = d.forms[0]; $.before(form, link); } diff --git a/script.coffee b/script.coffee index fc433cde4..fc99afd59 100644 --- a/script.coffee +++ b/script.coffee @@ -867,7 +867,9 @@ qr = return unless $.id 'recaptcha_challenge_field_holder' if conf['Hide Original Post Form'] link = $.el 'h1', innerHTML: "#{if g.REPLY then 'Open the Quick Reply' else 'Create a New Thread'}" - $.on $('a', link), 'click', qr.open + $.on $('a', link), 'click', -> + qr.open() + $('textarea', qr.el).focus() form = d.forms[0] $.before form, link g.callbacks.push (root) -> From 7a2eee99f76683ffd6b43e23bac665be58fc2629 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 6 Feb 2012 11:27:08 +0100 Subject: [PATCH 12/28] Focus the captcha on captcha error. Fix #187. --- 4chan_x.user.js | 1 + script.coffee | 3 +++ 2 files changed, 4 insertions(+) diff --git a/4chan_x.user.js b/4chan_x.user.js index a444bf560..278c5ea2c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1285,6 +1285,7 @@ el.textContent = err; if (node) $.replace(el.firstChild, node); qr.open(); + if (/captcha|verification/i.test(err)) $('[autocomplete]', qr.el).focus(); if (d.hidden || d.oHidden || d.mozHidden || d.webkitHidden) { return alert(err); } diff --git a/script.coffee b/script.coffee index fc99afd59..d4f82c505 100644 --- a/script.coffee +++ b/script.coffee @@ -931,6 +931,9 @@ qr = el.textContent = err $.replace el.firstChild, node if node qr.open() + if /captcha|verification/i.test err + # Focus the captcha input on captcha error. + $('[autocomplete]', qr.el).focus() alert err if d.hidden or d.oHidden or d.mozHidden or d.webkitHidden cleanError: -> $('.warning', qr.el).textContent = null From 3a13f862587a9e624dc4900af65e879bb4ce860e Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 6 Feb 2012 14:28:30 +0100 Subject: [PATCH 13/28] Cache sauce functions. --- 4chan_x.user.js | 34 +++++++++++++++++----------------- script.coffee | 26 +++++++++++++------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 278c5ea2c..60379c816 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -2588,12 +2588,24 @@ sauce = { init: function() { - var link, links, _i, _len; + var domain, fc, link, links, _i, _len; links = conf['sauces'].match(/^[^#].+$/gm); + if (!links.length) return; this.links = []; for (_i = 0, _len = links.length; _i < _len; _i++) { link = links[_i]; - this.links.push([link, link.match(/(\w+)\.\w+\//)[1]]); + domain = link.match(/(\w+)\.\w+\//)[1]; + fc = link.replace(/\$\d/, function(fragment) { + switch (fragment) { + case '$1': + return "' + img.src + '"; + case '$2': + return "' + img.parentNode.href + '"; + case '$3': + return "' + img.getAttribute('md5').replace(/\=*$/, '') + '"; + } + }); + this.links.push([Function('img', "return '" + fc + "'"), domain]); } return g.callbacks.push(this.node); }, @@ -2605,24 +2617,12 @@ for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; a = $.el('a', { - textContent: link[1], - href: sauce.href(link[0], img), - target: '_blank' + href: link[0](img), + target: '_blank', + textContent: link[1] }); $.add(span, $.tn(' '), a); } - }, - href: function(link, img) { - return link.replace(/\$\d/, function(fragment) { - switch (fragment) { - case '$1': - return img.src; - case '$2': - return img.parentNode.href; - case '$3': - return img.getAttribute('md5').replace(/\=+$/, ''); - } - }); } }; diff --git a/script.coffee b/script.coffee index d4f82c505..c2cdf082d 100644 --- a/script.coffee +++ b/script.coffee @@ -2051,31 +2051,31 @@ anonymize = sauce = init: -> - # return unless links = conf['sauces'].match /^[^#].+$/gm + return unless links.length @links = [] for link in links - @links.push [link, link.match(/(\w+)\.\w+\//)[1]] + domain = link.match(/(\w+)\.\w+\//)[1] + fc = link.replace /\$\d/, (fragment) -> + switch fragment + when '$1' + "' + img.src + '" + when '$2' + "' + img.parentNode.href + '" + when '$3' + "' + img.getAttribute('md5').replace(/\=*$/, '') + '" + @links.push [Function('img', "return '#{fc}'"), domain] g.callbacks.push @node node: (root) -> return if root.className is 'inline' or not span = $ '.filesize', root img = $ 'img', root for link in sauce.links a = $.el 'a', - textContent: link[1] - href: sauce.href link[0], img + href: link[0] img target: '_blank' + textContent: link[1] $.add span, $.tn(' '), a return - href: (link, img) -> - link.replace /\$\d/, (fragment) -> - switch fragment - when '$1' - img.src - when '$2' - img.parentNode.href - when '$3' - img.getAttribute('md5').replace /\=+$/, '' revealSpoilers = init: -> From df64f4628dab2932d1e6f6ace6881ece933055a7 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 6 Feb 2012 16:07:56 +0100 Subject: [PATCH 14/28] Add recursive filtering option. Close #128 --- 4chan_x.user.js | 8 +++++--- changelog | 1 + script.coffee | 7 ++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 60379c816..88c6e345e 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -91,6 +91,7 @@ 'Anonymize': [false, 'Make everybody anonymous'], 'Filter': [false, 'Self-moderation placebo'], 'Filter OPs': [false, 'Filter OPs along with their threads'], + 'Recursive Filtering': [false, 'Filter replies of filtered posts, recursively'], 'Reply Hiding': [true, 'Hide single replies'], 'Thread Hiding': [true, 'Hide entire threads'], 'Show Stubs': [true, 'Of hidden threads / replies'] @@ -617,9 +618,10 @@ _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { quote = _ref[_i]; - if (el = $.id(quote.hash.slice(1))) { - if (el.parentNode.parentNode.parentNode.hidden) { - _results.push($.addClass(quote, 'filtered')); + if ((el = $.id(quote.hash.slice(1))) && el.parentNode.parentNode.parentNode.hidden) { + $.addClass(quote, 'filtered'); + if (conf['Recursive Filtering']) { + _results.push(root.hidden = true); } else { _results.push(void 0); } diff --git a/changelog b/changelog index 4cff966b8..8e5766236 100644 --- a/changelog +++ b/changelog @@ -4,6 +4,7 @@ master - Mayhem Increase Sauce linking possibilites: Thumbnails, full images, MD5 hashes. + New option: Recursive Filtering: Filter replies of filtered posts. Unread Favicon is now optional, independent of Unread Count. Fix some compatibility issues with file drag and drop, notably with QuickDrag extension. diff --git a/script.coffee b/script.coffee index c2cdf082d..4cf0d2113 100644 --- a/script.coffee +++ b/script.coffee @@ -14,6 +14,7 @@ config = 'Anonymize': [false, 'Make everybody anonymous'] 'Filter': [false, 'Self-moderation placebo'] 'Filter OPs': [false, 'Filter OPs along with their threads'] + 'Recursive Filtering': [false, 'Filter replies of filtered posts, recursively'] 'Reply Hiding': [true, 'Hide single replies'] 'Thread Hiding': [true, 'Hide entire threads'] 'Show Stubs': [true, 'Of hidden threads / replies'] @@ -456,9 +457,9 @@ strikethroughQuotes = g.callbacks.push (root) -> return if root.className is 'inline' for quote in $$ '.quotelink', root - if el = $.id quote.hash[1..] - if el.parentNode.parentNode.parentNode.hidden - $.addClass quote, 'filtered' + if (el = $.id quote.hash[1..]) and el.parentNode.parentNode.parentNode.hidden + $.addClass quote, 'filtered' + root.hidden = true if conf['Recursive Filtering'] expandComment = init: -> From 1fbe52ba6755f9a4b3762830b959189ae1150464 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 6 Feb 2012 16:13:04 +0100 Subject: [PATCH 15/28] Stay classy, coffee-script. --- 4chan_x.user.js | 12 ++---------- script.coffee | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 88c6e345e..1ae193ba1 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -612,24 +612,16 @@ strikethroughQuotes = { init: function() { return g.callbacks.push(function(root) { - var el, quote, _i, _len, _ref, _results; + var el, quote, _i, _len, _ref; if (root.className === 'inline') return; _ref = $$('.quotelink', root); - _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { quote = _ref[_i]; if ((el = $.id(quote.hash.slice(1))) && el.parentNode.parentNode.parentNode.hidden) { $.addClass(quote, 'filtered'); - if (conf['Recursive Filtering']) { - _results.push(root.hidden = true); - } else { - _results.push(void 0); - } - } else { - _results.push(void 0); + if (conf['Recursive Filtering']) root.hidden = true; } } - return _results; }); } }; diff --git a/script.coffee b/script.coffee index 4cf0d2113..3606d51bb 100644 --- a/script.coffee +++ b/script.coffee @@ -460,6 +460,7 @@ strikethroughQuotes = if (el = $.id quote.hash[1..]) and el.parentNode.parentNode.parentNode.hidden $.addClass quote, 'filtered' root.hidden = true if conf['Recursive Filtering'] + return expandComment = init: -> From c5b06c7d9c43a7109b86421fd32eb6f2b757477f Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 7 Feb 2012 16:26:28 +0100 Subject: [PATCH 16/28] HOLY BALLS, load QR's iframe faster. Close #192 --- 4chan_x.user.js | 6 +++--- changelog | 1 + script.coffee | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1ae193ba1..c42d13b4a 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1207,7 +1207,7 @@ iframe = $.el('iframe', { id: 'iframe', hidden: true, - src: 'http://sys.4chan.org/post' + src: 'http://sys.4chan.org/favicon.ico' }); $.on(iframe, 'error', function() { return this.src = this.src; @@ -1216,7 +1216,7 @@ if (!qr.status.ready) { iframe.src = 'about:blank'; return setTimeout((function() { - return iframe.src = 'http://sys.4chan.org/post'; + return iframe.src = 'http://sys.4chan.org/favicon.ico'; }), 250); } }; @@ -3433,7 +3433,7 @@ } $.on(window, 'message', Main.message); if (location.hostname === 'sys.4chan.org') { - if (location.pathname === '/post') { + if (location.pathname === '/favicon.ico') { qr.message.init(); } else if (/report/.test(location.search)) { $.ready(function() { diff --git a/changelog b/changelog index 8e5766236..8ac257ce3 100644 --- a/changelog +++ b/changelog @@ -2,6 +2,7 @@ master - aeosynth prevent post form flicker - Mayhem + Load QR's iframe to sys.4chan.org faster. Thanks desuwa. Increase Sauce linking possibilites: Thumbnails, full images, MD5 hashes. New option: Recursive Filtering: Filter replies of filtered posts. diff --git a/script.coffee b/script.coffee index 3606d51bb..130757984 100644 --- a/script.coffee +++ b/script.coffee @@ -880,13 +880,13 @@ qr = iframe = $.el 'iframe', id: 'iframe' hidden: true - src: 'http://sys.4chan.org/post' + src: 'http://sys.4chan.org/favicon.ico' $.on iframe, 'error', -> @src = @src # Greasemonkey ghetto fix loadChecking = (iframe) -> unless qr.status.ready iframe.src = 'about:blank' - setTimeout (-> iframe.src = 'http://sys.4chan.org/post'), 250 + setTimeout (-> iframe.src = 'http://sys.4chan.org/favicon.ico'), 250 $.on iframe, 'load', -> unless @src is 'about:blank' then setTimeout loadChecking, 250, @ $.add d.body, iframe @@ -2660,7 +2660,7 @@ Main = $.on window, 'message', Main.message if location.hostname is 'sys.4chan.org' - if location.pathname is '/post' + if location.pathname is '/favicon.ico' qr.message.init() else if /report/.test location.search $.ready -> From 302fd108157036a646717b9f5e5592e248ef0012 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 7 Feb 2012 17:45:57 +0100 Subject: [PATCH 17/28] Fix overflow reset when closing the options with the keybind. Fix typo. --- 4chan_x.user.js | 13 +++++++------ script.coffee | 12 +++++++----- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index c42d13b4a..cf6c00458 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -890,7 +890,7 @@ break; case conf.close: if (o = $.id('overlay')) { - $.rm(o); + options.close.call(o); } else if (qr.el) { qr.close(); } @@ -2043,7 +2043,7 @@ \
    \
    Keybinds are disabled.
    \ -
    Allowed keys: Ctrl, Alt, a-z, A-Z, 0-1, Up, Down, Right, Left.
    \ +
    Allowed keys: Ctrl, Alt, a-z, A-Z, 0-9, Up, Down, Right, Left.
    \ \ \
    ActionsKeybinds
    \ @@ -2116,10 +2116,7 @@ overlay = $.el('div', { id: 'overlay' }); - $.on(overlay, 'click', function() { - d.body.style.removeProperty('overflow'); - return $.rm(overlay); - }); + $.on(overlay, 'click', options.close); $.on(dialog, 'click', function(e) { return e.stopPropagation(); }); @@ -2130,6 +2127,10 @@ options.time.call(time); return options.favicon.call(favicon); }, + close: function() { + $.rm(this); + return d.body.style.removeProperty('overflow'); + }, clearHidden: function() { $["delete"]("hiddenReplies/" + g.BOARD + "/"); $["delete"]("hiddenThreads/" + g.BOARD + "/"); diff --git a/script.coffee b/script.coffee index 130757984..05150375e 100644 --- a/script.coffee +++ b/script.coffee @@ -658,7 +658,7 @@ keybinds = options.dialog() unless $.id 'overlay' when conf.close if o = $.id 'overlay' - $.rm o + options.close.call o else if qr.el qr.close() when conf.spoiler @@ -1597,7 +1597,7 @@ options =
    Keybinds are disabled.
    -
    Allowed keys: Ctrl, Alt, a-z, A-Z, 0-1, Up, Down, Right, Left.
    +
    Allowed keys: Ctrl, Alt, a-z, A-Z, 0-9, Up, Down, Right, Left.
    ActionsKeybinds
    @@ -1660,9 +1660,7 @@ options = indicators[@name].hidden = @checked overlay = $.el 'div', id: 'overlay' - $.on overlay, 'click', -> - d.body.style.removeProperty 'overflow' - $.rm overlay + $.on overlay, 'click', options.close $.on dialog, 'click', (e) -> e.stopPropagation() $.add overlay, dialog $.add d.body, overlay @@ -1672,6 +1670,10 @@ options = options.time.call time options.favicon.call favicon + close: -> + $.rm this + d.body.style.removeProperty 'overflow' + clearHidden: -> #'hidden' might be misleading; it's the number of IDs we're *looking* for, # not the number of posts actually hidden on the page. From c7481477e16f064775618cc27111d5cd29c9c622 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 7 Feb 2012 17:48:59 +0100 Subject: [PATCH 18/28] Increase delay before checking if the script has been executed in the iframe. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index cf6c00458..8dea149ac 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1221,7 +1221,7 @@ } }; $.on(iframe, 'load', function() { - if (this.src !== 'about:blank') return setTimeout(loadChecking, 250, this); + if (this.src !== 'about:blank') return setTimeout(loadChecking, 500, this); }); $.add(d.body, iframe); if (conf['Persistent QR']) { diff --git a/script.coffee b/script.coffee index 05150375e..5788801be 100644 --- a/script.coffee +++ b/script.coffee @@ -887,7 +887,7 @@ qr = unless qr.status.ready iframe.src = 'about:blank' setTimeout (-> iframe.src = 'http://sys.4chan.org/favicon.ico'), 250 - $.on iframe, 'load', -> unless @src is 'about:blank' then setTimeout loadChecking, 250, @ + $.on iframe, 'load', -> unless @src is 'about:blank' then setTimeout loadChecking, 500, @ $.add d.body, iframe if conf['Persistent QR'] From 11522cc0d04a3ea78efd0c005d266225cf7d2cba Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 7 Feb 2012 20:28:21 +0100 Subject: [PATCH 19/28] Point out Greasemonkey's flaw. --- changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog b/changelog index 8ac257ce3..de1e73209 100644 --- a/changelog +++ b/changelog @@ -2,7 +2,7 @@ master - aeosynth prevent post form flicker - Mayhem - Load QR's iframe to sys.4chan.org faster. Thanks desuwa. + Load QR's iframe to sys.4chan.org faster, unless you use Greasemonkey. Thanks desuwa. Increase Sauce linking possibilites: Thumbnails, full images, MD5 hashes. New option: Recursive Filtering: Filter replies of filtered posts. From cce108dff38c8fa8c4bf76a098c0b47ec105097c Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 7 Feb 2012 20:41:02 +0100 Subject: [PATCH 20/28] Load robots.txt instead of favicon.ico in the iframe. --- 4chan_x.user.js | 6 +++--- script.coffee | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 8dea149ac..e99fb32a5 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1207,7 +1207,7 @@ iframe = $.el('iframe', { id: 'iframe', hidden: true, - src: 'http://sys.4chan.org/favicon.ico' + src: 'http://sys.4chan.org/robots.txt' }); $.on(iframe, 'error', function() { return this.src = this.src; @@ -1216,7 +1216,7 @@ if (!qr.status.ready) { iframe.src = 'about:blank'; return setTimeout((function() { - return iframe.src = 'http://sys.4chan.org/favicon.ico'; + return iframe.src = 'http://sys.4chan.org/robots.txt'; }), 250); } }; @@ -3434,7 +3434,7 @@ } $.on(window, 'message', Main.message); if (location.hostname === 'sys.4chan.org') { - if (location.pathname === '/favicon.ico') { + if (location.pathname === '/robots.txt') { qr.message.init(); } else if (/report/.test(location.search)) { $.ready(function() { diff --git a/script.coffee b/script.coffee index 5788801be..bf624d8d3 100644 --- a/script.coffee +++ b/script.coffee @@ -880,13 +880,13 @@ qr = iframe = $.el 'iframe', id: 'iframe' hidden: true - src: 'http://sys.4chan.org/favicon.ico' + src: 'http://sys.4chan.org/robots.txt' $.on iframe, 'error', -> @src = @src # Greasemonkey ghetto fix loadChecking = (iframe) -> unless qr.status.ready iframe.src = 'about:blank' - setTimeout (-> iframe.src = 'http://sys.4chan.org/favicon.ico'), 250 + setTimeout (-> iframe.src = 'http://sys.4chan.org/robots.txt'), 250 $.on iframe, 'load', -> unless @src is 'about:blank' then setTimeout loadChecking, 500, @ $.add d.body, iframe @@ -2662,7 +2662,7 @@ Main = $.on window, 'message', Main.message if location.hostname is 'sys.4chan.org' - if location.pathname is '/favicon.ico' + if location.pathname is '/robots.txt' qr.message.init() else if /report/.test location.search $.ready -> From a44a10055d1246d98aa4a420ab16c4c9c1256cbf Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 7 Feb 2012 20:50:35 +0100 Subject: [PATCH 21/28] Don't rely on d.head, use d.documentElement instead. --- 4chan_x.user.js | 11 ++++------- script.coffee | 7 ++----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index e99fb32a5..65d0f37b6 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1812,6 +1812,7 @@ textContent: "window.addEventListener('message'," + code + ",false)" }); ready = function() { + $.add(d.documentElement, script); if (location.hostname === 'sys.4chan.org') { qr.message.send({ req: 'status', @@ -1821,14 +1822,10 @@ return $.rm(script); }; if (d.documentElement) { - $.add(d.documentElement, script); - ready(); - return; - } - return $.ready(function() { - $.add(d.head, script); return ready(); - }); + } else { + return $.ready(ready); + } }, send: function(data) { data.changeContext = true; diff --git a/script.coffee b/script.coffee index bf624d8d3..31bd22d10 100644 --- a/script.coffee +++ b/script.coffee @@ -1400,18 +1400,15 @@ qr = parent.postMessage data, '*' script = $.el 'script', textContent: "window.addEventListener('message',#{code},false)" ready = -> + $.add d.documentElement, script if location.hostname is 'sys.4chan.org' qr.message.send req: 'status', ready: true $.rm script # Chrome can access the documentElement on document-start if d.documentElement - $.add d.documentElement, script ready() - return # other browsers will have to wait - $.ready -> - $.add d.head, script - ready() + else $.ready ready send: (data) -> data.changeContext = true data.qr = true From 1da1413b15e680417fcf80d514f1f3349bb685e7 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 8 Feb 2012 00:30:29 +0100 Subject: [PATCH 22/28] Typo. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 65d0f37b6..700c55e54 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1545,7 +1545,7 @@ case 0: return 'Verification (Shift + Enter to cache)'; case 1: - return 'Vertification (1 cached captcha)'; + return 'Verification (1 cached captcha)'; default: return "Verification (" + count + " cached captchas)"; } diff --git a/script.coffee b/script.coffee index 31bd22d10..b0f44e665 100644 --- a/script.coffee +++ b/script.coffee @@ -1154,7 +1154,7 @@ qr = when 0 'Verification (Shift + Enter to cache)' when 1 - 'Vertification (1 cached captcha)' + 'Verification (1 cached captcha)' else "Verification (#{count} cached captchas)" @input.alt = count # For XTRM RICE. From 504d03b9d2ecc3a2ccd0614ec75cb442ea1db577 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 8 Feb 2012 00:41:00 +0100 Subject: [PATCH 23/28] Don't return an archived image url if 404 redirect is disabled. Always enable image retrying on loading error. Close #196 --- 4chan_x.user.js | 3 ++- script.coffee | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 700c55e54..fe00db510 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3190,6 +3190,7 @@ if (url) return location.href = url; }, image: function(board, filename) { + if (!conf['404 Redirect']) return; switch (board) { case 'a': case 'jp': @@ -3371,7 +3372,7 @@ img = $.el('img', { src: url || a.href }); - if (conf['404 Redirect']) $.on(img, 'error', imgExpand.error); + $.on(img, 'error', imgExpand.error); return $.add(a, img); }, error: function() { diff --git a/script.coffee b/script.coffee index b0f44e665..ec4bcde14 100644 --- a/script.coffee +++ b/script.coffee @@ -2500,6 +2500,7 @@ redirect = redirect.thread() location.href = url if url image: (board, filename) -> #board must be given, the image can originate from a cross-quote + return unless conf['404 Redirect'] switch board when 'a', 'jp', 'm', 'tg', 'tv', 'u' "http://archive.foolz.us/#{board}/full_image/#{filename}" @@ -2605,7 +2606,7 @@ imgExpand = a = thumb.parentNode img = $.el 'img', src: url or a.href - $.on img, 'error', imgExpand.error if conf['404 Redirect'] + $.on img, 'error', imgExpand.error $.add a, img error: -> From eb4c557d905497fd034fc62575bb8dc132c64a14 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 8 Feb 2012 01:19:23 +0100 Subject: [PATCH 24/28] Some archive redirection refactor. Add a missing /. --- 4chan_x.user.js | 19 ++++++++++--------- script.coffee | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index fe00db510..55d88f130 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3186,22 +3186,24 @@ redirect = { init: function() { var url; - url = location.hostname === 'images.4chan.org' ? redirect.image(g.BOARD, location.pathname.split('/')[3]) : /^\d+$/.test(g.THREAD_ID) ? redirect.thread() : void 0; + url = location.hostname === 'images.4chan.org' ? redirect.image(location.href) : /^\d+$/.test(g.THREAD_ID) ? redirect.thread() : void 0; if (url) return location.href = url; }, - image: function(board, filename) { + image: function(href) { + href = href.split('/'); if (!conf['404 Redirect']) return; - switch (board) { + switch (href[3]) { case 'a': case 'jp': case 'm': case 'tg': case 'tv': case 'u': - return "http://archive.foolz.us/" + board + "/full_image/" + filename; + return "http://archive.foolz.us/" + href[3] + "/full_image/" + href[5]; } }, thread: function() { + if (!conf['404 Redirect']) return; switch (g.BOARD) { case 'a': case 'jp': @@ -3241,7 +3243,7 @@ case 'x': return "http://archive.no-ip.org/" + g.BOARD + "/thread/" + g.THREAD_ID; default: - return "http://boards.4chan.org/" + g.BOARD; + return "http://boards.4chan.org/" + g.BOARD + "/"; } } }; @@ -3376,13 +3378,12 @@ return $.add(a, img); }, error: function() { - var href, src, thumb, timeoutID, url; + var href, thumb, timeoutID, url; href = this.parentNode.href; thumb = this.previousSibling; - src = href.split('/'); imgExpand.contract(thumb); $.rm(this); - if (!(this.src.split('/')[2] === 'images.4chan.org' && (url = redirect.image(src[3], src[5])))) { + if (!(this.src.split('/')[2] === 'images.4chan.org' && (url = redirect.image(href)))) { if (g.dead) return; url = href + '?' + Date.now(); } @@ -3501,7 +3502,7 @@ }, ready: function() { var callback, form, node, nodes, _i, _j, _len, _len2, _ref; - if (conf['404 Redirect'] && d.title === '4chan - 404') { + if (d.title === '4chan - 404') { redirect.init(); return; } diff --git a/script.coffee b/script.coffee index ec4bcde14..96e128386 100644 --- a/script.coffee +++ b/script.coffee @@ -2495,16 +2495,19 @@ redirect = init: -> url = if location.hostname is 'images.4chan.org' - redirect.image g.BOARD, location.pathname.split('/')[3] + redirect.image location.href else if /^\d+$/.test g.THREAD_ID redirect.thread() location.href = url if url - image: (board, filename) -> #board must be given, the image can originate from a cross-quote + image: (href) -> + href = href.split '/' + # Do not use g.BOARD, the image url can originate from a cross-quote. return unless conf['404 Redirect'] - switch board + switch href[3] when 'a', 'jp', 'm', 'tg', 'tv', 'u' - "http://archive.foolz.us/#{board}/full_image/#{filename}" + "http://archive.foolz.us/#{href[3]}/full_image/#{href[5]}" thread: -> + return unless conf['404 Redirect'] switch g.BOARD when 'a', 'jp', 'm', 'tg', 'tv', 'u' "http://archive.foolz.us/#{g.BOARD}/thread/#{g.THREAD_ID}/" @@ -2515,7 +2518,7 @@ redirect = when '3', 'adv', 'an', 'ck', 'co', 'fa', 'fit', 'int', 'k', 'mu', 'n', 'o', 'p', 'po', 'pol', 'r9k', 'soc', 'sp', 'toy', 'trv', 'v', 'vp', 'x' "http://archive.no-ip.org/#{g.BOARD}/thread/#{g.THREAD_ID}" else - "http://boards.4chan.org/#{g.BOARD}" + "http://boards.4chan.org/#{g.BOARD}/" imgHover = init: -> @@ -2612,10 +2615,9 @@ imgExpand = error: -> href = @parentNode.href thumb = @previousSibling - src = href.split '/' imgExpand.contract thumb $.rm @ - unless @src.split('/')[2] is 'images.4chan.org' and url = redirect.image src[3], src[5] + unless @src.split('/')[2] is 'images.4chan.org' and url = redirect.image href return if g.dead # CloudFlare may cache banned pages instead of images. # This will fool CloudFlare's cache. @@ -2751,7 +2753,7 @@ Main = $.ready Main.ready ready: -> - if conf['404 Redirect'] and d.title is '4chan - 404' + if d.title is '4chan - 404' redirect.init() return if not $.id 'navtopr' From 84dbb47ea8493791a4c840fce0e5e9fe57aa9dd9 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 8 Feb 2012 01:45:37 +0100 Subject: [PATCH 25/28] Sync persona between tabs only if the QR's closed. Close #191 --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 55d88f130..fea38dfc1 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1649,7 +1649,7 @@ } $.sync('qr.persona', function(persona) { var key, val, _results; - if (qr.replies.length !== 1) return; + if (!qr.el.hidden) return; _results = []; for (key in persona) { val = persona[key]; diff --git a/script.coffee b/script.coffee index 96e128386..d569fc9f1 100644 --- a/script.coffee +++ b/script.coffee @@ -1234,7 +1234,7 @@ qr = $.on input, 'change', -> qr.selected[@name] = @value # sync between tabs $.sync 'qr.persona', (persona) -> - return if qr.replies.length isnt 1 + return unless qr.el.hidden for key, val of persona qr.selected[key] = val $("[name=#{key}]", qr.el).value = val From ce20c769b25bf35ccfdc7994960aca24ccd7cc0e Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 8 Feb 2012 18:25:32 +0100 Subject: [PATCH 26/28] Even simpler favicon refresh. --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index fea38dfc1..43ea8a696 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3141,7 +3141,7 @@ if (conf['Unread Count']) d.title = "(" + count + ") " + unread.title; if (!(conf['Unread Favicon'] && count < 2 || forceUpdate)) return; Favicon.el.href = g.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"]; - if (engine !== 'webkit') return $.add(d.head, $.rm(Favicon.el)); + if (engine !== 'webkit') return $.add(d.head, Favicon.el); } }; diff --git a/script.coffee b/script.coffee index d569fc9f1..4c247e293 100644 --- a/script.coffee +++ b/script.coffee @@ -2457,7 +2457,7 @@ unread = #`favicon.href = href` isn't enough on Opera #Opera won't always update the favicon if the href didn't not change if engine isnt 'webkit' - $.add d.head, $.rm Favicon.el + $.add d.head, Favicon.el Favicon = init: -> From 53c4568fb380fa6a26d3fdaf592eeada701e30bb Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Wed, 8 Feb 2012 19:37:13 +0100 Subject: [PATCH 27/28] Previous commit's infinitely faster on Chrome. Drop the conditional. --- 4chan_x.user.js | 2 +- script.coffee | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 43ea8a696..7938a682d 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3141,7 +3141,7 @@ if (conf['Unread Count']) d.title = "(" + count + ") " + unread.title; if (!(conf['Unread Favicon'] && count < 2 || forceUpdate)) return; Favicon.el.href = g.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"]; - if (engine !== 'webkit') return $.add(d.head, Favicon.el); + return $.add(d.head, Favicon.el); } }; diff --git a/script.coffee b/script.coffee index 4c247e293..7c7beaa4a 100644 --- a/script.coffee +++ b/script.coffee @@ -2456,8 +2456,7 @@ unread = #`favicon.href = href` doesn't work on Firefox #`favicon.href = href` isn't enough on Opera #Opera won't always update the favicon if the href didn't not change - if engine isnt 'webkit' - $.add d.head, Favicon.el + $.add d.head, Favicon.el Favicon = init: -> From 164285ec16271730173487a954364094c71802ff Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Fri, 10 Feb 2012 00:03:18 +0100 Subject: [PATCH 28/28] Less "awkward" qr links. Close #199 --- 4chan_x.user.js | 2 +- script.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 7938a682d..2a88e5d3a 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -1192,7 +1192,7 @@ if (!$.id('recaptcha_challenge_field_holder')) return; if (conf['Hide Original Post Form']) { link = $.el('h1', { - innerHTML: "" + (g.REPLY ? 'Open the Quick Reply' : 'Create a New Thread') + "" + innerHTML: "" + (g.REPLY ? 'Quick Reply' : 'New Thread') + "" }); $.on($('a', link), 'click', function() { qr.open(); diff --git a/script.coffee b/script.coffee index 7c7beaa4a..cbf62db6b 100644 --- a/script.coffee +++ b/script.coffee @@ -868,7 +868,7 @@ qr = init: -> return unless $.id 'recaptcha_challenge_field_holder' if conf['Hide Original Post Form'] - link = $.el 'h1', innerHTML: "#{if g.REPLY then 'Open the Quick Reply' else 'Create a New Thread'}" + link = $.el 'h1', innerHTML: "#{if g.REPLY then 'Quick Reply' else 'New Thread'}" $.on $('a', link), 'click', -> qr.open() $('textarea', qr.el).focus()