sjmc11 / tourguide-js

TourGuide is a Javascript library for creating user tours and on-boarding steps for your apps.
https://tourguidejs.com
MIT License
592 stars 27 forks source link

Best way to handle target elements not in DOM? #12

Closed mjgwood closed 6 months ago

mjgwood commented 1 year ago

More of a question than an issue, but I have target elements for many of my tour steps which don't exist at the time of initialisation. I'm currently handling these steps programatically with addSteps() when the target elements are added to the DOM, but it's quite cumbersome and it would be nice to have a way to check for the element's existence within the step itself.

The issue appears to be that the target element gets set to body if it isn't found when the tour is initialised. I thought refresh() might help but it doesn't semm to use the target value I initially provided.

Other libraries I've tried account for this by permitting target elements that don't exist, and then providing an async step method similar to beforeEnter() where you can wait for the element to exist before executing the rest of the step's code.

I could manually update each step's target using beforeEnter() e.g. tg.tourSteps[0].target = document.querySelector('#my-target'), but that is also a lot more code if I need to do it for several steps.

Do you have any suggestions, or have I missed some easier way to do it? Otherwise, would you be open to providing an option to override the default behaviour of setting target to body in computeTourSteps()?

Cheers

sirmspencer commented 1 year ago

πŸ‘ On this. Steps are computed too early, and if the tour starts even slightly before the all of the dom is loaded then it can't find any of the targets.

sirmspencer commented 1 year ago

Use cases for this are

sirmspencer commented 1 year ago

A computeOnChange option would likely help a lot here.

arnaudbroes commented 6 months ago

We're running into this issue as well because we need to switch tabs in a Vue app between steps. We're able to switch tabs through the onBeforeStepChange event or beforeEvent prop on the step, but the element highlighter and dialog do not reposition themselves after navigating to the new page, even if we implement a timeout to wait until the new view is rendered or when we call tg.refresh() or tg.updatePositions().

@sjmc11 would you be able to explain from a technical standpoint why calling tg.updatePositions() does not trigger an update of the element highlighter and dialog once the view is fully rendered? If your time is sparse I'm happy to see if I can cook up a PR but I'd need some insight first.

arnaudbroes commented 6 months ago

I've created a PR here that addresses this issue - https://github.com/sjmc11/tourguide-js/pull/29#issue-2165021199

If you add the new element or switch tabs in the onBeforeStepChange event and call refresh() in the onAfterStepChange event, you can easily target elements that do not exist on the page when the tour is started.

sjmc11 commented 6 months ago

Thanks @arnaudbroes

Apologies been unable to address this myself. I've reviewed and merged your PR. Will release a new NPM version.

arnaudbroes commented 6 months ago

@sjmc11 awesome, thank you! Don't worry about it, we're all busy. πŸ˜„

sjmc11 commented 6 months ago

Ver 0.0.13 now available on NPM https://www.npmjs.com/package/@sjmc11/tourguidejs