JSFiddle - React, Tailwind, and code Playground
by Mark
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<fieldset>
<legend>Settings</legend>
<input type="radio" id="FieldSize" name="PointBasis" value="fieldsize" data-bind="checked: settings.points.basis" /><label for="FieldSize">Field Size</label>
<input type="radio" id="Ceiling" name="PointBasis" value="ceiling" data-bind="checked: settings.points.basis" /><label for="Ceiling"><span data-bind="text: settings.points.ceiling"></span> Point Ceiling</label>
</fieldset>
<fieldset>
<legend>New Combatant</legend>
ID: <input type="text" id="CombatantID" />
<br />
<br />
Name: <input type="text" id="CombatantName" />
<br />
<br />
Division: <select id="Division" data-bind="foreach: divisions">
<option data-bind="text: name" />
</select>
<br />
<br />
<button id="Add" >Add Combatant</button>
</fieldset>
<table border="1">
<thead>
<th>Division</th>
<th>ID</th>
<th>Name</th>
<th>Kills</th>
<th>Time</th>
<th>Points</th>
</thead>
<tbody data-bind="foreach: {data: divisions, as: 'div'}">
<tr class="divheader">
<td data-bind="text: name" colspan="6"></td>
</tr>
<!-- ko foreach: combatants -->
<tr>
<td></td>
<td data-bind="text: ID"></td>
<td data-bind="text: name"></td>
<td class="align-right"><input type="text" data-bind="value: swords.kills"/></td>
<td class="align-right"><input type="text" data-bind="value: swords.time"/></td>
<td class="align-right" data-bind="text: $root.updatePoints($data, 'swords', $index(), div)"></td>
</tr>
<!-- /ko -->
</tbody>
</table>
JavaScript
ko.observableArray.fn.sortBy = function(evt, fld, direction){
var isdesc = direction && direction.toLowerCase() == 'desc';
return ko.observableArray(this.sort(function(a, b){
a = ko.unwrap(evt ? a[evt][fld]() : a[fld]());
b = ko.unwrap(evt ? b[evt][fld]() : b[fld]());
return (a == b ? 0 : a < b ? -1 : 1) * (isdesc ? -1 : 1);
}));
}
function ViewModel(data){
var self = this;
self.divisions = ko.observableArray([]).extend({notify: 'always'});
self.sortDivision = function(div, evt){
return div.sortBy(evt,'time','asc').sortBy(evt, 'kills', 'desc')
};
self.updatePoints = function(combatant, evt, val, div){
switch(combatant[evt].time().toLowerCase()){
case '0:00:00':
case 'none':
val = 0;
break;
case 'died':
val = 1;
break;
default:
switch(self.settings.points.basis()){
case 'ceiling':
val = self.settings.points.ceiling() - val;
if(val < self.settings.points.floor()){
val = self.setting.points.floor();
}
break;
default:
val = div.combatants().length - val;
}
}
combatant[evt].points(val);
return combatant[evt].points();
}
self.addCombatant = function(combatant){
ko.utils.arrayForEach(self.divisions(), function(d){
if(d.name() == combatant.division){
d.combatants.push({name: combatant.name,
ID: combatant.ID,
swords:{points: 0, time:'none', kills: 0}
});
}
console.log(ko.toJSON(self.divisions));
}
)}.bind(this);
ko.mapping.fromJS(data, {}, self);
}
var _vm;
$(function(){
$('#Add').on('click',
function(){
_vm.addCombatant({division: $('#Division option:selected').val(),
ID: $('#CombatantID').val(),
name: $('#CombatantName').val()});
});
});
$.getJSON('https://api.myjson.com/bins/3jack',
function(res){
_vm = new...