R. Srour
R. Srour

Reputation: 160

Javascript style not overwriting css

I have a simple HTML drawer that contains product recommendations. Javascript is used to toggle it open and close. In the HTML, there are 2 prices, the regular price and the discounted price. Both are visible on load. The JS is supposed to hide the discounted price(current price), if the current price is the same as the old price. Because then it's not necessary to show both(identical prices). But if there is an offer, it's supposed to show both.

The problem is, my javascript for opening and closing the drawer is working, but the code for hiding/showing both prices aren't. And I know the code is fine because it works on another product recommendation template I'm using(which isn't a drawer, but normal on-page element).

I've tried putting the price-code before the drawer-function code, but then the drawer doesn't respond to clicks and does not open anymore. When I use Preview in the software I'm using to inject product recommendations(Dynamic Yield), the prices are shown correctly. It's only when I preview it on the website itself, that it doesn't work. Both prices are shown even if they match.

Here is the JS:

(function() {
    var container = document.querySelectorAll('.dy-sliding-drawer-container')[0];
  var handler = container.querySelector('.dy-sliding-handle');
  function toggle() {
    if (container.className.indexOf('dy-open') > -1) {
      container.className = container.className.replace('dy-open','');
    } else {
      container.className = container.className.trim() + ' dy-open';
    }
  }
  handler.addEventListener('click', function(e) {
    e.preventDefault();
    e.stopPropagation();
    toggle();
  });
})();

var mq = window.matchMedia( "(max-width: 599px)" );
var itemPrices = document.querySelectorAll('.price-box');
for(var i=0; i<itemPrices.length; i++){

   var discount_price_element = itemPrices[i].getElementsByClassName("dynamic-price")[0];
   var price_element = itemPrices[i].getElementsByClassName("regular-price")[0];
   
   if(parseFloat(discount_price_element.innerHTML) == parseFloat(price_element.innerHTML)){
     discount_price_element.style.display = "none";
     
    if (mq.matches) {
    price_element.style.fontSize = "16px";
    price_element.style.paddingTop = "15px";
      } else {
    price_element.style.fontSize = "20px";
    }
    
     price_element.style.fontWeight = "700";
   } else {
     price_element.style.textDecoration = "line-through";
     price_element.style.paddingLeft = "10px";
   }
}

Is there anything I can do to make both codes work together? I've tried putting them in the same function, with no luck.

Here is the HTML(I guess the only relevant code here is the .price-box div, but I'm gonna paste everything in case you need it):

<div>
  <div class="dy-sliding-drawer-container" data-dy-strategy-container="">
    <div class="dy-sliding-handle">
      <div class="dy-sliding-handle-text">
        ${Title}
      </div>
    </div>

    <div class="dy-sliding-items-container dy-open">
      ${#Recommendation}
      <a href="${Item Link}" class="dy-rv-rcom-item">
        <div class="dy-rv-rcom-item-image-container item-${SKU}" style="  background-image: url(${Item Image}); background-size: cover;
            -webkit-background-size: cover;
            -moz-background-size: cover; 
            -o-background-size: cover;min-height: 50px;
  min-width: 50px;">
        </div>
        <div class="dy-rv-rcom-item-name">${Item Name}</div>
        <div class="dy-rv-rcom-item-price">
          <div class="price-box">
            <span class="dynamic-price">${product_price_dynamic},-</span>
            <span class="regular-price">${price},-</span>
          </div>
        </div>

        <!-- button -->
        <div class="product-item-actions add-to-cart-button-dy">
          <div class="actions-primary">
            <form data-role="tocart-form" action="https://www.norli.no/checkout/cart/add/uenc/${uenc}/product/${product_id}/" method="post">
              <input type="hidden" name="product" value="${product_id}" tabindex="0">
              <input type="hidden" name="uenc" value="${uenc}" tabindex="0">
              <input name="form_key" type="hidden" value="${formkey}" tabindex="0">
              <button type="submit" title="Handlekurv" class="action tocart primary" tabindex="0">
                <span class="tocart--short">Legg til</span>
              </button>
            </form>
          </div>
        </div>
        <div class="product actions product-item-actions read-more-button-dy" style="display: none !important;">
          <div class="actions-primary">
            <div class="fieldset">
              <div class="actions">
                <span class="out-of-stock-view-more lesmer-button" style="color:#FFF; display: none !important;">Les mer</span>
              </div>
            </div>
          </div>
        </div>
        <!-- button end -->
        
      </a>
      ${/Recommendation}
    </div>
  </div>
</div>

And if the CSS is needed, heres is the CSS for the relevant classes(old price and new price:

.price-box{
  display: flex;
  align-items: flex-end;
}

.dynamic-price{
  color:#dd1768;
  font-size:18px;
  font-weight:700;
  letter-spacing:-1.5px !important;
  padding-bottom:0px !important;
  margin-bottom:0px !important;
}

.regular-price{
  font-size:14px;
  letter-spacing:-1px !important;
  padding-bottom:0px !important;
  margin-bottom:0px !important;
  font-weight: 400;
}

Could anybody help me out? Keep in mind that the Javascript works fine for recommendation widgets which loads on-page, but not with this click-to-open drawer. Appreciate any help.

Upvotes: 0

Views: 80

Answers (1)

Carsten Massmann
Carsten Massmann

Reputation: 28236

Your script does basically work - provided the variables in your template have been replaced by actual values before the markup is rendered into the DOM. I have modified your data a little bit to demonstrate the correct behaviour on some same-price and some differing-price .price-box examples.

I also took the liberty of shortening your very verbose scripts. I have probably gone a bit too far, especially my .reduce() construct is not easy to read. But look at it as an extreme way of avoiding creating variable names.

(function(){
  var container = document.querySelector('.dy-sliding-drawer-container');
  container.querySelector('.dy-sliding-handle').onclick=e=>
   container.classList.toggle("dy-open");
})();

// var mq = window.matchMedia( "(max-width: 599px)" );
document.querySelectorAll('.price-box').forEach(p=>{
 [...p.querySelectorAll("span")].reduce((a,c)=>a.style.display=(a.textContent==c.textContent?"none":""))});
.dy-open {background-color:yellow}
.price-box{
  display: flex;
  align-items: flex-end;
}

.dynamic-price{
  color:#dd1768;
  font-size:18px;
  font-weight:700;
  letter-spacing:-1.5px !important;
  padding-bottom:0px !important;
  margin-bottom:0px !important;
}

.regular-price{
  font-size:14px;
  letter-spacing:-1px !important;
  padding-bottom:0px !important;
  margin-bottom:0px !important;
  font-weight: 400;
}
<div>
  <div class="dy-sliding-drawer-container" data-dy-strategy-container="">
<div class="dy-sliding-handle">
  <div class="dy-sliding-handle-text">
    ${Title}
  </div>
</div>

<div class="dy-sliding-items-container">
  ${#Recommendation}
  <a href="#${Item Link}" class="dy-rv-rcom-item">
    <div class="dy-rv-rcom-item-image-container item-${SKU}" style="  background-image: url(${Item Image}); background-size: cover;
        -webkit-background-size: cover;
        -moz-background-size: cover; 
        -o-background-size: cover;min-height: 50px;
  min-width: 50px;">
    </div>
    <div class="dy-rv-rcom-item-name">${Item Name}</div>
    <div class="dy-rv-rcom-item-price">
      <div class="price-box">
        <span class="dynamic-price">50,-</span>
        <span class="regular-price">50,-</span>
      </div>
    </div>
    <div class="dy-rv-rcom-item-name">${Item Name}</div>
    <div class="dy-rv-rcom-item-price">
      <div class="price-box">
       <span class="dynamic-price">50,-</span>
       <span class="regular-price">60,-</span>
      </div>
    </div>
    <div class="dy-rv-rcom-item-name">${Item Name}</div>
    <div class="dy-rv-rcom-item-price">
      <div class="price-box">
       <span class="dynamic-price">60,-</span>
       <span class="regular-price">60,-</span>
      </div>
    </div>
    <!-- button -->
    <div class="product-item-actions add-to-cart-button-dy">
      <div class="actions-primary">
        <form data-role="tocart-form" action="https://www.norli.no/checkout/cart/add/uenc/${uenc}/product/${product_id}/" method="post">
          <input type="hidden" name="product" value="${product_id}" tabindex="0">
          <input type="hidden" name="uenc" value="${uenc}" tabindex="0">
          <input name="form_key" type="hidden" value="${formkey}" tabindex="0">
          <button type="submit" title="Handlekurv" class="action tocart primary" tabindex="0">
            <span class="tocart--short">Legg til</span>
          </button>
        </form>
      </div>
    </div>
    <div class="product actions product-item-actions read-more-button-dy" style="display: none !important;">
      <div class="actions-primary">
        <div class="fieldset">
          <div class="actions">
            <span class="out-of-stock-view-more lesmer-button" style="color:#FFF; display: none !important;">Les mer</span>
          </div>
        </div>
      </div>
    </div>
    <!-- button end -->
    
  </a>
  ${/Recommendation}
</div>
  </div>
</div>

Explanation:

The .reduce() over all the <span>s in a .price-box div relies on the fact that the "reduced price" span always comes before the "regular price" one and that you will always have exactly two elements. When reduce() is called without the second (starting value) argument it takes the first array element (the "reduced price" span) as the starting value (a). The (only) "current" value in the iteration (c) will then be the regular price span. When the .textContent of both elements are the same the a span will be hidden, otherwise it will remain visible.

Upvotes: 1

Related Questions