I'd like to implement what this plugin does using jQuery: https://github.com/rmm5t/jquery-timeago
A short description of that plugin:
This will turn all abbr elements with a class of timeago and an ISO 8601 timestamp in the title (conforming to the datetime design pattern microformat):
<abbr class="timeago" title="2011-12-17T09:24:17Z">December 17, 2011</abbr>
Into something like this:
<abbr class="timeago" title="December 17, 2011">about 1 day ago</abbr>
Except using knockout my markup looks like this:
<abbr data-bind="attr: { title: Posted }" class="timeago"></abbr>
I think something isn't synced up because nothing is happening even if I put the call to timeago within the viewmodel itself. I'm guessing I need a subscriber that's attached to the observable "Posted" but I'm not sure how to set that up.
Your approach doesn't work, because timeago creates a cache via jQuery's data() function. Thus, simply updating the title isn't enough.
I think a custom binding is here the best and cleanest way to go:
ko.bindingHandlers.timeago = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var $this = $(element);
// Set the title attribute to the new value = timestamp
$this.attr('title', value);
// If timeago has already been applied to this node, don't reapply it -
// since timeago isn't really flexible (it doesn't provide a public
// remove() or refresh() method) we need to do everything by ourselves.
if ($this.data('timeago')) {
var datetime = $.timeago.datetime($this);
var distance = (new Date().getTime() - datetime.getTime());
var inWords = $.timeago.inWords(distance);
// Update cache and displayed text..
$this.data('timeago', { 'datetime': datetime });
$this.text(inWords);
} else {
// timeago hasn't been applied to this node -> we do that now!
$this.timeago();
}
}
};
Usage is as simple as this:
<abbr data-bind="timeago: Posted"></abbr>
Demo: http://jsfiddle.net/APRGc/1/
Here is an alternative, that really probably doesn't have any advantage over Niko's answer at all, except perhaps being a touch simpler :) --
usf.ko.bindings['timeago'] = {
update: function(element, valueAccessor) {
var $element, date;
date = ko.utils.unwrapObservable(valueAccessor());
$element = $(element);
if (date) {
$element.attr('title', date.toISOString());
$element.data('tiemago', false);
return $element.timeago();
}
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With