Is there a cleaner way to write JS to show and hide? - javascript

Hi I have a fiddle setup here that has 2 list items and when clicked they display by toggle a show/hide div - each with different content.
My worry is the way I have written the JS to control it. Is there a better way to do this?
Thanks
https://jsfiddle.net/b0xamuj8/
html:
<ul>
<li class="revealerone">item 1</li>
<li class="revealertwo">item 2</li>
</ul>
<div class="revealed one">this is some content one</div>
<div class="revealed two">this is some content two</div>
css:
ul {
list-style-type: mome;
margin: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
.revealed {
display: none;
background: green;
}
JS:
$(document).ready(function() {
$(".revealerone").click(function() {
$(".one").slideToggle("slow");
});
});
$(document).ready(function() {
$(".revealertwo").click(function() {
$(".two").slideToggle("slow");
});
});

You could use a data attribute to determine which "revealer" goes with which "revealed":
$(document).ready(function() {
$(".revealer").click(function() {
var id = "#" + $(this).data('item');
$(id).slideToggle("slow");
});
});
ul { list-style-type: none; margin: 0; }
li { display: inline-block; margin: 0 10px; }
.revealed { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="revealer" data-item="one">item 1</li>
<li class="revealer" data-item="two">item 2</li>
</ul>
<div class="revealed" id="one">this is some content one</div>
<div class="revealed" id="two">this is some content two</div>

You can store the target of the "revealer" in a data attribute and make your toggle code reusable like this:
HTML
<li class="revealer" data-target=".one">item 1</li>
<li class="revealer" data-target=".two">item 2</li>
JavaScript
$(".revealer").click(function() {
var target = $(this).data("target");
$(target).slideToggle("slow");
});
Demo: https://jsfiddle.net/alan0xd7/b0xamuj8/2/

In your case if HTML markup is consistent, you could use the index:
$(document).ready(function() {
$(".revealer").click(function() {
$(".revealed").eq($(this).index()).slideToggle("slow");
});
});
ul {
list-style-type: mome;
margin: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
.revealed {
display: none;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li class="revealer">item 1</li>
<li class="revealer">item 2</li>
</ul>
<div class="revealed">this is some content one</div>
<div class="revealed">this is some content two</div>

HTML:
<ul>
<li data-content-id="one" class="revealer">item 1</li>
<li data-content-id="two" class="revealer">item 2</li>
</ul>
<div class="revealed one">this is some content one</div>
<div class="revealed two">this is some content two</div>
JS:
$(document).ready(function() {
$(".revealer").click(function() {
var contentId = $(this).data("content-id");
$(".revealed." + contentId).slideToggle("slow");
});
});

Related

dropdown menu not opening and closing correctly

I have gotten it to open and close when hovering over the nav link but how do I keep it open so I can access the content on the menu? I need it to work exactly how a dropdown menu works.
This is what I have done so far I also need the html layout to stay the same.
$('.nav-link--dropdown').mouseover(function() {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown').mouseleave(function() {
$('.dropdown-menu').css('display', 'none');
});
ul {
list-style: none;
padding: 0px;
display: flex;
}
li {
margin-right: 10px;
}
.dropdown-menu {
display: none;
}
.dropdown-menu ul {
display: block;
background-color: grey;
color: white;
padding: 10px;
text-align: center;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav">
<ul>
<li class="nav-link">home</li>
<li class="nav-link--dropdown">dropdown</li>
</ul>
</div>
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
View on jsFiddle
Should remove margin use padding for that, if not when we enter that margin area mouse leave event will trigger.
$('.nav-link--dropdown').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.dropdown-menu').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
$('.dropdown-menu').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
ul {
list-style: none;
padding: 0px;
display: flex;
}
li {
padding: 10px;
}
.dropdown-menu {
display: none;
}
.dropdown-menu ul {
display: block;
background-color: grey;
color: white;
padding: 10px;
text-align: center;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="nav">
<ul>
<li class="nav-link">home</li>
<li class="nav-link--dropdown">dropdown</li>
</ul>
</div>
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
The problem you have here is that you leave the nav-link--dropdown when you move to your dropdown-menu. The simple solution: Include your dropdown-menu in your nav item.
$('.nav-link--dropdown').mouseover(function() {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown').mouseleave(function() {
$('.dropdown-menu').css('display', 'none');
});
ul {
list-style: none;
padding: 0px;
display: flex;
}
li {
margin-right: 10px;
}
.dropdown-menu {
display: none;
}
.dropdown-menu ul {
display: block;
background-color: grey;
color: white;
padding: 10px;
text-align: center;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav">
<ul>
<li class="nav-link">home</li>
<li class="nav-link--dropdown">
dropdown
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
</li>
</ul>
</div>
You can achieve this by bundling the menu item you want to hover over and it's dropdown in the same div.
<div class="nav">
<ul>
<li class="nav-link">home</li>
<div class="innerNav">
<li class="nav-link--dropdown">dropdown</li>
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
</div>
</ul>
</div>
And:
$('.innerNav').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.innerNav').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
See this JSFiddle: https://jsfiddle.net/rmdfqh6c/
Since your problem is the mouseleave event will trigger when you try to move the mouse to the bellow dropdown menu, if you really must keep the elements separated, add the dropdown-menu to the class that keeps the display:block
$('.nav-link--dropdown, .dropdown-menu').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown, .dropdown-menu').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
And remove margin/padding from menu items. Use line-height instead if you want some spacing:
.nav ul li {
line-height: 40px;
}
ul {
list-style: none;
margin: 0; // <--- I changed this from padding: 0px;
display: flex;
}
Otherwise the other suggested solutions to include the dropdown within you parent <ul> element is the best.
JSFiddle

How to selector complex situation multi-dimensional drop down menu

Hi I need to create a multi-dimensional drop-down menu. But my hover selection don't work. I don't know how to use selector from other class div parent to other class div parent. Look at the code in style. Javascript solution is welcome
<style>
body {
margin: autp;
}
#container {
display: table;
}
#lcontainer {
padding: 0 10px 0 10px;
display: table-cell;
}
#rcontainer {
padding: 0 10px 0 10px;
display: table-cell;
}
.rvcontainer {
display: none;
}
.lvcontainer:hover #rcontainer>.rvcontainer {
display: block;
}
</style>
<div id="container">
<div id="lcontainer">
<div class="lvcontainer">
Country
</div>
<div class="lvcontainer">
Genre
</div>
</div>
<div id="rcontainer">
<div class="rvcontainer">
Japan
<br> Korea
<br> American
<br>
</div>
<div class="rvcontainer">
Comedy
<br> Mystery
<br> Horror
<br>
</div>
</div>
</div>
Javascript solution but the problem the class don't work.
<script>
var lvcontainer = document.getElementsByClassName('lvcontainer');
var rvcontainer = document.getElementsByClassName('rvcontainer');
for(i=0; i<1; i++){
lvcontainer[i].addEventListener("mouseover", function(){
rvcontainer[i].style.display = "block":
}, FALSE);
}
</script>
For me is not very clear what is exactly your problem. But, to make a drop down menu on multiple levels you must use like this:
In html:
<ul>
<li>Link</li>
<li>Link</li>
<li>Link</li>
<li>Link
<ul>
<li>Link 2</li>
<li>Link 2</li>
<li>Link 2</li>
<li>Link 2
<ul>
<li>Link 3</li>
<li>Link 3</li>
<li>Link 3</li>
<li>Link 3</li>
<li>Link 3</li>
</ul>
</li>
</ul>
</li>
</ul>
And is css can be like this:
li > ul {
display: none;
}
li:hover > ul {
display: block;
}
li a:hover {
color: pink;
}
li ul li a:hover {
color: green;
}
li ul li ul a:hover {
color: yellow;
}
Is this case I choose to change color, but of course you can change any css property you want.
You can see a demo here

accordion type menu that closes all divs except one selected

I'm trying to do an accordion type menu without actually using the plugin. I have a jsfiddle here : https://jsfiddle.net/t7mafd2a/1/
I can toggle the menu but what I want is when one is open the other close, not just have them stay open when clicked.
$('.navContainer li div').click(function (e) {
e.preventDefault();
var $t = $(this);
$t.next('.navtoggle').toggleClass('active', 400);
});
.navtoggle { display: none; }
.active { display: block; } .navContainer { display: block; } ul, li { list-style: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navContainer">
<ul>
<li>
<div>Category 1</div>
<ul class="navtoggle">
<li>Test</li>
<li>Test</li>
</ul>
<div>Category 2</div>
<ul class="navtoggle">
<li>Test</li>
</ul>
<div>Category 3</div>
<ul class="navtoggle">
<li>Test</li>
</ul>
</li>
</ul>
</div>
Simply add this line before you do toggleClass
$('.navtoggle').removeClass('active');
This will remove the active class from all of your navtoggle elements before you open the one you just clicked.
Full code:
$('.navContainer li div').click(function(e) {
e.preventDefault();
var $t = $(this);
var $next = $t.next('.navtoggle');
$('.navtoggle').not($next).removeClass('active');
$next.toggleClass('active', 400);
});
$('.navContainer li div').click(function (e) {
e.preventDefault();
$('ul.active').removeClass('active');
var $t = $(this);
$t.next('.navtoggle').toggleClass('active', 400);
});
.navtoggle { display: none; }
.active { display: block; } .navContainer { display: block; } ul, li { list-style: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navContainer">
<ul>
<li>
<div>Category 1</div>
<ul class="navtoggle">
<li>Test</li>
<li>Test</li>
</ul>
<div>Category 2</div>
<ul class="navtoggle">
<li>Test</li>
</ul>
<div>Category 3</div>
<ul class="navtoggle">
<li>Test</li>
</ul>
</li>
</ul>
</div>

Floated elements jump when hiding another floated elements

I have grid of floated elements, for which I created a filter. I want this filter to hide and show the items and while doing so I want the items to re adjust with transitions and fades.. At the moment the items just jump around.
As you can see here:
JSFIDDLE
How can I make the items slide to their position?
Heres the code:
HTML
<ul class="filters">
<li data="1">filter 1</li>
<li data="2">filter 2</li>
<li data="3">filter 3</li>
<li data="4">filter 4</li>
</ul>
<br>
<ul class="items">
<li data="1">1</li>
<li data="2">2</li>
<li data="1">3</li>
<li data="3">4</li>
<li data="4">5</li>
<li data="2">6</li>
<li data="3">7</li>
<li data="4">8</li>
</ul>
CSS
ul {
list-style: none;
padding: 0;
}
.filters li {
float:left;
margin-right: 10px;
cursor: pointer;
}
.items li {
width: 100px;
height: 100px;
background: #ccc;
float: left;
margin: 20px;
}
JQUERY
$(document).ready( function() {
$('.filters li').click( function () {
var data;
data = $(this).attr('data');
$('.items li').each( function() {
if($(this).attr('data') !== data) {
$(this).fadeOut();
}
else {
$(this).fadeIn();
}
});
});
});
As I mentioned in the comments you would need a different operation than fadeIn/Out as that involves the display property and that cannot be animated or transitioned.
Animating non-display values seems more optimal.
Something like this:
$(document).ready(function() {
$('.filters li').click(function() {
var data;
data = $(this).attr('data');
$('.items li').each(function() {
if ($(this).attr('data') !== data) {
$(this).addClass('hidden');
} else {
$(this).removeClass('hidden');
}
});
});
});
ul {
list-style: none;
padding: 0;
}
.filters li {
float: left;
margin-right: 10px;
cursor: pointer;
}
.items li {
width: 100px;
height: 100px;
background: #ccc;
float: left;
margin: 20px;
transition: all .5s ease;
}
li.hidden {
height: 0;
width: 0;
margin: 0;
opacity: 0;
font-size: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="filters">
<li data="1">filter 1</li>
<li data="2">filter 2</li>
<li data="3">filter 3</li>
<li data="4">filter 4</li>
</ul>
<br>
<ul class="items">
<li data="1">1</li>
<li data="2">2</li>
<li data="1">3</li>
<li data="3">4</li>
<li data="4">5</li>
<li data="2">6</li>
<li data="3">7</li>
<li data="4">8</li>
</ul>
You could set a delay for the fade in to ensure the fade out has completed.
The 500ms delay below is is a slightly longer duration as the fade in.
$(document).ready(function() {
$('.filters li').click(function() {
var data;
data = $(this).attr('data');
$('.items li').each(function() {
if ($(this).attr('data') !== data) {
$(this).fadeOut();
} else {
$(this).delay(525).fadeIn();
}
});
});
});
ul {
list-style: none;
padding: 0;
}
.filters li {
float: left;
margin-right: 10px;
cursor: pointer;
}
.items li {
width: 100px;
height: 100px;
background: #ccc;
float: left;
margin: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="filters">
<li data="1">filter 1</li>
<li data="2">filter 2</li>
<li data="3">filter 3</li>
<li data="4">filter 4</li>
</ul>
<br>
<ul class="items">
<li data="1">1</li>
<li data="2">2</li>
<li data="1">3</li>
<li data="3">4</li>
<li data="4">5</li>
<li data="2">6</li>
<li data="3">7</li>
<li data="4">8</li>
</ul>
It's the overlap of fadeOut and fadeIn that makes it look like they are jumping.
Try hiding the filtered out items quick and slideDown the applicable boxes:
$(document).ready( function() {
$('.filters li').click( function () {
var data;
data = $(this).attr('data');
$('.items li').each( function() {
if($(this).attr('data') !== data) {
$(this).slideUp();
}
else {
$(this).delay(525).slideDown();
}
});
});
});

jquery - using stoppropagation for multiple events

I am using stopPropegation to aid me in the way my dropdowns work.
I am using it for multiple dropdowns to help me keep the dropdown open but if the user clicks anywhere else on the page then it will slide up the menu.
HTML
<nav id="moo">
<ul>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</li>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
</ul>
</div>
</li>
</ul>
</nav>
<div class="clear"></div>
<div id="login-top">Login</div>
<div id="user">roooar</div>
CSS
ul { padding: 0px; margin: 0px; }
li { display: inline; }
nav li { position: relative; }
nav i { cursor: pointer; font-weight: bold; background-color: red;padding: 5px; }
.dropdown { display: none; position: absolute; border:1px solid #ccc; padding: 10px; }
.dropdown li {
display: block;
}
.clear {
clear:both;
}
#login-top {
background:blue;
padding:10px;
color:white;
margin-top:30px
}
#user {
background:pink;
margin-top:10px;
padding:50px;
}
SCRIPT
$('#login-top').click(function () {
var $user = $('#user');
if ($('#user').is(':visible')) {
$user.slideUp(300);
} else {
$user.slideUp(300);
$user.slideDown(300);
}
});
$('nav > ul > li').click(function (e) {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
var target = $(e.target);
if (!$(target).parents(".dropdown").length) {
$('.dropdown').slideUp(300);
}
} else {
$('.dropdown').slideUp(300);
$childDropdown.slideDown(300);
}
});
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function () {
$(".dropdown").hide();
$("#user").slideUp();
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
I have 2 questions really about this.
Say if I click open the dropdown menu because I have included certain elements to be exempt from clicking elsewhere on the page - If I click anywhere else it will slide back up exactly how I want.
However, if I happen to click on the #login-top this will not make it slide up as I have added it to the code for the stopPropagation
Is there a may of making it work so that when ".dropdown" is active then you can click absolutely everywhere (including on the <div id='login'> And then when "#login" and "#user" is active you can click anywhere on "nav" and it will still slide up the div?
Is it the right thing to be doing by grouping all the classes and id's into the code:
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
(I am struggling to explain this but hopefully you can see what I mean if you look at the fiddle version)
http://jsfiddle.net/susannalarsen/Nt2ZM/1/

Categories

Resources