I created a simple navigation, but it doesn't work on mobile. When you click on the plus symbol or "Book 1 name" the list of links are suppose to appear, but for some reason it doesn't work, and when you click the plus symbol the ex symbol is suppose to appear. The book title should link should work on desktop, but not on mobile. Thanks!
$(document).ready(function () {
$(window).resize(function() {
if($(window).width() <= 550) {
$('.bookName').click(function(e){
e.preventDefault();
$('.bookNavigation ul li ul').toggleClass('toggleNav')
$(this).toggleClass('changeIcon');
});
} else {
$('.bookName').click(function(e){
return true;
});
}
});
});
.bookNavigation ul li ul{
display: flex;
}
.toggleNav{
display: block;
}
#media only screen and (max-width: 550px) {
.bookNavigation ul li ul{
display: none;
}
.bookName::before{
content: '+';
padding-right: 10px;
}
.bookName .changeIcon::before{
content: '-';
padding-right: 10px;
}
}
a{
text-decoration: none;
}
li{
list-style: none;
}
.bookNavigation{
margin-bottom: 100px;
}
.bookName{
text-transform: uppercase;
font-size: 30px;
}
li{
margin-right: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="bookNavigation">
<ul>
<li>
Book 1 Name
<ul>
<li>Book 1 Chapter 1</li>
<li>Book 1 Chapter 2</li>
<li>Book 1 Chapter 3</li>
</ul>
</li>
</ul>
</nav>
<p>you are in Book 1 Name cover page</p>
You can do this check $(window).width() <= 550 inside the click event rather than attaching the event based on screen-size. Please find the corrected code.
$('.bookName').click(function(e) {
if ($(window).width() <= 550) {
e.preventDefault();
$('.bookNavigation ul li ul').toggleClass('toggleNav')
$(this).toggleClass('changeIcon');
}
});
.bookNavigation ul li ul {
display: flex;
}
.bookNavigation ul li ul.toggleNav {
display: block;
}
#media only screen and (max-width: 550px) {
.bookNavigation ul li ul {
display: none;
}
.bookName::before {
content: '+';
padding-right: 10px;
}
.bookName .changeIcon::before {
content: '-';
padding-right: 10px;
}
}
a {
text-decoration: none;
}
li {
list-style: none;
}
.bookNavigation {
margin-bottom: 100px;
}
.bookName {
text-transform: uppercase;
font-size: 30px;
}
li {
margin-right: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="bookNavigation">
<ul>
<li>
Book 1 Name
<ul>
<li>Book 1 Chapter 1</li>
<li>Book 1 Chapter 2</li>
<li>Book 1 Chapter 3</li>
</ul>
</li>
</ul>
</nav>
<p>you are in Book 1 Name cover page</p>
Instead of checking on resize, check the window with inside buttonClickHandler like below
$(button).on('click', function(){
if($(window).width() <= 550){
// Code to toggle list
}
});
Another problem was the specificity of toggleNav css class.
.bookNavigation ul li ul {
display: none;
}
Above code is more specific than
.toggleNav {
display: block;
}
So the toggling toggleNav won't work because the 1st one will override this one. For fixing it create a class like the one below and toggle it on click. So that it will be hidden initially and will be removed on click.
.navHidden {
display: none
}
Check this pin for working example: https://codesandbox.io/s/bold-currying-39w11
Related
I have a nav menu bar.
This nav menu contain a sub menu.
When i click on the li the sub menu appear, but when i click again on the li to hide the sub menu this sub menu doesn't hide but if i click on another li the first sub menu disappear.
What i want to make is when i click on the li the sub menu apear and when i click again the sub menu disappear and if i click on another li that contain the class sub it should close any other sub menu and appear the sub menu of this li
i try toggle, classList.contains, if condition but this not work for me
below an example
let menuLi = document.querySelectorAll('.sub'),
subMenu = document.querySelectorAll('.sub-menu');
menuLi.forEach((li) => {
li.addEventListener('click', () => {
menuLi.forEach((li) => {
li.classList.remove('active');
});
if (li.classList.contains('active')) {
li.classList.remove('active');
} else {
li.classList.add('active');
}
})
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
list-style: none;
text-decoration: none;
}
.navbar {
display: flex;
align-items: center;
gap: 20px;
height: 60px;
padding: 10px;
background: red;
}
.sub {
position: relative;
}
.sub .sub-menu {
position: absolute;
top: 39px;
left: 0;
width: 100px;
display: none;
}
.sub .sub-menu li {
margin: 10px 0;
}
.sub.active .sub-menu {
display: block;
}
<ul class="navbar">
<li>
Home
</li>
<li class="sub">
Info
<ul class="sub-menu">
<li>Info 1</li>
<li>Info 2</li>
</ul>
</li>
<li class="sub">
image
<ul class="sub-menu">
<li>img 1</li>
<li>img 2</li>
</ul>
</li>
</ul>
I'd probably just keep previous state, reset state of all and set state accordingly.
menuLi.forEach((li) => {
li.addEventListener('click', () => {
const isOpened = li.classList.contains('active')
menuLi.forEach((li) => {
li.classList.remove('active');
});
if (isOpened) {
li.classList.remove('active');
} else {
li.classList.add('active');
}
})
});
i refer to this thread: JS using onclick event on li to display block
From desktop is ok but how do i do the same thing but that from the mobile you can touch the "disappearing" menu and make sure that it remains visible until the next touch?
I'm currently using this code here:
function dropdown() {
document.getElementById("Menuitems").style.display = "block";
}
#dropdown ul {
display: block;
transition-duration: 1s;
}
#dropdown ul li {
display: block;
background-color: #212121;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover>ul {
/*this is what the onclick event should do*/
display: block;
}
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
I just added an active class onclick .. the active class toggles on every click. and just add the same hover effect to active class
function dropdown() {
document.getElementById("Menuitems").classList.toggle("active");
}
#dropdown ul {
display: block;
transition-duration: 1s;
}
#dropdown ul li {
display: block;
background-color: #212121;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover>ul,
#dropdown ul li>ul.active{
/*this is what the onclick event should do*/
display: block;
}
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
Problem description:
In my menu when .mouseenter() the menu opens and when .mouseleave() it closes, but if i click a lot , the .mouseleave() event is executed.
This only happened on chrome browser.
I have other .click() events inside my menu, but every click I made, the .mouseleave() event is execute.
$(document).ready(function() {
$("#nav1 li").hover(
function() {
$(this).find('ul').slideDown();
},
function() {
$(this).find('ul').slideUp();
});
});
#nav1 a {
color: #FFFFFF;
}
#nav1 li ul li a:hover {
background-color: #394963;
}
div ul li ul {
background-color: #4a5b78;
list-style: none
}
#nav1 > li > a {
padding: 16px 18px;
display: block;
border-bottom: 2px solid #212121;
}
#nav1 li ul li a {
padding: 10px 0;
}
div {
background-color: #000000;
background-color: #343434;
width: 280px;
}
/* Hide Dropdowns by Default */
#nav1 li ul {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<ul id="nav1">
<li>Hover here and infinite click
<ul>
<li>Stage1</li>
<li>Stage2</li>
<li>Stage3</li>
<li>Stage4</li>
</ul>
</li>
<li>Menu Heading 2
<ul>
<li>Stage1</li>
<li>Stage2</li>
<li>Stage3</li>
<li>Stage4</li>
</ul>
</li>
</ul>
<div>
Try click "Hover here and infinite click" to see this problem.
EDIT:
As you guys said, the problem occurs in this example.
Here is a video: Video link
When you click many times the browser has lost the element reference, try this example:
<div id="container">
<ul id="nav1">
<li>Menu Heading 1
<ul>
<li>Stage1</li>
<li>Stage2</li>
<li>Stage3</li>
<li>Stage4</li>
</ul>
</li>
<li>Menu Heading 2
<ul>
<li>Stage1</li>
<li>Stage2</li>
<li>Stage3</li>
<li>Stage4</li>
</ul>
</li>
<li>Menu Heading 3
<ul>
<li>Stage1</li>
<li>Stage2</li>
<li>Stage3</li>
<li>Stage4</li>
</ul>
</li>
</ul>
<div>
Css
ul,
li,
a {
padding: 0px;
margin: 0px;
}
.show {
display: block !important;
}
#nav1 a {
color: #FFFFFF;
}
#nav1 li ul li a:hover {
background-color: #394963;
}
div ul li ul {
background-color: #4a5b78;
list-style: none
}
#nav1 > li > a {
background-color: #343434;
padding: 16px 18px;
text-decoration: none;
display: block;
border-bottom: 2px solid #212121;
background: linear-gradient(top, #343434, #111111);
}
#nav1 li ul li a {
padding: 10px 0;
padding-left: 30px;
text-decoration: none;
display: block;
}
div {
background-color: #000000;
background-color: #343434;
width: 280px;
}
/* Hide Dropdowns by Default */
#nav1 li ul {
display: none;
}
JS
$(document).ready(function() {
$("#nav1 li").hover(
function(e) {
let ulMenu = $(this).find('ul');
ulMenu.addClass('show');
//$(this).find('ul').slideDown();
},
function(e) {
if(e.relatedTarget){
let ulMenu = $(this).find('ul');
ulMenu.removeClass('show');
} else {
console.log('fail ');
}
//$(this).find('ul').slideUp();
});
});
Codepen Example Works
You can add a stropPropagation in your click event.
$("#nav1 li").click(
function(e){
e.stopPropagation();
});
maybe the event is getting lost in the process, try to verify it, and if so set the actual element.
see this: https://api.jquery.com/event.relatedTarget/
Working on a jQuery slide toggle where upon click of an item in a ul toggle down the corresponding item in another ul. I'm having trouble getting the click to be linked to the id and toggling the correct ul item.
jQuery is:
$(document).ready(function() {
//on click of subservices list item toggle down the corresponding subservices item
$(".subServices").find("li").hide().end() // Hide all other ULs
.click(function(e) {
if (this == e.target) { // if the handler element is where the event originated
$(this).children('ul.subServicesList.subServiceItem').slideToggle('fast');
}
});
});
Can anyone help :)
Fiddle here
First, ID of an element must be unique so you can't use same ID for subServices and SubServicesList. In the below solution we uses a data-target attribute for subServices.
Also you need to register the handler to .SubServicesList a element, not the SubServicesList
$(document).ready(function() {
//on click of subservices list item toggle down the corresponding subservices item
$(".subServices > li").hide().end() // Hide all other ULs
$('.SubServicesList a').click(function(e) {
$('#' + $(this).data('target')).slideToggle()
});
});
.SubServicesList {
display: block;
width: 55%;
text-align: center;
margin-left: auto;
margin-right: auto;
}
.SubServicesList li {
display: inline;
list-style: none;
list-style-type: none;
margin-right: 10px;
text-align: center;
line-height: 26px;
cursor: pointer;
}
.SubServicesList li a:hover {
color: #333333;
}
.subServices {
width: 75%;
margin: 0 auto;
}
.subServices li.subServiceItem {
display: block;
list-style: none;
list-style-type: none;
height: auto;
clear: both;
}
.subServices li.subServiceItem .image {
float: left;
display: block;
margin-right: 10px;
margin-bottom: 10px;
}
.subServices li.subServiceItem .image {
float: left;
display: block;
}
/*.subServices li.subServiceItem { display:none; } */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul class="SubServicesList">
<li><a data-target="1">Name 1</a></li>
<li><a data-target="2">Name 2</a></li>
<li><a data-target="3">Name 3</a></li>
</ul>
<ul class="subServices">
<li class="subServiceItem" id="1">
1 hwiufhwriufhiurhfiureh
</li>
<li class="subServiceItem" id="2">
2 hwiufhwriufhiurhfiureh
</li>
<li class="subServiceItem" id="3">
3 hwiufhwriufhiurhfiureh
</li>
</ul>
This is how I did it
$(".SubServicesList > li > a").click(function () {
$(".subServices>li").hide();
$(".subServices").find("li[id='" + $(this).attr('id') + "']").slideToggle(true);
});
Here is the JSFiddle
Is there a way through JavaScript to set the links on a timer before its closes out? I don't want it to seem so sensitive. Such as if a user accidentally mouses off the link it closes right away. Any video recommendation or links?
Thanks,
I am not using jQuery......
* {
padding: 0;
margin: 0;
}
body {
padding: 5px;
font-family: Cambria, "Hoefler Text", "Liberation Serif", Times, "Times New Roman", serif;
}
ul {
list-style: none;
}
ul li {
float: left;
padding-right: 1px;
position: relative;
}
ul a {
display: table-cell;
vertical-align: middle;
width: 100px;
height: 50px;
text-align: center;
background-color: #2F2F2F;
color: #AE0002;
text-decoration: none;
}
ul a:hover {
background-color: #828282;
color: #FFFFFF;
}
li > ul {
display: none;
position: absolute;
left: 0;
top: 100%;
}
li:hover > ul {
display: block;
}
li > ul li {
padding: 0px;
padding-top: 1px;
}
li > ul li > ul {
left: 100%;
top: 0;
padding-left: 1px;
}
li > ul li > ul li {
width: 100px;
}
<body>
<ul>
<li>Sports News
<ul>
<li>Football
<ul>
<li>NFL
</li>
<li>ESPN Football
</li>
</ul>
</li>
<li>Baseball
<ul>
<li>MLB
</li>
<li>ESPN Baseball
</li>
</ul>
</li>
<li>Soccer
<ul>
<li>FIFA
</li>
<li>ESPN Soccer
</li>
</ul>
</li>
<li>Basketball
<ul>
<li>NBA
</li>
<li>ESPN Basketball
</li>
</ul>
</li>
<li>Auto Racing
<ul>
<li>ESPN Racing
</li>
<li>Nascar
</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
Instead of css, show/hide ul using javascript. Handle mouseover and mouseout events to show/hide. To delay, on hover, show using timer and on mouseout, hide as well as clear the timer.
function show(ul) {
ul.css("display", "inline-block");
}
function hide(ul) {
ul.css("display", "none");
}
$("li").mouseover(function () {
var ul = $(this).children("ul");
var timer = setTimeout(function () {
show(ul);
}, 400);
$(this).data("timer", timer);
}).mouseout(function () {
var ul = $(this).children("ul");
var timer = $(this).data("timer");
clearTimeout(timer);
hide(ul);
});
Demo: http://jsfiddle.net/k06dLnmk/
You can use transition delay.
transition-delay:1s;
Similar Question:
Delay hover
or you can use javascript to toggle with the css clasess
window.setInterval("javascript function", milliseconds);
Edit: Oh sorry as the comment pointed out. display none does not work with transition delay. Would you consider using visibility property instead?
div > ul {
. . .
visibility:hidden;
opacity:0;
transition:visibility 0s linear 0.5s,opacity 0.5s linear;
}
div:hover > ul {
visibility:visible;
opacity:1;
transition-delay:0s;
}