5

I'm trying to get a dropdown menu to work correctly on touch based devices. The menu opens fine on click, but because the parent element is also a link it then takes the user to the link before a dropdown item has been selected.

Is there are way to make it so that (only on touch devices) the first tap of the parent element opens the dropdown and the second click brings you to the link?

I have a good knowledge of HTML and CSS but none really of javascript, so please be as descriptive as possible if the solution is script based.

Thanks

user1776763
  • 51
  • 1
  • 2
  • 1
    i'm a bit confused - do you want the dropdown menu to open when you click it or hover the mouse over it? –  Oct 26 '12 at 10:21
  • I want it to open on hover on a computer and when touched on a touch screen. But I want it to ignore the link on the first touch – user1776763 Oct 26 '12 at 10:32
  • hmmm...would you mind if i gave you an answer only for hovering over it with a mouse? I'll try and research for you about for a touch screen but you might need to code it all for a computer then put in on PhoneGap so it works for touch screens. –  Oct 26 '12 at 10:37
  • I have it working perfectly on hover with a mouse and it works on click on a touch screen. The problem lies in that the li also has a link. So the menu opens but the user is brought to the link aswell. – user1776763 Oct 26 '12 at 10:40
  • ok well i put an answer in and this one doesn't talk about a link - try putting the link into the code i gave you and it might work. sorry i misunderstoodx –  Oct 26 '12 at 10:55
  • no wait i think i got it - add in a 'onclick' line into my code where the first document.write is, something like `document.write('onclick = **link**...');` and it should work. then i think you're saying if you only roll over it you show the menu and if you click it then follow the link. Hope this helps xx –  Oct 26 '12 at 10:57

6 Answers6

3

Take a look at DoubleTapToGo:

"When you tap the parent item for the first time, DoubleTapToGo prevents the browser from opening a new URL but allows that if tapped once again in succession."

http://osvaldas.info/drop-down-navigation-responsive-and-touch-friendly

user3381264
  • 186
  • 1
  • 6
0

This may help. if you have a link

<a href="#">your drop down menu</a> I mean add # to href

Alternatively do this in JavaScript

var link = $('.menu').find('a');

$(document).on('touchstart', link, function (e) {
    e.preventDefault();
    //do your stuff
});
Om3ga
  • 30,465
  • 43
  • 141
  • 221
0
$('.has-sub').on("touchstart", function (e) {
 var submenu = $(this).find('ul').first();
 var link = $(this); //preselect the link
 if (link.hasClass('hover')) {
       link.removeClass('hover');
       $(submenu).slideUp(0);
       e.stopPropagation()
       return true;
 } else {
       $(submenu).slideDown(0);
       link.addClass('hover');
       e.stopPropagation();
       return false; //extra, and to make sure the function has consistent return points
 }

});

0

My solution is toggling the href content in javascript:

// JS

let dropdown = document.getElementsByClassName("dropdown")   
let droplink = document.getElementsByClassName("drop-link") 
//console.log(droplink[0].getAttribute('href')) to check code

for (let i = 0;i<dropdown.length;i++){ // if you have more than one dropdown
  dropdown[i].addEventListener('click', function(){
  // if dropdown is already displaying 
    if(dropdown[i].classList.contains('YourdisplayDropdownClass')){
      droplink[i].href = 'myhtmlpage.html'
    } else {
      droplink[i].href = '#'
      dropdown[i].classList.add('YourdisplayDropdownClass');
    }
  });
};

Structure in HTML

  <nav>
   <ul>
    <li class="dropdown"><a class="drop-link" ref="myhtmlpage.html">MyHTMLpage</a>
     <ul class="drop-menu">
      <li><a href="mysubpage1.html" class="drop-item">MySubpage1</a></li>
      <li><a href="mysubpage2.html" class="drop-item">MySubpage2</a></li>
     </ul>
    </li>
   </ul>
  </nav>
gl3yn
  • 301
  • 1
  • 3
  • 13
0

For those still looking for a way to do this, I have a solution:

