Bracket prototyping - 2
by goranobradovic
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js"></script>
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<br/>
<div class='container-fluid'>
<div data-bind="with:parameters">
<fieldset class='parameters table-bordered'>
<legend>
Bracket parameters
</legend>
<label for="numberOfParticipants">Number of participants</label>
<select id="numberOfParticipants" data-bind="options: availableNumberOfParticipants,
value: numberOfParticipants">
</select>
</fieldset>
<fieldset class='parameters table-bordered' data-bind="with:display">
<legend>
Display parameters
</legend>
<span class='float' style="display:none;">
<label for="useAlternateTemplate">Use alternate template</label>
<input id="useAlternateTemplate" type='checkbox' data-bind="checked:alternateTemplate" />
</span>
<label for='canvasWidth'>Width: <span id='canvasWidth' data-bind='text:width'></span></label>
</fieldset>
</div>
<br/>
<div class='container-fluid' data-bind="with:bracket">
<fieldset data-bind="if:numberOfParticipants">
<legend>
Bracket output
</legend>
<div data-bind="ifnot:$root.parameters.display.alternateTemplate()" style="display:none;">
<div data-bind="template: { name: 'match-template', data: final }">
</div>
</div>
<div class='clear'>
</div>
<div class='container container-fluid' data-bind="if:$root.parameters.display.alternateTemplate()" style="display:none;">
Second template
<div data-bind="template: {name: 'winner-match-template', data: final}">
</div>
</div>
<br/>
<div id='canvasBrackets'>
</div>
</fieldset>
</div>
</div>
<script type="text/html" id="match-template">
<table class='table table-hover table-bordered table-match'>
...
CSS
@import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
table.table-match>tbody>tr>td {
padding: 0px;
border-top: none;
}
table.table-match>tbody>tr>td>table.table-match>tbody>tr>td {
border-width: 0px;
border-left-width: 1px
}
table.table-match {
margin-bottom: 0px;
border-top: none;
}
.match-container {
display: -webkit-box;
/* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box;
/* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox;
/* TWEENER - IE 10 */
display: -webkit-flex;
/* NEW - Chrome */
display: flex;
list-style: none;
border: 1px gray solid;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.match-item {
padding: 0px;
width: 50%;
height: 100%;
margin: 0px;
line-height: 15px;
color: black;
font-weight: bold;
font-size: 14px;
text-align: center;
vertical-align: middle;
/*flex-flow: column;*/
align-items: stretch;
}
.match-team {
width: 100%;
height: 50%;
display: block;
}
svg {
border: 1px solid silver;
}
.node {
cursor: pointer;
}
.node circle {
stroke: steelblue;
stroke-width: 1.5px;
}
.link {
fill: none;
stroke: lightgray;
stroke-width: 1.5px;
}
JavaScript
function DisplayParameters() {
var self = this;
self.updateForNumberOfParticipants = function(numberOfParticipants) {
var depth = Math.ceil(Math.log2(numberOfParticipants)) + 1;
self.width(50 + self.maxLabel() * depth);
self.height(numberOfParticipants * 40);
};
self.width = ko.observable(1200);
self.height = ko.observable(800);
self.maxLabel = ko.observable(150);
};
function Parameters() {
var self = this;
self.display = new DisplayParameters();
self.display.alternateTemplate = ko.observable(false);
self.numberOfParticipants = ko.observable(0);
var optionsForDropdown = Array.apply(null, {
length: 127
}).map(Number.call, function(i) {
return i + 2;
});
self.availableNumberOfParticipants = ko.observableArray(optionsForDropdown);
self.numberOfParticipants.subscribe(self.display.updateForNumberOfParticipants);
};
function Team(name) {
var self = this;
self.className = 'team';
self.name = name;
self.children = [];
self.toJson = function() {
return {
name: self.name,
children: null
};
};
}
function Match(id, name, left, right) {
var self = this;
self.id = id;
self.className = 'match';
self.children = [left, right];
self.name = name;
self.toJson = function() {
return {
name: self.name,
children: self.children.map(function(item) {
return item.toJson();
})
};
};
};
function Bracket(parameters) {
var self = this;
self.parameters = parameters;
self.final = ko.observable(null);
var currentMatchNumber;
self.parameters.numberOfParticipants.subscribe(generateBracketMatches);
function generateBracketMatches(numberOfParticipants) {
currentMatchNumber = 1;
var teams = Array.apply(null, {
length: numberOfParticipants
}).map(Number.call, function(i) {
return i + 1;
})
.reverse();
console.log('//////////////////////////////////////////////////');
var matches = [];
var teamMatches =...