-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fuzzy time #341
Fuzzy time #341
Changes from 15 commits
cf12b3a
2f896e7
e4fbbcc
a183c52
4756ae0
f2b18ad
ef24d0c
7f2bdca
a893ce9
f243396
954d519
44b9ee3
20bdae5
361d8f0
59b993f
3aed6e4
75198a5
619ba72
c8a4ea1
d74c5c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/** | ||
* Timeago is a jQuery plugin that makes it easy to support automatically | ||
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). | ||
* | ||
* @name timeago | ||
* @version 0.10.0 | ||
* @requires jQuery v1.2.3+ | ||
* @author Ryan McGeary | ||
* @license MIT License - http://www.opensource.org/licenses/mit-license.php | ||
* | ||
* For usage and examples, visit: | ||
* http://timeago.yarp.com/ | ||
* | ||
* Copyright (c) 2008-2011, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org) | ||
*/ | ||
(function($) { | ||
$.timeago = function(timestamp) { | ||
if (timestamp instanceof Date) { | ||
return inWords(timestamp); | ||
} else if (typeof timestamp === "string") { | ||
return inWords($.timeago.parse(timestamp)); | ||
} else { | ||
return inWords($.timeago.datetime(timestamp)); | ||
} | ||
}; | ||
var $t = $.timeago; | ||
|
||
$.extend($.timeago, { | ||
//these will be overwritten in ../reddit.js (jquery document ready function) | ||
//based on i18n settings | ||
settings: { | ||
refreshMillis: 60000, | ||
allowFuture: false, | ||
strings: { | ||
prefixAgo: null, | ||
prefixFromNow: null, | ||
suffixAgo: "ago", | ||
suffixFromNow: "from now", | ||
seconds: "less than a minute", | ||
minute: "about a minute", | ||
minutes: "%d minutes", | ||
hour: "about an hour", | ||
hours: "about %d hours", | ||
day: "a day", | ||
days: "%d days", | ||
month: "about a month", | ||
months: "%d months", | ||
year: "about a year", | ||
years: "%d years", | ||
numbers: [] | ||
} | ||
}, | ||
inWords: function(distanceMillis) { | ||
var $l = this.settings.strings; | ||
var prefix = $l.prefixAgo; | ||
var suffix = $l.suffixAgo; | ||
if (this.settings.allowFuture) { | ||
if (distanceMillis < 0) { | ||
prefix = $l.prefixFromNow; | ||
suffix = $l.suffixFromNow; | ||
} | ||
} | ||
|
||
var seconds = Math.abs(distanceMillis) / 1000; | ||
var minutes = seconds / 60; | ||
var hours = minutes / 60; | ||
var days = hours / 24; | ||
var years = days / 365; | ||
|
||
function substitute(stringOrFunction, number) { | ||
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; | ||
var value = ($l.numbers && $l.numbers[number]) || number; | ||
return string.replace(/%d/i, value); | ||
} | ||
|
||
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || | ||
seconds < 90 && substitute($l.minute, 1) || | ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) || | ||
minutes < 90 && substitute($l.hour, 1) || | ||
hours < 24 && substitute($l.hours, Math.round(hours)) || | ||
hours < 48 && substitute($l.day, 1) || | ||
days < 30 && substitute($l.days, Math.floor(days)) || | ||
days < 60 && substitute($l.month, 1) || | ||
days < 365 && substitute($l.months, Math.floor(days / 30)) || | ||
years < 2 && substitute($l.year, 1) || | ||
substitute($l.years, Math.floor(years)); | ||
|
||
return $.trim([prefix, words, suffix].join(" ")); | ||
}, | ||
parse: function(iso8601) { | ||
var s = $.trim(iso8601); | ||
s = s.replace(/\.\d\d\d+/,""); // remove milliseconds | ||
s = s.replace(/-/,"/").replace(/-/,"/"); | ||
s = s.replace(/T/," ").replace(/Z/," UTC"); | ||
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 | ||
return new Date(s); | ||
}, | ||
datetime: function(elem) { | ||
// jQuery's `is()` doesn't play well with HTML5 in IE | ||
var isTime = $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); | ||
var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title"); | ||
return $t.parse(iso8601); | ||
} | ||
}); | ||
|
||
$.fn.timeago = function() { | ||
var self = this; | ||
self.each(refresh); | ||
|
||
var $s = $t.settings; | ||
if ($s.refreshMillis > 0) { | ||
setInterval(function() { self.each(refresh); }, $s.refreshMillis); | ||
} | ||
return self; | ||
}; | ||
|
||
function refresh() { | ||
var data = prepareData(this); | ||
if (!isNaN(data.datetime)) { | ||
$(this).text(inWords(data.datetime)); | ||
} | ||
return this; | ||
} | ||
|
||
function prepareData(element) { | ||
element = $(element); | ||
if (!element.data("timeago")) { | ||
element.data("timeago", { datetime: $t.datetime(element) }); | ||
/* Stops the title being overridden | ||
var text = $.trim(element.text()); | ||
if (text.length > 0) { | ||
element.attr("title", text); | ||
} | ||
*/ | ||
} | ||
return element.data("timeago"); | ||
} | ||
|
||
function inWords(date) { | ||
return $t.inWords(distance(date)); | ||
} | ||
|
||
function distance(date) { | ||
return (new Date().getTime() - date.getTime()); | ||
} | ||
|
||
// fix for IE6 suckage | ||
document.createElement("abbr"); | ||
document.createElement("time"); | ||
}(jQuery)); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1235,6 +1235,28 @@ $(function() { | |
$("#shortlink-text").click(function() { | ||
$(this).select(); | ||
}); | ||
|
||
/* Load fuzzy time i18n strings */ | ||
$.timeago.settings.strings = { | ||
prefixAgo: null, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add the prefix strings to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean this: https://github.com/reddit/reddit/pull/341/files#diff-2 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep! :) |
||
prefixFromNow: null, | ||
suffixAgo: r.strings.ta_ago, | ||
suffixFromNow: r.strings.ta_suffixFromNow, | ||
seconds: r.strings.ta_seconds, | ||
minute: r.strings.ta_minute, | ||
minutes: r.strings.ta_minutes, | ||
hour: r.strings.ta_hour, | ||
hours: r.strings.ta_hours, | ||
day: r.strings.ta_day, | ||
days: r.strings.ta_days, | ||
month: r.strings.ta_month, | ||
months: r.strings.ta_months, | ||
year: r.strings.ta_year, | ||
years: r.strings.ta_years | ||
}; | ||
|
||
/* Init fuzzy time on time elements */ | ||
$("time.fuzzy-time").timeago(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've been working on overhauling the JS code organization, and the mishmash of initialization code in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you prefer the file name to be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest defining an object named There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool - that's done now. |
||
}); | ||
|
||
function show_friend(account_fullname) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -516,7 +516,7 @@ | |
<%def name="timestamp(date, since=None)"> | ||
## todo: use pubdate attribute once things are <article> tags. | ||
## note: comment and link templates will pass a CachedVariable stub as since. | ||
<time title="${long_datetime(date)}" datetime="${date.isoformat()}"> | ||
<time class="fuzzy-time" title="${long_datetime(date)}" datetime="${date.isoformat()}"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I think about it... because all the elements will have a datetime field - does it need class="fuzzy-time" ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is sensible to include a class to avoid any other |
||
${unsafe(since or timesince(date))} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could place the "ago" string here so that pages are rendered with "posted 37 seconds ago" and therefore will be a less noticeable jump when the plugin changes it to "about a minute ago" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like What do you think @kemitche? Is a language-specific prefix and suffix sufficient for translators to handle fuzzy times, taking them out of the containing translatable string? (see the strings changes above) |
||
</time> | ||
</%def> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be sure to undo this! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be some checks in place before accessing the r.strings array then? In dev mode it will throw a few errors because r.strings would not have been defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running with
uncompressedJS == True
worked for me. Perhaps you forgot to runmake
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted back to true