CMS Development

lgriffee
Participante

JavaScript affecting multiple instances of a module on landing page

resolver

I'm trying to code a generic horizontal scroll module that ideally would be used several times on a landing page with the ability to add different content to each instance of the module. 

 

The issue I've run into is that when there are multiple instances of this module on one page they all trigger each other. Since the class/variable names of each instance of the module are the same, when you click the button to scroll one of them it scrolls all of them (see example here).

 

Is it possible to somehow add unique class identifiers for each instance of the module in both HTML/HubL and JavaScript? I've looked into using the {{name}} HubL token to leverage the unique module name but can't figure out a way I could possibly reference this in JavaScript.   

 

I have been able to get the functionality I want by creating two separate modules with different class names and JS variable names (example on this page) but was hoping there might be a way to do this for a generic module that you could easily add different content to it?

 

HTML:

<div class="horizontal-scroll-grid">
  <button class="horizontal-scroll-grid__left-button">
      <i class="horizontal-scroll-grid__button__icon fa fa-chevron-left" role="img" aria-label="Previous" focusable="false"></i>
  </button>
  
  <button class="horizontal-scroll-grid__right-button">
      <i class="horizontal-scroll-grid__button__icon fa fa-chevron-right" role="img" aria-label="Next" focusable="false"></i>
  </button>
  
  <ul class="horizontal-scroll-grid__scroll-grid">
    {% for item in module.scroll_item %}
      <li class="horizontal-scroll-grid__scroll-grid__item" style="background-image: url('{{ item.image.src }}');">
        <a class="horizontal-scroll-grid__scroll-grid__item__link" href="{{ item.link_url }}" alt="Learn more about {{ item.title }}" target="_blank">
            <h4 class="horizontal-scroll-grid__scroll-grid__item__title">{{ item.title }}</h4>
          </a>
      </li>
    {% endfor %}
  </ul>
</div>

Javascript&colon;

/* ==========================================================================
   HORIZONTAL SCROLL GRID MODULE
   ========================================================================== */

$(document).ready(function(){
 
  /* Page Setup
   ========================================================================== */
  // Make sure left scroll button is hidden by default on desktop
  $('.horizontal-scroll-grid__left-button').hide();
  
/* Events
   ========================================================================== */
  var scrollDistance = parseInt($('.horizontal-scroll-grid__scroll-grid__item').width()) + 
                         parseInt($('.horizontal-scroll-grid__scroll-grid').css('grid-column-gap').replace(/[^-\d\.]/g, ''));
  var maxScrollPosition = ($('.horizontal-scroll-grid__scroll-grid li').length - 2);
  var scrollPosition = 0; 
  
  // Handle content scrolling when left button clicked
  $('.horizontal-scroll-grid__left-button').click(function() { 
    event.preventDefault();
    $('.horizontal-scroll-grid__scroll-grid').animate({ scrollLeft: "-=" + scrollDistance + "px" });
    
    scrollPosition--; 
    
    // Hide the left button when there is no more content to scroll, otherwise show
    if (scrollPosition == 0){
      $('.horizontal-scroll-grid__left-button').hide();
    }else if (scrollPosition > 0 && scrollPosition < maxScrollPosition){
      $('.horizontal-scroll-grid__left-button').show();
      $('.horizontal-scroll-grid__right-button').show();
    }
   });
  
  // Handle content scrolling when right button clicked
  $('.horizontal-scroll-grid__right-button').click(function() {
    event.preventDefault();
    $('.horizontal-scroll-grid__scroll-grid').animate({ scrollLeft: "+=" + scrollDistance + "px" });
    
    scrollPosition++; 
    
    // Hide the right button when there is no more content to scroll, otherwise show
    if (scrollPosition == maxScrollPosition){
      $('.horizontal-scroll-grid__right-button').hide();
    }else if (scrollPosition > 0 && scrollPosition < maxScrollPosition){
      $('.horizontal-scroll-grid__left-button').show();
      $('.horizontal-scroll-grid__right-button').show();
    }
  });
  
  // Reset grid when window is resized 
  $(window).resize(function() {
     scrollPosition = 0; 
    scrollDistance = parseInt($('.horizontal-scroll-grid__scroll-grid__item').width()) + 
                       parseInt($('.horizontal-scroll-grid__scroll-grid').css('grid-column-gap').replace(/[^-\d\.]/g, ''));
    
    $('.horizontal-scroll-grid__scroll-grid').scrollLeft(0);
   
    if ($(window).width() < 1024){
      $('.horizontal-scroll-grid__left-button').hide();
      $('.horizontal-scroll-grid__right-button').hide();
    }else{
      $('.horizontal-scroll-grid__left-button').hide();
      $('.horizontal-scroll-grid__right-button').show();
    }
  });
}); 

  

0 Avaliação positiva
1 Solução aceita
Stephanie-OG
Solução
Conselheiro(a) de destaque

JavaScript affecting multiple instances of a module on landing page

resolver

Hey!

 

What I often do in these cases is use {{ mid }} to generate a unique ID for that instance of that module (check out this workaround) and then use that in my JavaScript.

 

You could either pull it in your script by adding the ID to a data attribute or you can add some of your script to <script> tags in the HTML using require_js so that you can access the HubL there. 

 

I hope that helps!

 


Stephanie O'Gay Garcia

HubSpot Design / Development

Website | Contact

 

If this helped, please mark it as the solution to your question, thanks!

Exibir solução no post original

3 Respostas 3
sylvain_pref
Colaborador(a) | Parceiro
Colaborador(a) | Parceiro

JavaScript affecting multiple instances of a module on landing page

resolver

Hi,

 

I've been doing this for a year or two. If I understand correctly the point here, you can do that:

 

<div id="my_prefix_id_{{ name }}">Stuff</div>

<style>
#my_prefix_id_{{ name }} {
   color: purple;
}
</style>

<script>
document.getElementById('my_prefix_id_{{ name }}').style.color = "purple";
</script>

 

Here, the code is visible in the source of your page. But if you want the code to appear in its respective files, do this:

 

<div id="my_prefix_id_{{ name }}">Stuff</div>

{% require_css %}
<style>
#my_prefix_id_{{ name }} {
   color: purple;
}
</style>
{% end_require_css %}

{% require_js %}
<script>
// You can use this value in a global js script.
let my_id = 'my_prefix_id_{{ name }}';
</script>
{% end_require_js %}

 

By doing this, you have a unique id for each instance of your module on the same page (add several times the module on a page, and you'll see each id will be unique), but the code of your module is unique too.

0 Avaliação positiva
Stephanie-OG
Solução
Conselheiro(a) de destaque

JavaScript affecting multiple instances of a module on landing page

resolver

Hey!

 

What I often do in these cases is use {{ mid }} to generate a unique ID for that instance of that module (check out this workaround) and then use that in my JavaScript.

 

You could either pull it in your script by adding the ID to a data attribute or you can add some of your script to <script> tags in the HTML using require_js so that you can access the HubL there. 

 

I hope that helps!

 


Stephanie O'Gay Garcia

HubSpot Design / Development

Website | Contact

 

If this helped, please mark it as the solution to your question, thanks!

lgriffee
Participante

JavaScript affecting multiple instances of a module on landing page

resolver

Thanks so much, Stephanie! This looks like exactly what I need. 

0 Avaliação positiva