1

I have folders on my page with class '.folder-ico'. When I click on some folder, the tiny menu inside this folder appears by calling function addTinyMenuInsideIco(). Now If I click any element except clicked folder or clicked folder's elements tiny menu should be removed by using removeTinnyMenuInsideIco(). Unfortunately, $('body').on('click',function(e){}... fires automatically after clicking on folder. Any tips how to do it properly?

<div class="folder-ico">
    <div class="folder-image">
    <h2>Ico 1</h2>
</div>

<div class="folder-ico">
    <div class="folder-image">
    <h2>Ico 2</h2>
</div>

<!-- ... -->

<div class="folder-ico">
    <div class="folder-image">
    <h2>Ico n</h2>
</div>

<script>

$('.folder-ico').on('click', whenClickOnIco);

function whenClickOnIco ()
{
    if(!$(this).hasClass('clicked'))
    {
        // Add class '.clicked'
        $(this).addClass('clicked');

        // Add tiny menu inside ico.
        addTinyMenuInsideIco();

        // Remember 'old this'
        let tempThis = this;

        // Add click event to all body elements.
        $('body').on('click',function(e)
        {
            // Clicked on some body element except class '.clicked'.
            if(!$(e.target).hasClass('clicked'))
            {
                // Remove class '.clicked'.
                $(tempThis).removeClass('clicked');

                // Remove tiny menu inside ico.
                removeTinnyMenuInsideIco();

                // Unbind click event.
                $('body').unbind('click');

                // Add event click to unbinded elements.
                $('.folder-ico').on('click', whenClickOnIco);
            }
        })
    }
}

</script>
Tomasz
  • 43
  • 1
  • 3

2 Answers2

0

Try following code in your event call:
event.preventDefault();

or you can prevent nested elements from firing the parent element's event by adding event.stopPropagation();

MDN preventDefault

MDN stopPropagation

javad bat
  • 4,236
  • 6
  • 26
  • 44
Eray Ismailov
  • 305
  • 3
  • 8
0

This behavior is called Bubbling (I'm suggesting you to read What is event bubbling and capturing?).

The idea's outlines is: when an event is fired inside an inner element, the event is fired first into the element, then, by order, is bubbled up into the parent elements.

Most of the time this is powerful. For example, if I have a button with an image inside, I want a click on the image to trigger the button's click event listeners. Unfortunately, sometimes, like in your case, you don't want that. Fortunately, there is a solution.

As you might know, each event listener in js has an event parameter. This parameter has a method called stopPropagation(), which stops the bubbling. So, what you need to do is the following:

function whenClickOnIco (e)
{
  e.stopPropagation();
  // ...
});
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
  • I should learn about Bubbling, but adding e.stopPropagaton() to whenClickOnIco() doesn't work. Anyway is it a good solution to put click inside click in my case? Maybe there is another way to do it? – Tomasz Dec 23 '19 at 13:18
  • @Tomasz Show your full code with stopPropagation(). – Chayim Friedman Dec 23 '19 at 13:38
  • @Tomasz And there is a easier way to do one-time event in jquery, using `once()` instead of `on()`. – Chayim Friedman Dec 23 '19 at 13:39
  • [link](https://jsfiddle.net/tomas_code/uksvz95a/1/) here you go. If you press longer on the folder the tiny menu activates. I added **e.stopPropagation();** at the be begining of the **tapLongPress(e)** function. Try to uncomment **('body').on('click',function(e)** and run. PS: I've also noticed that after longer pressing and releasing the mouse whenClickOnCatFolder fires and add .selected-folder-cat class which is not good... – Tomasz Dec 23 '19 at 17:56