I have a tabbing module that I'm beginning to modularise. The basic functionality is working but the slideUp function doesn't seem to be firing after the first time it is triggered. Instead tabs are just laying over the top of one another.
(function() {
var tabbing = {
init: function() {
this.cacheDom();
this.bindEvents();
},
cacheDom: function() {
this.el = $('.js-tab-panels');
this.tabs = this.el.find('.js-tabs');
this.navItem = this.tabs.find('.nav-item');
this.panel = this.navItem.closest(this.el);
},
bindEvents: function() {
this.navItem.on('click', this.toggleActive.bind(this));
},
toggleActive: function(el) {
this.panel.find('.js-tabs li.active').removeClass('active');
var add = $(el.target).closest(this.navItem);
add.addClass('active');
this.hidePanel();
},
hidePanel: function() {
this.panel.find('.panel.active').slideUp(300, this.showPanel());
},
showPanel: function() {
var panelToShow = this.panel.find('.js-tabs li.active').attr('rel');
this.panel.find('.panel.active').removeClass('active');
$('#' + panelToShow).slideDown(300, function() {
$(this).addClass('active');
});
}
};
tabbing.init();
})()
body {
background: #fafafa;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #333;
}
.tab-panels ul {
margin: 0;
padding: 0;
}
.tab-panels ul li {
list-style-type: none;
display: inline-block;
background: #999;
margin: 0;
padding: 3px 10px;
border-radius: 10px 10px 0 0;
color: #fff;
font-weight: 200;
cursor: pointer;
}
.tab-panels ul li:hover {
color: #fff;
background: #666;
}
.tab-panels ul li.active {
color: #fff;
background: #666;
}
.tab-panels .panel {
display: none;
background: #c9c9c9;
padding: 30px;
border-radius: 0 0 10px 10px;
}
.tab-panels .panel.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="js-tab-panels tab-panels">
<ul class="js-tabs tabs">
<li rel="panel1" class="nav-item active">panel1</li>
<li rel="panel2" class="nav-item">panel2</li>
<li rel="panel3" class="nav-item">panel3</li>
<li rel="panel4" class="nav-item">panel4</li>
</ul>
<div id="panel1" class="panel active">
content1<br/> content1
<br/> content1
<br/> content1
<br/> content1
<br/>
</div>
<div id="panel2" class="panel">
content2<br/> content2
<br/> content2
<br/> content2
<br/> content2
<br/>
</div>
<div id="panel3" class="panel">
content3<br/> content3
<br/> content3
<br/> content3
<br/> content3
<br/>
</div>
<div id="panel4" class="panel">
content4<br/> content4
<br/> content4
<br/> content4
<br/> content4
<br/>
</div>
</div>
In the hidePanel
function when you call .slideUp(300, this.showPanel());
you are passing the result of this.showPanel()
as the second argument of slideUp
function, but what you want is to execute this.showPanel
as the callback when slideUp
animation is complete.
So to fix that you just need to pass in a copy of the showPanel
function as the second argument instead of its result:
...slideUp(300, this.showPanel.bind(this));