Delay the jQuery event handler for a few milliseconds before triggering

I'm currently working on a navigation menu, but I've encountered some bugs and I'm struggling to fine-tune it completely. Here are the issues I'm facing, and any help or solutions would be greatly appreciated.

  1. The menu items (About Me | Portfolio | Blog | Contact Me) are being triggered too easily, even with a quick hover. How can I delay the trigger (mouseenter) for a few milliseconds (say 200ms) so that the menu is only activated if the user hovers over it for at least 200ms, and not unintentionally?

  2. The submenus (Portfolio One | Portfolio Two) sometimes disappear when their parent is hovered over, leaving the other submenu hanging. I suspect this is due to the easily triggered parent menu hover affecting its children. I need a solution to prevent the submenus from fading in and out rapidly and causing clutter.

Thank you in advance for any help!

Here is the fiddle link: https://jsfiddle.net/Herza/ut5nLdpa/

Here is the code snippet:

--------------HTML--------------------

<nav id="menu">
    <ul>
        <li>
            <a href="#">
                <p>About Me</p>
                <div></div>
            </a>
        </li><!--
     --><li id="portfolio" >
            <a>
                <p>Portfolio</p>
                <div></div>
            </a>
            <ul>
                <li id="one-port">
                    <a href="#">Portfolio One</a>
                </li>
                <li id="two-port">
                    <a href="#" >Portfolio Two</a>
                </li>
            </ul>
        </li><!--
     --><li>
            <a href="#" >
                <p>Blog</p>
                <div></div>
            </a>
        </li><!--
     --><li>
            <a href="#" >
                <p>Contact Me</p>
                <div></div>
            </a>
        </li>
    <ul>    
</nav>

---------------CSS-----------------

nav#menu .current {background-color: black; color: white;}
nav#menu > ul {margin: 0; padding: 0;}
nav#menu > ul > li {display: inline-block; list-style: none; position: relative;}
nav#menu > ul > li > a {text-decoration: none; display: block; padding: 0; height:  62px; width: 130px; text-align: center; font-family: "roboto-light"; line-height: 55px; color: black; font-size: 16px; cursor: pointer; overflow: hidden;}
nav#menu > ul > li > a > p {display: block; width: 100%; height: 62px; margin: 0; padding: 0; background-color: green;}
nav#menu > ul > li > a > div {display: block; width: 100%; height: 62px; margin: 0; padding: 0; background-color: black; background-image: url(https://lh3.googleusercontent.com/3mJFQFK6QV2X2RZHfDGruGeelc7R4KhigZliqmQKZQqRMdm13ZOR2ZPtBf3VMyagahrzA4gT3ZcB4VU=w1342-h479); background-size: auto; background-repeat: no-repeat; background-position: center center;}
nav#menu > ul > li > ul {position: absolute; left: 0px; padding: 0px; margin: 0px; width: 200px; height: 0px; background-color: white; display: block; }
nav#menu > ul > li > ul > li {list-style: none}
nav#menu > ul > li > ul > li > a {display: block; padding: 15px 10px 15px 35px; background-color: white; color: black; text-decoration: none; font-family: "roboto-light";  font-size: 16px; background-color: blue;}
nav#menu > ul > li > ul > li { position: absolute; width: 100%; border: 0; left: 100px; display: none;}
nav#menu > ul > li > ul > li#one-port {top: 0px; z-index: 36;}
nav#menu > ul > li > ul > li#two-port {top: 49px; z-index: 35;}
nav#menu > ul > li > ul > li#one-port > a {border-bottom: 1px solid black;}

-------------------- Jquery --------------------------------

