Questions › Bind event to div but 'not' inner div [duplicate]
Wayne O Asked

This question already has an answer here:

I have a set of divs that looks like this

<div class="videoThumbnail" data-videoid="4">
   <div class="video"><img src="some/Url" alt="video thumbnail preview"/></div>
   <div class="title">I'm a video</div>
   <div class="download"><span class="ui-icon ui-icon-arrowthickstop-1-s"></span></div>
</div>

Then I am binding an event to the videoThumbnail class. That function works fine and well but I now need to bind another event for when download is clicked. My two bind events look like this.

//Bind selecting a thumbnail to change the video
$( '.videoThumbnail' ).not( '.download' ).on( 'click', function ( t ) {
    alert('you are doing thumbnail stuff');
} );
//Bind download on the litle download icon
$( '.download' ).on( 'click', function ( t ) {
    alert('you want to download this');
} );

I would like the first bind event on videoThumbnail to only happen when it's not selecting the download within it. Unfortunately whenever i press the download icon both functions execute. How can I bind the first event to the videoThumbnail without binding it to the download that's inside of it?

Comments :
A. Wolff replied

Stop event propagation for click event on .download

miguelmpn replied

since the first click function only applies to two elements you can also bind directly to them $( '.videoThumbnail .video, .videoThumbnail .title' ).on( 'click', function ( t ) { alert('you are doing thumbnail stuff'); } );

Wayne O replied

@miguelmpn while that would work for this, I also have them in a for loop and there's 2 sets of them on the page, I thought that information irrelevant to the question though so I left it out.

miguelmpn replied

You can have different childs? but at least .download is always present?

Wayne O replied

You're right, it would always be the same classes, so that too is a viable answer


2 Answers :
Mosh Feu answered

You need to use event.stopPropagation

Code

$('.download').on('click', function(event){
   event.stopPropagation();
   // the click code..
});
Josh Crozier answered

Stopping propagtion will prevent the event from bubbling, thereby preventing any parent event listener from being notified of the event that was dispatched. This may have inadvertent side-effects resulting in other unintended events being suppressed.

A better approach is to check if event.target is the .download element or a descendant element of .download.

$('.videoThumbnail').on('click', function(event) {
  if (!$(event.target).closest('.download').length) {
    // clicked on ".videoThumbnail" and "event.target" is not ".download"
  }
});

Here is an example demonstrating that:

$('.videoThumbnail').on('click', function(event) {
  if (!$(event.target).closest('.download').length) {
    alert('clicked on ".videoThumbnail" and "event.target" is not ".download"');
  }
});


$('.download').on('click', function(event) {
  alert('clicked on the ".download" element');
});
.videoThumbnail { border: 1px solid; }
.download { background: #f00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="videoThumbnail" data-videoid="4">
  <div class="video">
    <img src="some/Url" alt="video thumbnail preview" />
  </div>
  <div class="download"><span class="ui-icon ui-icon-arrowthickstop-1-s">download</span>
  </div>
</div>

Mathletics replied
Stopping propagtion will prevent any other events from being fired. Huh? It will stop this click event from bubbling, but it won't affect any other events.;
Josh Crozier replied
@Mathletics Correct. I clarified by stating that it will prevent any parent event listener from being notified of the event that was fired.;