Iv run out of solutions that I can think of or find for this problem. I'm working on a fixed to the top of the page. The left side has a anchor that takes you to the top of the page, if hovered over it will show other external links. The right side is a list of page sections with anchors to scroll you to them.
this all works fine on desktop as hover and click are separate events, but on an ipad they are they same. On an iPad you should be able to touch the "Product List" list item and have the drop down menu appear. If touched again it will take you back to the top. Right now when you touch it will take you back to the top and display the hover.
Here is a jsfiddle recreating the code and issue. http://jsfiddle.net/hyaTV/5/
HTML
<ul class="one">
<li><a class="intrapage" href="#stage">Product Title</a>
<ul>
<li>other product</li> <!-- link that goes to different page -->
<li>other product</li> <!-- link that goes to different page -->
</ul>
</li>
</ul>
<ul class="two">
<li><a class="intrapage" href="#section_one">birds</a></li> <!-- goes to Birds section -->
<li><a class="intrapage" href="#section_two">bees</a></li> <!-- goes to bees section -->
</ul>
CSS
ul.one{float:left;list-style:none;}
ul.one ul{display:none;}
ul.one > li:hover ul{display:block;}
/* styling for right side nav */
ul.two{float:right;list-style:none;}
ul.two li{display:inline-block;}
JS
// scrolls window to element id with easing
$(".intrapage").click(function(event) {
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 850);
return false;
});
You could use iOS :hover issue to your advantage. I believe by changing your CSS to
ul.one > li ul { display: none; }
ul.one > li:hover ul { display: block; }
That said, above problem doesn't exist on other mobile OS. there're no way to mouse out on iOS.
It's better to detect if user is on mobile device and add .mobile with javascript to <body> then toggle the sub-menu on click events.
CSS
ul.one > li:hover ul, ul.one > li.hover ul { display: block; }
JS
$('body.mobile ul.one > li').click(function(e) {
$(this).toggleClass('hover');
});
I came up with a solution which appears to work. It will require your page to include the Modernizr JS to check if touch is supported or not.
JS
if (document.addEventListener) {
document.addEventListener("touchstart", function(){}, true);
}
if($('html').hasClass('touch')){
$('.one > li').click(function(e){
if($(this).hasClass('hover')){
// $(this).removeClass('hover');
} else {
$(this).toggleClass('hover');
}
});
$('html').bind('touchstart', function(){
if($('.one > li').is(':hover')){
// do nothing
} else {
$('.one > li.hover').removeClass('hover');
}
});
$('.one a.intrapage').click(function(event){
if($('.one > li').hasClass('hover')){
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 850);
return false;
} else {
event.preventDefault();
}
});
$(".two .intrapage").click(function(event) {
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 850);
return false;
});
} else {
$(".intrapage").click(function(event) {
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top - 50}, 850);
return false;
});
}
Related
I have created a simple dropdown menu with jquery
https://jsfiddle.net/pmksgz3w/
HTML
<ul>
<li>Page A</li>
<li>Page B
<ul>
<li>Dropdown</li>
<li>Dropdown</li>
</ul>
</li>
</ul>
Jquery
$(document).ready(function(){
$('ul> li').hover(function() {
$(this).find('ul').slideToggle();
});
});
When I hover over Page B, then the dropdown menu is shown. If I move the curser from Page B very slowly to the right (see picture) then the drop-down menu will close, since the li is not hovered for a short moment. How can I prevent that the dropdown menu will instantly close?
An even worse problem happens if I move the cursor extremely fast to the dropdown menu. Because then, the dropdown menu will slideUp and slideDown in an infinite loop.
I found at How to tell .hover() to wait? a promising solution from 2009 but the answer does not work when I try it,(Edit note: It works now, see edit below). Further it is mentioned that one should use hoverIntend plugin. I downloaded the plugin and changed my jQuery code to
$(document).ready(function(){
$('ul> li').hoverIntend(function() {
$(this).find('ul').slideToggle();
});
});
and although it improves some things, the above problem that it instantly closes and the infinite loop remains. How can I solve this problem?
Edit: I managed to solve the first problem! Now the dropdown does not close instantly!
https://jsfiddle.net/5sxvsu8w/
I had to change the jQUery code as follows:
$(document).ready(function(){
var timer;
$('ul> li').hover(function() {
clearTimeout(timer);
$(this).find('ul').slideDown('fast');
}, function() {
var list = $(this).find('ul');
timer= setTimeout(function() {
list.slideUp('fast');
}, 2000);
});
});
However, the infinite loop problem remains.
The solution you found in here is usefull, this javascript code maybe can help:
$(document).ready(function(){
$('.menu li').hover(
function () {
$('.sub', this).stop().slideDown(650);
},
function () {
$('.sub', this).stop().slideUp(650);
}
);
});
/*$('ul >li').hover(function() {
clearTimeout($(this).data('timeout'));
$('li > ul').slideDown('fast');
}, function() {
var t = setTimeout(function() {
$('li > ul').slideUp('fast');
}, 650);
$(this).data('timeout', t);
});*/
li{
list-style-type:none;
display: inline-block;
position: relative;
padding: 20px;
background-color: #08c;
}
li ul li{
min-width:200px;
}
li ul{
margin:0;
padding:0;
position: absolute;
top: 100%;
left:0;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li>Page A</li>
<li>Page B
<ul class="sub">
<li>Dropdown</li>
<li>Dropdown</li>
</ul>
</li>
</ul>
EDIT: I have changed my javascript code after some reseach; this solution unfortunately does not solve completely the first problem (it is still based on a timer) but avoids the infinite loop.
I'm creating a responsive site. I have a media query set up so that when the screen width drops below 768 px a class (lets call it "hiddenClass") is hidden. Then I implement Javascript to toggle this class into view on a button click. The problem I'm running into is that javascript seems to override the media query. So if I shrink the screen below 768px the "hiddenClass" disappears....then I click the button which displays the "hiddenClass".....then click the button once more to hide it on the smaller device again.....now I expand the window and the "hiddenClass" stays hidden even after it gets to the 768px. If I take out the javascript and shrink the window the "hiddenClass" performs like it should...which tells me javascript is overriding it.
Is there a CSS fix to this? I know I could always check for a window resize event in javascript to display the hiddenClass after it reaches 768px. Was just wondering if this can be handled with CSS....or if javascript is the way to fix it.
Update JSfiddle with JS commented out so you can see how it should work...then add in the JS to see the issue described above. The button is the 'menu' navigation element when you shrink the screen down and "hiddenClass" would be the "menu" class in the li's:
http://jsfiddle.net/or5vy17L/1/
HTML:
<ul>
<li class="menuButton">- Menu -</li>
<a href="index.html">
<li class="menu" >
Home
</li>
</a>
<a href="instagram.html">
<li class="menu" >
Instagram
</li>
</a>
<li class="menu">Clients</li>
<li class="menu">Nutrition</li>
<li class="menu">About Me</li>
<li class="menu">Contact</li>
</ul>
css:
li {
display:inline;
color:$font-color--nav;
cursor:pointer;
font-size:1.5em;
padding: .7em .7em .7em .7em;
//for space between margins
margin-right:-4px;
border-radius:.5em;
}
ul {
text-align:center;
}
.menuButton {
display:none;
}
#media (max-width:768px) {
ul {
padding:0px;
}
li {
display:list-item;
border:1px solid white;
padding:.2em .2em .2em .2em;
border-radius:0px;
}
.menu {
display:none;
}
.menuButton {
display:list-item;
}
}
javascript:
/****
$('ul').on('click', '.menuButton', function() {
$('.menu').slideToggle();
});
****/
The .hiddenclass is staying hidden because it is a inline style, and inline styles override nearly all other styles. You have two options, one is to override the inline style with a CSS, as described in this CSS Tricks post:
<div style="background: red;">
The inline styles for this div should make it red.
</div>
div[style] {
background: yellow !important;
}
JSFiddle Demo
According to this article, this CSS solution works in:
Internet Explorer 8.0
Mozilla Firefox 2 and 3
Opera 9
Apple Safari, and
Google Chrome
Or, use JS or JQuery to remove the inline style when the screen is resized:
$(window).resize(function(){
if($(this).width() >= 768){
$('.hiddenclass').show();
}
else{
$('.hiddenclass').hide();
}
});
JSFiddle Demo
I seem to have come across this issue myself and following the advice here, I've come up with this solution:
window.onresize = function() {
var menu = document.getElementById('nav').getElementsByTagName('ul')[0];
if(window.innerWidth >= 1024) menu.style.display = '';
};
function toggleMenu() {
var menu = document.getElementById('nav').getElementsByTagName('ul')[0];
var link = document.getElementById('nav').getElementsByTagName('a')[0];
if(menu.style.display == 'block') {
menu.style.display = 'none';
link.innerHTML = '▼';
}else{
menu.style.display = 'block';
link.innerHTML = '▲';
}
}
Explanation:
The toggleMenu() function controls the display/hiding of the menu, and the issue presented itself after resizing the window from < 1024px (drop-down style menu) to > 1024px, my normal "desktop" menu disappeared completely. Given that JavaScript inserts styles inline (i.e. as a element attribute, ) then on a resize of 1024 or higher, this inline style should be gone.
Problem fixed.
I'm working on http://www.variied.com/market/men/. I'm trying to create a toggle dropdown menu on the sidebar that is triggered when someone hits the "Tops" link on the sidebar, which will then toggle the content in the sub-menu to be displayed. Here's my current code
<style>
ul.category ul.sub-menu ul.sub-menu li a{
display:none
}
</style>
<script>
jQuery(document).ready(function() {
jQuery("#menu-item-746").click(function() {
jQuery(this).next("ul.category ul.sub-menu ul.sub-menu li a").toggle();
return false;
});
});
</script>
There are a few issues in this fiddle:
You have a class called #submenu it should just be submenu
You're passing the event so you can use e.preventDefault() (unless you prefer return false)
I would suggest setting the subnav ul to display: none and just toggling that and I would use slideToggle for a nicer effect.
JS
$("#menu-item-746").click(function(e) {
e.preventDefault();
$(this).next("ul").slideToggle();
});
HTML
<ul class="submenu">
<li id="menu-item-746">Test Item</li>
<ul>
<li>Test1</li>
<li>Test2</li>
</ul>
</ul>
CSS
.submenu ul{
display: none;
}
FIDDLE
UPDATE
I looked at your HTML on your site and it appears that your ul subnav is a child of your li not a sibling (it was a sibling in your fiddle). Try this:
$(this).find("ul").slideToggle();
Also from the code you have provided you are targeting an id which means this would only work for that 1 element. It appears the ones with a subnav have a class called .menu-item-has-children so I would target that, like so:
$(".sub-menu .menu-item-has-children").click(function(e) {
e.preventDefault();
$(this).find("ul.sub-menu").slideToggle();
});
NEW UPDATE
Target the a instead then:
$(".sub-menu .menu-item-has-children").on("click", " a:first", function(e) {
e.preventDefault();
$(this).siblings("ul.sub-menu").slideToggle();
});
I need to add a second level of submenus here.
Is there a dynamic solution, so only one submenu is opened, when clicking on the link?
And when clicking a link to a submenu (in the first submenu), then open this one?
And so on…
I already changed the jsfiddle a little, to have one level of sublevels more: http://jsfiddle.net/cRsZE/363/
Working example with one level of submenus: JSFiddle Demo
HTML:
<ul id="nav">
<li>Home</li>
<li class="parent">About
<ul class="sub-nav">
<li>Johnny</li>
<li>Julie</li>
<li>Jamie</li>
</ul>
</li>
<li>Contact</li>
</ul>
CSS:
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
jQuery:
$(document).ready(function() {
$('.parent').click(function() {
$('.sub-nav').toggleClass('visible');
});
});
Source: Creating Drop Down Menu on click CSS
Try,
CSS:
.hidden {
display: none;
}
JS:
$('ul ul').addClass('hidden');
$(document).ready(function () {
$('.parent').click(function (e) {
e.stopPropagation();
$(this).find('ul').first().toggleClass('hidden');
});
});
DEMO
I have a horizontal menu that is fixed to the top of the page and built by the following list:
<div id="menu">
<ul id="nav">
<li>Home</li>
<li>blog</li>
<li>more info</li>
<li>contact</li>
</ul>
</div>
Currently there is an empty space to the far left of the home menu link. How could I go about having an image of their logo show up in this location after the user scrolls down the page 150px?
I imagine this is a combo of javascript and CSS which is fine, I just need a roadmap of how to achieve the result. Thanks.
Place an element for the logo in the area you want it to be and provide it styling. Set it to display none at first.
Attach a scroll listener to the window. Check for if the page has scrolled 150px from the top. If it has change the display to block on the element with the logo. It if hasn't change the element to display none if it is visible.
You can do it with jQuery, if you'd like. The idea will be to go ahead and add the image, and then use JavaScript to add a class of hidden to the image (the image will be displayed whenever JavaScript is turned off, then), and then with jQuery, add or remove the class hidden depending on the scroll position.
<div id="menu">
<img src="path/to/logo.png" id="logo">
<ul id="nav">
<li>Home</li>
<li>blog</li>
<li>more info</li>
<li>contact</li>
</ul>
</div>
/* CSS */
.hidden {
display: none;
}
// jQuery
$(function() {
var logo = $('#logo');
logo.addClass('hidden');
$(window).scroll(function() {
if( +$(this).scrollTop > 149 ) {
logo.removeClass('hidden');
} else {
logo.addClass('hidden');
}
});
});
Just as a note, if you would like the image to always be hidden if JavaScript is off, then hard-code class="hidden" into the HTML. When JavaScript is turned on, the code will still work the same. It's just a preference of how you want your page to behave with vs without JavaScript being on.
here is a little example how you can show/hide an element on page scroll with jQuery. hope this helps: http://jsfiddle.net/KWyS2/
<script type="text/javascript">
$(document).ready(function(){
$(window).scroll(function(){
var scrollTop = $(window).scrollTop();
$('.addDistance').html(scrollTop);
if(scrollTop >= 150 ) {
$('.show-hide-me').fadeIn();
} else {
$('.show-hide-me').fadeOut();
}
})
})
</script>
<div class="show-hide-me"></div>
<div class="content"></div>
<p class="addDistance"></p>
<style text="type/css">
.show-hide-me {
display:none;
width:100px;height:100px;
background-color:orange;
position:fixed;
top:0px;
left:0px;
}
.content {
height:10000px;
background-color:fuchsia;
width:10px;
}
p {
position:fixed;
top:0px;right:0px;
border:solid 1px red;
}
</style>