ViewModel Test
by bombo
HTML
<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js"></script>
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-1.2.1.debug.js"></script>
<ul id="header" data-bind="template: { name: 'AddressHeaderEntry', foreach: Addresses }">
<li id="add" class="unselected" data-bind="click: Add">+</li>
</ul>
<div id="container" data-bind="template: {name: 'AddressEntry', foreach: Addresses }"></div>
<!-- Templates -->
<script id="AddressHeaderEntry" type="text/html">
<li class="headerEntry unselected" data-bind="click: GetFocus, css: { selected: Selected(), unselected: !Selected() }"><input data-bind="value: Name, enable: checkEnable" disabled="disabled" /></li>
</script>
<script id="AddressEntry" type="text/html">
<div class="entry" data-bind="visible: Selected">
<div class="field">
<label for="firstname">First name: </label>
<input type="text" id="firstname" data-bind="value: Firstname, enable: checkEnable" disabled="disabled" />
</div>
<div class="field">
<label for="lastname">Last name: </label>
<input type="text" id="lastname" data-bind="value: Lastname, enable: checkEnable" disabled="disabled" />
</div>
<div class="field">
<label for="street">Street: </label>
<input type="text" id="street" data-bind="value: Street, enable: checkEnable" disabled="disabled" />
</div>
<div class="toolbox">
<button data-bind="click: editEntry, text: buttonText"></button>
</div>
</div>
</script>
CSS
ul#header li {
float: left;
padding: 2px 6px;
border-left: 1px dotted #aaa;
border-top: 1px dotted #aaa;
border-right: 1px dotted #aaa;
}
.unselected, .unselected input {
cursor: pointer;
background: #eee;
}
.unselected, .unselected input[disabled] {
background: #eee;
}
#header li input {
width: 80px;
}
.unselected:hover {
color: #39b;
}
#container {
clear: both;
position: relative;
top: -1px;
border: 1px dotted #aaa;
z-index: 10;
-moz-box-shadow: 2px 2px 0px #888888; /* Firefox 3.6 and earlier */
-webkit-box-shadow: 2px 2px 0px #888888; /* Safari and Chrome */
box-shadow: 2px 2px 0px #888888;
}
.field {
margin: 5px;
}
.field label {
display: inline-block;
width: 150px;
text-align: right;
}
input[disabled] {
background: white;
border: none;
margin: 2px;
}
input {
border-color: #ccc;
}
.selected {
position: relative;
z-index: 100;
border-bottom: 1px solid white;
background: white;
cursor: auto;
-moz-box-shadow: 2px 0px 0px #888888; /* Firefox 3.6 and earlier */
-webkit-box-shadow: 2px 0px 0px #888888; /* Safari and Chrome */
box-shadow: 2px 0px 0px #888888;
}
.selected input {
font-weight: bold;
}
.toolbox {
text-align: right;
}
button {
background: #ccc;
border: none;
cursor: pointer;
padding: 4px 8px;
}
button:hover {
background: #eee;
}
JavaScript
//////////////////////////////////
// Constructors //
//////////////////////////////////
function VMKey(user, selectedEmployeeId, guid) {
this.User = user;
this.SelectedEmployeeId = selectedEmployeeId;
this.GUID = guid;
}
function VMHeader(modelID, name, description, action, key) {
this.ModelID = modelID;
this.ModelName = name;
this.Description = description;
this.Action = action;
this.Key = key;
}
function AddressesField(name, lastname, firstname, street) {
this.Name = ko.observable(name);
this.Lastname = ko.observable(lastname);
this.Firstname = ko.observable(firstname);
this.Street = ko.observable(street);
this.Selected = ko.observable(false);
this.buttonText = ko.observable('edit');
this.checkEnable = ko.dependentObservable(function () {
return this.buttonText() === 'accept';
}, this);
this.editEntry = function (event) {
if (this.buttonText() === 'edit') {
this.buttonText('accept');
} else {
this.buttonText('edit');
}
}.bind(this);
this.GetFocus = function (event) {
if (viewModel.focussedElement) {
viewModel.focussedElement.Selected(false);
viewModel.focussedElement.buttonText('edit');
}
viewModel.focussedElement = this;
this.Selected(true);
}.bind(this);
}
//////////////////////////////////
// ViewModel //
//////////////////////////////////
var viewModel = {
Header: new VMHeader(
'',
'AddressModel',
'This Model retrieves all information regarding Address Handling',
'GetCustomizing',
new VMKey()
),
Addresses: ko.observableArray([
new AddressesField('Current', 'Twartzen', 'Bruce', 'Now Street'),
new AddressesField('Future', 'Twartzen', 'Bruce', 'Future Blvd.')
]),
Add: function () {
this.Addresses.push(new AddressesField('New'));
},
...