1

Hi what I'm trying to do is run a campaign where all products on the site will have a sale banner. Some products will already have a sale banner, but for the rest of the products that don't then i want to add a banner to these. I've been able to do this, but the issue i'm having is, if a product is Out of Stock then i don't want the sale banner to be added to these products.

I've created a snippet trying to show what i've got so far.

  • Product 1 is a product that already has a sale banner.
  • Product 2 is a product that doesn't have a sale banner
  • Product 3 is a product that doesn't have a sale banner and is out of stock

Product 1 has a sale banner so nothing needs to be done to this. For Product 2 i want the sale banner to be added & for Product 3 i don't want a sale banner to be added as it is out of stock.

Any help on this would be much appreciated.

$(".saleWrapper").each(function(index){
  if ($(this).children('.promoText').length === 0){
    $(this).append("<span class='promoText'>I'm ALSO on Sale</span>");
  }
})
.product-wrapper {
  display: inline-block;
  border: 1px solid black;
}
.promoText {background: red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="product-wrapper">
<p>Product 1</p>
  <div class="saleWrapper">
      <span class="promoText">I'm on Sale</span>
  </div>
</div>

<div class="product-wrapper">
<p>Product 2</p>
  <div class="saleWrapper"></div>
</div>

<div class="product-wrapper">
<p>Product 3</p>
  <div class="saleWrapper"></div>
  <div class="productOutOfStock">
    <p class="outOfStock">I'm Out Of Stock</p>
  </div>
</div>
leek1234
  • 470
  • 2
  • 9
  • Go the other way: `$(".product-slab__cta").closest(".product-slab__wrapper").find(".product-slab__markdown-promotion").append("ADD MESSAGE");` – freedomn-m Mar 22 '21 at 16:27
  • @freedomn-m I've completely reworded my question and updated my code as well, hope this makes more sense – leek1234 Mar 22 '21 at 19:29
  • There was nothing wrong with how the title/code was (the question text was a little confusing, but the comment clarified this - don't know why you got a downvote) – freedomn-m Mar 22 '21 at 19:32
  • Here's a related question asking for "select X unless it has a sibling Y" (not sibling) - there's no selector for this, but there are work arounds. https://stackoverflow.com/questions/7866784/css-no-sibling-selector#:~:text=3%20Answers&text=There%20is%20no%20sibling%20selector,(or%20not)%20by%20class.&text=But%20this%20selector%20means%20that,regardless%20of%20type%20or%20class. – freedomn-m Mar 22 '21 at 19:41
  • @freedomn-m Thanks for your help on this and for your explanations, works great thank you! – leek1234 Mar 23 '21 at 08:11
  • Sorry one last question @freedomn-m is there also a way to include another rule where if the href contains the string "bundle" in the url to exclude this product as well. So the code would look similar to this: – leek1234 Mar 23 '21 at 08:41
  • You'll probably be better going to back to a `.each()` and applying multiple, *separate* `if` statements within that (or use `.filter()`). Adding much more to the selector will make it unmaintainable. – freedomn-m Mar 23 '21 at 08:47

1 Answers1

2

The updated / reworded question is essentially the same and has the same problem.

Section 3's "out of stock" message is not a child of .saleWrapper - so you can't (easily) start at saleWrapper.

Instead, start at the product-wrapper, find the products that match, then locate the place to add the message. See the original answer below for more details.

$(".product-wrapper:not(:has(.promoText,.productOutOfStock))")
    .find(".saleWrapper")
    .append("<span class='promoText'>I'm ALSO on Sale</span>");
.product-wrapper {
  display: inline-block;
  border: 1px solid black;
}
.promoText {background: pink;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="product-wrapper">
<p>Product 1</p>
  <div class="saleWrapper">
      <span class="promoText">I'm on Sale</span>
  </div>
</div>

<hr/>

<div class="product-wrapper">
<p>Product 2</p>
  <div class="saleWrapper"></div>
</div>

<hr/>

<div class="product-wrapper">
<p>Product 3</p>
  <div class="saleWrapper"></div>
  <div class="productOutOfStock">
    <p class="outOfStock">I'm Out Of Stock</p>
  </div>
</div>

Edit: answer to original question

print the message on any products that don't have a sale banner i.e the second product only in this example

Within the :has() you can put any selector, in this case, you want the , selector (or).

:has(.product-slab__markdown-promotion-inner,.product-slab__cta)

However, your __cta is not inside the current product-slab__markdown-promotion so you have to start a level up at product-slab__wrapper - then once you have the correct __wrapper(s) you can then move back down into the location where you want to add the message, using .find().

You can also remove the .each() as jquery already operates on collections

Giving:

$(".product-slab__wrapper:not(:has(.product-slab__markdown-promotion-inner,.product-slab__cta))")
    .find(".product-slab__markdown-promotion")
    .append("<span class='product-slab__markdown-promotion-inner'><span class='promo-text'>ADD MESSAGE</span></span>");
.product-slab__wrapper {
  display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="product-slab__wrapper">
  <div class="product-slab__markdown-promotion">
    <div class="product-slab__markdown-promotion-inner">
      <span class="promo-text">20% discount</span>
    </div>
  </div>
  <div class="product-slab__stock"></div>
  <p>€0,00</p>
</div>

<hr/>
<div class="product-slab__wrapper">
  <div class="product-slab__markdown-promotion">
  </div>
  <div class="product-slab__stock"></div>
  <p>€0,00</p>
</div>

<hr/>


<div class="product-slab__wrapper">
  <div class="product-slab__markdown-promotion"></div>
  <div class="product-slab__stock"><p class="btn btn__secondary btn__disabled product-slab__cta btn--full" disabled="">Out of stock</p></div>
  <p>€0,00</p>
</div>
freedomn-m
  • 27,664
  • 8
  • 35
  • 57