Knockout.JS - Bindings - Forms
Greek Letters
by Marventus
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<h2>Bindings - Forms</h2>
<form>
<h4>New letter:</h4>
<input data-bind='value: letterToAdd, valueUpdate: "afterkeydown"' />
<p id="status-container"><span id="status-msg" data-bind="visible: statusMsg() !== '', text: statusMsg, css: {error: removing}"></span> </p>
<div class="buttons">
<button id="add" data-bind="enable: activeList() === 'available' && letterToAdd() !== '', click: addLetter">Add</button>
<button id="remove" data-bind="disable: activeList() === 'available' || letterToAdd() === '', click: removeLetter">Remove</button>
<button id="clear" data-bind="enable: letterToAdd() !== '', click: clearLetter">Clear</button>
</div>
</form>
<main class="summary">
<div id="available-letters" class="fifty">
<h4>Available Letters:</h4>
<select multiple="multiple" data-bind="foreach: availLetters, hasFocus: activeList() === 'available'">
<option data-bind="text: $data, event: { click: $root.updateNew, dblclick: $root.updateLists }">
</option>
</select>
</div>
<div id="selected-letters" class="fifty last">
<h4>Selected Letters:</h4>
<select multiple="multiple" data-bind="foreach: selLetters, hasFocus: activeList() === 'selected'">
<option data-bind="text: $data, event: { click: $root.updateNew, dblclick: $root.updateLists }">
</option>
</select>
</div>
</main>
CSS
body {
background: rgba(247, 243, 222, 0.9);
color: #777;
font: 16px Arial, Helvetica, sans-serif;
max-width: 100%;
margin: 0 auto;
padding: 1em 3em;
text-align: center;
}
a,
a:hover,
a:visited,
a:active,
a:focus,
h2 {
color: rgb(139, 116, 61);
}
button,
input,
select {
box-sizing: border-box;
border: 1px solid rgba(139, 116, 61, 0.6);
padding: 0.5em 1em;
width: 100%;
}
button:focus,
input:focus,
select:focus {
border: 1px solid rgba(139, 116, 61, 1);
box-shadow: 0;
outline: 0;
}
select {
height: 10em;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: bold;
margin: 0;
}
h2 {
font-size: 2em;
margin: 0;
}
h4 {
font-size: 1.2em;
margin-bottom: 1em;
}
form,
main {
margin: 1em auto;
max-width: 80%;
}
main {
padding: 0.5em 1em;
position: relative;
}
main p {
margin-top: 0;
}
p {
font-size: 0.9rem;
margin: 0.5em 0;
}
.buttons {
box-sizing: border-box;
height: 2em;
}
.buttons button {
border-color: rgba(0, 0, 0, 0.15);
border-radius: 3px;
box-sizing: border-box;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 0.7em;
height: 2em;
margin: 1em 0 0;
max-width: 25%;
outline: none;
text-transform: uppercase;
}
.buttons button:disabled {
cursor: default;
opacity: 0.3;
}
.buttons button:last-of-type {
margin-right: 0;
}
#add {
background: #8d8;
}
#clear {
background: rgba(139, 116, 61, 0.9);
}
#remove {
background: #f88;
}
#status-container {
margin: 0.5em 0 0;
text-align: left;
}
#status-container span {
color: #6c6;
font-weight: bold;
}
#status-container span.error {
color: #c66;
}
.fifty {
float: left;
margin-top: 1em;
width: 48%;
}
.fifty.last {
float: right;
}
JavaScript
var greekLettersStr = "alpha, beta, gamma, delta, epsilon, zeta, eta, theta, iota, kappa, lambda, mu, nu, xi, omicron, pi, rho, sigma, tau, upsilon, phi, chi, psi, omega",
greekLettersArr = greekLettersStr.replace(/\s/g, "").split(","),
greekLettersModel = function() {
var self = this;
self.availLetters = ko.observableArray(greekLettersArr);
self.selLetters = ko.observableArray([]);
self.letterToAdd = ko.observable("");
self.statusMsg = ko.observable("");
self.removing = ko.observable(false);
self.activeList = ko.observable("available");
self.addLetter = function(data) {
var letter = self.letterToAdd() !== "" ? self.letterToAdd() : data;
if (!self.letterExists(letter, self.selLetters)) {
self.selLetters.push(letter);
self.handleStatusMsg("Letter sucessfully added.", false);
}
self.letterToAdd("");
};
self.clearLetter = function() {
self.letterToAdd("");
};
self.letterExists = function(letter, list){
if (letter !== "")
return $.inArray(letter, list) > -1;
};
self.removeLetter = function(data) {
var letter = self.letterToAdd() || data;
if( self.letterExists(letter, self.selLetters()) ) {
self.selLetters.remove(letter);
self.letterToAdd("");
self.handleStatusMsg("Letter succesfully removed.", true);
}
};
self.updateLists = function(data, event) {
self.updateNew(data, event);
if(self.activeList() === "available")
self.addLetter(data);
else
self.removeLetter(data);
};
self.updateNew = function(data, event) {
self.letterToAdd(data);
self.activeList( $(event.target).closest(".fifty").attr("id").split("-")[0] );
};
...