From e5131c86c22c5577c0e27db04481084caf635dc5 Mon Sep 17 00:00:00 2001 From: Byron Jones Date: Tue, 14 Apr 2015 13:20:00 +0800 Subject: Bug 1146767: update relative dates without refreshing the page --- extensions/BugModal/web/bug_modal.js | 2 +- extensions/BugModal/web/time_ago.js | 142 +++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 extensions/BugModal/web/time_ago.js (limited to 'extensions/BugModal/web') diff --git a/extensions/BugModal/web/bug_modal.js b/extensions/BugModal/web/bug_modal.js index bd529fab1..87d173680 100644 --- a/extensions/BugModal/web/bug_modal.js +++ b/extensions/BugModal/web/bug_modal.js @@ -134,7 +134,7 @@ $(function() { }); // use non-native tooltips for relative times and bug summaries - $('.rel-time, .bz_bug_link').tooltip({ + $('.rel-time, .rel-time-title, .bz_bug_link').tooltip({ position: { my: "left top+8", at: "left bottom", collision: "flipfit" }, show: { effect: 'none' }, hide: { effect: 'none' } diff --git a/extensions/BugModal/web/time_ago.js b/extensions/BugModal/web/time_ago.js new file mode 100644 index 000000000..59f12692a --- /dev/null +++ b/extensions/BugModal/web/time_ago.js @@ -0,0 +1,142 @@ +/* + * this is a port of perl's Time::Duration module, which has the following + * license: + * + * Copyright 2006, Sean M. Burke C, all rights reserved. This + * program is free software; you can redistribute it and/or modify it under the + * same terms as Perl itself. + * + * This program is distributed in the hope that it will be useful, but without + * any warranty; without even the implied warranty of merchantability or + * fitness for a particular purpose. + */ + +$(function() { + 'use strict'; + + function separate(seconds) { + // breakdown of seconds into units, starting with the most significant + + var remainder = seconds; + var tmp; + var wheel = []; + + // years + tmp = Math.floor(remainder / (365 * 24 * 60 * 60)); + wheel.push([ 'year', tmp, 1000000000 ]); + remainder -= tmp * (365 * 24 * 60 * 60); + + // days + tmp = Math.floor(remainder / (24 * 60 * 60)); + wheel.push([ 'day', tmp, 365 ]); + remainder -= tmp * (24 * 60 * 60); + + // hours + tmp = Math.floor(remainder / (60 * 60)); + wheel.push([ 'hour', tmp, 24 ]); + remainder -= tmp * (60 * 60); + + // minutes + tmp = Math.floor(remainder / 60); + wheel.push([ 'minute', tmp, 60 ]); + remainder -= tmp * 60; + + // seconds + wheel.push([ 'second', Math.floor(remainder), 60 ]); + return wheel; + } + + function approximate(precision, wheel) { + // now nudge the wheels into an acceptably (im)precise configuration + FIX: do { + // constraints for leaving this block: + // 1) number of nonzero wheels must be <= precision + // 2) no wheels can be improperly expressed (like having "60" for mins) + + var nonzero_count = 0; + var improperly_expressed = -1; + + for (var i = 0; i < wheel.length; i++) { + var tmp = wheel[i]; + if (tmp[1] == 0) { + continue; + } + ++nonzero_count; + if (i == 0) { + // the years wheel is never improper or over any limit; skip + continue; + } + + if (nonzero_count > precision) { + // this is one nonzero wheel too many + + // incr previous wheel if we're big enough + if (tmp[1] >= (tmp[tmp.length - 1] / 2)) { + ++wheel[i - 1][1]; + } + + // reset this and subsequent wheels to 0 + for (var j = i; j < wheel.length; j++) { + wheel[j][1] = 0; + } + + // start over + continue FIX; + + } else if (tmp[1] >= tmp[tmp.length - 1]) { + // it's an improperly expressed wheel (like "60" on the mins wheel) + improperly_expressed = i; + } + } + + if (improperly_expressed != -1) { + // only fix the least-significant improperly expressed wheel (at a time) + ++wheel[improperly_expressed - 1][1]; + wheel[improperly_expressed][1] = 0; + + // start over + continue FIX; + } + + // otherwise there's not too many nonzero wheels, and there's no + //improperly expressed wheels, so fall thru... + } while(0); + + return wheel; + } + + function render(wheel) { + var parts = []; + wheel.forEach(function(element, index) { + if (element[1] > 0) { + parts.push(element[1] + ' ' + element[0]); + if (element[1] != 1) { + parts[parts.length - 1] += 's'; + } + } + }); + + if (parts.length == 0) { + return "just now"; + } + parts[parts.length - 1] += ' ago'; + if (parts.length == 1) { + return parts[0]; + } + if (parts.length == 2) { + return parts[0] + ' and ' + parts[1]; + } + parts[parts.length - 1] = 'and ' + parts[parts.length - 1]; + return parts.join(', '); + } + + window.setInterval(function() { + var now = Math.floor(new Date().getTime() / 1000); + $('.rel-time').each(function() { + $(this).text(render(approximate(2, separate(now - $(this).data('time'))))); + }); + $('.rel-time-title').each(function() { + $(this).attr('title', render(approximate(2, separate(now - $(this).data('time'))))); + }); + }, 60000); +}); -- cgit v1.2.3-24-g4f1b