Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Implemented only one Interval on a page. #122

Closed
wants to merge 2 commits into from

3 participants

@mweibel

This commit will fix jquery.timeago's issue to have an interval
for each timeago element on a page.
By doing this it also removes destroyed elements automatically.

As such, this commit fixes rmm5t/jquery-timeago#96 and
rmm5t/jquery-timeago#90.

Please share your comments. My code might not be the most idiomatic jQuery plugin code ever - please let me know what could be done better in your opinion, as well as let me know if there are any bugs.

Michael Weibel added some commits
Michael Weibel Implemented only one Interval on a page.
This commit will fix jquery.timeago's issue to have an interval
for each timeago element on a page.
By doing this it also removes destroyed elements automatically.

As such, this commit fixes rmm5t/jquery-timeago#96 and
rmm5t/jquery-timeago#90.
7891957
Michael Weibel Reset default refreshMillis again (done for debugging purposes 525a468
@mweibel

Just a quick update: Since I opened this pull request it has been in production at our website and it seems to work without any issues.
Wondering why this hasn't been merged yet nor got any comment.

@rmm5t
Owner

@mweibel, I'm sorry about that. I've been very busy trying to kick off a new company. I've done a poor job of shepherding the project lately. I really appreciate your passion and ambition for this.

Here are some reasons why I haven't been able to give this PR more time:

  1. It lacks tests. The timeago test suite needs some work as a whole, but I cannot pull in such a sweeping change without some coverage, especially to ensure some backwards compatibility.
  2. Timeago has changed quite a bit since this PR, and at a minimum, this PR needs a rebase and squash (i.e commits like 525a468 really shouldn't be in a PR, because they should have been squashed first). I haven't checked to see what kind of merge conflicts these changes bring right now.
  3. I haven't given it much thought yet, but on the surface, it looks like a lot of code for what it does. Maybe that's unavoidable, but #90 looks more streamlined on the surface. I'm more apt to pull these things one small change at a time (i.e. auto-cleanup of removed elements then consolidating to one timer).
  4. In the back of my mind, I've been wanting to give timeago two things a) a new, cleaner test suite and b) A bit of a rewrite to incorporate the many open feature requests with a better underlying design to make future changes easier. That, of course, keeps getting postponed, and my fault.

In summary, I think the features and ideas behind this PR are excellent. I think the project as a whole needs some work first, and that's currently on me.

@mweibel

No worries, I know how hard it is sometimes to keep a project at life ;)

I'll take a closer look on your points but from a quick look I agree on them. I'll see whether I can fix those in a timely manner.

@mweibel mweibel closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 28, 2013
  1. Implemented only one Interval on a page.

    Michael Weibel authored
    This commit will fix jquery.timeago's issue to have an interval
    for each timeago element on a page.
    By doing this it also removes destroyed elements automatically.
    
    As such, this commit fixes rmm5t/jquery-timeago#96 and
    rmm5t/jquery-timeago#90.
This page is out of date. Refresh to see the latest.
Showing with 71 additions and 9 deletions.
  1. +71 −9 jquery.timeago.js
View
80 jquery.timeago.js
@@ -3,8 +3,8 @@
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* @name timeago
- * @version 1.1.0
- * @requires jQuery v1.2.3+
+ * @version 1.2.0
+ * @requires jQuery v1.7.0+
* @author Ryan McGeary
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*
@@ -36,6 +36,16 @@
};
var $t = $.timeago;
+ // destroyed event handler comes from:
+ // http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom/10172676#10172676
+ jQuery.event.special.timeagodestroyed = {
+ remove: function(o) {
+ if (o.handler) {
+ o.handler($(this));
+ }
+ }
+ };
+
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
@@ -115,6 +125,55 @@
isTime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
+ },
+
+ elements: [],
+
+ initInterval: function() {
+ if (!$(document).data('timeago_interval')) {
+ var intervalId = setInterval(function() {
+ for (var i = 0, elLength = $t.elements.length; i < elLength; i++) {
+ $t.elements[i].trigger('timeago:update');
+ }
+ }, $t.settings.refreshMillis);
+ $(document).data('timeago_interval', intervalId);
+ }
+ },
+
+ removeInterval: function() {
+ clearInterval($(document).data('timeago_interval'));
+ for (var i = 0, elLength = $t.elements.length; i < elLength; i++) {
+ $t.elements[i].off('timeago:update');
+ }
+ $t.elements = [];
+ },
+
+ updateHandler: function(evt) {
+ refresh.apply(this);
+ },
+
+ addElement: function(elem) {
+ var index = $t.elements.length,
+ $elem = $(elem);
+ // prevent double add.
+ if($elem.data('timeagoIndex') !== undefined) {
+ return;
+ }
+ refresh.apply(elem);
+ $elem.data('timeagoIndex', index);
+ $t.elements.push($elem);
+ $elem.on('timeago:update', $t.updateHandler);
+ $elem.on('timeagodestroyed', $t.removeElement);
+ },
+ removeElement: function(elem) {
+ var $elem = $(elem),
+ elemIndex = $elem.data('timeagoIndex');
+ $(elem).off('timeago:update');
+ $t.elements.splice(elemIndex, 1);
+ // update indexes of the remaining elements after the index
+ for (var i = elemIndex, elLength = $t.elements.length; i < elLength; i++) {
+ $t.elements[i].data('timeagoIndex', i);
+ }
}
});
@@ -123,12 +182,13 @@
// functions are called with context of a single element
var functions = {
init: function(){
- var refresh_el = $.proxy(refresh, this);
- refresh_el();
- var $s = $t.settings;
- if ($s.refreshMillis > 0) {
- setInterval(refresh_el, $s.refreshMillis);
- }
+ $t.addElement(this);
+ },
+ remove: function() {
+ $t.removeElement(this);
+ },
+ removeInterval: function() {
+ $t.removeInterval();
},
update: function(time){
$(this).data('timeago', { datetime: $t.parse(time) });
@@ -137,6 +197,8 @@
};
$.fn.timeago = function(action, options) {
+ $t.initInterval();
+
var fn = action ? functions[action] : functions.init;
if(!fn){
throw new Error("Unknown function name '"+ action +"' for timeago");
@@ -162,7 +224,7 @@
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if ($t.settings.localeTitle) {
- element.attr("title", element.data('timeago').datetime.toLocaleString())
+ element.attr("title", element.data('timeago').datetime.toLocaleString());
} else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
element.attr("title", text);
}
Something went wrong with that request. Please try again.