vendor: 7,020 bytes, lines 1-221
1/** 2 * Timeago is a jQuery plugin that makes it easy to support automatically 3 * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). 4 * 5 * @name timeago 6 * @version 1.4.1 7 * @requires jQuery v1.2.3+ 8 * @author Ryan McGeary 9 * @license MIT License - http://www.opensource.org/licenses/mit-license.php 10 * 11 * For usage and examples, visit: 12 * http://timeago.yarp.com/ 13 * 14 * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) 15 */ 16 17(function (factory) { 18 if (typeof define === 'function' && define.amd) { 19 // AMD. Register as an anonymous module. 20 define(['jquery'], factory); 21 } else { 22 // Browser globals 23 factory(jQuery); 24 } 25}(function ($) { 26 $.timeago = function(timestamp) { 27 if (timestamp instanceof Date) { 28 return inWords(timestamp); 29 } else if (typeof timestamp === "string") { 30 return inWords($.timeago.parse(timestamp)); 31 } else if (typeof timestamp === "number") { 32 return inWords(new Date(timestamp)); 33 } else { 34 return inWords($.timeago.datetime(timestamp)); 35 } 36 }; 37 var $t = $.timeago; 38 39 $.extend($.timeago, { 40 settings: { 41 refreshMillis: 60000, 42 allowPast: true, 43 allowFuture: false, 44 localeTitle: false, 45 cutoff: 0, 46 strings: { 47 prefixAgo: null, 48 prefixFromNow: null, 49 suffixAgo: "ago", 50 suffixFromNow: "from now", 51 inPast: 'any moment now', 52 seconds: "less than a minute", 53 minute: "about a minute", 54 minutes: "%d minutes", 55 hour: "about an hour", 56 hours: "about %d hours", 57 day: "a day", 58 days: "%d days", 59 month: "about a month", 60 months: "%d months", 61 year: "about a year", 62 years: "%d years", 63 wordSeparator: " ", 64 numbers: [] 65 } 66 }, 67 68 inWords: function(distanceMillis) { 69 if(!this.settings.allowPast && ! this.settings.allowFuture) { 70 throw 'timeago allowPast and allowFuture settings can not both be set to false.'; 71 } 72 73 var $l = this.settings.strings; 74 var prefix = $l.prefixAgo; 75 var suffix = $l.suffixAgo; 76 if (this.settings.allowFuture) { 77 if (distanceMillis < 0) { 78 prefix = $l.prefixFromNow; 79 suffix = $l.suffixFromNow; 80 } 81 } 82 83 if(!this.settings.allowPast && distanceMillis >= 0) { 84 return this.settings.strings.inPast; 85 } 86 87 var seconds = Math.abs(distanceMillis) / 1000; 88 var minutes = seconds / 60; 89 var hours = minutes / 60; 90 var days = hours / 24; 91 var years = days / 365; 92 93 function substitute(stringOrFunction, number) { 94 var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; 95 var value = ($l.numbers && $l.numbers[number]) || number; 96 return string.replace(/%d/i, value); 97 } 98 99 var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || 100 seconds < 90 && substitute($l.minute, 1) || 101 minutes < 45 && substitute($l.minutes, Math.round(minutes)) || 102 minutes < 90 && substitute($l.hour, 1) || 103 hours < 24 && substitute($l.hours, Math.round(hours)) || 104 hours < 42 && substitute($l.day, 1) || 105 days < 30 && substitute($l.days, Math.round(days)) || 106 days < 45 && substitute($l.month, 1) || 107 days < 365 && substitute($l.months, Math.round(days / 30)) || 108 years < 1.5 && substitute($l.year, 1) || 109 substitute($l.years, Math.round(years)); 110 111 var separator = $l.wordSeparator || ""; 112 if ($l.wordSeparator === undefined) { separator = " "; } 113 return $.trim([prefix, words, suffix].join(separator)); 114 }, 115 116 parse: function(iso8601) { 117 var s = $.trim(iso8601); 118 s = s.replace(/\.\d+/,""); // remove milliseconds 119 s = s.replace(/-/,"/").replace(/-/,"/"); 120 s = s.replace(/T/," ").replace(/Z/," UTC"); 121 s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 122 s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900 123 return new Date(s); 124 }, 125 datetime: function(elem) { 126 var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); 127 return $t.parse(iso8601); 128 }, 129 isTime: function(elem) { 130 // jQuery's `is()` doesn't play well with HTML5 in IE 131 return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); 132 } 133 }); 134 135 // functions that can be called via $(el).timeago('action') 136 // init is default when no action is given 137 // functions are called with context of a single element 138 var functions = { 139 init: function(){ 140 var refresh_el = $.proxy(refresh, this); 141 refresh_el(); 142 var $s = $t.settings; 143 if ($s.refreshMillis > 0) { 144 this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis); 145 } 146 }, 147 update: function(time){ 148 var parsedTime = $t.parse(time); 149 $(this).data('timeago', { datetime: parsedTime }); 150 if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString()); 151 refresh.apply(this); 152 }, 153 updateFromDOM: function(){ 154 $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) }); 155 refresh.apply(this); 156 }, 157 dispose: function () { 158 if (this._timeagoInterval) { 159 window.clearInterval(this._timeagoInterval); 160 this._timeagoInterval = null; 161 } 162 } 163 }; 164 165 $.fn.timeago = function(action, options) { 166 var fn = action ? functions[action] : functions.init; 167 if(!fn){ 168 throw new Error("Unknown function name '"+ action +"' for timeago"); 169 } 170 // each over objects here and call the requested function 171 this.each(function(){ 172 fn.call(this, options); 173 }); 174 return this; 175 }; 176 177 function refresh() { 178 //check if it's still visible 179 if(!$.contains(document.documentElement,this)){ 180 //stop if it has been removed 181 $(this).timeago("dispose"); 182 return this; 183 } 184 185 var data = prepareData(this); 186 var $s = $t.settings; 187 188 if (!isNaN(data.datetime)) { 189 if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) { 190 $(this).text(inWords(data.datetime)); 191 } 192 } 193 return this; 194 } 195 196 function prepareData(element) { 197 element = $(element); 198 if (!element.data("timeago")) { 199 element.data("timeago", { datetime: $t.datetime(element) }); 200 var text = $.trim(element.text()); 201 if ($t.settings.localeTitle) { 202 element.attr("title", element.data('timeago').datetime.toLocaleString()); 203 } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { 204 element.attr("title", text); 205 } 206 } 207 return element.data("timeago"); 208 } 209 210 function inWords(date) { 211 return $t.inWords(distance(date)); 212 } 213 214 function distance(date) { 215 return (new Date().getTime() - date.getTime()); 216 } 217 218 // fix for IE6 suckage 219 document.createElement("abbr"); 220 document.createElement("time"); 221}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.