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