Pregunta

I have an observableArray for insert message. I want to display all messages using knockout. I want to use a custom scrollbar graphic - jScrollPane. (plugin LINK)

How can I fix my example for display custom scrollbar from jScrollPane?

Example: http://jsfiddle.net/aZpgY/3/

HTML:

<h2>Chat with knockout binding</h2>
<div id="chat-content" data-bind="foreach: messages">
    <div data-bind="text: messageText"></div>
</div>

<br />

<form data-bind="submit: sendMessage">
    message: <input data-bind="value: message" placeholder="Insert your massage" /><br />
    <button type="submit">Add</button>
</form>

<h2>Example content - without knockout binding</h2>

<div id="example-content">
    <div>Text</div>
    <div>Text</div>   
    <div>Text</div>   
    <div>Text</div>   
    <div>Text</div>   
    <div>Text</div> 
    <div>Text</div>  
    <div>Text</div>      
</div>

CSS:

#chat-content, #example-content{
    width: 300px; 
    height: 100px; 
    overflow: auto;
}

JS:

function Message(data) {
    this.messageText = ko.observable(data.messageText);
}

function ChatViewModel() {
    // Data
    var self = this;
    self.messages = ko.observableArray([]);
    self.message = ko.observable();


    // Operations
    self.sendMessage = function() {
        self.messages.push(new Message({ messageText: this.message() }));
        self.message("");
    };
    self.removeTask = function(task) { self.tasks.remove(task) };
}

ko.applyBindings(new ChatViewModel());

$(function(){

    $('#chat-content').jScrollPane();
    $('#example-content').jScrollPane();

});
¿Fue útil?

Solución

Create a custom binding handler to initialize and update the jScrollPane instance:

ko.bindingHandlers.jScrollPane = {
  init: function(element, valueAccessor) {
    var o = valueAccessor() || {};

    // initialize
    $(element).jScrollPane(o.options);

    var reinit = function() {
      var scroll = $(element).data("jsp");
      if (scroll) {
         scroll.reinitialise();  
      } 
    };

    // handle window resize (though not really necessary if your chat box has a set pixel width)
    $(window).resize(reinit);

    // add subscription to observable if passed in
    if(o.subscribe) {
      o.subscribe.subscribe(function() {
        // use setTimeout so the DOM finishes updating before reinitialising
        setTimeout(reinit, 0);
      });
    }
  }
};

Call the new jScrollPane handler on the #chat-content div, passing in the messages observable so it knows when to refresh the scroll bar. Put the foreach binding handler in a child element to prevent it from interfering with the DOM changes that jScrollPane makes.

<div id="chat-content" data-bind="jScrollPane: { subscribe: messages }">
  <div data-bind="foreach: messages">
    <div data-bind="text: messageText"></div>
  </div>
</div>

JSFiddle: http://jsfiddle.net/aZpgY/7/


jScrollPane binding handler adapted from here: http://jsfiddle.net/rniemeyer/NgNvf/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top