usablica / intro.js

Lightweight, user-friendly onboarding tour library
http://introjs.com
Other
22.8k stars 2.59k forks source link

onBeforeChange delay before next step #1600

Closed pg1671 closed 2 years ago

pg1671 commented 2 years ago

Description

When calling an onBeforeChange action sometimes the UI needs a short period to update.

Introjs will continue to the next step and the target of the step may not yet be in the correct position or created and the step will not display correctly.

Can we add a short delay delay after calling the onBeforeChange function or allow the user to define a custom delay.

This allows whatever action was taken in onBeforeChange to update the UI before the next step tries to use it.

Actual Behavior

Screen Shot 2022-03-03 at 8 01 24 am

The highlight should be around the new button which is inside a menu that must be clicked so the menu appears before the step runs.

In the image the highlight is at the top of the menu, probably where the button is positioned when it is hidden before the ui component moves it to its final position when displayed.

If I add an alert box in the onBeforeChange function that delays return the highlight is correctly around the button.

tgamauf commented 2 years ago

I have exactly the same problem - some of my pages render graphs using chart.js and it takes a few seconds until the data is loaded and the graph rendered.

I solved it for now by adding a general description of the page that isn't associated to any element as the first step.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

tgamauf commented 2 years ago

It‘s not stale, you just didn‘t respond …

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

tgamauf commented 2 years ago

Still not stale …

afshinm commented 2 years ago

Intro.js callback functions are now capable of understanding Promise objects. Would it be possible to use a Promise object in the onBeforeChange callback? That would allow you to add a short delay before the next step is rendered.

tgamauf commented 2 years ago

Thanks, that solves the issue for me!

LimpEmu commented 2 years ago

Is it possible to post an example for this feature beyond the syntax in the documentation ? I would like to start the tour, explain several features, then make a change to the page without exiting the tour, and continue the tour with the updated page. I cannot figure out how to set this up. Many thanks!

afshinm commented 2 years ago

@LimpEmu here is the example https://introjs.com/docs/examples/advanced/async-await

LimpEmu commented 2 years ago

Yes, I am aware of this example. It doesn't help me with what I am trying to do :) Thank you for getting back to me.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

banagale commented 1 year ago

I also wasn't able to use the docs example to accomplish what I wanted done.

The pattern I'm using is below.

I tried a number of ways to use the promise to delay progression to the next step but could not get it to work. (On currentStep === 1, autoPasteBtnEl never was created in time to attach the click event. It does not seem to have any trouble in currentStep === 0.

FWIW, I was able to get around this by instead adding a helper function that watched for the existence of the element. The function is described here and uses the MutationObserver api.

When I include a function based on this above link and await its completion, I can delay intro.js as long as necessary for elements in the next step to appear.

It could be I'm just not using the promise correctly. I'd prefer not to use an unnecessary helper function. Any feedback appreciated.

  const wizardObj = introJs();

  wizardObj.setOptions({
    steps: wizardSteps,
  });

  wizardObj.onafterchange(async () => {
    const currentStep = wizardObj.currentStep();
    if (currentStep === 0) {
      console.log('Tour started.');
        // Defined a few elements as constants
        // Added an addEventListener click logic to one element
               console.log('element clicked...');
               console.log('going to next step');
               await wizardObj.nextStep();
           });
    } else if (currentStep === 1) {
      console.log('Paste the URL.', currentStep);
      const autoPasteBtnEl = document.getElementById('paste-url-shortcut-btn') as HTMLButtonElement;
      autoPasteBtnEl.addEventListener('click', () => {
      // An input box on the screen is filled with a value.
      });
renakollmannsuhr commented 1 year ago

I also had no luck implementing the documentation suggestion