JSFiddle - React, Tailwind, and code Playground
by manchagnu
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.1.0/knockout-min.js"></script>
<ul class='links'>
<li><a href='#addserver'>Add server</a></li>
<li><a href='#projects'>Projects</a></li>
<li><a href='#help'>Help</a></li>
</ul>
<div class="content" data-bind="with: $data">
<div data-bind="view: {data: $data.Selected}"></div>
</div>
JavaScript
//
// Extender to setup selectable views and the bucket of views
//
ko.extenders.viewManager = function (target, options) {
if (target() === null || target() === undefined) {
target({});
}
if (ko.isObservable(target.Selected) == false ) {
target().Selected = ko.observable(null);
}
if (ko.isObservable(target.Select) == false) {
target.Select = ko.observable(null);
}
target.Select.subscribe(function (newValue) {
var views = target();
var newView = views[newValue] || false;
// If the view does not exist, then we just exit out.
if (newView === false) {
return;
}
target().Selected(newView);
});
target.push = function () {
var args = arguments;
target.valueWillMutate();
var _target = target();
for (var arg in args) {
var items = args[arg];
for (var item in items) {
_target[item] = items[item];
}
}
target.valueHasMutated();
}
return target;
};
//
// Custom binding to setup the view handler itself.
//
ko.bindingHandlers.view = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
var data = ko.utils.unwrapObservable(options['data']) || {};
if (typeof data.init === 'function') {
// Provide a container to host any new html added in the init callback.
data.element = $("<div>").appendTo(element);
data.init.call(data, data.element);
// Make sure we only call init once.
delete data.init;
}
if (typeof data.update === 'function') {
data.update.call(data, data.element);
}
// Customize this logic if you want to move the element containers around
// when selecting a new view.
...