jQuery mouse event blocks default propagation

401
June 04, 2017, at 11:54 PM

I have an issue with a full-body-overlay effect when clicking on any link.

The wanted effect is:

  1. when any link of the page is "pushed" (mousedown or touchstart), an image overlay appears on the top of the whole body (hiding the complete content of the page)
  2. when the link is (or should be) "released" (mouseup or touchend), the overlay should disappear and the original clicked link target should happen (the "href" attribute must be followed for instance).

The first part is OK: I added an event handler listening the "mousedown touchstart" events on every links. The second part is more complicated as the overlay does not trigger the "release" action of the link (the overlay is over the content with the link). So I attached a "mousedown touchend" event handler on the whole document, which works, but the default behavior of the clicked link (go to its "href" attribute for instance) is never fired :(

Here is my JS:

$(document).ready(function(){
    // the full-page overlay selector
    var $overlay = $('.body-overlay');
    // a flag to keep a trace of clicked element
    var overlay_triggered = false;
    // the "mousedown" event handler
    function show_overlay(evt)
    {
        var $target = $(evt.target);
        if (overlay_triggered === false) {
            $overlay.show();
            overlay_triggered = $target;
            $(document).on('mouseup touchend', hide_overlay);
        }
        return true;
    }
    // the "mouseup" event handler
    function hide_overlay(evt)
    {
        if (overlay_triggered !== false) {
            $(document).off('mouseup touchend', hide_overlay);
            $overlay.hide();
            // !!! - here I try to trigger a classic click but it never works
            $(overlay_triggered).click();
            overlay_triggered = false;
        }
        return true;
    }
    // attachment of the mousedown handler on all links
    $(document).on('mousedown touchstart', 'a', show_overlay);
});

I made a JS Fiddle to show it more clearly.

Does someone know about any mistake here ? Is my logic wrong ?

Answer 1

The problem is caused by the way jQuery executes .click(). It is a shortcut for jQuery's trigger('click') method, and this is what the documentation says:

Although .trigger() simulates an event activation, complete with a synthesized event object, it does not perfectly replicate a naturally-occurring event.

The solution is to call the click method on the DOM element itself. It seems though that the MDN documentation announces the same limitations apply to that method:

The HTMLElement.click() method simulates a mouse click on an element.

However, the click() method will not initiate navigation on an <a> element.

...but in trying this with the current versions of Firefox, Chrome and Edge, the DOM click method does launch the <a> navigation (also when href has a http URL).

So, change this:

overlay_triggered = $target;

to:

overlay_triggered = evt.target;

And change this (which was overkill anyway):

$(overlay_triggered).click();

to:

overlay_triggered.click();

See the updated jsfiddle.

Answer 2

I am not exactly sure why this won't work but I got it working by changing $(overlay_triggered).click(); to window.location = $(overlay_triggered).attr("href");

Answer 3

I have slightly modified the JS part of yours, and all is okay now The thing i did is holding the target's href value in a variable ( I stored the target's href value in 'href' vaiable in the code below ), and after that "window.location = href;" in 'hide_overlay' function does the trick.

<script>
    $(document).ready(function(){
        // the full-page overlay selector
        var $overlay = $('.body-overlay');
        // a flag to keep a trace of clicked element
        var overlay_triggered = false;
        var href = false;
        // the "mousedown" event handler
        function show_overlay(evt)
        {
            var $target = $(evt.target);
            href = evt.target.href;
            if (overlay_triggered === false) {
                $overlay.show();
                overlay_triggered = $target;
                $(document).on('mouseup touchend', hide_overlay);
            }
            return true;
        }
        // the "mouseup" event handler
        function hide_overlay(evt)
        {
            if (overlay_triggered !== false) {
                $(document).off('mouseup touchend', hide_overlay);
                $overlay.hide();
                // !!! - here I try to trigger a classic click but it never works
                if( href ) {
                    window.location = href;
                }
                overlay_triggered = false;
            }
            return true;
        }
        // attachment of the mousedown handler on all links
        $(document).on('mousedown touchstart', 'a', show_overlay);
    });
</script>
Rent Charter Buses Company
READ ALSO
Ajax multiple file upload to jersey doesn&#39;t work

Ajax multiple file upload to jersey doesn't work

I've been researching like crazy trying to figure out the problem but can't seem to succeedI am trying to upload multiple files to my restful java server (jersey)

245
One of two functions not triggered

One of two functions not triggered

I have the following html codeThe goal is to have an image which will follow the mouse till you click it

259
C#, MVC, jQuery and readable page

C#, MVC, jQuery and readable page

I've created a site with some functionalities with jQuery and MVCI'm using div and other guide line for a good site

448