Knockout Prototype Meta Editor
by Ben Clayton
HTML
<div style="height:100px"></div>
<div data-bind="foreach: keywords">
<div class="row">
<combo-widget params="value: parent"></combo-widget>
<combo-widget params="value: child"></combo-widget>
</div>
</div>
<button data-bind="click: add">Add</button>
CSS
.ncselect {
position: relative;
display:inline-block;
}
.optionlist {
border: 1px solid gray;
width: 125px;
max-height: 200px;
overflow: auto;
position: absolute;
z-index: 2;
bottom: 28px;
background-color: #FFFFFF;
}
.selectinput {
width: 100px;
}
.ipwrapper {
display: inline-block;
position: relative;
}
.ipwrapper input {
height: 20px;
}
.combotrigger {
font-family: arial;
font-weight: bold;
line-height: 24px;
display: inline-block;
position: relative;
background-color: white;
width: 20px;
height: 24px;
cursor: pointer;
text-align: center;
border: 1px solid #C0C0C0;
left: -4px;
top: 1px;
}
JavaScript
ko.components.register('combo-widget', {
viewModel: function(params) {
var self = this;
self.value = ko.observable(params.value);
self.optionsOpen = ko.observable(false);
self.people = ko.observableArray([{
firstName: "Bert",
lastName: "Bertington"
}, {
firstName: "Bess",
lastName: "Bessington"
}]);
self.openCombo = function() {
this.optionsOpen(!this.optionsOpen());
}.bind(this);
self.addPerson = function() {
self.people.push({
firstName: "first ",
lastName: "last "
});
}.bind(this);
self.selectFromList = function(option) {
this.value(option.firstName);
this.optionsOpen(false);
}.bind(this);
self.removePerson = function() {
self.people.remove(this);
}.bind(this);
self.currentFilter = ko.observable(); // property to store the filter
self.filterProducts = ko.computed(function() {
if (!this.currentFilter()) {
return this.people();
} else {
return ko.utils.arrayFilter(this.people(), function(option) {
return option.firstName == this.currentFilter();
}.bind(this));
}
}.bind(this));
self.filter = function() {
this.currentFilter(this.value());
}.bind(this);
},
template: '<div class="ncselect">\
<div class="optionlist" data-bind="visible: optionsOpen">\
<table>\
<tbody data-bind="foreach: people" >\
<tr data-bind="click: $parent.selectFromList" >\
<td data-bind="text: firstName" ></td>\
<td data-bind="text: lastName" > </td>\
</tr>\
</tbody>\
</table>\
</div>\
<div class="ipwrapper" >\
<input class="selectinput" type="text" data-bind="value: value" />\
<div data-bind="click: openCombo" class="combotrigger">v</div>\
</div>\
</div>'
});
function metaeditor() {
this.keywords = ko.observableArray();
this.add = function() {
this.keywords.push({
...