Knockout seat selector
Using simple knockout js for selecting seats for a particular venue / event.
by Dejan Vasic
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<div class="container">
<div>
Tickets:
<div>
<span class="ticket-legend">
<i class="fa fa-times"></i>
</span>
<span>Reserved / Booked</span>
</div>
<div data-bind="foreach: tickets">
<div>
<span class="ticket-legend" data-bind="style: style"></span>
<span data-bind="text: ticketName"></span>
<span data-bind="text: price"></span>
</div>
</div>
</div>
<div class="seat-selector">
<h4 data-bind="text: venueName"></h4>
<div data-bind="foreach: rows">
<div class="row" data-bind="foreach: seats">
<div class="seat" data-bind="click: $root.selectSeat, css : { 'not-available' : notAvailable, 'selected' : selected}, style : style">
<i class="glyphicon glyphicon-check" data-bind="visible: selected()"></i>
<i class="glyphicon glyphicon-unchecked" data-bind="visible: !selected() && !notAvailable()"></i>
<i class="fa fa-times" data-bind="visible: notAvailable"></i>
</div>
</div>
</div>
</div>
<div class="well" data-bind="visible: readyToProceed">
<div>
Selected:
<div data-bind="foreach: selectedSeats">
<div>
seat number <span data-bind="text: id"></span>
</div>
</div>
</div>
<button class="btn btn-primary">
Proceed <i class="fa fa-arrow-right"></i>
</button>
</div>
</div>
CSS
.seat-selector {
text-align: center;
}
.seat {
border: 1px solid #eee;
height: 50px;
width: 50px;
border-radius: 10px;
margin: auto;
display: inline-block;
text-align: center;
padding: 15px 0;
cursor: pointer;
}
.not-available {
background-color: #eee;
}
.selected {
background-color: #a5d8c7;
border-color: #333;
border-width: 2px;
}
.row {
text-align: center;
margin-top: 10px;
}
.ticket-legend {
width: 20px;
height: 20px;
border-radius: 10%;
background-color: #eee;
display: inline-block;
text-align: center;
}
JavaScript
var serverData = {
name: "The Grand Hotel",
rows: [{
name: "A",
seats: [{
id: '1',
notAvailable: true,
category: 'Vip',
colourCode: '#E9E581'
}, {
id: '2',
category: 'Vip',
colourCode: '#E9E581'
}, {
id: '3',
category: 'Vip',
colourCode: '#E9E581'
}, {
id: '4',
category: 'Vip',
colourCode: '#E9E581'
}]
},
{
name: "B",
seats: [{
id: '1',
category: 'General',
colourCode: '#A3CDDF'
}, {
id: '2',
notAvailable: true,
category: 'General',
colourCode: '#A3CDDF'
}, {
id: '4',
category: 'General',
colourCode: '#A3CDDF'
}, {
id: '5',
category: 'General',
colourCode: '#A3CDDF'
}, {
id: '6',
category: 'General',
colourCode: '#A3CDDF'
}]
}
]
}
function Seat(data, row) {
var me = this;
me.id = ko.observable(data.id);
me.notAvailable = ko.observable(data.notAvailable || false);
me.selected = ko.observable(data.selected || false);
me.row = row;
me.style = ko.observable({
'background-color': data.notAvailable ? '#eee' : data.colourCode
});
}
function Row(data) {
var me = this;
me.name = ko.observable(data.name);
me.seats = ko.observableArray();
for (var i = 0; i < data.seats.length; i++) {
me.seats.push(new Seat(data.seats[i], me));
}
}
function SeatSelector(venueDetails, tickets, selections) {
var me = this;
me.tickets = tickets;
me.selectedSeats = ko.observableArray();
me.venueName = ko.observable(venueDetails.name);
me.rows = ko.observableArray();
me.readyToProceed = ko.computed(function() {
return me.selectedSeats().length > 0;
});
for (var i = 0; i < venueDetails.rows.length; i++) {
me.rows.push(new Row(venueDetails.rows[i]));
}
this.selectSeat = function(seat) {
if...