Walktrough



  • Hi there,

    I have developed a Walktrough, that explains the app. And asks the right permissions on a iphone.
    example: https://dribbble.com/shots/2377487-Walkthrough-Illustrations

    But now i’m stuck at the following. I cant make the walktrough a one time thing that only shows when you install the app for the first time (or delete and re-install)

    I’m wondering is there a special code/script that i can use to create a walktrough that is only visible for first time user?



  • @james_d The simplest way I can think of, is to use localStorage. So basically do something like this:

    if (localStorage.getItem("walkthroughShown") === null) {
      localStorage.setItem('useDetailedStats', 'true');
      // code to show walkthrough for the first and only time goes here
    }
    

    Hope this helps!



  • First of all thank you, I have updated the script into the following:

    if(localStorage.getItem("page1") && localStorage.getItem("page4"))
        // perform walkthrough
    else
        // show one time screens
    

    I now i have the remaining “bugs”
    When you restart the application, you see the first screen for a few micro seconds.
    And on a android device when you press the “back” button it opens the the first walktrough page

    Do you got any suggestions for that?

    thanks!



  • Can you post your code? I think this is more of a workflow issue because you shouldn’t have these problems. I would approach the problem as developing the app without the walk-through, then in the code provided push the walk-through pages to the navigation stack and then destroy them after they are viewed so they are completely removed from the stack. This would prevent the back button issue and such.



  • The code/pages is as followed:

    1. Welcome message
    2. Language switcher
    3. Ask for gps location (only IOs)
    4. Ask for push notification (only Ios)
    5. Login with facebook
    switch (e.target.id)
     {
      case "page-welc":
       if(localStorage.getItem("page-welc") == "true" && localStorage.getItem("page4") == "true"){
        sNavigator.pushPage('mainHome.html', {animation : 'slide'});
       }
       else{
        localStorage.setItem("page-welc","true");
       }
       break;
      case "slideTwo":
       if(localStorage.getItem("slideTwo") == "true"){
        sNavigator.pushPage('page2.html', {animation : 'slide'});
       
       }else{
        localStorage.setItem("slideTwo","true");
       }
       break;
      case "page2":
       if(localStorage.getItem("page2") == "true"){
        sNavigator.pushPage('page3.html', {animation : 'slide'});
       }else{
        localStorage.setItem("page2","true");
       }
       break;
      case "page3":
       getCurrentLocation();
       if(localStorage.getItem("page3") == "true"){
        sNavigator.pushPage('page4.html', { animation : 'slide' } )
       }else{
        localStorage.setItem("page3","true");
       }
       break;
      case "page4":
       showPushNotificationDialog();
       if(localStorage.getItem("page4") == "true"){
        sNavigator.pushPage('mainHome.html', {animation : 'slide'});
       }else{
        localStorage.setItem("page4","true");
       }
       break;
      
     }
    


  • @james_d In my opinion, you have made the code way too complex. The simplest thing is to always have mainHome.html be your default loaded page your index.html if you will. Then I would do this, this is the very first line of JS either in your script tag or your script file:

    
    if (localStorage.getItem("walkThroughPage") === null) {
        localStorage.setItem("walkThroughPage","page-welc.html");
       sNavigator.pushPage('page-welc.html', {animation : 'slide'});
    } else if (localStorage.getItem("walkThroughPage")!='mainHome.html'){
       sNavigator.pushPage(localStorage.getItem("walkThroughPage"), {animation:  'slide'});
    }
    
    document.addEventListener("show", function(event){
       if (localStorage.getItem("walkThroughPage")!='mainHome.html'){
          localStorage.setItem("walkThroughPage",event.target.id);
     }
    }
    

    Now, just make sure that your ids are consistent and use the name of the page you want loaded. So what we are doing is, checking to see if the page last viewed has been set, if not then begin the walk through, if it has then go to where they were last. If none of the requirements are met in the if else, then it has been completed and just load the application as normal. This way there is no flicker of your walk-through showing.

    Now, the event listener checks on page show, if the walk through has not been complete then add to the localStorage the current page being viewed. This should then allow you to progress through the walk–through, also capturing if they click back and then exit the app, so it will return them to what they viewed last until they complete the walk-through.

    Disclaimer, I just woke up and wrote this off the top of my head. It has not been tested. I will check it out in the next few hours though.



  • @munsterlander
    I used your code, but it did not work, still have the same problem.

    • You can see the welcome screen load
    • You can press the back button on android devices

    Btw i used your site and shared the full index.html (old file from yesterday) file with you since i don’t want to share it here. Am I doing something wrong?

    And thanks for the help you that you have provided so far



  • @james_d Sorry for being confused. What site did you upload it to? There might be some feature that I am unaware of with these platforms! :grinning: Also, I will work up an example here for you within the next hour.



  • @munsterlander

    http://www.cfuze.com/

    I used the contact form, with a dropbox link



  • @james_d Oh! Right-o! I’m goofy. :smiley:

    I haven’t reviewed your code, but I did this below and have it working great on the device. I will take a look at your code here shortly:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="mobile-web-app-capable" content="yes" />
        <meta http-equiv="Content-Security-Policy" content="default-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
        <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
        <link href='https://fonts.googleapis.com/css?family=Roboto:400,300italic,300,400italic,500,700,700italic,500italic' rel='stylesheet' type='text/css'>
        <title>Onsen UI Forum Help by Munsterlander</title>
    
        <script src="components/loader.js"></script>
        <script src="lib/onsenui/js/onsenui.js"></script>
    
        <link rel="stylesheet" href="lib/onsenui/css/onsenui.css" type="text/css" media="all" />
        <link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css" type="text/css" media="all" />
    
        <script>
        ons.ready(function() {   
            if (localStorage.getItem("walkThroughPage") === null) {
                localStorage.setItem("walkThroughPage","pg1");
               myNav.pushPage('pg1', {animation : 'slide'});
            } else if (localStorage.getItem("walkThroughPage")!='complete'){
               myNav.pushPage(localStorage.getItem("walkThroughPage"), {animation:  'slide'});
            }
            
            document.addEventListener("show", function(event){
               if (localStorage.getItem("walkThroughPage")!='complete'){
                  localStorage.setItem("walkThroughPage",event.target.id);
                }
            });
        });
        </script>
    
    </head>
    <body>
       
        <ons-navigator id="myNav">
            <ons-page>
                <h4>My Home Page</h4>
                <p>
                    My actual app always goes here
                </p>
                <ons-button onclick="localStorage.removeItem('walkThroughPage');">Reset App</ons-button> 
            </ons-page>         
        </ons-navigator>
        <ons-template id="pg1">
            <h4>First page of walkthrough</h4>
            <ons-button onclick="myNav.replacePage('pg2');localStorage.setItem('walkThroughPage','pg2');">Go to Page 2</ons-button>
        </ons-template>    
        <ons-template id="pg2">
            <h4>Second page of walkthrough</h4>
            <ons-button onclick="myNav.replacePage('pg3');localStorage.setItem('walkThroughPage','pg3');">Go to Page 3</ons-button>
        </ons-template>    
        <ons-template id="pg3">
            <h4>Final page of walkthrough</h4>
            <ons-button onclick="myNav.popPage();localStorage.setItem('walkThroughPage','complete');">Go to App</ons-button>
        </ons-template>
    </body>
    </html>
    


  • @james_d After reviewing your code, I think that if you implement the events I have on my buttons, you will see what you are hoping for. The only issue, is I am replacing the page to prevent back button issues and keep the stack only 1 page deep, so with your back buttons, you are going to have to push the previous page. I would really recommend using replacePage for this this application though.

    The easiest way to explain it, is the navigation stack is like a deck of cards. Your main app page is the bottom card. For this application, I would never want more than one card on top of it. It keeps it light and makes it easy to get to the app. Plus it prevents unneeded views being in the way on app reload.

    Hope this helps and let me know through here if there are any issues.



  • @munsterlander the sample code you provided will throw an error because
    if (localStorage.getItem(“walkThroughPage”) === null) {
    localStorage.setItem(“walkThroughPage”,“pg1”);
    ** myNav.**pushPage(‘pg1’, {animation : ‘slide’});
    }
    myNav will be undefined, which you basically defined later in the code i-e
    <ons-navigator id=“myNav”>
    So how can somebody use a variable when it is not even defined?



  • @Husnain-Tahir The full code I provided was a working example. You can copy it into a new project and run it successfully. To answer your question regarding if the element is attached to the DOM, you will notice that the section of code you reference is wrapped in ons.ready() function. This insures the code is not executed until all elements are initialized and attached to the DOM. I have also posted other ways of doing this as well using event listeners and such.



  • @munsterlander oh sorry i forgot to mention ons.ready();, yeah that code will definitely execute, but thing is that i we have more than 1500 lines of code in a single file, it will take a while for ons.ready() to fire, and when it fires it will show the walkthrough may be even for a moment, but it will definitely show it.



  • @Husnain-Tahir So is the problem with the file size resulting in a long load time or that so many items are being attached to the DOM that the pushPage takes too long to execute?



  • @munsterlander the problem is that so many items are being attached to the DOM.



  • @Husnain-Tahir Sorry for taking so long to get back to you. If you have that many lines and that many items attaching to the DOM, then you are probably exceeding the memory of the device and that is why you are experiencing some issues.

    It would seem to me, that you might want to reconsider the UI of the app and possibly utilize a different template system, navigators, and/or pages to introduce the information. Is there a reason that so many items need to be attached at one time?



  • The post maybe is a bit old and you may have found a solution but i thought i would drop my answer since i developed an application with the very same idea (one time walk through screens etc.) recently.

    The way you propose is too complex! You can create one page that holds a carousel with the slides you want to have in your walk through and when done (either by pressing a button or reaching the end of walk through), use the resetToPage function (in order to force navigator to clear the page stack and make root page your main page. That way pressing the back button will not go through the tutorial page). Navigate to your root page that you want and store in localStorage a value, in order to read when your app opens, to know if it’s the first time or not.

    Example

    walkthroupage.html

    <ons-page id="walkthroughpage.html">
        <ons-carousel swipeable auto-scroll fullscreen var="tutorialslider" >
            <ons-carousel-item style="background-color: #607D8B;">
               TUTORIAL PAGE 1 (FILL WITH IMAGES etc.)
            </ons-carousel-item>
            <ons-carousel-item style="background-color: #607D8B;">
                TUTORIAL PAGE 2 (ADD SOME BUTTONS FOR ACTIONS)
            </ons-carousel-item>
            <ons-carousel-item style="background-color: #607D8B;">
               TUTORIAL PAGE 3 (...)
            </ons-carousel-item>
            <ons-carousel-cover>
                <ons-button class="cover-skip" ng-click="doneWalkthrough()" modifier="quiet">
                    Skip
                </ons-button>
                <div class="cover-label">
                    <span class="indicators"> <ons-icon icon="md-circle" size="5px"></ons-icon> </span>
                    <span class="indicators"> <ons-icon icon="md-circle" size="5px"></ons-icon> </span>
                    <span class="indicators"> <ons-icon icon="md-circle" size="5px"></ons-icon> </span>
                    <span class="indicators"> <ons-icon icon="md-circle" size="5px"></ons-icon> </span>
                    <span class="indicators"> <ons-icon icon="md-circle" size="5px"></ons-icon> </span>
                </div>
            </ons-carousel-cover>
        </ons-carousel>
    </ons-page>
    

    In your controller

       $scope.doneWalkthrough= function(){
            window.localStorage.setItem("opened_once",true);
            yourNavigator.resetToPage("main.html");
        };
    

    And when your app opens you can check if you should show your walkthrough page or not like this:

    /*will be false the very first time a user opens the app because no key 'opened_once' will be found in localStorage. When the walk through page completes then it will become true (which means that it's not the first time the user opened the app*/
    var firstime = window.localStorage.getItem("opened_once") || false;  
    if(!firstime)
      yourNavigator.replacePage('walkthroughpage.html');
    

    Hope it helps



  • @jcdenton Excellent demo and a simple way to implement a walk-through. There was one additional requirement though, remember where the user left off in the walk-through if they depart the app and come back. With a tweak, I would believe you could accomplish that pretty quickly. Excellent write up!



  • @munsterlander

    Yes you are right.

    Keeping where the user left off could be done by keeping the current index of the carousel each time a change (slide) occurs.

    Then, if the app should show the walkthrough page, it should do one more check to see if there is any index already set in localStorage. If yes then start the carousel on that index otherwise from the first.


Log in to reply