$(document).ready(function(){

    $("nav > ul > li").mouseenter(function(){
        $(this).children("a").children("p").animate({margin: "-62 0 0 0"},300);
    })
    $("nav > ul > li").mouseleave(function(){
        $(this).children("a").children("p").animate({margin: "0 0 0 0"},300);
    })

    $("nav > ul > li#portfolio").mouseenter(function(){
        $(this).children("ul").contents().clearQueue(); 
        $(this).children("ul").children("li#one-port").delay(0).queue(function(){
            $(this).animate({left: "0"},{queue: false, duration: 400})
            $(this).fadeIn({queue: false, duration: 400});
            $(this).dequeue();
        })
        $(this).children("ul").children("li#two-port").delay(250).queue(function(){
            $(this).animate({left: "0"},{queue: false, duration: 400})
            $(this).fadeIn({queue: false, duration: 400});
            $(this).dequeue();
        })
    })

    $("nav > ul > li#portfolio").mouseleave(function(){ 
        $(this).children("ul").contents().clearQueue();                                         
        $(this).children("ul").children("li#one-port").delay(0).queue(function(){
            $(this).animate({left: "100"},{queue: false, duration: 400})
            $(this).fadeOut({queue: false});
            $(this).dequeue();
        })
        $(this).children("ul").children("li#two-port").delay(250).queue(function(){
            $(this).animate({left: "100"},{queue: false, duration: 400})
            $(this).fadeOut({queue: false});
            $(this).dequeue();
        })      
    })
})

Answer №1

Although you've already found a solution using the hoverintent plugin, I'd like to offer an alternative approach that requires no javascript whatsoever, relying solely on a few css transitions. The benefits of this method include:

  • Avoiding the need to load additional kB's for javascript
  • Graceful degradation - users without javascript will still see the menu
  • Optimized css transitions for smoother animations
  • Utilizing efficient properties like translate and opacity to enhance performance without needing extra plugins for jQuery

Without delay, here's what I've come up with. It may require some tweaking with the values, but it serves as a proof of concept. The actual code is surprisingly simple:

HTML:

<nav>
    <ul>
        <li><a href="#">About Me</a></li>
        <li><a href="#">Portfolio</a>
            <ul>
                <li><a href="#">Web Design</a></li>
                <li><a href="#">Digital Illustration</a></li>
            </ul>
        </li>
        <li><a href="#">Blog</a></li>
        <li><a href="#">Contact Me</a></li>
    </ul>   
</nav>

CSS:

/* general */
nav a {
    text-align: center;
    display: block;
    color: black;
    text-decoration: none;
    padding: 18px;
}
nav ul {
    list-style: none;
}

/* main menu */
nav > ul > li {
    display: inline-block;
    vertical-align: middle;
    position: relative;
}
nav > ul > li > a {
    background: green;
    overflow: hidden;
    position: relative;
}
nav > ul > li > a:after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background: black;
    transform: translate(0, 100%);
    transition: transform .4s .2s;
}
nav > ul > li:hover > a:after {
    transform: translate(0,0);
}

/* sub menu */
nav > ul > li > ul {
    position: absolute;
    top: 100%;
}
nav > ul > li > ul > li > a {
    white-space: nowrap;
    background: blue;
    transform: translate(100%, 0);
    opacity: 0;
    transition: transform .4s .3s, opacity .4s .3s;
}
nav > ul > li:hover > ul > li > a {
    transform: translate(0, 0);
    opacity: 1;
}

/* repeat this for each sub item you add, increasing the child 
   number (2) and adding .2s to the delay. Can be easily automated 
   with a css preprocessor like sass or less
*/
nav > ul > li > ul > li:nth-child(2) > a {
    transition-delay: .5s;
}

The code is relatively straightforward, but don't hesitate to reach out if you need any clarifications.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

using javascript to create two choices

