HoverIntent knockout binding

86 views Asked by At

I have a list of items dynamically rendered by knockout data binding. I need to bind the hoverIntent event with that instead of mouseover and mouseleave events.

<a data-bind="attr: { title: $data.Header, href: $root.GetUrl() }, event: { mouseover: function() { $root.showPopup($data.Id) }, mouseleave: function() { $root.hidePopup($data.Id) } }">
<span data-bind="html: $data.Header"></span> </a>

The functions are simply as follows;

 self.showPopup = function(id) {
     $("#popup-"+id).slideDown();
 };

 self.hidePopup = function(id) {
     $("#popup-"+id).slideUp();
 };

Please help. Thanks

2

There are 2 answers

0
webketje On BEST ANSWER

Custom bindings is how you should do it. In this case a simple wrapper around $().hoverIntent should suffice.

ko.bindingHandlers.hoverIntent = {
    // note: if your hoverIntent options are not observable/ subject to change, 
    // you would be better off specifying this function as init, not update
    update: function(elem, value) {
        var options = ko.utils.unwrapObservable(value());
        if (typeof options === 'object') {
            for (var option in options)
                options[option] = ko.utils.unwrapObservable(options[option]);
        }
       $(elem).hoverIntent(options);
    }
}

The binding above enables 2 of the hoverIntent parameter syntaxes: .hoverIntent(handlerInOut) and .hoverIntent(optionsObject), for example:

 <a data-bind="hoverIntent: $root.togglePopup">handlerInOut param</a>
 <a data-bind="hoverIntent: { 
     over: $root.showPopup, 
     out: $root.hidePopup, 
     timeout: timeout }">optionsObject param</a>

See it in action in a fiddle.

0
JotaBe On

When you bind a ko event, the handler will automatically receive the item bound to the trigger element as parameter, so that you can access it. You can modify your code like this to make it work:

HTML View:

<a data-bind="attr: { title: $data.Header, href: $root.GetUrl() }, 
   event: { mouseover: $root.showPopup, mouseleave: $root.hidePopup}">
<span data-bind="html: $data.Header"></span> </a>

View Model:

self.showPopup = function(data) {
    $("#popup-"+data.id).slideDown();
};

self.hidePopup = function(id) {
    $("#popup-"+id).slideUp();
};

And, even better that this, you can use a custom binding that directly manages the popup. This Q&A is related, and this. You'll propbably find other implementations if you google "popup ko custom binding". And here you have a perfect explanation of custom bindings, in case you have to implement your own.