Knockout Popover
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/css/bootstrap.css">
<div class="accordion" id="accordion2">
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle arrow-up" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">
Collapsible Group Item #1
</a>
</div>
<div id="collapseOne" class="accordion-body collapse in">
<div class="accordion-inner">
<p> first table</p>
<p>First Content</p>
</div>
</div>
</div>
</div>
<ul data-bind="foreach: persons">
<li> <span data-bind="text: 'name : '+name()+' email : '+ email()">
</span>
<a href="#" data-bind="popover: {content :'#popover_content',id: id}" data-title="<strong>Person details</strong>" data-placement="bottom"> Edit
</a>
</li>
</ul>
<script id="popover_content" type="text/html">
<div class="row"> Name: <input type="text" data-bind="value: name, valueUpdate: 'afterkeydown'"/> Email: <input type="text" data-bind="value: email, valueUpdate: 'afterkeydown'"/></div>
<br>
<div class="row">
<center>
<div class="span3 offset1">
<button class="btn btn-small btn-danger" data-bind="click: $root.closePopover">Cancel</button > </div>
</center > </div>
</script>
CSS
.arrow-down {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAAHwAAAB8ARUP7eQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAACISURBVChTvc+xCoNAEIThDXkQH8FCYhGwsRLEgJ2lEN81VQg2toIW2qVK7z9RREEtHfjg7liWOTslIZzxeJhgYhU+uOmykwQd3rpEaNEg1cMiFzyh4Rc82BU5fqjxf5xS4AstUwMtmJNBm0r4eKCHhtViMzFUTzSsGkd/W9XbrLGXO9zxeG7MBoKmGaM1wCzfAAAAAElFTkSuQmCC) no-repeat right;
}
.arrow-up {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAbrQAAG60BIeRSlQAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAANpJREFUOE9jGJzAwsJCyM7OztPMzIwPKkQ8sLe353F2dl7v6ur6BEjPBmI1qBRxAGgAh6OjY4m7u/t/oCF/gQacBtJuUGmiAQvQC7YuLi5fgZr/Ozk5fQCyC6ByxANLS0sxoAsuAzX/dXNz+w9kzwKGDydUmijADPSSA9AVv4CG/Ae5CIhjoXL4gY2NjSjQxlKghtdQb5wGGhYClcYPgBotgQG5BqjxN9TpM4CaNaDS+AEoDQA13ABpBNr+G2hQkpWVFS9UmijABDTAEGj7DqAhIFuZIMLYAAMDAPuUQ9EUeG3QAAAAAElFTkSuQmCC) no-repeat right;
}
JavaScript
var ViewModel = function () {
var self = this;
self.persons = ko.observableArray([{
id: '1',
name: ko.observable('Mounir'),
email: ko.observable('[email protected]')
}, {
id: '2',
name: ko.observable('Sam'),
email: ko.observable('[email protected]')
}]);
self.closePopover = function (person) {
$('#popover' + person.id + "_click").popover("hide");
};
};
ko.bindingHandlers.popover = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var attribute = ko.utils.unwrapObservable(valueAccessor());
var cssSelectorForPopoverTemplate = attribute.content;
var popOverTemplate = "<div id='" + attribute.id + "-popover'>" + $(cssSelectorForPopoverTemplate).html() + "</div>";
$(element).popover({
content: popOverTemplate,
html: true,
trigger: 'manual'
});
$(element).attr('id', "popover" + attribute.id + "_click");
$(element).click(function () {
$(this).popover('toggle');
var thePopover = document.getElementById(attribute.id + "-popover");
childBindingContext = bindingContext.createChildContext(viewModel);
ko.applyBindingsToDescendants(childBindingContext, thePopover);
});
}
};
ko.applyBindings(new ViewModel());
$('.accordion-group').on('show', function() {
$(this).find('.accordion-toggle').removeClass('arrow-down').addClass('arrow-up');
});
$('.accordion-group').on('hide', function() {
$(this).find('.accordion-toggle').removeClass('arrow-up').addClass('arrow-down');
});