Knockoutjs.com - Simple list example
http://knockoutjs.com/examples/simpleList.html
by Barry Carter
HTML
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script src="https://rawgit.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<div class='liveExample'>
<div>
<div class="subheader">
<h1>Mode</h1>
<mode-button params="text: 'Campaign => Team', modeId: 0, mode: mode"></mode-button>
<mode-button params="text: 'Team => User', modeId: 1, mode: mode"></mode-button>
<mode-button params="text: 'Queue => User', modeId: 2, mode: mode"></mode-button>
</div>
<div>
Filter On
<span><input type="checkbox" data-bind="checked: options.filterOnSelected" />Selected</span>
<span><input type="checkbox" data-bind="checked: options.filterOnDrag" />Drag</span>
<span data-bind="visible: $root.selectedEntity, click: $root.selectedEntity(undefined)">Reset</span>
</div>
<!-- ko with: selectedEntity -->
<div data-bind="text: name">
</div>
<!-- /ko -->
<p>Your items:</p>
<span class='tlentity primary'>
<h2 data-bind="text: entityType"></h2>
<div data-bind="foreach: $root.modeArrs">
<div class='entity' data-bind="
draggable: { data: $data, options:{ start: $root.startDrag, stop: $root.endDrag } },
click: $root.entity_click, css: { 'selected-entity': $data === $root.selectedEntity() }">
<div data-bind="text: name"></div>
</div>
</div>
</span>
<span data-bind="foreach: topLevelItems">
<div class='tlentity' data-bind="visible: $root.tlItemVisible($data), droppable: { data: $root.dropped('normal', $data),
options: { greedy: true, classes: {'ui-droppable-hover': 'highlight' }, over:...
CSS
body { font-family: arial; font-size: 14px; }
.liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
.liveExample input { font-family: Arial; }
.liveExample b { font-weight: bold; }
.liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
.liveExample select[multiple] { width: 100%; height: 8em; }
.liveExample h2 { margin-top: 0.4em; }
.tlentity {
display: inline-block;
width: 150px;
height: 400px;
background-color: blue;
vertical-align: top;
padding: 2px;
}
.tlentity.primary {
background-color: green;
margin-right: 8px;
}
.tlentity h2 {
font-size:1.5em;
margin: 3px 3px 10px 1px;
}
.entity-wrap {
display: block;
}
.entity {
display: flex;
width: 150px;
}
.team-primary {
display: flex;
width: 10px;
height: 10px;
background-color: red;
}
.selected-entity {
background-color: blue;
}
.drop-entity {
display: block;
width: 150px;
height: 200px;
background-color: red;
}
.subheader {
display: inline-flex;
}
.subheader > h1 {
font-size: 1.2em;
font-weight: bold;
margin: 2px 5px 0px 0px;
}
.subheader mode-button {
width: 180px;
margin: 3px;
border: 1px solid #5a5959;
}
.mode-button-el {
background-color: #d7d7d7;
display: inline-flex;
width: 100%;
}
.mode-button-el.active {
background-color: green;
}
JavaScript
var users = [{id: 1, name: "Bob", teamIds: [1, 2], primaryTeamId: 1, queueIds: [1,2]},
{id: 1, name: "Jim", teamIds: [1], primaryTeamId: 1, queueIds: [1,3]},
{id: 1, name: "Jane", teamIds: [2,3], primaryTeamId: 2, queueIds: [1,2, 3]}];
var teams = [{id: 1, name: "Team 1", campIds: [2]},
{id: 2, name: "Team 2", campIds: [1]}, {id: 3, name: "Team 3", campIds: [2]}];
var camps = [{id: 1, name: "Camp 1"}, {id: 2, name: "Camp 2"},{id: 3, name: "Camp 3"}];
var queues = [{id: 1, name: "Queue 1"}, {id: 2, name: "Queue 2"},{id: 3, name: "Queue 3"}];
ko.components.register('mode-button', {
viewModel: function(params) {
var self = this;
this.text = params && params.text || '';
this.mode = params && params.mode || '';
this.modeId = params && params.modeId || 0;
this.isActive = ko.pureComputed(function() {
return self.mode() == self.modeId ? 'active' : '';
});
this.click = function(data, event) {
self.mode(self.modeId)
}
},
template: { element: 'mode-button-template' }
});
var SimpleListModel = function(items) {
var self = this;
var ocamps = ko.mapping.fromJS(camps);
var oteams = ko.mapping.fromJS(teams);
var ousers = ko.mapping.fromJS(users);
var oqueues = ko.mapping.fromJS(queues);
this.topLevelItems = ko.observableArray(ocamps());
this.mode = ko.observable(0); // start in camp->team
this.selectedEntity = ko.observable();
this.selectedTopLevelId = ko.observable();
this.entity_click = function(data, event) {
self.selectedEntity(data);
}
this.modeArrs = ko.observableArray([]);
this.modeArrPropName = "Id";
this.entityType = ko.observable("");
this.modeChange = ko.observable()
this.mode.subscribe(function(d) {
var mode = self.mode();
if (mode === 0) {
self.modeArrs(oteams());
self.modeArrPropName = "campIds";
self.topLevelItems(ocamps());
...