I am facing a small complication between two select options in my javascript code. Here is the snippet of my javascript: function displayVals() { var singleValues = $("select option:selected").text(); //to stay selected $("#hiddenselect").val(s ...

What is the best way to save multiple HTML widgets in my HTML file using R and plot.ly?

I have recently started experimenting with plot.ly in R and I am fascinated by the ability to easily publish graphs directly in html using htmlwidgets. However, I have encountered a challenge when trying to save multiple widgets in the same html file. Curr ...

Retrieve the id by using the `$` selector

I am trying to achieve the following in my code : <table> @foreach(var foo in Model.List) { <tr> <td><a href="#" class="MnuCustomerSelect" id="@foo.Id">Select</a></td> <td>@foo.Id</td> ...

What type of JavaScript scope is accessible by an anchor tag's href attribute?

My current query involves using an <a> tag to invoke a JavaScript function: <a href="javascript:doSomething();">link</a> In which scope does this JS function need to be defined in order to be reachable? Is declaring it globally necessar ...

Perfect CSS Menu Hover Effect

I created my own navigation menu, and I'm struggling with one thing... How do I change the A tag color to white when hovering over the ul id "navitemul"? I've tried #lovedating#navitemul:hover #lovedating a {color:white} and other methods, but no ...

Achieving vertical alignment of button contents in Bootstrap 4

Incorporating bootstrap 4 and material icons into my app has presented a challenge. Specifically, the issue arises when I attempt to create a button that contains both text and an icon. .button-icon { vertical-align: middle; } <button class="button ...

Getting the value of a session variable in JavaScript from a PHP file

Despite the numerous inquiries on this topic, I am still struggling to comprehend it. Scenario: An image with a hyperlink When the image is clicked: Verify if session exists If session exists, open the link If session does not exist, display the login ...

Steps for adding a navbar that slides horizontally and overlaps other links on a webpage

I am attempting to design a sliding navigation menu using JQuery. The concept involves having multiple main sections, each with several subsections. When a user hovers over a section, the subsections will expand horizontally. If another section is current ...

Creating a line break in HTML using Bootstrap

Reference the source provided, specifically the red alert option. Here is an example: <div class="alert alert-dismissible alert-danger"> <button type="button" class="close" data-dismiss="alert">&times;</button> <strong> ...

Create a feature that allows users to dynamically add and remove image fields, with the ability to insert the selected images into a database

I'm currently using the following code and I am able to add attachments, but I'm facing an issue when trying to remove them. Can someone please help me with this problem? I tried adding an alert on the remove button and it seems to be working, h ...

Nested foreach loops interacting with one another

I am attempting to execute multiple nested foreach loops and stop at 12 iterations, however the current code I have is not functioning as expected. While it displays the desired output, there seems to be an issue where only the first image in each director ...

Tips for displaying the attributes of a product when making edits within a modal utilizing jquery, ajax, and Laravel

Struggling to update product details through a modal populated with inputs, including dropdowns and radio buttons. Using jQuery AJAX for data retrieval from the table. // show editing modal $('body').on('click','#editrentalhsedeta ...

Transferring Arrays to AJAX communication

I am facing an issue with passing both a string array and an array of string arrays to a webservice through AJAX in my ASP.NET application. Unfortunately, I keep encountering the following error: {"Message":"Invalid object passed in, : or } expected. (16) ...

HTML5 Video validation is not working properly

In my current project, I initially used embedded Youtube videos but faced issues with validation. Decided to explore HTML5 video elements as an alternative, but encountered some challenges. While attempting to validate the code, strange errors popped up: ...

Is the input box failing to show up on your screen?

I recently tackled the task of creating a commenting feature for RSS articles Throughout my journey with PHP coding, I encountered an issue where the input box for comments was not displaying. https://i.stack.imgur.com/gJIlu.png Check out the snippet fr ...

Discovering the file names of JavaScript files within a context path and dynamically loading them

I am currently working on a Struts application where I need to dynamically load a JSP file with its corresponding JavaScript file upon menu selection. Although the functionality is working smoothly, I am facing an issue in loading the JavaScript file along ...

Utilizing Bootstrap divs for multiline display in Yii2 platform

Currently, I am utilizing a list in Bootstrap CSS which is responsive and beneficial. However, I am faced with the challenge of creating a notification list with lengthy text akin to that on Facebook. My query pertains to the technique required to make th ...

Executing a jQuery code within a WordPress theme

I have been attempting to implement the following script within the header.php file of a Wordpress website: <script> jQuery(function($) { jQuery('[href=#membership]').attr( 'data-menu-top', '500' ); }); ...

It is not permitted to incorporate the navbar.html file into any other modules

As someone new to web development, I have been facing challenges while working with Django This is the code for my project's modules. {% include 'navbar.html' %} <h1>projects template</h1> <p>Lorem Ipsum is simply dummy ...

Cherrypy/Chrome: Issue with jquery ajax request remaining pending after several successful requests

My current project involves a Cherrypy server that receives a JSON array from a client via AJAX call. The server then manipulates the array and sends it back to the client. However, I've noticed an issue where after a few smooth requests, the next req ...