Reduce recalculation needed for RelativeDates

Capture more state in closure scopes. Pretty clever, at the expense of
simplicity.
This commit is contained in:
queue 2013-02-07 10:31:35 -07:00
parent b49664a11a
commit bed90cfd03
2 changed files with 58 additions and 35 deletions

View File

@ -3558,11 +3558,11 @@
node: function(post) { node: function(post) {
var dateEl, diff, utc; var dateEl, diff, utc;
dateEl = $('.postInfo > .dateTime', post.el); dateEl = $('.postInfo > .dateTime', post.el);
utc = dateEl.dataset.utc * 1000;
dateEl.title = dateEl.textContent; dateEl.title = dateEl.textContent;
utc = dateEl.dataset.utc * 1000;
diff = Date.now() - utc; diff = Date.now() - utc;
dateEl.textContent = RelativeDates.relative(diff); dateEl.textContent = RelativeDates.relative(diff);
RelativeDates.setUpdate(dateEl, diff); RelativeDates.setUpdate(dateEl, utc, diff);
return RelativeDates.flush(); return RelativeDates.flush();
}, },
relative: function(diff) { relative: function(diff) {
@ -3576,29 +3576,38 @@
}, },
stale: [], stale: [],
flush: $.debounce($.SECOND, function() { flush: $.debounce($.SECOND, function() {
var dateEl, diff, _i, _len, _ref; var now, update, _i, _len, _ref;
if (d.hidden) { if (d.hidden) {
return; return;
} }
now = Date.now();
_ref = RelativeDates.stale; _ref = RelativeDates.stale;
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
dateEl = _ref[_i]; update = _ref[_i];
if (d.contains(dateEl)) { update(now);
diff = Date.now() - dateEl.dataset.utc * 1000;
dateEl.textContent = RelativeDates.relative(diff);
RelativeDates.setUpdate(dateEl, diff);
}
} }
RelativeDates.stale = []; RelativeDates.stale = [];
clearTimeout(RelativeDates.timeout); clearTimeout(RelativeDates.timeout);
return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL); return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL);
}), }),
setUpdate: function(dateEl, diff) { setUpdate: function(dateEl, utc, diff) {
var markStale, setOwnTimeout, update;
setOwnTimeout = function(diff) {
var delay; var delay;
delay = diff > $.HOUR ? diff % $.HOUR : diff > $.MINUTE ? diff % $.MINUTE : diff % $.SECOND; delay = diff > $.HOUR ? diff % $.HOUR : diff > $.MINUTE ? diff % $.MINUTE : diff % $.SECOND;
return setTimeout((function() { return setTimeout(markStale, delay);
return RelativeDates.stale.push(dateEl); };
}), 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);
} }
}; };

View File

@ -2849,17 +2849,18 @@ RelativeDates =
node: (post) -> node: (post) ->
dateEl = $ '.postInfo > .dateTime', post.el dateEl = $ '.postInfo > .dateTime', post.el
utc = dateEl.dataset.utc * 1000 # convert data-utc to milliseconds
# Show original absolute time as tooltip so users can still know exact times # Show original absolute time as tooltip so users can still know exact times
# Since "Time Formatting" runs `node` before us, the title tooltip will # Since "Time Formatting" runs `node` before us, the title tooltip will
# pick up the user-formatted time instead of 4chan time when enabled. # pick up the user-formatted time instead of 4chan time when enabled.
dateEl.title = dateEl.textContent dateEl.title = dateEl.textContent
# convert data-utc to milliseconds
utc = dateEl.dataset.utc * 1000
diff = Date.now() - utc diff = Date.now() - utc
dateEl.textContent = RelativeDates.relative diff dateEl.textContent = RelativeDates.relative diff
RelativeDates.setUpdate dateEl, diff RelativeDates.setUpdate dateEl, utc, diff
# Main calls @node whenever a DOM node is added (update, inline post, # Main calls @node whenever a DOM node is added (update, inline post,
# whatever), so use also this reflow opportunity to flush any other dates # whatever), so use also this reflow opportunity to flush any other dates
@ -2889,31 +2890,44 @@ RelativeDates =
# stuttering won't be noticed), falling back to INTERVAL while the page # stuttering won't be noticed), falling back to INTERVAL while the page
# is visible. # is visible.
# #
# each individual dateTime element will be added to the stale list when it # each individual dateTime element will add its update() function to the stale list
# needs to change. # when it to be called.
stale: [] stale: []
flush: $.debounce($.SECOND, -> flush: $.debounce($.SECOND, ->
# no point in changing the dates until the user sees them # no point in changing the dates until the user sees them
return if d.hidden return if d.hidden
for dateEl in RelativeDates.stale
if d.contains dateEl # not removed from DOM now = Date.now()
diff = Date.now() - dateEl.dataset.utc * 1000 update now for update in RelativeDates.stale
dateEl.textContent = RelativeDates.relative diff
RelativeDates.setUpdate dateEl, diff
RelativeDates.stale = [] RelativeDates.stale = []
# reset automatic flush
clearTimeout RelativeDates.timeout clearTimeout RelativeDates.timeout
RelativeDates.timeout = setTimeout RelativeDates.flush, RelativeDates.INTERVAL) RelativeDates.timeout = setTimeout RelativeDates.flush, RelativeDates.INTERVAL)
# Add element to stale list when the relative date string would change # create function `update()`, closed over dateEl and diff, that, when called
# diff is in milliseconds between dateEl and now # from `flush()`, updates the element, and re-calls `setOwnTimeout()` to
setUpdate: (dateEl, diff) -> # re-add `update()` to the stale list later.
setUpdate: (dateEl, utc, diff) ->
setOwnTimeout = (diff) ->
delay = if diff > $.HOUR delay = if diff > $.HOUR
diff % $.HOUR diff % $.HOUR
else if diff > $.MINUTE else if diff > $.MINUTE
diff % $.MINUTE diff % $.MINUTE
else else
diff % $.SECOND diff % $.SECOND
setTimeout (-> RelativeDates.stale.push dateEl), delay 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: ->