How to highlight selected tab in tabbed navigation - javascript

How in this example can I set the highlight of the selected tab?
And how can I set the first tab to be active when the page is opened, if none is set?
var $tabs = $('.tabs > div'), _currhash, $currTab;
function showTab() {
if($currTab.length>0) {
$tabs.removeClass('active');
$currTab.addClass('active');
}
}
$tabs.each(function() {
var _id = $(this).attr('id');
$(this).attr('id',_id+'_tab');
});
function anchorWatch() {
if(document.location.hash.length>0) {
if(_currhash!==document.location.hash) {
_currhash = document.location.hash;
$currTab = $(_currhash+'_tab');
showTab();
}
}
}
setInterval(anchorWatch,300);
.tabs > div { display:none;}
.tabs > div.active { display:block;}
a { display:inline-block; padding:0.5em;}
.tabs > div { padding:1em; border:2px solid #ccc;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
tab1
tab2
tab3
<div class="tabs">
<div id="tab1">content one</div>
<div id="tab2">content two</div>
<div id="tab3">content three</div>
</div>
Thank you!
JSFiddle

Related

Adding class names on hover based on conditions

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 class active to another .tabs div (because the hovered on tabs 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.
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.

Using .bind and .unbind to move a li

I'm trying to figure out how I can use bind to move the selected li's from box1 to box2 and from box2 back to box1. Stuck on this and need some help. Also when a li is selected and moved over to the next box by clicking Move Right, they stack on every click. How can I fix that?
code:
$(document).ready(function(){
$(".box1 ul li").click(function(){
if($(this).hasClass("active-li")==true)
{
$(this).removeClass("active-li");
}
else
{
$(this).addClass("active-li");
}
});
$(".box1 ul li").click(function(){
var x=$(this).data("drink");
$("#btt1").click(function(){
$(".box2 ul").append(x);
$(x).bind("click", bindLi);
});
});
$(x).bind("click", bindLi);
});
function bindLi(){
alert("hello");
}
CSS:
.box1{border:1px solid black; width:200px; height:200px; float:left; margin-top:100px; margin-left:50px;}
.box2{border:1px solid black; width:200px; height:200px; float:left; margin-top:100px; margin-left:100px;}
.button-container{width:80px; height:30px; float:left; margin-top:200px; margin-left:100px;}
.active-li{background-color:yellow;}
ul li:hover{cursor:pointer;}
HTML:
<div class="box1" id="box1">
<ul>
<li data-drink="beer">
Beer
</li>
<li data-drink="water">
Water
</li>
<li data-drink="soda">
Soda
</li>
<li data-drink="juice">
Juice
</li>
</ul>
</div>
<div class="button-container">
<input type="button" id="btt1" name="btt1" value="Move Right" />
<input type="button" id="btt2" name="btt2" value="Move Left" />
</div>
<div class="box2" id="box2">
<ul></ul>
</div>
JSFiddle:
https://jsfiddle.net/fgo455zt/
Please take a look at below code:
https://jsfiddle.net/fgo455zt/5/
We can simply the code as follows:
$(document).ready(function() {
$(".box1 ul li, .box2 ul li").click(function() {
$(this).toggleClass("active-li"); //highlight the clicked li
});
$("#btt1, #btt2").click(function() {
var sourceUL = null;
var targetUL = null;
//depending upon which button clicked we are moving selected li to and from source to target UL
if ($(this).attr("id") == "btt1") {
sourceUL = $(".box1 ul");
targetUL = $(".box2 ul");
} else {
sourceUL = $(".box2 ul");
targetUL = $(".box1 ul");
}
$(sourceUL).find("li.active-li").each(function() {
$(this).removeClass("active-li"); //removing the active class before moving the li
$(targetUL).append($(this));
});
});
});

accordion+tab = previous content does not disappear

When I click different links from different accordion elements content is displayed below previous one
$('.accordion').on('click', '.accordion-control', function(e){
e.preventDefault(); // Prevent default action of button
$(this) // Get the element the user clicked on
.next('.accordion-panel') // Select following panel
.not(':animated') // If it is not currently animating
.slideToggle(); // Use slide toggle to show or hide it
});
$('.tab-list').each(function(){ // Find lists of tabs
var $this = $(this); // Store this list
var $tab = $this.find('li.active'); // Get the active list item
var $link = $tab.find('a'); // Get link from active tab
var $panel = $($link.attr('href')); // Get active panel
$this.on('click', '.tab-control', function(e) { // When click on a tab
e.preventDefault(); // Prevent link behavior
var $link = $(this), // Store the current link
id = this.hash; // Get href of clicked tab
if (id && !$link.is('.active')) { // If not currently active
$panel.removeClass('active'); // Make panel inactive
$tab.removeClass('active'); // Make tab inactive
$panel = $(id).addClass('active'); // Make new panel active
$tab = $link.parent().addClass('active'); // Make new tab active
}
});
});
When I click different links from different accordion elements content is displayed below previous one
/********** ACCORDION **********/
.accordion, .menu {
background-color: #f2f2f2;
color: #666;
margin: 0;
padding: 0;
overflow: auto;}
.accordion li {
padding: 0;
list-style-type: none;}
.accordion-control {
background-color: rgba(0,0,0,0);
color: red;
display: block;
width: 100%;
padding: 0.5em 0.5em 0.5em 0.7em;
margin: 0;
}
.accordion-panel {
display: none;
}
.accordion-panel p {
margin: 20px;
}
.accordion-panel img {
display: block;
clear: left;
}
/*************** Panels ***************/
.tab-panel {
display: none;
}
.tab-panel.active {
display: block;
}
How do I make the previous content disappear?
<ul class="accordion">
<li class="active"><a class="tab-control" href="#tab-0">Misc Features</a></li>
<li>
<button class="accordion-control">Armory</button>
<div class="accordion-panel">
<ul class="tab-list">
<li><a class="tab-control" href="#tab-1">S grade</a></li>
<li><a class="tab-control" href="#tab-2">A grade</a></li>
<li><a class="tab-control" href="#tab-3">B grade</a></li>
<li><a class="tab-control" href="#tab-4">C grade</a></li>
</ul>
</div>
</li>
<li>
<button class="accordion-control">Weaponry</button>
<div class="accordion-panel">
<ul class="tab-list">
<li><a class="tab-control" href="#tab-5">Special Ability</a></li>
</ul>
</div>
</li>
<li>
<button class="accordion-control">Jewelry</button>
<div class="accordion-panel">
<ul class="tab-list">
<li><a class="tab-control" href="#tab-6">Raid Boss Jewelry</a></li>
</ul>
</div>
</li>
</ul>
<div class="content"> <!-- Content -->
<div class="tab-panel active" id="tab-0">misc features</div>
<div class="tab-panel" id="tab-1">armor S</div>
<div class="tab-panel" id="tab-2">armor A</div>
<div class="tab-panel" id="tab-3">armor B</div>
<div class="tab-panel" id="tab-4">armor C</div>
<div class="tab-panel" id="tab-5">weapon SA</div>
<div class="tab-panel" id="tab-6">RB jewelry</div>
</div>
Here is how you can do this:
$('.accordion .accordion-panel').not(this).slideUp();
$(this) // Get the element the user clicked on
.next('.accordion-panel') // Select following panel
.not(':animated') // If it is not currently animating
.slideToggle(); // Use slide toggle to show or hide it
Here is the demo.
Reference: jQuery: exclude $(this) from selector

show navigation dropdown without bumping content down

I am modifying some jQuery that shows a div when nav links are hovered.
html:
About
<div class="drop" id="drop-about">
<div class="drop-holder">
<div class="grey-block">
<strong class="title">Sub Nav</strong>
<ul>
more links ...
</ul>
</div>
</div>
</div>
jQuery to show dropdowns:
function initSlideDrops() {
var activeClass = 'drop-active';
var animSpeed = 300;
jQuery('#nav ul li').each(function() {
var item = jQuery(this);
var link = item.find('>a[data-drop^="#"]');
//if (!link.length) return;
// Modifications to add hover events to nav menu
if (!link.length) {
jQuery(this).on('mouseover', function (e) {
jQuery("li").removeClass("drop-active");
jQuery('.drop').each(function () {
jQuery(this).stop().animate({
height: 0
}, animSpeed);
});
});
return;
};
var href = link.data('drop');
var drop = jQuery(href).css({
height: 0
});
if(!drop.length) return;
var dropHolder = drop.find('>.drop-holder');
var close = drop.find('.btn-close');
function showDrop(elem) {
elem.stop().animate({
height: dropHolder.innerHeight()
}, animSpeed, function() {
elem.css({
height: ''
});
});
}
function hideDrop(elem) {
elem.stop().animate({
height: 0
}, animSpeed);
}
link.on('click', function(e) {
e.preventDefault();
item.add(drop).toggleClass(activeClass).siblings().removeClass(activeClass);
if(item.hasClass(activeClass)) {
showDrop(drop);
hideDrop(drop.siblings());
} else {
hideDrop(drop);
location.href = link.attr('href');
}
});
close.on('click', function(e) {
e.preventDefault();
item.add(drop).removeClass(activeClass);
hideDrop(drop);
});
// Modifications to add hover events to nav menu
link.on('mouseover', function (e) {
e.preventDefault();
item.add(drop).toggleClass(activeClass).siblings().removeClass(activeClass);
if (item.hasClass(activeClass)) {
showDrop(drop);
hideDrop(drop.siblings());
} else {
hideDrop(drop);
//location.href = link.attr('href');
}
});
drop.on('mouseleave', function (e) {
e.preventDefault();
item.add(drop).removeClass(activeClass);
hideDrop(drop);
});
});
}
This is all working, however the dropdown navigation causes the content to bump down, rather than sliding on top of the site body. I would like the main content to remain where it is, with the navigation showing on top when hovered. I have tried adding z-index during the animate event but could not get it to work. What is the proper way to accomplish this?
Any help is appreciated.
Edit:
SASS:
.drop{
#extend %clearfix;
overflow:hidden;
text-transform:uppercase;
letter-spacing: 1.65px;
.drop-holder{
overflow:hidden;
}
}
Try Adding position:absolute; to .drop-holder. See snippet below.
You will also want to remove overflow:hidden; from .drop.
.drop{
#extend %clearfix;
/* overflow:hidden; - Remove this */
text-transform:uppercase;
letter-spacing: 1.65px;
position:relative; /* add this so .drop is positioned relative to .drop */
}
.drop-holder {
position:absolute;
border:solid 1px teal; /*for demonstration*/
}
About
<div class="drop" id="drop-about">
<div class="drop-holder">
<div class="grey-block">
<strong class="title">Sub Nav</strong>
<ul>
more links ...
</ul>
</div>
</div>
</div>
<div>content <br />content <br />content <br />content <br />content <br />content <br />content <br />
</div>
Positioning property must be specified when using z-index.
Example. Apply
.drop{
#extend %clearfix;
overflow:hidden;
text-transform:uppercase;
letter-spacing: 1.65px;
position:relative; /*Positioning applied here*/
z-index:1;
}
This should fix your problem.

Cannot hide all div contents

I'm making collapsible/expandable divs, similar to accordions, where if I click a specific title, contents related to the title will appear. And if I click on a different title, previously opened contents will close before revealing the current contents for the recently clicked title, so that only one contents section is open at a time. I've got that sorted out.
<div class="container">
<div class="title">ONE</div>
<div class="content">Content One</div>
</div>
<div class="container">
<div class="title">TWO</div>
<div class="content">Content Two</div>
</div>
<div class="container">
<div class="title">THREE</div>
<div class="content">Content Three</div>
</div>
<div class="container">
<div class="title">FOUR</div>
<div class="content">Content Four</div>
</div>
However, I'm trying to make it so that all divs can be collapsed and all contents hidden. I'm having a really hard time figuring that part out. Here's what I have so far:
$(".title").click(function () {
$content = $(this).next();
if (!($content.is(":visible"))) {
$(".content").slideUp("fast");
$content.slideToggle(200);
}
});
DEMO: http://jsfiddle.net/2skczuze/
I'm fairly new with Javascript so I can't figure out how to make an expanded div to collapse without opening another div.
Step1 :Collapse all content divs except the current one.
Step2 : Toggle the visiblility of the current content div.
$(".title").click(function () {
$(".content").not($(this).next()).slideUp();
$(this).next().slideToggle();
});
Fiddle
You can use:
$(".title").click(function () {
$(this).next().slideToggle('fast').parent().siblings().find('.content').slideUp('fast');
});
Working Demo
Just add and else condition to your code :
$(".title").click(function () {
$content = $(this).next();
if (!($content.is(":visible"))) {
$(".content").slideUp("fast");
$content.slideToggle(200);
} else {
$content.slideToggle(200);
}
});
JSFIDDLE: http://jsfiddle.net/ghorg12110/2skczuze/3/
All you need is to extract one line of code from your if statement:
$(".title").click(function () {
$content = $(this).next();
$(".content").slideUp("fast"); // It is outside of if now
if (!($content.is(":visible"))) {
$content.slideToggle(200);
}
});
Here is the Demo: http://jsfiddle.net/2skczuze/5/
Try this DEMO
Just add an if statement, when the next content is visible:
$(".title").click(function () {
$content = $(this).next();
if (!($content.is(":visible"))) {
$(".content").slideUp("fast");
$content.slideToggle(200);
} else {
$content.slideUp("fast");
}
});
If you want to make an expanded div collapse without opening another div
then can be do in this way
$(".title").click(function () {
$content = $(this).next();
if (($content.is(":visible"))) {
$content.slideToggle(200);
}
if (!($content.is(":visible"))) {
$(".content").slideUp("fast");
$content.slideToggle(200);
}
});
Is this what you want? Just add an else block and toggle the element again.
Html
<div class="container">
<div class="title">ONE</div>
<div class="content">Content One</div>
</div>
<div class="container">
<div class="title">TWO</div>
<div class="content">Content Two</div>
</div>
<div class="container">
<div class="title">THREE</div>
<div class="content">Content Three</div>
</div>
<div class="container">
<div class="title">FOUR</div>
<div class="content">Content Four</div>
</div>
Css
.container {
width:300px;
margin-bottom:5px;
border:1px solid #d3d3d3;
text-align:center;
}
.container .title {
background-color:#00ffcc;
width:auto;
padding: 2px;
cursor: pointer;
font-weight: bold;
}
.container .content {
background-color: #f0f0f0;
display: none;
padding : 5px;
}
Javascript
$(".title").click(function () {
$content = $(this).next();
if (!($content.is(":visible"))) {
$(".content").slideUp("fast");
$content.slideToggle(200);
}
else
{
$content.slideToggle(200);
}
});
http://jsfiddle.net/2skczuze/1/

Categories