alex-oleshkevich / vue-introjs

intro.js bindings for Vue.
MIT License
301 stars 53 forks source link

introjs triggers tour on completely different view #44

Closed bakztfuture closed 5 years ago

bakztfuture commented 5 years ago

Notice a really odd behaviour, follows this pattern:

  1. IntroJS runs the tour once my component has dynamically rendered
  2. If I press back, and go to the homepage and enter a search again it will run the tour directly on the homepage view image you can see that in localstorage first_tour is set to true which means the tour has already ran, so it should not be running at all.

Also, note how it has no elements to bind to on the homepage so it just attaches itself to the top left corner of the page, and for some reason starts on the second step.

For some reason, this is what I see when I inspect the element ... it appears to be binding to the CDN code in my index.html file, not sure if this is relevant: image

Basic outline of my code:

watch: {
    myVar: { 
        handler: function(){
            /* only start the tour once the actual elements have finished dynamically loading in the DOM */
            /* otherwise, introJS does not have any elements to actually bind to, or gets the positions wrong */
            this.$nextTick(() => {    
                if (this.results.hits.length > 0 && !this.loggedIn && !first_tour){
                    /* dynamically load my steps */
                    this.$intro().addSteps(
                        [
                            {
                                intro: "Step 1",
                                element: this.$refs.step_1,
                                position: "right",
                                disableInteraction: true // don't let the user click inside of the highlighted element
                            },
                            {
                                intro: "Step 2",
                                element: this.$refs.step_2,
                                position: "left",
                                disableInteraction: true
                            },
                            {
                                intro: "Step 3",
                                element: this.$refs.step_3_parent.$refs.step3_child_element,
                                position: "right",
                                disableInteraction: true
                            }
                        ]
                    )
                    .setOptions({
                        exitOnOverlayClick: false, // don't let the user click "out" of the tour to exit
                        overlayOpacity: 0.5 // changed to 0.5 felt it was too dark by default
                    })
                    .start() // start the tour
                    .oncomplete(function () { // callback tour completion
                        console.log("done");
                    })
                    .onexit(function () {
                        console.log("exited"); // callback tour exit
                    });
                }
            });
        },
        deep: true,
        immediate: false // don't load the tour right away
    }

what can I do about this? Note how my code clearly specifies only create the tour if the user is not logged in or has not done the tour before (as per record in local storage).

Is there any work around to just disable the tour so that it doesn't run on other pages? I can't tell if it's loading on the homepage or just loading prematurely when its going to the next page ... still shouldn't be acting this way.

I've tried lots of things including removing steps from the introJS instance upon exit or completion, I've tried setting display:none to introJS classes on the homepage, I've tried setting introJS to null, I've also tried triggering alerts throughout the introJS instantiation but for whatever reason, this unexpected behaviour won't go away.

This unexpected behaviour appears once in a while on Chrome but occurs frequently on Safari.

Any ideas would be greatly appreciated.

bakztfuture commented 5 years ago

figured it out.

turns out introJS was dynamically creating two tours (one after the other), which is what I was missing.

Fixed this by:

  1. Moving the IntroJS instantiation to the updated() lifecycle hook
  2. Creating a variable which tracks if the tour is already created to prevent a second tour from being instantiated. New outline of my code:
    data: function(){
    return {
        tourRunning: false
    }
    },
    updated() {
    var first_tour = localStorage.getItem('first_tour') || false;
    if (this.results.hits.length > 0 && !this.loggedIn && first_tour == false){
        if (this.tourRunning == false){
            this.tourRunning = true;
            this.$intro().addSteps(this.generateMySteps())
            .setOptions({
                exitOnOverlayClick:  false,
                overlayOpacity: 0.5
            })
            .start()
            .oncomplete(function () {
                localStorage.setItem('first_tour', true);
            })
            .onexit(function () {
                localStorage.setItem('first_tour', true);
            });
        }
    }
    }