JSFiddle - React, Tailwind, and code Playground
HTML
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css">
<div class="legends">
<input id="legAvailable" type="checkbox" disabled />
<label for="legAvailable"> Available</label>
<input id="legAvailable" type="checkbox" data-status="notavailable" disabled />
<label for="legAvailable"> Not Available</label>
<input id="legBooked" type="checkbox" data-status="booked" checked disabled />
<label for="legBooked"> Booked</label>
<input id="legBooked" type="checkbox" checked disabled />
<label for="legBooked"> Selected</label>
</div>
<div id="seats">
</div>
<div>
<br />
<h4>Mode</h4>
<input type="radio" name="mode" value="false" class="flexiSeatsMode" />Single
<input type="radio" name="mode" value="true" class="flexiSeatsMode" />Multiple
</div>
<div class="methods">
<button type="button" id="btnGetSelected">Get Selected</button>
</div>
CSS
/* Reset */
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
margin: 10px;
line-height: 1;
font-family: Arial;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* Custom */
div.legends {
font-family: Arial;
font-size: 12px;
margin: 10px 0;
color: #666;
}
div.methods {
margin: 10px 0;
}
div.row {
line-height: 12px;
}
input[type=checkbox] {
display: none;
}
/* to hide the checkbox itself */
input[type=checkbox] + label:before {
font-family: FontAwesome;
font-size: 12px;
display: inline-block;
margin: 0 1px;
}
input[type=checkbox] + label:before {
content: "\f111";
color: #ddd;
cursor: pointer;
}
input[type=checkbox]:checked + label:before {
content: "\f111";
color: #2980b9;
}
input[type=checkbox]:disabled[data-status=booked] + label:before {
content: "\f111";
color: #27ae60;
}
input[type=checkbox]:disabled[data-status=notavailable] + label:before {
content: "\f111";
color: #999;
}
JavaScript
(function($) {
$.fn.flexiSeats = function(options) {
var scope = this;
//Options
var settings = $.extend({
rows:1,
columns:1,
booked: [],
notavailable: [],
multiple: true
}, options);
//Local Variables
var _available = [];
var _notavailable = [];
var _booked = [];
var _selected = [];
var _multiCursor = 0;
var _multiStart = '';
var _multiEnd = '';
//Create Initial Layout
for (i = 0; i < settings.rows; i++) {
var _row = $('<div class="row"></div>');
for (j = 0; j < settings.columns; j++) {
var _id = i + '-' + j;
var _checkbox = $('<input id="seat' + _id + '" type="checkbox" />');
var _label = $('<label for="seat' + _id + '"></label>');
if ($.inArray(_id, settings.booked) >= 0) {
_checkbox.prop('disabled', 'disabled');
_checkbox.attr('data-status', 'booked');
_booked.push(_id);
} else if ($.inArray(_id, settings.notavailable) >= 0) {
_checkbox.prop('disabled', 'disabled');
_checkbox.attr('data-status', 'notavailable');
_notavailable.push(_id);
} else {
_available.push(_id);
}
_row.append(_checkbox);
_row.append(_label);
}
this.append(_row);
}
//Events
this.on('click', 'input:checkbox', function() {
if ($(this).data('status') == 'booked')
return false;
var _id = $(this).prop('id').substr(4);
if (settings.multiple === true) {
if (_multiCursor == 0) {
_multiCursor = 1;
_multiStart = _id;
} else {
_multiCursor = 0;
_multiEnd = _id;
selectMultiple(_multiStart, _multiEnd);
_multiStart = '';
_multiEnd = '';
}
} else {
if ($(this).prop('checked') == true)
selectSeat(_id);
else {
deselectSeat(_id);
}
}
});
//Private...