0

I have this sample HTML,

<ul id=1>
    <li>
        <select class='test1'>test1</select>
    </li>
    <li>
         <select class='test222'>test222</select>
    </li>
    <li>
        <ul>
           <li>
              <select class='test222'>test222</select>
           </li>
        </ul>        
    </li>
    <li>
        <select class='test3'>test3</select>
    </li>
</ul>
<ul id=2>
    <li>
        <select class='test11'>test11</select>
    </li>
    <li>
        <select class='test12'>test13</select>
    </li>
    <li>
        <select class='test13'>test13</select>
    </li>
</ul>

Now I have a javascript variable

var $cursor = $("ul#1"); // this variable is dynamic; This cannot be modified

My goal is how do I check if specific path exists?

I want to check if this path exists,

$cursor > li > ul > li > select.test222

Not this one,

$cursor > li > select.test222

I am getting error when doing this

$($cursor+" > li > ul > li select.test222");

Thank You,

apelidoko
  • 782
  • 1
  • 7
  • 23
  • 1
    What error are you getting? and you are missing `" "` around your ids' – Stender Oct 29 '20 at 07:52
  • Uncaught Error: Syntax error, unrecognized expression: [object Object] > ul > li select.test222 – apelidoko Oct 29 '20 at 07:55
  • 1
    `if ($('> li > ul > li select.test222', $cursor).length) { alert('exists!'); }`. [JSFiddle](https://jsfiddle.net/dont_panic/t86p297w/) – Don't Panic Oct 29 '20 at 08:21
  • @Don'tPanic can you post this as an answer? I keep forgetting you can change the target of a lookup - the second parameter is so rarely used. – VLAZ Oct 29 '20 at 08:23
  • @VLAZ Sure, done. The question is really a dup IMO but I guess it combines 2 common questions, so might be useful in future. – Don't Panic Oct 29 '20 at 08:33

3 Answers3

3

You can use selector context to target a selector to search another selector, instead of the document root. So in this case, we can do:

var $selector = $('> li > ul > li select.test222', $cursor);

And then it is just a matter of using the standard way to check if that selector exists:

if ($selector.length) {
    // Your specific selector path exists
    // ...
}

Working JSFiddle.

Don't Panic
  • 13,965
  • 5
  • 32
  • 51
0

Seems like you are getting $cursor as an element, where you actually just want the id

I added some variables to get the attribute, and use it in your selector, and check the length of the object.

If the object has length, then it exists.

var cursor = $("ul#1"); // this variable is dynamic; This cannot be modified
var id = cursor.attr('id');
var elementToCheck = $("#"+id+" > li > ul > li select.test222").length;
if(elementToCheck){
  console.log('element exists');
} else {
  console.log('element does not exists');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id=1>
    <li>
        <select class='test1'>test1</select>
    </li>
    <li>
         <select class='test222'>test222</select>
    </li>
    <li>
        <ul>
           <li>
              <select class='test222'>test222</select>
           </li>
        </ul>        
    </li>
    <li>
        <select class='test3'>test3</select>
    </li>
</ul>
<ul id=2>
    <li>
        <select class='test11'>test11</select>
    </li>
    <li>
        <select class='test12'>test13</select>
    </li>
    <li>
        <select class='test13'>test13</select>
    </li>
</ul>
Stender
  • 2,446
  • 1
  • 14
  • 22
  • This will not work if the `$cursor` element doesn't have an ID. – VLAZ Oct 29 '20 at 08:11
  • @VLAZ if the cursor element, does not have an id, then the path does not exist and it will return false, which was what the question was about. – Stender Oct 29 '20 at 09:32
  • I mean if the cursor element was defined as `$cursor = $('ul.first')` which presumably matches a single element. And that element doesn't have an ID. – VLAZ Oct 29 '20 at 09:39
  • @VLAZ true, but then it would also mean that the path requested does not exists, since it does not contain the ID - furthermore, the $cursor variable could not be modified according to the OP, and looking at the structure, I would say that it is safe to assume that the section he is working with will always have an ID - If this is (for example) a for loop, then why would the UL suddenly be missing an ID? – Stender Oct 29 '20 at 10:00
  • But you are right - if the structure of the data suddently changes to not have an id, then it would always return false. but `$cursor = $('ul.first')` would not brake it if the ul still has an id. – Stender Oct 29 '20 at 10:02
  • According to OP, the `$cursor` variable is dynamically generated, so it might technically be made to match any element, not only specifically `ul#1`. – VLAZ Oct 29 '20 at 10:02
  • @VLAZ, that depends on how it is generated - if this is generated to always pick one of the ULs, then it is fine. What other element on the page would have that same path generated - seems unlikly and unlogical to have another element on the page, which also contains the path `> li > ul > li select.test222` – Stender Oct 29 '20 at 10:07
  • If the structure of the `
      `s changes, then they could definitely have
    – VLAZ Oct 29 '20 at 10:11
  • if the structure changes, then the path doesn't exists.... – Stender Oct 29 '20 at 10:13
  • But it should. Structure changes so the `
      `s don't have an ID and the `$cursor` changes to still target the correct element. The expanded selector could still match.
    – VLAZ Oct 29 '20 at 10:15
0

You need to programmatically traverse the tree using jQuery by using $.children:

var $cursor = $("ul#1"); // this variable is dynamic; This cannot be modified

//$cursor > li > ul > li > select.test222
var elements = $cursor
  .children("li")
  .children("ul")
  .children("li")
  .children("select.test222");
  
console.log("$cursor > li > ul > li > select.test222 exists:", elements.length > 0);

//$cursor > li > ul > li > select.test333
var elements2= $cursor
  .children("li")
  .children("ul")
  .children("li")
  .children("select.test333");
  
console.log("$cursor > li > ul > li > select.test333 exists:", elements2.length > 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id=1>
    <li>
        <select class='test1'>test1</select>
    </li>
    <li>
         <select class='test222'>test222</select>
    </li>
    <li>
        <ul>
           <li>
              <select class='test222'>test222</select>
           </li>
        </ul>        
    </li>
    <li>
        <select class='test3'>test3</select>
    </li>
</ul>
<ul id=2>
    <li>
        <select class='test11'>test11</select>
    </li>
    <li>
        <select class='test12'>test13</select>
    </li>
    <li>
        <select class='test13'>test13</select>
    </li>
</ul>

Here is what happens when the route isn't matched:

var $cursor = $("ul#1"); // this variable is dynamic; This cannot be modified

//$cursor > li > ul > li > select.test222
var elements = $cursor
  .children("li")
  .children("ul")
  .children("li")
  .children("select.test222");
  
console.log("$cursor > li > ul > li > select.test222 exists:", elements.length > 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id=1>
    <li>
        <select class='test1'>test1</select>
    </li>
    <li>
         <select class='test222'>test222</select>
    </li>
    <li>
        <ul>
           <li>
              
           </li>
        </ul>        
    </li>
    <li>
        <select class='test3'>test3</select>
    </li>
</ul>
<ul id=2>
    <li>
        <select class='test11'>test11</select>
    </li>
    <li>
        <select class='test12'>test13</select>
    </li>
    <li>
        <select class='test13'>test13</select>
    </li>
</ul>

You could also use $.find and give it a selector, however, it matches any subtree, not anything that starts from the current element. So, it can work:

var $cursor = $("ul#1"); // this variable is dynamic; This cannot be modified

//$cursor > li > ul > li > select.test222
var elements = $cursor
  .find("li > ul > li > select.test222");
  
console.log("$cursor > li > ul > li > select.test222 exists:", elements.length > 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id=1>
    <li>
        <select class='test1'>test1</select>
    </li>
    <li>
         <select class='test222'>test222</select>
    </li>
    <li>
        <ul>
           <li>
              <select class='test222'>test222</select>
           </li>
        </ul>        
    </li>
    <li>
        <select class='test3'>test3</select>
    </li>
</ul>
<ul id=2>
    <li>
        <select class='test11'>test11</select>
    </li>
    <li>
        <select class='test12'>test13</select>
    </li>
    <li>
        <select class='test13'>test13</select>
    </li>
</ul>

Beware that it might produce a false positive if you only expect these to be the children of the current element:

var $cursor = $("ul#1"); // this variable is dynamic; This cannot be modified

//$cursor > li > ul > li > select.test222
var elements = $cursor
  .find("li > ul > li > select.test222");
  
console.log("$cursor > li > ul > li > select.test222 exists:", elements.length > 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id=1>
    <li>
        <select class='test1'>test1</select>
    </li>
    <li>
         <select class='test222'>test222</select>
    </li>
    <div> <!-- extra element, so now it's not a direct child of ul#1 -->
      <li>
          <ul>
             <li>
                <select class='test222'>test222</select>
             </li>
          </ul>        
      </li>
    </div>
    <li>
        <select class='test3'>test3</select>
    </li>
</ul>
<ul id=2>
    <li>
        <select class='test11'>test11</select>
    </li>
    <li>
        <select class='test12'>test13</select>
    </li>
    <li>
        <select class='test13'>test13</select>
    </li>
</ul>
VLAZ
  • 26,331
  • 9
  • 49
  • 67