简体   繁体   中英

How to check if there's an element inside another element with JavaScript

The main idea is: I have a list of beverage in a div and I'd like to check if the beverages are out of stock or not , and click the first drink available in stock. It needs to be in JavaScript (without JQuery)

The elements are in this hierarchy :

Main div containing all the drinks: class="ob-menu-items__items"

Each drink will be in a H4 class="ob-menu-item__title"

If the product is out of stock there will be a span class="ob-menu-item__out-of-stock" with the text " - Out of Stock"

So far I try this (and got stuck):

for (var i = 0; i < 7; i++) {
    // iterating over each drink.
    var drink = document.getElementsByClassName("ob-menu-item__title")[i];
    if (document.getElementsByClassName(".ob-menu-item__out-of-stock").parents(drink).length == 1) {
        // There's out of stock text
        // Do nothing and go to the next drink 
    } else {
        //The product is available. Clik the drink and exit the loop
        document.getElementsByClassName("ob-menu-item__title")[i].click();
        break;
    }
} 

Thanks!

Replace your if condition as below and it will work as expected. It will find elements inside drinks which has class ob-menu-item__out-of-stock .

if (drink.getElementsByClassName("ob-menu-item__out-of-stock").length > 0)

Please refer this answer which says .getElementsByClassName("home")[0] should not be used. You can alternatively use .querySelectorAll() like below. Replace getElementsByClassName with querySelectorAll and pass class name with class selector (.) . So document.getElementsByClassName("ob-menu-item__title")[i] will be replaced with document.querySelectorAll(".ob-menu-item__title")[i] .

To find elements inside selected element you can use element.querySelectorAll which is done inside if with drink.querySelectorAll(".ob-menu-item__out-of-stock").length

for (var i = 0; i < 7; i++) {
    // iterating over each drink.
    var drink = document.querySelectorAll(".ob-menu-item__title")[i];
    if (drink.querySelectorAll(".ob-menu-item__out-of-stock").length > 0) {
        // There's out of stock text
        // Do nothing and go to the next drink 
    } else {
        //The product is available. Clik the drink and exit the loop
        drink.click();
        break;
    }
}

Try it below.

 // get all drink var drinks = document.querySelectorAll(".ob-menu-item__title"); // iterating over each drink. for (var i = 0; i < drinks.length; i++) { let drink = drinks[i]; if (drink.querySelectorAll(".ob-menu-item__out-of-stock").length > 0) { console.log('out of stock. i = ' + i); // There's out of stock text // Do nothing and go to the next drink } else { //The product is available. Clik the drink and exit the loop console.log('In stock. i = ' + i); drink.click(); break; } }
 <div class='ob-menu-items__items'> <h4 class='ob-menu-item__title'> item0<span class='ob-menu-item__out-of-stock'> - Out of stock</span> </h4> <h4 class='ob-menu-item__title'> item4<span class='ob-menu-item__out-of-stock'> - Out of stock</span> </h4> <h4 class='ob-menu-item__title'> item2<span class='ob-menu-item__out-of-stock'> - Out of stock</span> </h4> <h4 class='ob-menu-item__title'> item3 </h4> <h4 class='ob-menu-item__title'> item4 </h4> <h4 class='ob-menu-item__title'> item5 </h4> <h4 class='ob-menu-item__title'> item6 </h4> </div>

You could use childElementCount to find how many items there are. See https://www.w3schools.com/jsref/prop_element_childelementcount.asp

for (var i = 0; i < 7; i++) {
    var drink = document.getElementsByClassName("ob-menu-item__title")[i];
    if (document.getElementsByClassName.("ob-menu-item__out-of-stock").parents(drink).length == 1) {
        // There's out of stock text
        // Do nothing and go to the next drink 
    } else {
        //The product is available. Clik the drink and exit the loop
        document.getElementsByClassName("ob-menu-item__title")[i].click();
        break;
    }
}

The hard-coded 7 in the for loop initialization doesn't look good. You can just find all the drinks by document.querySelectorAll and then find the one to click by checking for the span in each of them.

ES6 one-liner:

[...document.querySelectorAll('.ob-menu-item__title')]
  .find( drink => !drink.querySelector('.ob-menu-item__out-of-stock') )
  .click()

What it does is: converts the querySelectorAll result into an Array, then uses Array.prototype.find method which returns the first element that satisfied the callback, and the call back in this case returns true if given element doesn't contain the "out of stock" span.

More "classic" JS:

var firstInStock = Array.from(document.querySelectorAll('.ob-menu-item__title'))
  .find( function(drink){
    if( drink.querySelector('.ob-menu-item__out-of-stock') ){
      return false;
    }
    return true;
  });
firstInStock.click()

Or if you really want a for loop:

var drinks = document.querySelectorAll('.ob-menu-item__title');
for(var i=0; i< drinks.length; i++){
   if( !drink.querySelector('.ob-menu-item__out-of-stock') ){
     drink.click();
     break;
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM