jQuery preventDefault according to a :hover state on Mobile - javascript

Please help me to figure out how to handle the situation. We have a link. There is :hover css rule for that link that expands an additional block of links.
$('li').children('a').on('click', function(e) {
if ( $(this).siblings('div').is(':hidden') ) {
e.preventDefault();
}
});
ul {
list-style-type: none;
border: 1px solid black;
background-color: white;
}
a {
display: block;
height: 30px;
line-height: 30px;
}
li:hover div {
display: block;
}
li div {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<ul>
<li>
Google
<div>
GMail
Maps
</div>
</li>
</ul>
The idea: Need to preventDefault for the first link until the additional links expanded. On desktop you won't spot the difference (if only you remove the :hover CSS rule, and try to click on the first link, it won't work since the rest links are hidden). Right behavior: User hovers first link, sees the others, and after that he is able to click on the first link.
The problem starts on mobiles since hover and click are the same. When user clicks on the first link, it will perform href, even though the additional links were hidden at the moment of clicking. But since the :hover rule applies at the same time of clicking on the link, JS treat it as if links were already opened and doesn't prevent default. Means my current IF statement is FALSE on mobile devices a second before actual click. Please help me to find the right approach.
A solution without using jquery-mobile is warmly welcomed! Thank you!

Here is a possible solution: Always run preventDefault. And base on the visibility of the div, decide to show the links or go to the href.
$('li').children('a').on('click', function(e) {
e.preventDefault();
var $links = $(this).siblings('div');
if ($links.is(':hidden')) {
$links.show();
} else {
window.location.href = this.href;
}
});
ul {
list-style-type: none;
border: 1px solid black;
background-color: white;
}
a {
display: block;
height: 30px;
line-height: 30px;
}
li:hover div {
display: block;
}
li div {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<ul>
<li>
Google
<div>
GMail
Maps
</div>
</li>
</ul>
PS: It is more likely to be a user experience problem to me. On touch devices, we don't really have hover event. Therefore it is hard to provide same experience as desktop. Usually there would be a slightly different design on mobile devices, like a dropdown menu toggles on tap or touchstart events in this case.

Related

How can I use hover and click depending on different devices?

I have a menu button which is half visible and half outside the screen. The full button is visible only when it is 'hovered' (I've written CSS for this, the button moves horizontal so it is displayed fully). Now this works on Desktop website. But as you know hover is not available on Mobile sites, so hover is converted to click. The click makes the button fully visible but it does not hide again when clicked again, because we have not defined click event to display and hide it, because it won't interfere with hover.
So is there any short and efficient way to do this, so that hover works on desktop and click works on phone for the same (display and hide) function?
You can use CSS or jQuery or both.
For your case, I suggest you set a hover function within a break-point that suits desktops and a click function within a break-point that suits mobile device. See my example below and adjust as needed.
$(document).ready(function() {
// When document is ready check window width, then choose hover/click
if ($(window).width() > 768) {
$("div").hover(function() {
$(this).toggleClass("increase");
});
} else {
$("div").click(function() {
$(this).toggleClass("increase");
});
}
});
div {
width: 50px;
height: 15px;
line-height: 45px;
margin: 0 auto;
background: red;
color: white;
border-radius: 5px;
text-align: center;
cursor: pointer;
overflow: hidden;
transition: all 1s;
}
div.increase {
width: 150px;
height: 45px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div> I am the Button</div>
Note: in my example; hover toggles the height/width when device width is wider than 768px, while a click toggles the height/width when device width is less than 768px
its simple try this
1 - disable hover on mobile device using media query
#media screen and (max-width:767px){
button:hover{ just disable css u r using }
}
2- add this jquery - this code adding and removing a class on the button click
$('button').click(function(){
$(this).toggleClass('btnClick');
});
3: now write the same hover css for this class
.btnClick{
}

Why when I open a submenu page scroll up?

I am creating a menu for the mobile, that when I click on an item in a submenu appears. The problem is that if I do this when the page is scrolled a bit, the page scrolls back up ... (whether open or close the submenu).
This obviously does not happen when the page is not scrolled
This is the code:
http://jsfiddle.net/qsq4y9d8/3/
this a css of submenu item
.lisottomenu {
letter-spacing: 0.02em;
display: block;
background: #E4BF85;
border-top: 1px solid #fff;
font-size: 14px;
list-style-type: none;
width:100%;
}
this css of item parent
ul li.leaf {
background: #646464 none repeat scroll 0 0;
border-top: 1px solid #a0a0a0;
display: block;
font-size: 15px;
letter-spacing: 0.02em;
list-style-type: none;
position: relative;
}
This is the problem:
(the problem is the auto-scroll)
I hope you can help me, even though the code is a bit long and I do not write well in English ...
Per my comment:
Any <a> with an href containing a "#" places a # in the URL which in turn looks for an empty anchor. Since one doesn't exist, it defaults to scrolling to the top.
Remove the "#" from your links and it won't scroll to the top anymore
Change
Link
to
Link
and it should stop scrolling to the top.
You have so many elements being created and removed and styles erased and added to the elements every time the menu is clicked, I think the browser just tries to refresh the layout or something.
Try adding and removing classes that show and hide your sub menus, and have your elements in your html from the start, instead of creating and destroying so much (unless they need to be dynamically generated from the server or something)
The problem is that the sub menu is making the entire window higher, so it has to make this scroll just when you are closing the sub-menu.
It is just how the browser reacts to this kind of height change.
One solution would to give the side menu defined max-height, and overflow-y:scroll.
#content, #sidebar-first {
display: inline;
float: left;
position: relative;
overflow-y: scroll;
max-height: 370px;
}
This way, when the the sidemenus are opening it wont affected the height of the document.
fiddle - http://jsfiddle.net/qsq4y9d8/9/

How to close responsive fullscreen menu when user clicks on a link?

I have one of those responsive menus on my one-pager site which brings up a transparent fullscreen menu when the hamburger icon is clicked. The fullscreen menu closes when user clicks the close button (X) at the top right, so everything works fine. But since most of my site is one-page, all the links in the menu are also links within the same page. When user clicks one of those links, the page jumps there as intended but the transparent fullscreen menu still stays fullscreen as it is...
The menu should disappear when user clicks on a link exactly as it does when user clicks the close button. This is the problem I'm trying to solve and I'm sure it requires just a few lines of Javascript but I'm not so fluent in JS.
This is the website:
http://www.artegradesign.com
Here's the related code (maybe there's more to it, not sure):
HTML
<div class="menu-btn"></div>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Work</li>
<li>Contact</li>
</ul>
</nav>
CSS
.menu-btn {
cursor: pointer;
height: 60px;
width: 60px;
display: inline;
z-index: 99;
position: absolute;
top: 2px;
right: 5%;
}
.close-btn {
position: fixed;
z-index: 100;
}
nav {
position: fixed;
top: -1600px;
left: 0;
right: 0;
background-color: rgba(0,26,51,0.95);
transition: all 0.5s;
color: white;
min-height: 100%;
z-index: 99;
}
.open {
top: 0;
}
JS
$(document).ready(function(){
$('.menu-btn').click(function(){
$('nav').toggleClass('open');
$(this).toggleClass('close-btn');
$('.container').toggle();
})
})
Update: I managed to close the fullscreen menu (with the js below) when clicking on a link, but it also makes the menu button disappear entirely. So I still need a hero to bring it back!
$(document).ready(function(){
$('nav li a').click(function(){
$('nav').toggle();
})
})
Thanks!
Seems less ideal how the click event is being handled, but because you are just looking for a toggle when you click it (for both closing and opening), you can just tie a link click in with triggering the menu click like so:
$('nav li a').on('click', function(){
$('.menu-btn').trigger('click');
});
I do suggest using an ID or a specific class for your nav, however. It could easily break if you added a nav element with an unordered link list anywhere else in the site.

