I've created a tabbed module which works by getting content that is in the .content
div (which is hidden) and displaying it in a empty div called .overview
.
The idea behind this tabbed module is that, on hover (or when class active exists), the content on the right will change based on what header is being selected from the left. I.e. If I hover over a header named "Red", the .overview
div on the right will spit out "red".
However, the issues I'm having are the following:
In the demo below, don't hover on any of the headers. The
.overview
div has no content - which is obviously not ideal. If.tabs
has class.active
, then I want its content displayed on the right. I have a counter running which changes class active every 5 seconds. I don't only want to show stuff on hover.Having said the above, if I hover over another
tabs
div, I want the counter to stop - to prevent it from adding classactive
to another.tabs
div (because the hovered ontabs
is active.
Demo:
$(document).ready(function() {
// add class .active on li hover
$('.tabs').mouseenter(function() {
//$('.tabs').removeClass('active');
$(this).parents('.tabs').addClass('active');
});
// Change active tab every x seconds
$(function() {
var list = $(".tabs"),
currentActive = 0;
time = 5; // interval in seconds
setInterval(function() {
currentActive = (currentActive + 1) % list.length;
list.removeClass('active').eq(currentActive).addClass('active');
}, time * 1000);
});
})
var overview = $('.overview');
$('.tabs').each(function(i) {
var thisTab = $(this);
var thisContent = thisTab.find('.content').html();
// when class .active exists, change content in .overview
if ($('.tabs').hasClass('active')) {
overview.html(thisContent);
}
// on hover, change content in .overview
thisTab.on('mouseenter', function(e) {
thisTab.addClass('active');
overview.html(thisContent);
})
.on('mouseleave', function(e) {
thisTab.removeClass('active');
overview.html('');
});
});
.tabs.active {
background: none yellow;
}
.list {
flex-basis: 40%;
}
.list li {
list-style-type: none;
}
.overview {
flex-basis: 60%;
border: 1px solid blue;
}
.content {
display: none;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="d-flex flex-row">
<div class="list">
<li class="tabs active">
<div class="header"><span>Header</span></div>
<div class="content">
<p>Content 1</p>
</div>
</li>
<li class="tabs">
<div class="header"><span>Header 2</span></div>
<div class="content">
<p>Content 2</p>
</div>
</li>
<li class="tabs">
<div class="header"><span>Header 3</span></div>
<div class="content">
<p>Content 3</p>
</div>
</li>
</div>
<div class="overview"> </div>
</div>
Edit:
I've managed to make some movement on issue 1. I've added:
if ($('.tabs').hasClass('active')) {
overview.html(thisContent);
}
Which now, without hover, displays content in .overview
, however, the content doesn't change when another tab is .active
(i.e. in the demo, don't hover over anything, wait and it just shows content 3 for all headers.
2 Answers 2
I would do the following (I have commented what I have changed)
$(document).ready(function() {
var list = $(".tabs"),
overview = $('.overview'),
autoInterval, // interval var
currentActive = 0; // make this global to this closure
overview.html(list.eq(0).find('.content').html()); // set overview content
startInterval(); // start interval straight away
// add class .active on li hover
list.mouseenter(function() {
var thisTab = $(this);
currentActive = list.index(this); // set current active
list.removeClass('active'); // remove active class
thisTab.addClass('active'); // add active class
clearInterval(autoInterval); // clear the interval whilst hovering
var thisContent = thisTab.find('.content').html(); // get content
overview.html(thisContent); // set overview content
});
list.mouseleave(function() {
startInterval(); // restart the interval on mouseleave
});
function startInterval() {
// Change active tab every x seconds
time = 5; // interval in seconds
autoInterval = setInterval(function() {
currentActive = (currentActive + 1) % list.length;
list.removeClass('active');
var currentTab = list.eq(currentActive);
currentTab.addClass('active');
overview.html(currentTab.find('.content').html()); // set overview content
}, time * 1000);
}
});
.tabs.active {
background: none yellow;
}
.list {
flex-basis: 40%;
}
.list li {
list-style-type: none;
}
.overview {
flex-basis: 60%;
border: 1px solid blue;
}
.content {
display: none;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="d-flex flex-row">
<div class="list">
<li class="tabs active">
<div class="header"><span>Header</span></div>
<div class="content">
<p>Content 1</p>
</div>
</li>
<li class="tabs">
<div class="header"><span>Header 2</span></div>
<div class="content">
<p>Content 2</p>
</div>
</li>
<li class="tabs">
<div class="header"><span>Header 3</span></div>
<div class="content">
<p>Content 3</p>
</div>
</li>
</div>
<div class="overview"> </div>
</div>
As soon as you add the mouseenter
event, you need to stop the interval, you have the method clearInterval
to do so.