KnockoutJS Tabs
by Farzad Cyrus
HTML
<div id="wrapper">
<h3>
<p>You have selected the <strong data-bind="text: selectedSection().name"></strong></p>
</h3>
<div class="tab">
<ul class="tab-nav" data-bind="foreach: sections">
<li data-bind="css: {active: isSelected}, click: $parent.selectedSection">
<a href="#"><span data-bind="text: name" /></a>
</li>
</ul>
<div class="tab-content" data-bind="template: {name: getTemplate}">
</div>
</div>
<p>You can select the third tab or random tab by clicking the buttons bellow.<br>The random button was clicked <strong data-bind="text: numberOfClicks"></strong> times.</p>
<p>
<button data-bind="click: selectThirdTab">Selected Third Tab</button>
<button data-bind="click: selectRandomTab">Select Random Tab</button>
</p>
</div>
<script id="one" type="text/html">
<div class="inner">The content of the first tab goes here</div>
</script>
<script id="two" type="text/html">
<div class="inner">The content of the second tab goes here</div>
</script>
<script id="three" type="text/html">
<div class="inner">The content of the third tab goes here</div>
</script>
CSS
body, html {
font-family: Arial;
color:#223344;
font-size: 12px;
}
p {
padding: 0 0 10px 0;
margin: 10px 0 0 0;
line-height:18px;
}
#wrapper {
padding:20px;
}
.tab {
width:400px;
height:auto;
}
.tab-nav {
list-style-type:none;
border-bottom:1px solid #cccccc;
}
.tab-nav li {
display:inline-block;
width:auto;
height:30px;
line-height:30px;
border:1px solid #cccccc;
background:#eeeeee;
padding:0 10px;
margin-bottom:-1px;
cursor: pointer;
margin-right: 2px;
}
.tab-nav li a {
text-decoration:none;
color:#222222;
}
.tab-nav li.active {
background:#ffffff;
border-bottom-color:#ffffff;
}
.tab-content {
border-width: 0 1px 1px 1px;
border-style: solid;
border-color:#cccccc;
padding:20px;
}
button {
border: 1px solid #114477;
background: #3a5a7a;
width: auto;
height: 30px;
padding: 0 10px;
line-height:30px;
display:inline-block;
margin: 0 10px 0 0;
color:#ffffff;
cursor:pointer;
}
strong {
font-weight: bold;
}
JavaScript
function randomIntFromInterval(min,max) {
return Math.floor(Math.random() * (max-min + 1) + min);
}
var tab = function (name, id, selected) {
this.name = name;
this.id = id;
this.isSelected = ko.computed(function () {
return this === selected();
}, this);
}
var ViewModel = function () {
var self = this;
self.selectedSection = ko.observable();
self.sections = ko.observableArray([
new tab('First Tab', 'one', self.selectedSection),
new tab('Second Tab', 'two', self.selectedSection),
new tab('Third Tab', 'three', self.selectedSection)
]);
var numberOfTabs = self.sections().length,
firstTab = 0,
secondTab = 1,
thirdTab = 2,
lastTab = numberOfTabs - 1;
// Inialising the Default Tab
self.selectedSection(self.sections()[firstTab]);
self.getTemplate = function (item) {
var selected = self.selectedSection();
return selected && selected.id;
};
// Select the Third Tab
self.selectThirdTab = function() {
self.selectedSection(self.sections()[thirdTab]);
}
self.numberOfClicks= ko.observable(0);
self.incrementClickCounter = function() {
var previousCount = this.numberOfClicks();
this.numberOfClicks(previousCount + 1);
}
// Select Random Tab
self.selectRandomTab = function() {
if (numberOfTabs > 1) {
// Limiting Number of Clicks to 3
if(self.numberOfClicks() < 3) {
self.incrementClickCounter(1);
self.selectedSection(self.sections()[randomIntFromInterval(0, lastTab)]);
}
} else {
alert('Sorry there isn\'t enough number of tabs!');
}
}
}
ko.applyBindings(new ViewModel());