2012-06-29 32 views
12

Tôi muốn thực hiện những gì plugin này không sử dụng jQuery: https://github.com/rmm5t/jquery-timeagoLàm thế nào tôi có thể thực hiện một ngày thay thế mờ bằng cách sử dụng Knockout?

Một mô tả ngắn về plugin:

tác này sẽ tắt tất cả các yếu tố abbr với một lớp timeago và một tiêu chuẩn ISO 8601 dấu thời gian trong tiêu đề (phù hợp với các mẫu thiết kế datetime microformat):

<abbr class="timeago" title="2011-12-17T09:24:17Z">December 17, 2011</abbr> 

Into một cái gì đó như thế này:

<abbr class="timeago" title="December 17, 2011">about 1 day ago</abbr> 

Trừ sử dụng loại trực tiếp đánh dấu của tôi trông như thế này:

<abbr data-bind="attr: { title: Posted }" class="timeago"></abbr> 

Tôi nghĩ rằng một cái gì đó không được đồng bộ hóa lên vì không có gì đang xảy ra ngay cả khi tôi đặt cuộc gọi đến timeago trong viewmodel riêng của mình. Tôi đoán tôi cần một thuê bao được gắn vào "Được đăng" có thể quan sát nhưng tôi không chắc chắn cách thiết lập điều đó.

Trả lời

22

Cách tiếp cận của bạn không hoạt động, vì timeago tạo bộ nhớ cache thông qua hàm data() của jQuery. Vì vậy, chỉ cần cập nhật tiêu đề là không đủ.

Tôi nghĩ rằng một tùy chỉnh ràng buộc là đây là cách tốt nhất và sạch nhất để đi:

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(); 
     } 
    } 
}; 

Cách sử dụng cũng đơn giản như thế này:

<abbr data-bind="timeago: Posted"></abbr> 

Demo: http://jsfiddle.net/APRGc/1/

+0

Sẽ thử điều này ở đây sau vài phút, đó là tuyến đường tôi bắt đầu xuống nhưng không chắc chắn. Cảm ơn câu trả lời. – rball

+0

Điều này làm việc hoàn hảo cho tôi. Lam tôt lăm. – mfanto

+1

Thay thế dòng '$ this.attr ('title', value);' với '$ this.attr ($. Timeago.isTime ($ this)? 'Datetime': 'title', value);' do đó, nó sẽ làm việc với '

1

Dưới đây là một thay vào đó, điều đó thực sự có lẽ không có lợi thế so với câu trả lời của Niko chút nào, ngoại trừ có lẽ là một liên lạc đơn giản hơn :) -

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(); 
    } 
    } 
}; 
+0

Giải pháp này có một bất lợi chính: 'timeago ('refresh')' có nghĩa là không có gì khác với 'timeago()', bởi vì không có phương thức "làm mới" công khai. Điều này về cơ bản có nghĩa là mỗi lần có thể quan sát được cập nhật, một bộ hẹn giờ mới được tạo với "setInterval" để quản lý tự động làm mới. Vì vậy, bạn có một bộ nhớ tiềm ẩn rò rỉ ở đây. – Niko

+1

@Niko: "Làm mới" là một lỗi đánh máy (mơ tưởng?). :) Bạn nói đúng về setInterval là một rò rỉ bộ nhớ tiềm ẩn. Mã đề xuất của tôi không nên được sử dụng vì lý do đó. –

Các vấn đề liên quan