GTS Joe
GTS Joe

Reputation: 4162

jQuery filter() and closest()

I'm trying to learn how to use jQuery's closest() and filter() methods. closest() traverses up the DOM tree while filter() traverses down.

In the following code, after a user clicks the link, jQuery should search up the DOM until it finds the "row" class, search down until it finds the "test" class then return the text in that element. Why is console log printing blank instead of "Hello?"

$('.button').on('click', function(e) {
	console.log( $(this).closest('.row').filter('.test').text() );
	e.preventDefault();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
		<tr class="row">
			<td><span class="test">Hello</span>
				<table>
					<tr>
						<td><a class="button" href="#">Button 1</a></td>
					</tr>
				</table>
			</td>
		</tr>
	</table>

Upvotes: 1

Views: 1144

Answers (2)

empiric
empiric

Reputation: 7878

You are mixing up filter() and find()

filter()

Reduce the set of matched elements to those that match the selector

This will not return anything because closest('.row') does not contain an element with .test

find()

Get the descendants of each element in the current set of matched elements

Searches for .test down the DOM starting at the element returned by closest('.row')

$('.button').on('click', function(e) {
  console.log($(this).closest('.row').find('.test').text());
  e.preventDefault();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tr class="row">
    <td><span class="test">Hello</span>
      <table>
        <tr>
          <td><a class="button" href="#">Button 1</a></td>
        </tr>
      </table>
    </td>
  </tr>
</table>

When you really want to use filter() instead if find() you could do something like this:

$('.button').on('click', function(e) {
var text;
 $(this).closest('.row').filter(function(){
 	 text = $( ".test", this ).text();
   return $( ".test", this ).length === 1;
  });
  console.log(text);
  e.preventDefault();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tr class="row">
    <td><span class="test">Hello</span>
      <table>
        <tr>
          <td><a class="button" href="#">Button 1</a></td>
        </tr>
      </table>
    </td>
  </tr>
</table>

But I would not recommend this as it defies the purpose of having a dedicated function for that.

Upvotes: 2

dokgu
dokgu

Reputation: 6040

So basically you misunderstood what filter() does. From what you say you're wanting to do you should use find() instead.

HTML

<table>
  <tr class="row">
    <td><span class="test">Hello</span>
      <table>
        <tr>
          <td><a class="button" href="#">Button 1</a></td>
        </tr>
      </table>
    </td>
  </tr>
</table>

jQuery

$(document).ready(function() {
  $('.button').on('click', function(e) {
    console.log($(this).closest('.row').find('.test').text());
    e.preventDefault();
  });
});

Fiddle for you to play around.

EDIT:

To clarify here's what filter() does:

Reduce the set of matched elements to those that match the selector or pass the function's test.

So in you original code - your matched element is the .row element. You're trying to reduce that to elements that has test as a class as well.

Upvotes: 3

Related Questions