3
votes

I have three div boxes

The first div main has an id of "main" and contains two other boxes with id "menu_header" and "menu_options"

this is my html

<div id="main">
 <div id="menu_header">
  </div>
  <div id="menu_options">
  </div>
</div>
<span>Something here</span>

this is my css

#main{
  display:table-cell;
  position:relative;
  top:100px;
  border:solid purple;
}
#menu_header{
  position:relative;
  border:solid black;
  background:red;
  width:100px;
  top:200px;
  height:100px;
 /* -moz-transition-property:bottom;
  -moz-transition-duration:2s;
  transition-property:top;
  transition-duration:1s;*/
}
#menu_options{
  background:blue;
  position:absolute;
  bottom:0%;
  border:solid black;
  width:100px;
  height:100px;
}
/*#menu_header:active{
  top:100px;
}*/

(ignore css transition since it was commented out)

this is my javascript

function test(e){
 //if(e.target.id=="menu_options"){return};
 $('#menu_header').animate({top:'-10'},1000);
  //var t=document.getElementById('menu_header')
 // t.setAttribute('top','40px');
  t.style="position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
}
document.getElementById('main').addEventListener('click',test,false)

finally this is my lab rat jsfiddle link http://jsfiddle.net/repzeroworld/ev7k688s/

In this scenario, when I set a click event handler on my parent container with id "main" everything works perfectly except that whenever click on this parent's container child div with id "menu_options" it also triggers the handler

I found the link below but somehow the event.propogation() solution here seems not to work in my case.

clicking on child element also triggers click event on it parent

One nasty hack, to prevent the any actions from executing if the child div capture the event was

if(e.target.id=="menu_header"){return};

THe above I commented out in my javascript code.

Question: why is the child div with id "menu_options" capturing the event from the parent container with id "main" despite me setting false on add EventListener to prevent event bubbling.?

3
It's event.stopPropagation(), not event.propagation(). Setting false with addEventListener() does not disable bubbling.user1106925

3 Answers

3
votes

The cause

Passing false to .addEventListener() does not disable bubbling. It simply makes it so that the event fires during the bubbling phase instead of the capturing phase.

When an event takes place, it starts at the root of the DOM and enters the "capturing" phase. This means that the event works its way from the document to the event.target, firing any "capturing" handlers it finds along the way.

Once it reaches the event.target, it reverses course, and traverses back up to the document, invoking any "bubbling" handlers it finds.

So because you passed false as the third argument, the handler will be invoked during that last "bubbling" phase.

So you see, this does not do anything to prevent nested elements from invoking the handler.


The solution

If you only want to invoke the handler when clicking on the actual element, and none of its children, simply halt the handler if this does not equal e.target.

function test(e){
   if (this != e.target)
      return;

   $('#menu_header').animate({top:'-10'},1000);
   var t=document.getElementById('menu_header')
   t.setAttribute('top','40px');
   t.style="position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
}
document.getElementById('main').addEventListener('click',test,false)
1
votes

You can restrict event bubbling by 2 scenario. 1. Put Click event on each DOM object, means child to parent and put event.stropPropagation(). 2. Identify the DOM object using e.target.id and return "false".[We are using this]

Code below

<script>
        function test(e) {
            if (e.target.id == "menu_header") { return }
            else if (e.target.id == "menu_options") { return }
            $('#menu_header').animate({ top: '-10' }, 1000);
            var t = document.getElementById('menu_header')
            t.setAttribute('top','40px');
            t.style = "position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
        }
         window.onload = function () {
        document.getElementById('main').addEventListener('click', test, false);
    }
</script>
1
votes

Try to stop propagation in the child element. See here.

function test(){
 $('#menu_header').animate({top:'10'},1000);
  //var t=document.getElementById('menu_header')
 // t.setAttribute('top','40px');
  //t.style="position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
}

function stopPropagation(e){
    e.stopPropagation();
}

document.getElementById('main').addEventListener('click',test,false);

document.getElementById('menu_header').addEventListener('click',stopPropagation,false);