Emi Matchu
5bf2ef42a0
The silly motivation is that I wanted to remove `.prettierignore`, which just exists to omit that one folder from `npm run format`. But it also seems like this is the standard place to put them—a standard created long after we first set this up lol
152 lines
4.7 KiB
JavaScript
152 lines
4.7 KiB
JavaScript
/**
|
|
* 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.11.4
|
|
* @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-2012, Ryan McGeary (ryan -[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 if (typeof timestamp === "number") {
|
|
return inWords(new Date(timestamp));
|
|
} else {
|
|
return inWords($.timeago.datetime(timestamp));
|
|
}
|
|
};
|
|
var $t = $.timeago;
|
|
|
|
$.extend($.timeago, {
|
|
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",
|
|
wordSeparator: " ",
|
|
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 < 42 && substitute($l.day, 1) ||
|
|
days < 30 && substitute($l.days, Math.round(days)) ||
|
|
days < 45 && substitute($l.month, 1) ||
|
|
days < 365 && substitute($l.months, Math.round(days / 30)) ||
|
|
years < 1.5 && substitute($l.year, 1) ||
|
|
substitute($l.years, Math.round(years));
|
|
|
|
var separator = $l.wordSeparator === undefined ? " " : $l.wordSeparator;
|
|
return $.trim([prefix, words, suffix].join(separator));
|
|
},
|
|
parse: function(iso8601) {
|
|
var s = $.trim(iso8601);
|
|
s = s.replace(/\.\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) {
|
|
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
|
|
return $t.parse(iso8601);
|
|
},
|
|
isTime: function(elem) {
|
|
// jQuery's `is()` doesn't play well with HTML5 in IE
|
|
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
|
|
}
|
|
});
|
|
|
|
$.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) });
|
|
var text = $.trim(element.text());
|
|
if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
|
|
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));
|