skip to Main Content

I have a side bar that is displayed in all views. In that side bar I have a dropdown menu to select some tours that are made with intro.js. There is a quick start, that works perfect. I want to add some options with the names of the views in the tutorial dropdown so that when I click on it I go to the view and start the tutorial. Important, there is an option to start a tutorial when you enter that view, but I don’t want that, because if I access redirected from another part it will always start the tutorial, I want it to start only from the tutorial dropdown menu. The problem I have is that my js function switches me to another view but the tutorial starts and stops from one (it shows a fraction of a second).

This is what i have. The dropdown menu:

<div class="language-selector">
    <!-- Dropdown Trigger -->
    <a id="tutorial" class="dropdown-trigger sidebar-links a" href="#" data-target="tutorialDropdown">
        <span style="display: flex; align-items: center;">
            <i class="fas fa-question-circle"></i>
                {% trans "Tutorial" %}
            <i class="fas fa-caret-down"></i>
        </span>
    </a>    
    <!-- Dropdown Structure -->
    <ul id="tutorialDropdown" class="dropdown-content">
        <li>
            <button class="start-tour-button" onclick="startTourAndRedirect('quick-start', '')">
                Quick Start
            </button>
        </li>
        <li>
            <button class="start-tour-button" onclick="startTourAndRedirect('review-panel', '{% url 'validate' %}')">
                 Review Panel
            </button>
        </li>   
    </ul>
</div>

My js code:

function startTourAndRedirect(tourName, url) {
    if (url !== "") {
        window.location.href = url;
    }

    let steps = [];

    if (tourName == "quick-start") {
        steps = [
            /* steps for quic-start */
        ];
    } else if (tourName == "review-panel") {
        steps = [
            /* steps for review-panel */
        ];
    } 
    console.log(steps);
    if (steps.length > 0) {
        introJs()
            .setOptions({
                steps: steps,
                showProgress: true,
                showBullets: false,
                disableInteraction: true,
            })
            .start();
    }
    else {
        console.log("No steps found");
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    I solved this, saving in a cookie the selected tour name, and starting the tutorial when the view changes.

    <ul id="tutorialDropdown" class="dropdown-content">
        <li>
            <button class="start-tour-button" onclick="setSelectedTour('review-panel', '{% url 'validate' %}')">
            Review Panel
            </button>
        </li>
        <li>
            <button class="start-tour-button" onclick="setSelectedTour('activity-feed', '{% url 'activity_feed' %}')">
            Activity Feed
            </button>
        </li>
    </ul>
    

    and the js code:

    function setSelectedTour(tourName, url) {
        document.cookie = `selectedTour=${tourName}; expires=; path=/; max-age=3`;
        if (url !== '') {
            window.location.href = url;
        }
    }
    
    // Function to get the selected tour name from the cookie
    function getSelectedTour() {
        const name = "selectedTour=";
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            let cookie = cookies[i].trim();
            if (cookie.indexOf(name) === 0) {
                return cookie.substring(name.length, cookie.length);
            }
        }
        return "";
    }
    
    // Function to start the selected tour
    function startSelectedTour() {
        const selectedTour = getSelectedTour();
        if (selectedTour) {
            startTour(selectedTour);
        }
    }
    
    function startTour(tourName) {
        let jsonData;
    
        fetch('/config/stepsTours.json')
            .then(response => response.json())
            .then(data => {
                jsonData = data;
                let steps = [];
                // Load steps for the selected tour
                if (tourName == "review-panel" && jsonData["review-panel"]) {
                    steps = jsonData["review-panel"];
                } else if (tourName == "activity-feed" && jsonData["activity-feed"]) {
                    steps = jsonData["activity-feed"];
                }
                // Start the tutorial
                if (steps.length > 0) {
                    const intro = introJs()
                        .setOptions({
                            steps: steps,
                            showProgress: true,
                            showBullets: false,
                            disableInteraction: true,
                        });
                    intro.start();
                } else {
                    console.log("No steps found");
                }
            })
            .catch(error => console.error('Error loading JSON file:', error));
    }
    
    window.addEventListener('load', function () {
        startSelectedTour();
    });
    

  2. This issue is happening because startTourAndRedirect starts the tour but immediately redirects the page.

    To solve this, you need to delay the redirection until the tour is complete. To achieve this, you can use the callback function provided by intro.js. Here’s how you can do this.

    if (steps.length > 0) {
        const intro = introJs()
            .setOptions({
                steps: steps,
                showProgress: true,
                showBullets: false,
                disableInteraction: true,
            })
            .onexit(function() { // This is the callback function
                // Tour is completed
                if (url !== "") {
                    window.location.href = url;
                }
            });
    
        intro.start();
    }
    

    As you can see in the code above, .onexit callback is called when the tour exist, and within this callback function, we are checking if URL redirection is provided, and then redirecting.

    Full code:

    function startTourAndRedirect(tourName, url) {
        let steps = [];
    
        if (tourName == "quick-start") {
            steps = [
                /* steps for quic-start */
            ];
        } else if (tourName == "review-panel") {
            steps = [
                /* steps for review-panel */
            ];
        } 
    
        if (steps.length > 0) {
            const intro = introJs()
                .setOptions({
                    steps: steps,
                    showProgress: true,
                    showBullets: false,
                    disableInteraction: true,
                })
                .onexit(function() {
                    // Tour is completed
                    if (url !== "") {
                        window.location.href = url;
                    }
                });
    
            intro.start();
        }
        else {
            console.log("No steps found");
        }
    }
    

    Hope it helps 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search