knockout-sortable
https://github.com/rniemeyer/knockout-sortable
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.debug.js"></script>
<script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<div class="row">
<div class="col-sm-6 col-md-6 col-lg-6">
<div class="panel panel-default">
<div class="panel-heading">FIELDS <a class="pull-right" href="#" data-bind="click: addComponent"><span class="glyphicon glyphicon-plus"></span> Add field</a></div>
<div class="panel-body">
<ul class="list-group" data-bind="sortable: {data:components,handle:''}">
<li class="list-group-item" data-bind="css: { active : $root.isComponentSelected($data) }">
<span class="glyphicon glyphicon-sort"></span>
<span data-bind="visible: !$root.isComponentSelected($data)">
<a href="#" data-bind="text: name, click: $root.selectedComponent"></a>
</span>
<span data-bind="visibleAndSelect: $root.isComponentSelected($data)">
<input data-bind="value: name, event: { blur: $root.clearComponent }" />
</span>
</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6">
<div class="panel panel-default">
<div class="panel-heading">PROPERTIES</div>
<div class="panel-body">
<ul class="list-group" data-bind="foreach: components">
<li class="list-group-item" data-bind="text: name"></li>
</ul>
</div>
</div>
</div>
</div>
CSS
.add-field-button {
}
JavaScript
var Component = function(name) {
this.name = ko.observable(name);
}
var ViewModel = function() {
var self = this;
self.components = ko.observableArray([
new Component("Textfield"),
new Component("Dropdown"),
]);
self.selectedComponent = ko.observable();
self.clearComponent = function(data, event) {
if (data === self.selectedComponent()) {
self.selectedComponent(null);
}
if (data.name() === "") {
self.component.remove(data);
}
};
self.addComponent = function() {
var component = new Component("new");
self.selectedComponent(component);
self.components.push(component);
};
self.isComponentSelected = function(component) {
return component === self.selectedComponent();
};
};
//control visibility, give element focus, and select the contents (in order)
ko.bindingHandlers.visibleAndSelect = {
update: function(element, valueAccessor) {
ko.bindingHandlers.visible.update(element, valueAccessor);
if (valueAccessor()) {
setTimeout(function() {
$(element).find("input").focus().select();
}, 0); //new tasks are not in DOM yet
}
}
};
ko.applyBindings(new ViewModel());