Merge pull request #897 from qqueue/relativedate
Relative Dates, close #758
This commit is contained in:
commit
0a9c2ff75c
111
4chan_x.user.js
111
4chan_x.user.js
@ -81,7 +81,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var $, $$, Anonymize, ArchiveLink, AutoGif, Build, CatalogLinks, Conf, Config, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Get, ImageExpand, ImageHover, Keybinds, Main, Menu, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, ReplyHiding, ReportLink, RevealSpoilers, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Time, TitlePost, UI, Unread, Updater, Watcher, d, g, _base;
|
var $, $$, Anonymize, ArchiveLink, AutoGif, Build, CatalogLinks, Conf, Config, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Get, ImageExpand, ImageHover, Keybinds, Main, Menu, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, RelativeDates, ReplyHiding, ReportLink, RevealSpoilers, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Time, TitlePost, UI, Unread, Updater, Watcher, d, g, _base;
|
||||||
|
|
||||||
Config = {
|
Config = {
|
||||||
main: {
|
main: {
|
||||||
@ -91,6 +91,7 @@
|
|||||||
'404 Redirect': [true, 'Redirect dead threads and images'],
|
'404 Redirect': [true, 'Redirect dead threads and images'],
|
||||||
'Keybinds': [true, 'Binds actions to keys'],
|
'Keybinds': [true, 'Binds actions to keys'],
|
||||||
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time'],
|
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time'],
|
||||||
|
'Relative Post Dates': [false, 'Display post times as "3 minutes ago" or similar. Hover tooltip will display the original or formatted timestamp'],
|
||||||
'File Info Formatting': [true, 'Reformats the file information'],
|
'File Info Formatting': [true, 'Reformats the file information'],
|
||||||
'Comment Expansion': [true, 'Expand too long comments'],
|
'Comment Expansion': [true, 'Expand too long comments'],
|
||||||
'Thread Expansion': [true, 'View all replies'],
|
'Thread Expansion': [true, 'View all replies'],
|
||||||
@ -516,8 +517,19 @@
|
|||||||
size = unit > 1 ? Math.round(size * 100) / 100 : Math.round(size);
|
size = unit > 1 ? Math.round(size * 100) / 100 : Math.round(size);
|
||||||
return "" + size + " " + ['B', 'KB', 'MB', 'GB'][unit];
|
return "" + size + " " + ['B', 'KB', 'MB', 'GB'][unit];
|
||||||
},
|
},
|
||||||
hidden: function() {
|
debounce: function(wait, fn) {
|
||||||
return d.hidden || d.oHidden || d.mozHidden || d.webkitHidden;
|
var timeout;
|
||||||
|
timeout = null;
|
||||||
|
return function() {
|
||||||
|
if (timeout) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
} else {
|
||||||
|
fn.apply(this, arguments);
|
||||||
|
}
|
||||||
|
return timeout = setTimeout((function() {
|
||||||
|
return timeout = null;
|
||||||
|
}), wait);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1841,7 +1853,7 @@
|
|||||||
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
||||||
$('[autocomplete]', QR.el).focus();
|
$('[autocomplete]', QR.el).focus();
|
||||||
}
|
}
|
||||||
if ($.hidden()) {
|
if (d.hidden) {
|
||||||
return alert(el.textContent);
|
return alert(el.textContent);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3033,7 +3045,7 @@
|
|||||||
}
|
}
|
||||||
$.add(d.body, dialog);
|
$.add(d.body, dialog);
|
||||||
$.on(d, 'QRPostSuccessful', this.cb.post);
|
$.on(d, 'QRPostSuccessful', this.cb.post);
|
||||||
return $.on(d, 'visibilitychange ovisibilitychange mozvisibilitychange webkitvisibilitychange', this.cb.visibility);
|
return $.on(d, 'visibilitychange', this.cb.visibility);
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
http://freesound.org/people/pierrecartoons1979/sounds/90112/
|
http://freesound.org/people/pierrecartoons1979/sounds/90112/
|
||||||
@ -3052,7 +3064,7 @@
|
|||||||
return setTimeout(Updater.update, 500);
|
return setTimeout(Updater.update, 500);
|
||||||
},
|
},
|
||||||
visibility: function() {
|
visibility: function() {
|
||||||
if ($.hidden()) {
|
if (d.hidden) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Updater.unsuccessfulFetchCount = 0;
|
Updater.unsuccessfulFetchCount = 0;
|
||||||
@ -3088,7 +3100,7 @@
|
|||||||
return Updater.scrollBG = this.checked ? function() {
|
return Updater.scrollBG = this.checked ? function() {
|
||||||
return true;
|
return true;
|
||||||
} : function() {
|
} : function() {
|
||||||
return !$.hidden();
|
return !d.hidden;
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
load: function() {
|
load: function() {
|
||||||
@ -3159,7 +3171,7 @@
|
|||||||
Updater.count.className = count ? 'new' : null;
|
Updater.count.className = count ? 'new' : null;
|
||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
if (Conf['Beep'] && $.hidden() && (Unread.replies.length === 0)) {
|
if (Conf['Beep'] && d.hidden && (Unread.replies.length === 0)) {
|
||||||
Updater.audio.play();
|
Updater.audio.play();
|
||||||
}
|
}
|
||||||
Updater.unsuccessfulFetchCount = 0;
|
Updater.unsuccessfulFetchCount = 0;
|
||||||
@ -3187,7 +3199,7 @@
|
|||||||
var i, j;
|
var i, j;
|
||||||
i = +Conf['Interval'];
|
i = +Conf['Interval'];
|
||||||
j = Math.min(this.unsuccessfulFetchCount, 9);
|
j = Math.min(this.unsuccessfulFetchCount, 9);
|
||||||
if (!$.hidden()) {
|
if (!d.hidden) {
|
||||||
j = Math.min(j, 6);
|
j = Math.min(j, 6);
|
||||||
}
|
}
|
||||||
return Math.max(i, [5, 10, 15, 20, 30, 60, 90, 120, 240, 300][j]);
|
return Math.max(i, [5, 10, 15, 20, 30, 60, 90, 120, 240, 300][j]);
|
||||||
@ -3537,6 +3549,68 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RelativeDates = {
|
||||||
|
INTERVAL: $.MINUTE,
|
||||||
|
init: function() {
|
||||||
|
Main.callbacks.push(this.node);
|
||||||
|
return $.on(d, 'visibilitychange', this.flush);
|
||||||
|
},
|
||||||
|
node: function(post) {
|
||||||
|
var dateEl, diff, utc;
|
||||||
|
dateEl = $('.postInfo > .dateTime', post.el);
|
||||||
|
dateEl.title = dateEl.textContent;
|
||||||
|
utc = dateEl.dataset.utc * 1000;
|
||||||
|
diff = Date.now() - utc;
|
||||||
|
dateEl.textContent = RelativeDates.relative(diff);
|
||||||
|
RelativeDates.setUpdate(dateEl, utc, diff);
|
||||||
|
return RelativeDates.flush();
|
||||||
|
},
|
||||||
|
relative: function(diff) {
|
||||||
|
var number, rounded, unit;
|
||||||
|
unit = (number = diff / $.DAY) > 1 ? 'day' : (number = diff / $.HOUR) > 1 ? 'hour' : (number = diff / $.MINUTE) > 1 ? 'minute' : (number = diff / $.SECOND, 'second');
|
||||||
|
rounded = Math.round(number);
|
||||||
|
if (rounded !== 1) {
|
||||||
|
unit += 's';
|
||||||
|
}
|
||||||
|
return "" + rounded + " " + unit + " ago";
|
||||||
|
},
|
||||||
|
stale: [],
|
||||||
|
flush: $.debounce($.SECOND, function() {
|
||||||
|
var now, update, _i, _len, _ref;
|
||||||
|
if (d.hidden) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
now = Date.now();
|
||||||
|
_ref = RelativeDates.stale;
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
update = _ref[_i];
|
||||||
|
update(now);
|
||||||
|
}
|
||||||
|
RelativeDates.stale = [];
|
||||||
|
clearTimeout(RelativeDates.timeout);
|
||||||
|
return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL);
|
||||||
|
}),
|
||||||
|
setUpdate: function(dateEl, utc, diff) {
|
||||||
|
var markStale, setOwnTimeout, update;
|
||||||
|
setOwnTimeout = function(diff) {
|
||||||
|
var delay;
|
||||||
|
delay = diff > $.HOUR ? diff % $.HOUR : diff > $.MINUTE ? diff % $.MINUTE : diff % $.SECOND;
|
||||||
|
return setTimeout(markStale, delay);
|
||||||
|
};
|
||||||
|
update = function(now) {
|
||||||
|
if (d.contains(dateEl)) {
|
||||||
|
diff = now - utc;
|
||||||
|
dateEl.textContent = RelativeDates.relative(diff);
|
||||||
|
return setOwnTimeout(diff);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
markStale = function() {
|
||||||
|
return RelativeDates.stale.push(update);
|
||||||
|
};
|
||||||
|
return setOwnTimeout(diff);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
FileInfo = {
|
FileInfo = {
|
||||||
init: function() {
|
init: function() {
|
||||||
if (g.BOARD === 'f') {
|
if (g.BOARD === 'f') {
|
||||||
@ -5307,12 +5381,28 @@
|
|||||||
settings.disableAll = true;
|
settings.disableAll = true;
|
||||||
localStorage.setItem('4chan-settings', JSON.stringify(settings));
|
localStorage.setItem('4chan-settings', JSON.stringify(settings));
|
||||||
}
|
}
|
||||||
|
Main.polyfill();
|
||||||
if (g.CATALOG) {
|
if (g.CATALOG) {
|
||||||
return $.ready(Main.catalog);
|
return $.ready(Main.catalog);
|
||||||
} else {
|
} else {
|
||||||
return Main.features();
|
return Main.features();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
polyfill: function() {
|
||||||
|
var event, prefix, property;
|
||||||
|
if (!('visibilityState' in document)) {
|
||||||
|
prefix = 'mozVisibilityState' in document ? 'moz' : 'webkitvisibilityState' in document ? 'webkit' : 'o';
|
||||||
|
property = prefix + 'VisibilityState';
|
||||||
|
event = prefix + 'visibilitychange';
|
||||||
|
d.visibilityState = d[property];
|
||||||
|
d.hidden = d.visibilityState === 'hidden';
|
||||||
|
return $.on(d, event, function() {
|
||||||
|
d.visibilityState = d[property];
|
||||||
|
d.hidden = d.visibilityState === 'hidden';
|
||||||
|
return $.event(d, new CustomEvent('visibilitychange'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
catalog: function() {
|
catalog: function() {
|
||||||
if (Conf['Catalog Links']) {
|
if (Conf['Catalog Links']) {
|
||||||
CatalogLinks.init();
|
CatalogLinks.init();
|
||||||
@ -5374,6 +5464,9 @@
|
|||||||
if (Conf['Time Formatting']) {
|
if (Conf['Time Formatting']) {
|
||||||
Time.init();
|
Time.init();
|
||||||
}
|
}
|
||||||
|
if (Conf['Relative Post Dates']) {
|
||||||
|
RelativeDates.init();
|
||||||
|
}
|
||||||
if (Conf['File Info Formatting']) {
|
if (Conf['File Info Formatting']) {
|
||||||
FileInfo.init();
|
FileInfo.init();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
master
|
master
|
||||||
- Mayhem
|
- Mayhem
|
||||||
Add /int/ archive redirection for threads, and post resurrection.
|
Add /int/ archive redirection for threads, and post resurrection.
|
||||||
|
- Queue
|
||||||
|
Add relative time ("35 seconds ago") date formatting option.
|
||||||
|
|
||||||
2.37.6
|
2.37.6
|
||||||
- Mayhem
|
- Mayhem
|
||||||
|
|||||||
143
script.coffee
143
script.coffee
@ -6,6 +6,7 @@ Config =
|
|||||||
'404 Redirect': [true, 'Redirect dead threads and images']
|
'404 Redirect': [true, 'Redirect dead threads and images']
|
||||||
'Keybinds': [true, 'Binds actions to keys']
|
'Keybinds': [true, 'Binds actions to keys']
|
||||||
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time']
|
'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time']
|
||||||
|
'Relative Post Dates': [false, 'Display post times as "3 minutes ago" or similar. Hover tooltip will display the original or formatted timestamp']
|
||||||
'File Info Formatting': [true, 'Reformats the file information']
|
'File Info Formatting': [true, 'Reformats the file information']
|
||||||
'Comment Expansion': [true, 'Expand too long comments']
|
'Comment Expansion': [true, 'Expand too long comments']
|
||||||
'Thread Expansion': [true, 'View all replies']
|
'Thread Expansion': [true, 'View all replies']
|
||||||
@ -397,8 +398,19 @@ $.extend $,
|
|||||||
# Round to an integer otherwise.
|
# Round to an integer otherwise.
|
||||||
Math.round size
|
Math.round size
|
||||||
"#{size} #{['B', 'KB', 'MB', 'GB'][unit]}"
|
"#{size} #{['B', 'KB', 'MB', 'GB'][unit]}"
|
||||||
hidden: ->
|
# a function that will execute at most every 'wait' ms. executes immediately
|
||||||
d.hidden or d.oHidden or d.mozHidden or d.webkitHidden
|
# if possible, else discards invocation
|
||||||
|
debounce: (wait, fn) ->
|
||||||
|
timeout = null
|
||||||
|
return ->
|
||||||
|
if timeout
|
||||||
|
# stop current reset
|
||||||
|
clearTimeout timeout
|
||||||
|
else
|
||||||
|
fn.apply this, arguments
|
||||||
|
|
||||||
|
# after wait, let next invocation execute immediately
|
||||||
|
timeout = setTimeout (-> timeout = null), wait
|
||||||
|
|
||||||
$.cache.requests = {}
|
$.cache.requests = {}
|
||||||
|
|
||||||
@ -1422,7 +1434,7 @@ QR =
|
|||||||
if QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
|
if QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
|
||||||
# Focus the captcha input on captcha error.
|
# Focus the captcha input on captcha error.
|
||||||
$('[autocomplete]', QR.el).focus()
|
$('[autocomplete]', QR.el).focus()
|
||||||
alert el.textContent if $.hidden()
|
alert el.textContent if d.hidden
|
||||||
cleanError: ->
|
cleanError: ->
|
||||||
$('.warning', QR.el).textContent = null
|
$('.warning', QR.el).textContent = null
|
||||||
|
|
||||||
@ -2458,7 +2470,7 @@ Updater =
|
|||||||
$.add d.body, dialog
|
$.add d.body, dialog
|
||||||
|
|
||||||
$.on d, 'QRPostSuccessful', @cb.post
|
$.on d, 'QRPostSuccessful', @cb.post
|
||||||
$.on d, 'visibilitychange ovisibilitychange mozvisibilitychange webkitvisibilitychange', @cb.visibility
|
$.on d, 'visibilitychange', @cb.visibility
|
||||||
|
|
||||||
###
|
###
|
||||||
http://freesound.org/people/pierrecartoons1979/sounds/90112/
|
http://freesound.org/people/pierrecartoons1979/sounds/90112/
|
||||||
@ -2472,7 +2484,7 @@ Updater =
|
|||||||
Updater.unsuccessfulFetchCount = 0
|
Updater.unsuccessfulFetchCount = 0
|
||||||
setTimeout Updater.update, 500
|
setTimeout Updater.update, 500
|
||||||
visibility: ->
|
visibility: ->
|
||||||
return if $.hidden()
|
return if d.hidden
|
||||||
# Reset the counter when we focus this tab.
|
# Reset the counter when we focus this tab.
|
||||||
Updater.unsuccessfulFetchCount = 0
|
Updater.unsuccessfulFetchCount = 0
|
||||||
if Updater.timer.textContent < -Conf['Interval']
|
if Updater.timer.textContent < -Conf['Interval']
|
||||||
@ -2500,7 +2512,7 @@ Updater =
|
|||||||
if @checked
|
if @checked
|
||||||
-> true
|
-> true
|
||||||
else
|
else
|
||||||
-> ! $.hidden()
|
-> ! d.hidden
|
||||||
load: ->
|
load: ->
|
||||||
switch @status
|
switch @status
|
||||||
when 404
|
when 404
|
||||||
@ -2555,7 +2567,7 @@ Updater =
|
|||||||
Updater.count.className = if count then 'new' else null
|
Updater.count.className = if count then 'new' else null
|
||||||
|
|
||||||
if count
|
if count
|
||||||
if Conf['Beep'] and $.hidden() and (Unread.replies.length is 0)
|
if Conf['Beep'] and d.hidden and (Unread.replies.length is 0)
|
||||||
Updater.audio.play()
|
Updater.audio.play()
|
||||||
Updater.unsuccessfulFetchCount = 0
|
Updater.unsuccessfulFetchCount = 0
|
||||||
else
|
else
|
||||||
@ -2580,7 +2592,7 @@ Updater =
|
|||||||
getInterval: ->
|
getInterval: ->
|
||||||
i = +Conf['Interval']
|
i = +Conf['Interval']
|
||||||
j = Math.min @unsuccessfulFetchCount, 9
|
j = Math.min @unsuccessfulFetchCount, 9
|
||||||
unless $.hidden()
|
unless d.hidden
|
||||||
# Don't increase the refresh rate too much on visible tabs.
|
# Don't increase the refresh rate too much on visible tabs.
|
||||||
j = Math.min j, 6
|
j = Math.min j, 6
|
||||||
Math.max i, [5, 10, 15, 20, 30, 60, 90, 120, 240, 300][j]
|
Math.max i, [5, 10, 15, 20, 30, 60, 90, 120, 240, 300][j]
|
||||||
@ -2827,6 +2839,96 @@ Time =
|
|||||||
S: -> Time.zeroPad Time.date.getSeconds()
|
S: -> Time.zeroPad Time.date.getSeconds()
|
||||||
y: -> Time.date.getFullYear() - 2000
|
y: -> Time.date.getFullYear() - 2000
|
||||||
|
|
||||||
|
RelativeDates =
|
||||||
|
INTERVAL: $.MINUTE
|
||||||
|
init: ->
|
||||||
|
Main.callbacks.push @node
|
||||||
|
|
||||||
|
# flush when page becomes visible again
|
||||||
|
$.on d, 'visibilitychange', @flush
|
||||||
|
node: (post) ->
|
||||||
|
dateEl = $ '.postInfo > .dateTime', post.el
|
||||||
|
|
||||||
|
# Show original absolute time as tooltip so users can still know exact times
|
||||||
|
# Since "Time Formatting" runs `node` before us, the title tooltip will
|
||||||
|
# pick up the user-formatted time instead of 4chan time when enabled.
|
||||||
|
dateEl.title = dateEl.textContent
|
||||||
|
|
||||||
|
# convert data-utc to milliseconds
|
||||||
|
utc = dateEl.dataset.utc * 1000
|
||||||
|
|
||||||
|
diff = Date.now() - utc
|
||||||
|
|
||||||
|
dateEl.textContent = RelativeDates.relative diff
|
||||||
|
RelativeDates.setUpdate dateEl, utc, diff
|
||||||
|
|
||||||
|
# Main calls @node whenever a DOM node is added (update, inline post,
|
||||||
|
# whatever), so use also this reflow opportunity to flush any other dates
|
||||||
|
# flush is debounced, so this won't burn too much cpu
|
||||||
|
RelativeDates.flush()
|
||||||
|
|
||||||
|
# diff is milliseconds from now
|
||||||
|
relative: (diff) ->
|
||||||
|
unit = if (number = (diff / $.DAY)) > 1
|
||||||
|
'day'
|
||||||
|
else if (number = (diff / $.HOUR)) > 1
|
||||||
|
'hour'
|
||||||
|
else if (number = (diff / $.MINUTE)) > 1
|
||||||
|
'minute'
|
||||||
|
else
|
||||||
|
number = diff / $.SECOND
|
||||||
|
'second'
|
||||||
|
|
||||||
|
rounded = Math.round number
|
||||||
|
unit += 's' if rounded isnt 1 # pluralize
|
||||||
|
|
||||||
|
"#{rounded} #{unit} ago"
|
||||||
|
|
||||||
|
# changing all relative dates as soon as possible incurs many annoying
|
||||||
|
# redraws and scroll stuttering. Thus, sacrifice accuracy for UX/CPU economy,
|
||||||
|
# and perform redraws when the DOM is otherwise being manipulated (and scroll
|
||||||
|
# stuttering won't be noticed), falling back to INTERVAL while the page
|
||||||
|
# is visible.
|
||||||
|
#
|
||||||
|
# each individual dateTime element will add its update() function to the stale list
|
||||||
|
# when it to be called.
|
||||||
|
stale: []
|
||||||
|
flush: $.debounce($.SECOND, ->
|
||||||
|
# no point in changing the dates until the user sees them
|
||||||
|
return if d.hidden
|
||||||
|
|
||||||
|
now = Date.now()
|
||||||
|
update now for update in RelativeDates.stale
|
||||||
|
RelativeDates.stale = []
|
||||||
|
|
||||||
|
# reset automatic flush
|
||||||
|
clearTimeout RelativeDates.timeout
|
||||||
|
RelativeDates.timeout = setTimeout RelativeDates.flush, RelativeDates.INTERVAL)
|
||||||
|
|
||||||
|
# create function `update()`, closed over dateEl and diff, that, when called
|
||||||
|
# from `flush()`, updates the element, and re-calls `setOwnTimeout()` to
|
||||||
|
# re-add `update()` to the stale list later.
|
||||||
|
setUpdate: (dateEl, utc, diff) ->
|
||||||
|
setOwnTimeout = (diff) ->
|
||||||
|
delay = if diff > $.HOUR
|
||||||
|
diff % $.HOUR
|
||||||
|
else if diff > $.MINUTE
|
||||||
|
diff % $.MINUTE
|
||||||
|
else
|
||||||
|
diff % $.SECOND
|
||||||
|
setTimeout markStale, delay
|
||||||
|
|
||||||
|
update = (now) ->
|
||||||
|
if d.contains dateEl # not removed from DOM
|
||||||
|
diff = now - utc
|
||||||
|
dateEl.textContent = RelativeDates.relative diff
|
||||||
|
setOwnTimeout diff
|
||||||
|
|
||||||
|
markStale = -> RelativeDates.stale.push update
|
||||||
|
|
||||||
|
# kick off initial timeout with current diff
|
||||||
|
setOwnTimeout diff
|
||||||
|
|
||||||
FileInfo =
|
FileInfo =
|
||||||
init: ->
|
init: ->
|
||||||
return if g.BOARD is 'f'
|
return if g.BOARD is 'f'
|
||||||
@ -4274,11 +4376,33 @@ Main =
|
|||||||
settings.disableAll = true
|
settings.disableAll = true
|
||||||
localStorage.setItem '4chan-settings', JSON.stringify settings
|
localStorage.setItem '4chan-settings', JSON.stringify settings
|
||||||
|
|
||||||
|
Main.polyfill()
|
||||||
|
|
||||||
if g.CATALOG
|
if g.CATALOG
|
||||||
$.ready Main.catalog
|
$.ready Main.catalog
|
||||||
else
|
else
|
||||||
Main.features()
|
Main.features()
|
||||||
|
|
||||||
|
polyfill: ->
|
||||||
|
# page visibility API
|
||||||
|
unless 'visibilityState' of document
|
||||||
|
prefix = if 'mozVisibilityState' of document
|
||||||
|
'moz'
|
||||||
|
else if 'webkitvisibilityState' of document
|
||||||
|
'webkit'
|
||||||
|
else
|
||||||
|
'o'
|
||||||
|
|
||||||
|
property = prefix + 'VisibilityState'
|
||||||
|
event = prefix + 'visibilitychange'
|
||||||
|
|
||||||
|
d.visibilityState = d[property]
|
||||||
|
d.hidden = d.visibilityState is 'hidden'
|
||||||
|
$.on d, event, ->
|
||||||
|
d.visibilityState = d[property]
|
||||||
|
d.hidden = d.visibilityState is 'hidden'
|
||||||
|
$.event d, new CustomEvent 'visibilitychange'
|
||||||
|
|
||||||
catalog: ->
|
catalog: ->
|
||||||
if Conf['Catalog Links']
|
if Conf['Catalog Links']
|
||||||
CatalogLinks.init()
|
CatalogLinks.init()
|
||||||
@ -4337,6 +4461,9 @@ Main =
|
|||||||
if Conf['Time Formatting']
|
if Conf['Time Formatting']
|
||||||
Time.init()
|
Time.init()
|
||||||
|
|
||||||
|
if Conf['Relative Post Dates']
|
||||||
|
RelativeDates.init()
|
||||||
|
|
||||||
if Conf['File Info Formatting']
|
if Conf['File Info Formatting']
|
||||||
FileInfo.init()
|
FileInfo.init()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user