1/*
2 * timeago: a jQuery plugin, version: 0.9.1 (2010-08-30)
3 * @requires jQuery v1.2.3 or later
4 *
5 * Timeago is a jQuery plugin that makes it easy to support automatically
6 * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
7 *
8 * For usage and examples, visit:
9 * http://timeago.yarp.com/
10 *
11 * Licensed under the MIT:
12 * http://www.opensource.org/licenses/mit-license.php
13 *
14 * Copyright (c) 2008-2010, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org)
15 */
16(function($) {
17  $.timeago = function(timestamp) {
18    if (timestamp instanceof Date) return inWords(timestamp);
19    else if (typeof timestamp == "string") return inWords($.timeago.parse(timestamp));
20    else return inWords($.timeago.datetime(timestamp));
21  };
22  var $t = $.timeago;
23
24  $.extend($.timeago, {
25    settings: {
26      refreshMillis: 60000,
27      allowFuture: false,
28      strings: {
29        prefixAgo: null,
30        prefixFromNow: null,
31        suffixAgo: "ago",
32        suffixFromNow: "from now",
33        seconds: "%d seconds",  // Local modification.
34        minute: "about a minute",
35        minutes: "%d minutes",
36        hour: "about an hour",
37        hours: "about %d hours",
38        day: "a day",
39        days: "%d days",
40        month: "about a month",
41        months: "%d months",
42        year: "about a year",
43        years: "%d years",
44        numbers: []
45      }
46    },
47    inWords: function(distanceMillis) {
48      var $l = this.settings.strings;
49      var prefix = $l.prefixAgo;
50      var suffix = $l.suffixAgo;
51      if (this.settings.allowFuture) {
52        if (distanceMillis < 0) {
53          prefix = $l.prefixFromNow;
54          suffix = $l.suffixFromNow;
55        }
56        distanceMillis = Math.abs(distanceMillis);
57      }
58
59      var seconds = distanceMillis / 1000;
60      var minutes = seconds / 60;
61      var hours = minutes / 60;
62      var days = hours / 24;
63      var years = days / 365;
64
65      function substitute(stringOrFunction, number) {
66        var string = $.isFunction(stringOrFunction) ? stringOrFunction(number) : stringOrFunction;
67        var value = ($l.numbers && $l.numbers[number]) || number;
68        return string.replace(/%d/i, value);
69      }
70
71      var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
72        seconds < 90 && substitute($l.minute, 1) ||
73        minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
74        minutes < 90 && substitute($l.hour, 1) ||
75        hours < 24 && substitute($l.hours, Math.round(hours)) ||
76        hours < 48 && substitute($l.day, 1) ||
77        days < 30 && substitute($l.days, Math.floor(days)) ||
78        days < 60 && substitute($l.month, 1) ||
79        days < 365 && substitute($l.months, Math.floor(days / 30)) ||
80        years < 2 && substitute($l.year, 1) ||
81        substitute($l.years, Math.floor(years));
82
83      return $.trim([prefix, words, suffix].join(" "));
84    },
85    parse: function(iso8601) {
86      var s = $.trim(iso8601);
87      s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
88      s = s.replace(/-/,"/").replace(/-/,"/");
89      s = s.replace(/T/," ").replace(/Z/," UTC");
90      s = s.replace(/([\+-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
91      return new Date(s);
92    },
93    datetime: function(elem) {
94      // jQuery's `is()` doesn't play well with HTML5 in IE
95      var isTime = $(elem).get(0).tagName.toLowerCase() == "time"; // $(elem).is("time");
96      var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
97      return $t.parse(iso8601);
98    }
99  });
100
101  $.fn.timeago = function() {
102    var self = this;
103    self.each(refresh);
104
105    var $s = $t.settings;
106    if ($s.refreshMillis > 0) {
107      setInterval(function() { self.each(refresh); }, $s.refreshMillis);
108    }
109    return self;
110  };
111
112  function refresh() {
113    var data = prepareData(this);
114    if (!isNaN(data.datetime)) {
115      $(this).text(inWords(data.datetime));
116    }
117    return this;
118  }
119
120  function prepareData(element) {
121    element = $(element);
122    if (!element.data("timeago")) {
123      element.data("timeago", { datetime: $t.datetime(element) });
124      var text = $.trim(element.text());
125      if (text.length > 0) element.attr("title", text);
126    }
127    return element.data("timeago");
128  }
129
130  function inWords(date) {
131    return $t.inWords(distance(date));
132  }
133
134  function distance(date) {
135    return (new Date().getTime() - date.getTime());
136  }
137
138  // fix for IE6 suckage
139  document.createElement("abbr");
140  document.createElement("time");
141})(jQuery);
142