tooltip

This is an attempt at getting Bootstrap tooltips working with rendering from a dynamic Knockout template.

HTML

<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js"></script>
<script type="text/html" id="tile-tooltip-template">
    <h2 data-bind = "text: firstName"></h2>
    <span data-bind="text: address"></span >
</script>
<a data-bind="tooltip: { templateId: 'tile-tooltip-template',
                         templateData: {firstName: firstName, address: address},
                         options: {placement: 'bottom'} }">Hover on me</a>

<br/>
<br/>
<br/>
<a href="#" data-bind="click: changeTooltip">Change tooltip data</a>

JavaScript

ko.renderTemplateHtml = function (templateId, templateData) {
    var node = $("<div />");

    //create a dependency for each observable property in the data object
    for(var prop in templateData)
        if( templateData.hasOwnProperty(prop) && ko.isObservable(templateData[prop]))
            templateData[prop]();

    ko.renderTemplate(templateId, templateData, {}, node[0]);
    return node.html();
};

ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var settings = ko.utils.unwrapObservable(valueAccessor()),
            options = {};

        ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
        ko.utils.extend(options, settings.options);
        
        $(element).tooltip(options);
        
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).tooltip("destroy");
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var settings = ko.utils.unwrapObservable(valueAccessor());
        var html =  ko.renderTemplateHtml(settings.templateId, settings.templateData); 
        $(element).data('bs.tooltip').options.title = html;
    },
    options: {
        placement: "top",
        trigger: "hover",
        html: true
    }
};

ko.applyBindings({
    firstName: ko.observable('Initial Name'),
    address: ko.observable('55 Walnut Street, #3'),
    changeTooltip: function () {        
        this.firstName('New Name');
    }
});