Dessauges Antoine
Dessauges Antoine

Reputation: 593

Selector multiple class in parent

Maybe it's a bit specific on my project but I want to know if there is a better way to do it.

For a job project I have a website who used a third part iframe where I can't edit the html. I need to add a click event on some part of this iframe (example). The html coming from the iframe look like this :

<div class="a">
   <div class="b">
     <div class="c">
        <div class="c1">
           C1
        </div>
        <div class="c2">
           C2
        </div>
        <div class="c3">
           C3
        </div>
     </div
   </div
</div>

I need to add my event on the c2 and c3 but not on the c1 div so I create a selector like this : $('.a .b .c .c2, .a .b .c .c3')

It's work fine but in my case the class name are much longer (so my selector has like 100 character...) and the .c2 and .c3 class are used on other part of the project so I need to keep the .a .b. .c part.

Is this possible to do selector like this $('.a .b .c (.c2 || .c3)') ?

Or have you any idea ? Like stoping the selector on .c and detect the target class ? Is this really a better solution ?

Upvotes: 1

Views: 2108

Answers (3)

Terry
Terry

Reputation: 66228

Instead of using string concatenation of generate the selector, just use jQuery's .find() method:

$('.a .b .c').find('.c2, .c3')

If you prefer supplying the parent's context, you can also do this:

var $parent = $('.a .b .c');
$('.c2, .c3', $parent);

This approach will work if you want to bind the click event to the elements without relying on event bubbling:

// Solution 1
$('.a .b .c').find('.c2, .c3').click(function() {
    // Handle click event
});

// Solution 2
var $parent = $('.a .b .c');
$('.c2, .c3', $parent).click(function() {
    // Handle click event
});

In the event that you need to indeed rely on event bubbling, then you will have to check against the event target's parents:

$('body').on('click', '.c2, .c3', function() {
  // GUARD: Do not proceed if element is not a child of `.a .b .c`
  var $t = $(this);
  if (!$('.a .b .c').find($t).length) {
    return;
  }
  
  // Handle click event
  console.log('clicked');
});
.c1, .c2, .c3 {
  cursor: pointer;
  color: green;
}

.a .b .c .c1,
.foobar .foobaz .foobarbaz .c1, 
.foobar .foobaz .foobarbaz .c2,
.foobar .foobaz .foobarbaz .c3 {
  cursor: not-allowed;
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<p>Elements are child of <code>.a .b .c</code>.</p>

<div class="a">
   <div class="b">
     <div class="c">
        <div class="c1">
           C1 (will not fire event)
        </div>
        <div class="c2">
           C2 (will fire event)
        </div>
        <div class="c3">
           C3 (will fire event)
        </div>
     </div>
   </div>
</div>

<hr />

<p>Elements are not child of <code>.a .b .c</code>.</p>

<div class="foobar">
   <div class="foobaz">
     <div class="foobarbaz">
        <div class="c1">
           C1 (will not fire event)
        </div>
        <div class="c2">
           C2 (will not fire event as parents do not match)
        </div>
        <div class="c3">
           C3 (will not fire event as parents do not match)
        </div>
     </div>
   </div>
</div>

Upvotes: 2

Vivek Tankaria
Vivek Tankaria

Reputation: 1311

You can simply use

$(".c2,.c3").click(function(e){
//handle click event
});

Upvotes: -1

fdomn-m
fdomn-m

Reputation: 28621

You can use a variable to store the common parts:

var selector = ".a .b .c ";
$(selector + ".c2, " + selector + ".c3").hide();

You can also use .find(), which looks like it might be closest to your requirement:

$(".a .b .c").find(".c1, c2").hide();

If there's more, you can use .add(), something like:

var selector = ".a .b .c ";
var parts = [ ".c2", ".c3" ];

var jq = null;
$.each(parts, function(i, val) {
  if (jq == null)
      jq = $(selector + val);
  else
      jq.add(selector + val);
});
jq.hide();

Upvotes: 1

Related Questions