1

Suppose I have such a structure:

<div id="content">
    <div>
        <span>
            <b>
                <i>
                    <u>
                        <span>Price</span>
                    </u>
                </i>
            </b>
        </span>
    </div>
</div>

In this case, the number of tags inside the div #content and which ones they don't know me. I only have access to the id content.

How do I get the selector to the latest span which contains the text Price?

p.s. lastChild method returns the last child within the selected selector, but not deeper!

Mohammad
  • 21,175
  • 15
  • 55
  • 84
Dmitry
  • 45
  • 7

4 Answers4

2

Select all children of #content using * selector and use .filter() to filtering element. In callback filter elements hasn't any child.

$("#content *").filter(function(){
  return $("*", this).length == 0;
});
// Or using ES6
$("#content *").filter((i,v) => $("*", v).length == 0);

var ele = $("#content *").filter((i,v) => $("*", v).length == 0);
console.log(ele[0].outerHTML);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="content">
    <div>
        <span>
            <b>
                <i>
                    <u>
                        <span>Price</span>
                    </u>
                </i>
            </b>
        </span>
    </div>
</div>
Mohammad
  • 21,175
  • 15
  • 55
  • 84
0

You can use .find(): https://api.jquery.com/find/

This will recursively look for your selector, so: $('#content').find('span') will give you two spans, one for the first nested span and one for the second nested span. The downside is that if you have multiple spans you'll need to find the right one.

If you can put an identifier in the last one, say a class named 'target-class', than you know you'll find the right one: $('#content').find('span.target-class');

Kai
  • 1,156
  • 8
  • 18
0

First of all let's fix your syntax. You can't put an <span> directly within a <u>. You need a <li> node. Also you can't/shouldn't put block elements such as ul within inline elements (span, a, b, i...). And even <b> and <i> are not recommended, better use semantic markup such as <strong> or <em> instead.

Now your problem. I think you don't have to care about being the last node. If you know the text contained is "Price" you can look for it in the following way:

var selector = $('#content').find(":contains('Price')");
$(selector).addClass('highlighted');
.highlighted {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="content">
    <div>
        <u>
          <li>
              <span>Price</span>
          </li>
        </u>
    </div>
</div>

If this solution does not fits your needs, to get the last node you have to get all of them an check if they have children or not. Once they don't, you've reached your target. But I have to say that this is a solution you could have found in SO. Select deepest child in jQuery

Daniel Abril
  • 418
  • 3
  • 11
  • 1. Tags I entered arbitrarily for example 2. I do not know the text inside the tags, it can be any. My task is to replace text and save somewhere the whole tag chain. – Dmitry May 14 '19 at 12:47
  • Good, but think that we are going to use your code to solve your problem. Syntax error can cause the code to break. You should take care of syntax to save us time fixing it. That's all. Hope you understand. – Daniel Abril May 14 '19 at 12:51
  • 2. That's why I gave you two answers. – Daniel Abril May 14 '19 at 12:57
  • Yes, thanks for the comment, I will consider the syntax errors next time. – Dmitry May 14 '19 at 13:06
0

Jquery Way - You could target all spans $() and target the latest span using slice() method.

$('#content span').slice(-1)[0];

Javascript way - Find all spans using querySelectorAll(), You'd get a NodeArray, you can convert it to Array using Array.from() and slice() last item from it which is latest span.

Array.from(document.querySelectorAll('#content span')).slice(-1)[0]