Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hopscotch tour step on dynamically generated content

I am implementing several of Hopscotch tours in my app.

So far I have managed to make many tours without any problem but today, I am facing a challenge I could not resolve far.

My question is: how do I get a tour step target to work on dynamically generated content?

Here is the HTML:

<div class="pacote-destino-quartos-wrapper">
    <div class="pacote-destino-quartos-internal-wrapper">
        <h4>Todos os Destinos</h4>
        <div class="dynamic_nested_form_wrapper quartos_external_wrapper" data-destino="todos">
            <span class="add-child-link-wrapper">
                <a href="javascript:void(0)" class="add_child btn btn-info" data-association="quartos">
                    <i class="icon-plus icon-white"></i>
                </a>
            </span>
        </div>
    </div>
</div>

Whenever I click the link it dynamically creates a div which contains many elements; one of them is a div with a class called .quarto-config-wrapper.

If I try to make my Hopscotch tour go to this element, it does not work; my guess the dynamically created elements are not available in the DOM for manipulation.

Here is my Hopscotch steps code:

{
    title: "Adicionar um novo quarto",
    content: "content here",
    target: $('.add-child-link-wrapper')[0],
    placement: "left",
    width: 500,
    yOffset: -15,
    nextOnTargetClick: true,
    showNextButton: false
},
{
    title: "Menu de configuração do quarto",
    content: "content here",
    target: $('.quarto-config-wrapper')[0],
    placement: "left",
    width: 700,
    yOffset: -15,
    nextOnTargetClick: true,
    showNextButton: false,
    delay: 1200
}

The first step works but the second does not.

What am I doing wrong and how can I fix it?

like image 792
Guido Avatar asked Mar 11 '14 14:03

Guido


Video Answer


2 Answers

I solved this problem by having the target of a step be a getter so it queries the dom for the target when it arrives at the step itself

{ get target() { return document.querySelector('#your-step-target'); }
like image 187
w0ps Avatar answered Sep 17 '22 13:09

w0ps


What I do to wait for AJAX calls is the following:

{
  title: "Title",
  content: "Content",
  target: '.triggerAjax',
  placement: 'bottom',
  onNext: function() {
    $('.triggerAjax').click();

    var checkExist = setInterval(function() {
      $element = $('.dynamicallyLoaded');

      if ($element.is(':visible')) {
        clearInterval(checkExist);

        window.hopscotch.startTour(window.hopscotch.getCurrTour(), window.hopscotch.getCurrStepNum());
      }
    }, 100);
  },
  multipage: true
},

Using multipage tells hopscotch to not continue. Then the onNext function checks if the element we want to target next is present and starts the tour again.

Of course, if you need this more often, extract it as a general function to keep your code clean and short.

like image 35
Luksurious Avatar answered Sep 17 '22 13:09

Luksurious