Is it possible to prevent hidden elements jumping into view on focus

I've been tasked to create an accessible/responsive carousel and have come across an issue in Chrome regarding the focus of hidden elements.
As per this jsfiddle (http://jsfiddle.net/ft1oosep/); if you tab until the hidden element gets focus you'll see the link is hoisted into view without any update to the css properties of the element.
For the carousel, this causes problems as I need to keep track of where the carousel is at any given time. I've attempted to blur on focus but even that seems too late. Is there an easy solution to this problem or am I going to develop some complex focus/tab management?
Thanks in advance
(Please, no responses suggesting carousels are a bad idea... Its the task I've been set)
Example Code:
<style>
body {
background-color: #f2f2f2;
font-family: 'Arial';
font-size: 13px;
}
div {
width: 200px;
height: 200px;
overflow: hidden;
background-color: #ffffff;
}
a {
width: 200px;
height: 200px;
text-align: center;
background: #A6C6DD;
display: block;
color: #ffffff;
text-decoration: none;
}
a:last-child {
background: #746F9E;
}
</style>
<p>Pressing tab forces hidden link into view.</p>
<div>
Visible Link
Hidden Link
</div>
In my case, I added a dynamic tabindex attribute, so that when the tab-able elements where hidden, it was tabindex="-1" (prevent all tabbing) and when visible it becomes tabindex="0" (tab-able in the normal browser tab-order).
The code will likely be specific to the instance, but in general, set the tabindex attribute of the problmatic element to tabindex="-1" on render, then in the event that makes the problmatic element visible set tabindex="0" on that element whenever it is visible (and back to tabindex="-1"` once hidden again.)
Accessibility note: very rarely should anything other than -1 (disable tabbing) or 0 (normal tabbing flow) be used for tabindex values.
Would adding a node with js after the first link gets blurred be of any help ? So while the carousel is running there is no node there until tabbed through.

Change focus on press Up/Down button

everyone!
I've div tag, for instance
<style>
#DistrictStyle li:hover { background-color: rgb(129,171,242);}
</style>
<div id="DistrictList" style= "display: none;
z-index: 500;
list-style-type: none;
border: 1px solid rgb(129,171,242);
background-color: white;
max-height:150px;
overflow-y:scroll; position:absolute;
left: 208px; top: 135px; "><ul id="DistrictStyle"></ul></div>
So, now on mouse click of record of this list I fill several fields. And I need to navigate by Up/Down button thru list.
<li onclick='fill_distr(" + x + ");'>" + "</li>";
How can I achieve this? Can I only use pure JS or ought to use jQuery? I guess I should catch events of mouse focus and press "enter".
Thanks in advance.
You can go both ways. JQuery allows easy event handling though. Check out the documentation for all functions.
Note: Not sure if you use HTML5, but if it's the case you shouldn't use style attributes in your html elements.. Just saying :)
Edit: Just to point you in the right direction. event.which should do for you :)

Categories