First you can detect whether the device is a touch screen by detecting if the primary input type is pointer: coarse (answer from https://stackoverflow.com/a/52855084)

Then, if the device is a touch device, count how many times the link has been clicked. On the first click, prevent the default behaviour using .preventDefault(), and the dropdown should open but not the link. On the second click, don't suppress this behaviour and the link will open.

So, define a variable to keep track of the count, add your on click function to the link and prevent the default action if it is the first click:

var dropdown_clicked = 0;
//for touchscreens, click 1 = open dropdown, click 2 = open link
$("#dropdown > a").on('click', function (e) {
  if(window.matchMedia("(pointer: coarse)").matches) {
  //pointer:coarse = touchscreen
    dropdown_clicked += 1;
    if (dropdown_clicked == 1){
      e.preventDefault();
    }
    if (dropdown_clicked == 2){
      dropdown_clicked = 0;
    }
  }

Make sure your functions are defined within $(document).ready(function(){ }); as this method uses jQuery.


For context, I have this method for opening the dropdown on hover:
$("#dropdown").hover(function () {
//slideToggle = display or hide the matched elements with a sliding motion
//stop(true,true) stops the animation from repeating
$(this).find('ul').stop(true, true).slideToggle('medium');
});

And the dropdown HTML:

<ul>
    <li><a href="index.php">home</a></li>
    <li id="dropdown"><a href="page.php">my dropdown</a>
        <ul>
             <li>dropdown content</li>
             <li>dropdown content</li>
        </ul>
    </li>
</ul>
-1
function createMenu(menuName,menuTitle,menuEntries,left,width) {

 numEntries = menuEntries.length;

document.write('<div class="menuTitle" style="left:0px; width:100px;"');
document.write('onMouseover="menuToggle(\'' + menuName + '\');"');
document.write('onMouseout="menuToggle(\'' + menuName + '\');">');
document.write(menuTitle);
document.write('</div>');

     document.write('<div id="myMenu" class="menu" style="left:0px; width:100px;"');
     document.write('onMouseout="menuToggle(\'' + menuName + '\')">');
     for (i = 0; i < numEntries; i++) {
        document.write('<a href="' + menuEntries[i].url + '" class="menuEntry">' + menuEntries[i].entry + '</a><br>');
     }
     document.write('</div>');

}

  function menuToggle(target) {

     targetMenu = (document.getElementById) ? document.getElementById(target).style : eval("document." + target);
     targetMenu.top = (parseInt(targetMenu.top) == 22) ? -2000 : 22;

     }
  // -->
  </script>

this is JavaScript for creating a drop-down menu that drops when the mouse is hovered over it - it's from a book called JavaScript in 10 Simple Steps or Less by Arman Danesh. He's a great author and will probably explain this a lot better than me - but here goes;

what you're doing is creating a function with predefined variables as declared in the (). the line numEntries... sets the value of the variable numEntries as the length of predefined variable menuEntries. In other words, (in this example the number of entries programmed is three, making numEntries = 3) however many entries you code is the value of numEntries.

the document.write stuff may look confusing, but it's just javascript code which holds the HTML code, because just putting the div on it's own would break the program since you're putting this in script tags. if you don't understand me at any point just ask and i'll tell you what's in the textbook when i have it on me later.

That's the first function dealt with, the second is what makes the menu dropdown on the mouse hover. i don't know how to explain this clearly to you without quoting the book, but i'll try if you need me to explain it. I can give you the whole example if you need the HTML code for displaying the menu too, I have it on my computer.

Hope this helps and please just ask if you need me to go over anything. I'll keep researching how to alter it for a touch screen for you x

  • 1
    Thanks for this. The website is already live though, so I cant rebuild the whole menu system in javascript. Its created with CSS, but I'm looking for a script that will tell the parent element how to perform – user1776763 Oct 26 '12 at 11:36
  • ok - why don't you try making a .js file? that way you just add in all of your code to that new file then add a link to it in your `` tag, something like `` –  Oct 26 '12 at 11:50