开发者

Get clicked element ID

开发者 https://www.devze.com 2023-02-26 03:57 出处:网络
I prepared a demo HERE My problem: I\'m trying to get the ID of the clicked element. It returns always the ID of the element that CONTAINS other elements: the \'outer\' DIV开发者_StackOverflow parent

I prepared a demo HERE

My problem: I'm trying to get the ID of the clicked element. It returns always the ID of the element that CONTAINS other elements: the 'outer' DIV开发者_StackOverflow parent ID.

Interesting is, that adding alert(...) (uncomment in the DEMO) it results with TWO alerts! How? Why?

The first indicating the ID of the overlaying DIV and the second alert: the ID 'container'. How to get the ID of the exact clicked element?

  $(document).ready(function(){

    $('div').each(function(){
      $(this).click(function(){
        $('#clicked_info').html($(this).attr('id'));
        //alert($(this).attr('id')); // try THIS! wow! 
      });
    });

  });

Is it also possible to grab all the elements ID subject to the mouse(click) like alert does, but without the alert?


The reason is something called event bubbling. When an event is triggered on an element, its ancestor elements are informed of the event. If they have any event handlers bound for that event, they will be triggered too.

In this case, a click on #div3 triggers the handler on that element (hence the alert div3) and then the event bubbles up to the container element, and triggers the handler on that element (since you bound the handler to all div elements). Since the container handler was triggered second, that is the result put in #clicked_info. (div3 is put there by the first handler, but immediately replaced.)

To get round this, there are several solutions. My preferred solution is to apply the id of the originating function, which is the target property of the event object:

$(this).click(function(event){
    $('#clicked_info').html(event.target.id);
});

Modified example. Note that I have also simplified your code: the each call is unnecessary as click binds to every element in the selection.

I think this solution is better than stopping propagation because it doesn't stop propagation! Propagation is frequently useful (that's why it exists, after all) and some other aspect of your code may rely upon it.


Since your click handler is applied to all divs, there's a click handler on both the inner divs and the container. When you click once, the handlers for both are executed. If you want to only show the inner div you could prevent the event "bubbling up" by doing this:

$('div').each(function(){
  $(this).click(function(e){
    e.stopPropagation();
    $('#clicked_info').html($(this).attr('id'));
  });
});


My guess is that it's because the click event bubbles up from the inner divs to the containing div. The click handler function for that div will be called last, and will overwrite whatever value is in your #clicked_info element.

If you want only the handler for the inner divs to be called, then you have to select them specifically when attaching the click handler:

$(document).ready(function(){
    $('div#container > div').each(function(){
      $(this).click(function(){
        $('#clicked_info').html($(this).attr('id'));
      });
    });
  });

Edit: Or, even easier, just return false from your handler function. This will stop event propagation to the containing elements.


You are assigning click handler to all the div elements and since the div#container is parent of all divs that element's id is returned.

Change your ready event code to as below:

  $(document).ready(function(){

      $(".cssInner").click(function(){
        $('#clicked_info').html($(this).attr('id'));
        //alert($(this).attr('id')); // try THIS! wow! 
      });

  });

Working example: http://jsbin.com/udeha4/15/edit


I think this is what you meant:

$(document).ready(function(){
  $('div .cssInner').click(function(){
    $('#clicked_info').html($(this).attr('id'));
    //alert($(this).attr('id')); // try THIS! wow! 
  });
});

In this case you set the click event to happen on the inner elements only!


The .each() is not needed when the needed click selector is already used $('div'), referring to any 'div' element in the DOM.


The click event will propagate up the DOM tree by default,
returning on every Event Bubble the current Element ID.

Alert pauses the bubble execution, alerting the current element ID making clearly visible the bubbling stage when a positive result this.id is met.
Without using alert or console.log (in the example of writing the result on-page), all previous detected ID's will be overwritten on the flight by the newest registered, resulting in only the last registered ID.

Let's say we have this simple HTML structure ad we click the paragraph element:

<div id="container">
   Container element
   <div id="box">
      Box element
      <p>Paragraph</p>
   </div>
</div>

Now let's prevent the event propagate using event.stopPropagation()

$(function() {

  $('div').click(function( ev ) {
    ev.stopPropagation();
    console.log(  this.id  ); // "box"
  });

});

In the above example, (! even if we clicked the p element) the element Selector bound to the click event was $('div'); further propagation was prevented - returning the desired result: "box".

Using the above code in a similar fashion but listening instead for event.target we might end having a wrong result:

$(function(){

  $('div').click(function( ev ){
    console.log(  ev.target.id  ); // ""
                                   // "" 
  });

});

cause the actual registered event.target element was the HTML Paragraph element. Having two nested div elements (#box and #container) the console.log result ends having a bubbled event trough our two DIVs Selectors logging the same (empty) event.target value twice (// "" // "").

To see exactly the current event.currentTarget element the bubbling is currently on - we can do:

console.log(ev.currentTarget.id+' '+ev.currentTarget.tagName); // "box DIV"
                                                               // "container DIV"

still resulting in the last DIV element.

After exploring all the above results, the answer is to stop/cancel the event to bubble up the DOM tree using event.stopPropagation() and getting the event.currentTarget.id or simply this.id cause our jQuery selector is already the desired $('div') Element.


Now knowing that events bubble up the DOM and
to get a list of all Elements ID
we just allow the event to propagate, and collect the ID into an Array like in this example:

$(function(){

  var allIDs = []; // Empty Array

  $('div').on('mousedown', function( ev ){ // 
    allIDs.push( this.id ); // Push all bubbling DIVs ID into array!!
    console.log( "All IDs: " + allIDs );
    console.log( "Ev. bubbled Selector ID: " + this.id ); // First Parent
    console.log( "Target ID: " + ev.target.id ); // The targeted one
  }).on('mouseup', function(){
    allIDs = []; // Reset array for further clicks inspections
  });

}); 

jsBin demo

0

精彩评论

暂无评论...
验证码 换一张
取 消