Convert <li> to accordion - javascript

I'm new here.
I'm trying to convert my <li> into an accordion in the mobile view.
I actually have something similar to:
<div class="general" id="horizontalTab">
<div class="list">
<nav>
<ul>
<li class="item1">Item 1</li>
<li class="item2">Item 2</li>
<li class="item3">Item 3</li>
</ul>
</nav>
<div>
<div>
<div class="item1">Description 1</div>
<div class="item2">Description 2</div>
<div class="item3">Description 3</div>
<div>
<div>
And I have this on the footer.php
<script src="<?php echo get_stylesheet_directory_uri(); ?>/assets/js/jquery.responsiveTabs.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
var $tabs = $('#horizontalTab');
$tabs.responsiveTabs({
rotate: false,
startCollapsed: 'accordion',
collapsible: 'accordion'
});
});
</script>
But it shows me "Uncaught TypeError: oTab is undefined"
So every time I click on the li it displays the related div description.
Now I'd like to convert that into an accordion for the mobile version and moving the description under its <li>.
Any ideas?
I've tryied following this: https://www.jqueryhub.com/responsive-tabs-to-accordion-jquery-plugin-responsive-tabs/ but it's not working :(
Thanks!

Works for me if I remove the div class="list" and add a
If you ignore the demo, you will of course have issues
Note the tabs are not horizontal if they do not have enough horizontal space
$(document).ready(function() {
var $tabs = $('#horizontalTab');
$tabs.responsiveTabs({
rotate: false,
startCollapsed: 'accordion',
collapsible: 'accordion'
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/responsive-tabs/1.4.4/js/jquery.responsiveTabs.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/responsive-tabs/1.4.4/css/responsive-tabs.min.css" />
<div class="general" id="horizontalTab">
<ul>
<li>Tab-1</li>
<li>Tab-2</li>
<li>Tab-3</li>
</ul>
<div id="item1">Tab content 1</div>
<div id="item2">Tab content 2</div>
<div id="item3">Tab content 3</div>
</div>

Here's the (tautological) way to do it:
var test = document.getElementById("test");
test.addEventListener("click", function(e) {
console.log("click: " + e.target.tagName);
var selected = test.querySelector("li.selected");
if (selected) selected.classList.toggle("selected");
e.target.classList.add("selected");
});
li.accord p{
display: none;
}
li.accord.selected p{
display: block;
}
/* It's a good idea to add this negative style too */
li.accord:not(.selected) p {
display: none;
}
li.accord {
background: grey;
}
<ul id = "test">
<li class="accord">1<p>1</p></li>
<li class="accord">2<p>2</p></li>
<li class="accord">3<p>3</p></li>
</ul>

Related

How to show one div at a time with least lines of code?

I am trying to show only one div at a time once a link is clicked. My codepen I was working on is here if someone could take a look. I'm trying to use jQuery so that when an element inside a list item is clicked it toggles that div item to display ONLY until another item is clicked which hides the previous item.
$( "#home_div" ).hide();
$( "#about_div" ).hide();
$( "#home" ).click(function() {
$('#home_div').toggle();
});
$( "#about" ).click(function() {
$('#about_div').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<head>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/animate.css#3.5.2/animate.min.css">
</head>
<body>
<header class="header">
<ul class="main-nav">
<li id="home">Home</li>
<li><a id="about" href="#">About</a></li>
<li><a id ="portfolio" href="#">Portfolio</a></li>
<li><a id="contact" href="#">Contact</a></li>
</ul>
<div id="home_div"></div>
<div id="about_div"></div>
<div id="portfolio_div"></div>
<div id="contact_div"></div>
</header>
</body>
To make this work in a generic manner (and therefore keep the JS as short as possible) you can place the id of the target content within the href property of the a elements. Then you can simply toggle() the target div whilst hiding its siblings, like this:
$('.main-nav a').click(function(e) {
e.preventDefault();
$($(this).attr('href')).toggle().siblings().hide();
});
#content-container div {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<ul class="main-nav">
<li>Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
<div id="content-container">
<div id="home_div">Home</div>
<div id="about_div">About</div>
<div id="portfolio_div">Portfolio</div>
<div id="contact_div">Contact</div>
</div>
Give all the content a common class. Then use the id of the nav link to create selector for the content to show
$('.main-nav a').click(function(e) {
e.preventDefault();
// hide all content class and filter the matching id to show
$('.content').hide().filter('#' + this.id + '_div').show();
});
.content {
display: none
}
.content:first-of-type {
display: block
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<head>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css#3.5.2/animate.min.css">
</head>
<body>
<header class="header">
<ul class="main-nav">
<li><a id="home" href="#">Home</a></li>
<li><a id="about" href="#">About</a></li>
<li><a id="portfolio" href="#">Portfolio</a></li>
<li><a id="contact" href="#">Contact</a></li>
</ul>
<div class="content" id="home_div">home_div</div>
<div class="content" id="about_div">about_div</div>
<div class="content" id="portfolio_div"></div>
<div class="content" id="contact_div">portfolio_div</div>
</header>
</body>
How about zero javascript? You could change the menu to be labels that tie to radio buttons that control which div shows. The CSS only shows the div immediately after the radio button that is currently selected, modifiable by clicking any of the menu labels.
[name=mainNavState] { display: none; }
[name=mainNavState] + div { display: none; }
[name=mainNavState]:checked + div { display: inherit; }
<ul class="main-nav">
<li id="home"><label for="homeState">Home</label></li>
<li><label for="aboutState">About</label></li>
<li><label for="portfolioState">Portfolio</label></li>
<li><label for="contactState">Contact</label></li>
</ul>
<input type="radio" name="mainNavState" id="homeState" checked>
<div id="home_div"> My Home Stuff </div>
<input type="radio" name="mainNavState" id="aboutState">
<div id="about_div"> My About Stuff </div>
<input type="radio" name="mainNavState" id="portfolioState">
<div id="portfolio_div"> My Portfolio Stuff </div>
<input type="radio" name="mainNavState" id="contactState">
<div id="contact_div"> My Contact Stuff </div>

submenu not loading on hover

I have menu and submenu which was created totally as divs instead of ul li. So, on hovering the menu element, I need to target a particular div and show as submenu. I have written a jquery event by passing submenu id as data-target to target the specific div to show as submenu. When I apply break points, the loop is going inside., but unable to remove initial property of submenu (display:none) to (display:block). Here is the plunker link for more details. please let me know where i`m going wrong.
I understand this div approach is not right one. But I have to develop according to existing HTML
$("#mainDiv div").hover(function () {
var menuliID = this.id; // id of clicked li by directly accessing DOMElement property
console.log(liID);
var subMenuId = jQuery(this).attr('data-target'); // jQuery's .attr() method
console.log(subMenuId);
jQuery('#' + menuliID).hover(function(){
console.log("entered inside function");
$('#' + subMenuId).css('display', 'block !important');
console.log('"#' + subMenuId + '"');
},
function () {
console.log("entered inside 2nd function")
jQuery('#' + subMenuId).css('display', 'none');
}
);
}
);
please change
$('#' + subMenuId).css('display', 'block !important');
into
$('#' + subMenuId).show();
as it is not necessary to apply .css() as you can do your work with .show() or .hide()
and please see my working snippet
// Code goes here
$("#mainDiv > .menuli").hover(function () {
var menuliID = this.id; // id of clicked li by directly accessing DOMElement property
console.log(menuliID);
var subMenuId = jQuery(this).attr('data-target'); // jQuery's .attr() method
console.log(subMenuId);
if($('#' + subMenuId).is(":visible")){
$('#' + subMenuId).hide();
}else{
$('#' + subMenuId).show();
}
}
);
/* Styles go here */
#mainDiv div{
border:1px solid;
width:30%;
}
.submenu{
position:absolute;
top:0;
left:24%;
}
.submenu ul li{
border:1px solid;
list-style:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div id="mainDiv">
<div id="menu1" class="menuli" data-target="submenu1">Menu1</div>
<div id="menu2" class="menuli" data-target="submenu2">Menu2</div>
<div id="menu3" class="menuli" data-target="submenu3">Menu3</div>
</div>
<div id="submenu1" class="submenu" style="display:none;">
<ul>
<li>Subelement1</li>
<li>Subelement2</li>
<li>Subelement3</li>
</ul>
</div>
<div id="submenu2" class="submenu" style="display:none;">
<ul>
<li>Subelement4</li>
<li>Subelement2</li>
<li>Subelement3</li>
</ul>
</div>
<div id="submenu3" class="submenu" style="display:none;">
<ul>
<li>Subelement5</li>
<li>Subelement2</li>
<li>Subelement3</li>
</ul>
</div>
</body>
</html>
You can simplify your code to the following. You just need to toggle the display of the sub menus when hover over main menu.
I have attached hover event to submenu so that it is displayed on mouse over.
//Toggle display of submenu when hover on main menu
$("#mainDiv div").hover(function () {
$('#' + $(this).attr('data-target')).toggle();
});
//Display submenu when hover on it
$(".submenu").hover(function(){
$(this).show();
}, function(){
$(this).hide();
})
.submenu {
border: 1px solid transparent;
}
.menuli{
padding-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mainDiv" style="display:inline-flex;padding-top:10px;">
<div id="menu1" class="menuli" data-target="submenu1">Menu1</div>
<div id="menu2" class="menuli" data-target="submenu2">Menu2</div>
<div id="menu3" class="menuli" data-target="submenu3">Menu3</div>
</div>
<div id="submenu1" class="submenu" style="display:none;">
<ul>
<li>Subelement1</li>
<li>Subelement2</li>
<li>Subelement3</li>
</ul>
</div>
<div id="submenu2" class="submenu" style="display:none;">
<ul>
<li>Subelement4</li>
<li>Subelement2</li>
<li>Subelement3</li>
</ul>
</div>
<div id="submenu3" class="submenu" style="display:none;">
<ul>
<li>Subelement5</li>
<li>Subelement2</li>
<li>Subelement3</li>
</ul>
</div>

Toggle class using javascript between two

classList to remove class using Javascript is not working, or is it because of any other error in code
Code: http://codepen.io/DPK_RAO/pen/VPXxoJ/
<ul class="nav">
<li>Video 1</li>
<li>Video 2</li>
</ul>
<div class="video1 active" id="video1">Link 1</div>
<div class="video2" id="video2">Link 2</div>
CSS:
.video1, .video2{
display:none;
}
.active{
display:block;
}
JS
document.getElementById("link1").addEventListner("click", activeVideo1);
function activeVideo1(){
document.getElementById("video2").classList.remove("active");
var v1 = document.getElementById("video1");
v1.className += "active";
}
document.getElementById("link2").addEventListner("click", activeVideo2);
function activeVideo2(){
document.getElementById("video1").classList.remove("active");
var v2 = document.getElementById("video2");
v2.className += "active";
}
When I run the script I get the following error in the console:
Uncaught TypeError: document.getElementById(...).addEventListner is
not a function
So your script isn't even getting to the removeClass function and it stops in the event's listener part.
You write the function with a typo.
it's
addEventListener
Another note:
Replace this:
v1.className += "active";
with:
v1.className += " active"; //added a blank
Updated codepen
why don't you just add the class as in
var v2 = document.getElementById("video2");
v2.classList.add('active');
?
You've a typo in addEventListner should be addEventListener note the e:
addEventListener
____________^
Since you're using jQuery it could be just simple like the following example :
$("#link1").on("click", function(){
$("#video2").removeClass("active");
$("#video1").addClass("active");
});
$("#link2").on("click", function(){
$("#video1").removeClass("active");
$("#video2").addClass("active");
});
.video1, .video2{
display:none;
}
.active{
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav">
<li>Video 1</li>
<li>Video 2</li>
</ul>
<div class="video1 active" id="video1">Link 1</div>
<div class="video2" id="video2">Link 2</div>
Solution using pure JS :
document.getElementById("link1").addEventListener("click", function(){
document.getElementById("video2").classList.remove("active");
document.getElementById("video1").classList.add("active");
});
document.getElementById("link2").addEventListener("click", function(){
document.getElementById("video1").classList.remove("active");
document.getElementById("video2").classList.add("active");
});
.video1, .video2{
display:none;
}
.active{
display:block;
}
<ul class="nav">
<li>Video 1</li>
<li>Video 2</li>
</ul>
<div class="video1 active" id="video1">Link 1</div>
<div class="video2" id="video2">Link 2</div>

Maintain my CSS even if I click outside of the item

I am learning CSS and by now I have this :
https://jsfiddle.net/marquesm91/ahwxwyca/
Basically, I want to highlight the element I clicked on and stay highlighted when I click outside of the element. When I am switching between elements it only highlights the actual element.
$(function() {
$('#menu').metisMenu({
toggle: false // disable the auto collapse. Default: true.
});
});
#menu a:hover,
#menu a:focus {
color: #fff;
background-color: #2a6496;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/onokumus/metisMenu/master/dist/metisMenu.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link href="http://rawgit.com/onokumus/metisMenu/master/dist/metisMenu.min.css" rel="stylesheet" />
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container-fluid">
<div class="row">
<div class="col-xs-6">
<aside class="sidebar">
<nav class="sidebar-nav">
<ul class="metismenu" id="menu">
<li>
Menu<span class="glyphicon arrow"></span>
<ul aria-expanded="false">
<li>item 2.1
</li>
<li>item 2.2
</li>
<li>item 2.3
</li>
<li>item 2.4
</li>
</ul>
</li>
</ul>
</nav>
</aside>
</div>
</div>
</div>
By now, my CSS don't help me. Any suggestions?
CSS can interact with hover, but does not have the capability to interact with clicks in the way you describe. You will need Javascript.
$('#menu').find("a").click(function(){
$(this).css("background-color","#2a6496");
$(this).css("color","#fff");
});
Here's a fiddle.
PS, When making fiddles with jQuery, be sure to select jQuery from the JS menu.
Maybe this is closer to what you want:
$('#menu').find("a").focus(function() {
$('#menu').find("a").each(function() {
$(this).css("background-color", "initial");
$(this).css("color", "initial");
});
$(this).css("background-color", "#2a6496");
$(this).css("color", "#fff");
});
https://jsfiddle.net/zq0cpohb/
This only highlights the last element clicked on..
This isn't really possible without some CSS hack.
The best way to do this would be through JavaScript.
Try something like this:
$("#menu a").click(function() {
$(this).addClass("focused");
});
And the CSS:
.focused {
color: #fff;
background-color: #2a6496;
}

jQuery adding and removing classes dynamically when the user clicked

I've a problem with the following code. I've two tabs in my navigation Tab-1 & Tab-2, when the user click on any tab, then I want to add the active class to it and at the same time I want to remove the active class from previously active tab. Also the tab which is currently active should display its content and have to hide the remaining content. It means when the user clicked on any tab it should display only its content and the other contents should be hidden. Please help me thank you.
<style>
.wrapper .tabs {
display: none;
}
.wrapper .tabs.active {
display: block;
}
</style>
<div class="wrapper">
<!-- Navigation -->
<ul class="nav">
<li class="active">Tab-1</li>
<li>Tab-2</li>
</ul>
<!-- Panel-1 -->
<div id="tab-1" class="tabs active">
<p>Tab-1 Content</p>
</div>
<!-- Panel-2 -->
<div id="tab-2" class="tabs">
<p>Tab-2 Content</p>
</div>
</div>
<!-- Script -->
<script>
$(document).ready(function () {
$('.nav li').click(function() {
$('.nav li.active').removeClass('active');
$(this).addClass('active');
});
// To display content for active class only
$('.nav li').click(function() {
$('.wrapper .tabs.active').removeClass('active');
$(this).addClass('active');
});
});
</script>
You can use .eq(), .index() at click event attached to selector "a[href^='#tab-']" which selects element where href begins with #tab-, create variable referencing elements where id begins with tab-, call event.preventDefault() within click function to prevent navigation to document fragment, .hide(), .show()
$(document).ready(function() {
var a = $("a[href^='#tab-']");
var tabs = $("[id^=tab]");
a.click(function(e) {
e.preventDefault();
tabs.hide().eq(a.index(this)).show()
})
})
#tab-1 {
display: block;
}
[id^="tab"]:not(#tab-1) {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js">
</script>
<div class="wrapper">
<!-- Navigation -->
<ul class="nav">
<li>
Tab-1
</li>
<li>
Tab-2
</li>
</ul>
<!-- Panel-1 -->
<div id="tab-1" class="tabs active">
<p>Tab-1 Content</p>
</div>
<!-- Panel-2 -->
<div id="tab-2" class="tabs">
<p>Tab-2 Content</p>
</div>
</div>

Categories

Resources