Ipad hover event jQuery - javascript

Im trying to create a false hover event for my site using jQuery...
I have created the following only all the child elements in my list now return false also as opposed to linking to the correct page...
if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
$("ul.sf-menu li.i").click(function(e) {
e.preventDefault();
});
}
Has anybody an idea on an alternative method that could work?
HTML
<ul class="sf-menu"> <li>Home<li class="i">Weddings
<ul>
<li>Peel Suite</li>
<li>The Hall</li>
<li>The Grounds</li>
<li>Food & Drink</li>
<li>Pricing</li>
</ul>
</li>

well. without HTML its kind of hard to tell. But you are stopping the default behavior of the browser when the user clicks on the li (and therefor also its children, which I suppose is an anchor/link).
you could check if its a link or an anchor on click and handle it differently;
$("ul.sf-menu li.i").click(function(e) {
if (e.target.nodeName!=="A"){
e.preventDefault();
//do your hover code
}
else{
//do nothing, because the user wants the link to load
}
});

change youre selector so it only matches the first level of listpoints, also i dont see a class i so you might need to drop that from the selector aswell.
$("ul.sf-menu > li")

Related

Why is event.stopPropagation also stopping my Bootstrap Collapse?

I have a list item (#planAdminMenuItem) that has an onclick attribute. This list item has an icon inside of it (.spinner) that will collapse #collapseExample. Whenever the .spinner is clicked, I want it to run bootstrap collapse only. I do not want it to run drawPlanAdmin function. I have tried adding event.stopPropagation to my toggleSpinnerLeftMenu function, but whenever I do that, it also stops the bootstrap collapse. The parent click is blocked, but so is bootstrap collapse.
THE PHP & HTML CODE
<ul>
<li id="planAdminMenuItem" onclick="plan.drawPlanAdmin();">
Book Plan
<span class="icn icn-chevron-down spinner" onclick="ui.toggleSpinnerLeftMenu(this,event);" data-toggle="collapse" data-target="#collapseExample" data-aria-expanded="true" aria-controls="collapseExample"></span>
</li>
<!-- the collapsable area -->
<li id="collapseExample" class="collapse in">
<ul>
<li onclick="plan.drawRunListAdmin();">
Run List View
</li>
<li onclick="plan.drawLadderAdmin();">
Ladder View
</li>
</ul>
</li>
</ul>
THE JS CODE
toggleSpinnerLeftMenu:function(el,event){
el = jQuery(el);
if(el.hasClass('icn-chevron-up')){
el.addClass('icn-chevron-down');
el.removeClass('icn-chevron-up');
}else if(el.hasClass('icn-chevron-down')){
el.addClass('icn-chevron-up');
el.removeClass('icn-chevron-down');
}
event.stopPropagation(); //why is this stopping the collapse also?
},
stopPropagation is doing exactly what it is meant to do.
If you want the parent element to be propagated by the click on the inner element then simply don't do event.stopPropagation at all.
Though for some reasons if you need to have that then my suggestion is: call the function like
toggleSpinnerLeftMenu:function(el,event){
el = jQuery(el);
if(el.hasClass('icn-chevron-up')){
el.addClass('icn-chevron-down');
el.removeClass('icn-chevron-up');
}else if(el.hasClass('icn-chevron-down')){
el.addClass('icn-chevron-up');
el.removeClass('icn-chevron-down');
}
plan.drawPlanAdmin(); // Call the function inside of the child element's click handler.
event.stopPropagation(); //why is this stopping the collapse also?
},
Update: Since you described the issue more clearly in the comment, which has a solution completely south of what I've written above, I am updating with the new content that may be able to help.
Instead of attaching two event handlers, one using an inline onClick attribute and another using Bootstrap's data-collapse, use one:
$(".spinner").on("click", function(event) { // tip: Give a better id or class name
$('#collapseExample').collapse({toggle: true});
ui.toggleSpinnerLeftMenu(this, event);
});
This is the general idea of doing this, you may still have to make some adjustments to your method calls to fit it in.

Detect Right Click From Class Selector?

I have the below HTML which is generated using jQuery from an AJAX call:
<ul id="ul-container">
<li class="li-item" data-deviceKey="1">Data1</li>
<li class="li-item" data-deviceKey="2">Data2</li>
</ul>
I then have this jQuery code:
$('.li-item').mousedown(function(e) {
if(e.which == 3) {
console.log('Right Click Detected on '+$(this).attr('data-deviceKey'));
}
});
I am trying to detect a right mouse click, and then do something when it occurs.
This does not work, and it's stressing me out. I've tried literally every combination under the sun in order to try and get this to work. There's way too many to list, but literally nothing will detect the right click event.
Weirdly, if i set the selector to the ul's ID, it will then detect it? But, the problem is, i need to obtain the data-deviceKey attribute from the selected li.
Has anyone got any idea where the issue is here?
Things I've tried
1: Pretty much every reply in this: How to distinguish between left and right mouse click with jQuery
2: Detecting the right click on the ul's ID then finding the "closest" li element, which just returned the first li element in the list.
3: In my actual code, my li has 3 classes attached, i've tried using all of these which has not worked
4: tried using $('#ul-container li') to no avail.
Is it even possible to detect a right click on a class? Where am i going wrong? Please help before i have no hair left!
This is just a guess, but if you're loading the HTML content via an AJAX call, then you need to register the click handler after the HTML is inserted into the DOM.
Try registering the mousedown in the AJAX request's .done callback:
$.ajax({
url: "test.html",
}).done(function() {
$('.li-item').mousedown(function(e) {
if (e.which == 3) {
console.log('Right Click Detected on ' + $(this).attr('data-deviceKey'));
}
});
});

Touch-screen users have to click link twice for it to work

I have this drop-down menu that drops down on hover normally, but on touch devices, I simply made it so that you can click to open it as well.
The problem is that it seems like the <ul> that drops down isn't completely in focus or something because I have to click the links twice on my iPhone 4 to make them work.
Here's the code I'm working with:
$(document).ready(function() {
$('.myMenu > li').bind('mouseover', openSubMenu);
$('.myMenu > li').bind('mouseout', closeSubMenu);
$('.myMenu > li').bind('click', toggleSubMenu);
/* Also tried, currently using:
$('.myMenu > li').bind('tap', toggleSubMenu);
*/
function openSubMenu() {
$(this).find('ul').addClass("hovered");
};
function closeSubMenu() {
$(this).find('ul').removeClass("hovered");
};
function toggleSubMenu() {
$(this).find('ul').toggleClass("hovered").focus();
};
});
The .focus() was the fix I tried adding. It didn't break the code but didn't fix it either. I know there are several things I can do to make it better for touch-devices, but for now, the click method is what I'm sticking with.
By the way:
.hovered{
opacity:1 !important;
visibility: visible !important;
}
The HTML setup is basically <ul>s inside <ul>s like you would expect from a drop-down menu. If you for some reason want the markup just say so and I'll add it.
EDIT: Here's the link to the website I'm working on:
http://bok-it.underbakke.net
EDIT: Some additional information you might find useful that I noticed just now. The first time I click the link, the CSS on that link acts like it's hovered (as : hover) when I click on the sub-link the first time the main link (the one I first clicked to show the dropdown) loses the state of hover. This is why I think this is a focus issue.
EDIT: The HTML markup as requested:
<ul class="myMenu">
<li><span class="icon-home"></span> Framside</li>
<li><span class="icon-cart"></span> Butikk
<ul>
<li><span class="icon-cart"></span> Sand</li>
<li><span class="icon-cart"></span> Sauda</li>
<li><span class="icon-cart"></span> Nettbutikk</li>
</ul>
</li>
<li><span class="icon-console"></span> IT Tjenester
<ul>
<li><span class="icon-console"></span> Driftsavtale</li>
<li><span class="icon-console"></span> ASP & VPS</li>
<li><span class="icon-console"></span> OvervÄking</li>
<li><span class="icon-console"></span> Nettverk</li>
</ul>
</li>
<li><span class="icon-info"></span> Support
<ul>
<li><span class="icon-info"></span> Fjernsupport</li>
<li><span class="icon-info"></span> Utskrift ASP</li>
<li><span class="icon-info"></span> RDP: Rycloud</li>
<li><span class="icon-info"></span> TeamViewer Host</li>
</ul>
</li>
<li><span class="icon-mail"></span> Kontakt Oss</li>
</ul>
--------------SOLUTION--------------
EDIT: For people that are seeking the solution to this, here's the jQuery that fixed it for me (You should also give #jonsuh an upvote for wipping out the solution):
$(".myMenu li ul li a").on("touchend", function(event) {
window.location.href = $(this).attr("href");
});
When you mouseover a link in the submenu, the state of the parent list item changes.
However in iOS, when you click on a link in the submenu, it detects that the parent list item state needs to change, so instead of executing a tap, it's changing the state of the item, which is why it's requiring a second tap. (I hope this makes sense).
To cut to the chase, make sure there isn't a state change in the parent list item. Keep it the same when you hover over it as when you're hovering over the submenu links.
I haven't tested these and it's tough when I'm not working with the code live, but possible solutions could be as follows:
You could do it with jQuery and detecting a touch end, which isn't the best solution, but it should work:
$(".myMenu ul li a").on("touchend", function(event) {
window.location.href = $(this).attr("href");
});
Another is to try to keep the state the same with CSS and it may keep Safari from detecting a change in state. (I removed my CSS answer since it didn't work)
Read this: http://sitr.us/2011/07/28/how-mobile-safari-emulates-mouse-events.html
But if a clickable element also does something on mouseover then tapping on that element will trigger a mouseover event instead of a click. Tapping on the same element again will produce a click event.
If you have a mouseover event, iOS (maybe other OSes) will fire that upon initial click rather than the actual click event. I'd add some alerts to your JS to see which event, exactly, is being called on that initial tap.
Instead of having the click event of Jquery try the tap event like
$('.myMenu > li').bind('tap', toggleSubMenu);
Documentation for Tap
I forget where I found this solution but with jQuery I do something like this and it seems to do the trick:
$(document).ready(function() {
$('a,input').bind('touchend', function() {});
});
I used to use 'touchstart' but 'touchend' seems to be working better.

Jquery click function exclude children

Hey I'm having an issue figuring this one out.
JS
$('.jrm-menu-categories,#overlay-2').click(function() {
$('#overlay-2').toggle();
$('#overlay-3').hide();
});
HTML
<ul id="megaUber" class="megaMenu">
<li id="menu-item-1459" class="jrm-menu-categories">
<ul class="sub-menu sub-menu-1">
So basically what my JS does is create an overlay/modal effect when a sub menu is opened via click. I have the code repeated a few times with different classes and overlay ids hence the last line of code (needed so that only one overlay is shown at a time). Quickest and simplest way for a beginner like me, but that's not the subject.
When a sub-menu is open, and a user clicks anywhere in the sub-menu it toggles the overlay. I'm assuming this is because when I selected .jrm-menu-categories in the JS, it also selected the child elements, which happen to be .sub-menu
I'm thinking I need to use the .not() function, but can't figure it out.
can you guys help me with this? if possible write the code so I can try it out
Thanks!
You can try adding a second click handler to the children that will always return false. That way the click won't propagate up and dismiss:
$('.jrm-menu-categories').children('.sub-menu').click(function (e) {
e.stopPropagation(); // prevent click propagation, so parent click never fires.
})
You can test for the clicked item.
$('.jrm-menu-categories,#overlay-2').click(function(e) {
if (this == e.target){
$('#overlay-2').toggle();
$('#overlay-3').hide();
}
});

iPad - dropdown navigation better practice?

I have a web application that is expected to run on iPad. I do not wish to create a "dropdown" HTML element for navigation (ie. a select element) since I have plenty of real estate. I want to use my existing desktop-style "hover over then select" type navigation, but replace the hover event with a tap.
I only need to support mobile Safari for iPad, though other browser support could be a plus.
Here's how the nav is structured:
<nav id="main_navigation">
<ul>
<li>
<a id="nav_home" href="/index.jsp">home</a>
</li>
<li class="menuHasDrop" id="selected">
<a id="parent" href="/parent.jsp">parent</a>
<span class="navArrow"></span>
<ul>
<li><a id="foo" href="/foo.jsp">foo</a></li>
<li><a id="bar" href="/bar.jsp">bar</a></li>
</ul>
</li>
<li>
<a id="baz" href="baz.jsp">baz</a>
</li>
</ul>
</nav>
And here's how I'm detecting and enabling touch:
fc.enableTouch = function() {
(function() {
try {
document.createEvent('TouchEvent');
fc.touchEnabled = true;
} catch(e) {}
})();
if (fc.touchEnabled) {
$(document).ready(function() {
// disable clicks on parents
var $menus = $('.menuHasDrop');
$menus.on('click', '>a', function(e){
return false;
})
// listen for clicks on others
$('#main_navigation').on('click', $menus, function(e) {
e.stopImmediatePropagation();
var $this = $(this);
if ($this.parent().children('ul').length > 0) {
$menus.find('ul').hide();
$this.toggleClass('expanded');
if($this.hasClass('expanded')) {
$this.find('ul').show();
}
}
});
});
} else {
// console.log('not detecting touch');
}
}();
The "expanded" class is just a flag. I could set a flag another way, but it shouldn't matter much.
So, this all "works"... but there are two things bugging me:
There's a flicker of a shadow of some sort over the parent nav when I click it. I'm sure it's an OS "clicked a link" indicator, but it's not explicitly provided by CSS or the JavaScript. If anybody has seen such a thing, do you know how to disable it?
Every now and then on a fluke it seems, the UL representing the sub-menu seems to appear, go away, and appear again. Again, I don't THINK the logic itself would be able to cause this, so it might be browser-specific.
Other useful background information: there are always one or more content areas being refreshed via ajax calls, but the page itself is not being refreshed and the navigation area does not have any functions acting on it during the request.
I guess what I'm asking more than a code review is: "Are these just iOS quirks that I have to live with?" and "is there a definitive better practice for touch-enabling dropdowns?" Secondarily, all "I see a problem with your code" advice will be welcomed and appreciated. :)
To get rid of tap colour
-webkit-tap-highlight-color:rgba(0,0,0,0);
For binding, use touchstart/touchend what I have done in my current project is to detect touch, if touch enabled bind only touchstart and end, if not then bind click
I would also add a class to the anchor that you are targeting using ">a", that's really slow
$(#el).on('touchstart', function() {
// if class exist
// go to link
// else
// add class and open dropdown
});
For my current project we set up a virtual event handler to detect if the touch is a touchmove or just a regular touchstart
You can also do something like this
$(#el).on('touchstart', function() {
$(this).trigger('click');
// or you can use prevent default and stopPropagation
return false;
});
or bind on touchend, whatever works better for you

Categories

Resources