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'>
<stack-master params="data: modeArrs, options: $root.stackOptions, name: entityType"></stack-master>
</span>
<span data-bind="foreach: stacks">
<stack params="data: $data, options: $root.stackOptions"></stack>
</span>
</div>
</div>
<template type="text/template" id="hover-template">
<div data-bind="visible: $root.hoverTemplate() == 'hover-template-hovering', template: 'hover-template-hovering'"></div>
<div data-bind="visible: $root.hoverTemplate() == 'hover-exists-template', template: 'hover-template-exists'"></div>
<div data-bind="visible: $root.hoverTemplate() == 'hover-template-hover-new', template: 'hover-template-hover-new'"></div>
</template>
<template type="text/template"...
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' }
});
ko.components.register('stack-master', {
viewModel: function(params) {
var self = this;
this.items = params && params.data || [];
this.name = params && params.name || "?";
this.draggingEntity = params && params.options && params.options.draggingEntity || ko.observable(undefined);
this.dragSourceStack = params && params.options && params.options.dragSourceStack || ko.observable(undefined);
this.startDrag = function(data, e, f) {
self.dragSourceStack(undefined);
self.draggingEntity(ko.dataFor(this));
}
this.endDrag = function(data, event) {
self.dragSourceStack(undefined);
self.draggingEntity(undefined);
}
},
template: { element: 'stack-master-template' }
});
ko.components.register('stack', {
viewModel: function(params) {
var self = this;
// params
...