barrypicker
barrypicker

Reputation: 10088

How do I select an element having a specific child using jQuery?

Assume the following html snippet...

HTML Example

<div class="panel">
    <input type="hidden" class="id" value="1"></input>
    <div class="collection">
        <div>
            <input type="hidden" class="id" value="1"></input>
            <input type="text" value="hello world"></input>
        </div>
        <div>
            <input type="hidden" class="id" value="2"></input>
            <input type="text" value="goodbye moon"></input>
        </div>
    </div>
</div>
<div class="panel">
    <input type="hidden" class="id" value="2"></input>
    <div class="collection">
        <div>
            <input type="hidden" class="id" value="3"></input>
            <input type="text" value="some text"></input>
        </div>
        <div>
            <input type="hidden" class="id" value="4"></input>
            <input type="text" value="whatever"></input>
        </div>
    </div>
</div>

How would I craft a jQuery selector to select the div with class 'panel' where the child element is a hidden input with class 'id' and value of 2?

My current attempt selects the child element, not the parent. I could just call to get the parent now that I have the child, but I am looking for a selector that gets me the parent the first time around.

Selector that gets the child...

var element = $(".panel > input[type='hidden'][value='2'].id");

I also tried :has but it selected both panels because it selects on all descendants, not just the child and div 'colection' has a hidden input with class 'id' and value 2 on the first panel.

Here is my complete testing example...

Complete Testing Example:

$(document).ready(function () {
  var element = $(".panel > input[type='hidden'][value='2'].id");
  var elements = $(".panel").has("input[type='hidden'][value='2'].id");
});
<html>
	<head>
		<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
	</head>
	<body>
		<div class="panel">
		    <input type="hidden" class="id" value="1"></input>
		    <div class="collection">
		        <div>
		            <input type="hidden" class="id" value="1"></input>
		            <input type="text" value="hello world"></input>
		        </div>
		        <div>
		            <input type="hidden" class="id" value="2"></input>
		            <input type="text" value="goodbye moon"></input>
		        </div>
		    </div>
		</div>
		<div class="panel">
		    <input type="hidden" class="id" value="2"></input>
		    <div class="collection">
		        <div>
		            <input type="hidden" class="id" value="3"></input>
		            <input type="text" value="some text"></input>
		        </div>
		        <div>
		            <input type="hidden" class="id" value="4"></input>
		            <input type="text" value="whatever"></input>
		        </div>
		    </div>
		</div>
	</body>
</html>

Upvotes: 1

Views: 177

Answers (3)

billyonecan
billyonecan

Reputation: 20250

Select the input first, then just get the parent panel:

$( 'input.id[type="hidden"][value="2"]' ).parent( '.panel' );

The first selector will select both of the matching inputs, the call to .parent() with the .panel selector will reduce the collection to elements whose immediate parent is .panel

If you want it in a single selector, I suppose you could do:

$( '.panel:has(> input.id[type="hidden"][value="2"])' )

Just bear in mind this is a much less performant selector.

Upvotes: 0

Titus
Titus

Reputation: 22474

You can do something like this:

$(".panel:has(> input.id[type=hidden][value=2])");

HERE is the documentation for the :has(...) selector.

var $e = $(".panel:has(> input.id[type=hidden][value=2])");
console.log("Number of elements matching the selector:",$e.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="panel">
    <input type="hidden" class="id" value="1"></input>
    <div class="collection">
        <div>
            <input type="hidden" class="id" value="1"></input>
            <input type="text" value="hello world"></input>
        </div>
        <div>
            <input type="hidden" class="id" value="2"></input>
            <input type="text" value="goodbye moon"></input>
        </div>
    </div>
</div>
<div class="panel">
    <input type="hidden" class="id" value="2"></input>
    <div class="collection">
        <div>
            <input type="hidden" class="id" value="3"></input>
            <input type="text" value="some text"></input>
        </div>
        <div>
            <input type="hidden" class="id" value="4"></input>
            <input type="text" value="whatever"></input>
        </div>
    </div>
</div>

Upvotes: 2

random_user_name
random_user_name

Reputation: 26150

You can do what you've described by utilizing the .has() method, with the > direct child combinator, like so:

var elements = $(".panel").has("> input[type='hidden'][value='2'].id");

Working Snippet:

// no-conflict safe shorthand document ready
jQuery(function($) {
  // utilize .has with the > child combinator
  var elements = $(".panel").has("> input[type='hidden'][value='2'].id");
  elements.css({border: '2px solid red'});
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<div class="panel">
  <input type="hidden" class="id" value="1"></input>
  <div class="collection">
    <div>
      <input type="hidden" class="id" value="1"></input>
      <input type="text" value="hello world"></input>
    </div>
    <div>
      <input type="hidden" class="id" value="2"></input>
      <input type="text" value="goodbye moon"></input>
    </div>
  </div>
</div>
<div class="panel">
  <input type="hidden" class="id" value="2"></input>
  <div class="collection">
    <div>
      <input type="hidden" class="id" value="3"></input>
      <input type="text" value="some text"></input>
    </div>
    <div>
      <input type="hidden" class="id" value="4"></input>
      <input type="text" value="whatever"></input>
    </div>
  </div>
</div>

Upvotes: 3

Related Questions