Back Button Navbar Solution

2,078 views
Skip to first unread message

Luca

unread,
Sep 10, 2019, 9:59:11 AM9/10/19
to oTree help & discussion

Hi everyone,


Given that there are frequent questions about a “back” button for oTree, I want to share my simple solution. It uses the bootstrap navigation header bootstrap navigation header and a small chunk of javascript. The bootstrap navbar allows a page to have different tabs. The javascript code enables switching between different tabs when the “back” or “next” button is pressed. Once the navbar is hidden, graphically there is no difference between two html pages in the oTree page sequence and a single html page in the oTree page sequence consisting of two tabs. The crucial differences is however that now users can use the “back” button to review past pages (tabs), which is not possible for two html pages in the oTree page sequence.


Note this solution works best for instructions and pages without form fields in general. This is because this solution works soley over HTML/CSS/Javascript. oTree handles a page consisting of different tabs the same as any other single page, so if users switch between different tabs, they do not advance in the page sequence. Accordingly, input through form fields is only saved once users leave the last tab. Similarly, methods like before_next_page are only triggered once the last “next” button is pressed, since this is the only proper “next” button.


The solution can be played and downloaded via oTree Hub: https://www.otreehub.com/projects/back-button/. The first app shows the solution with the navbar visible, the second with a hidden navbar. The third app shows a simple application, where the first two tabs can be used as instructions and the last tab consists of a comprehension test. If users fail the test, they are brought back to the beginning of the instructions. The advantage of this solution is that it does not hack the oTree page sequence and does not interfere with any internal process of oTree.


The bootstrap navbar offers further customization and styling, so it’s worth to check the bootstrap documentation. Feedback and comments welcome!


Best,

Luca

Chris (oTree)

unread,
Sep 10, 2019, 10:26:57 AM9/10/19
to oTree help & discussion
Thanks Luca for sharing this! I'm sure many people will find it useful :) i will take a look.

Yuet

unread,
May 18, 2020, 2:38:09 AM5/18/20
to oTree help & discussion

Wow Luca, thank you so much for sharing this, it is really useful~

Luca於 2019年9月10日星期二 UTC+8下午9時59分11秒寫道:

Oğuz Özcan

unread,
May 18, 2020, 4:10:17 AM5/18/20
to oTree help & discussion
Hello Luca,

Many thanks from my side as well, it is really good practice and very functional to handle back button via this technique. Pretty good approach to create controls as well, well used in my project.


10 Eylül 2019 Salı 16:26:57 UTC+2 tarihinde Chris @ oTree yazdı:

Nora

unread,
Feb 6, 2021, 3:45:12 AM2/6/21
to oTree help & discussion
Thank you for this Luca, very appreciated!

Nishtha Sharma

unread,
Feb 11, 2021, 10:13:50 AM2/11/21
to oTree help & discussion
Hi,

Thanks a lot for this! I am sorry for requesting even more spoon-feeding but I cannot figure out how to change the number of tabs here. It seems like some part of this code implements 3 pages strictly. I need to put the back button on 18 pages. How can I do that? It works for 3 pages but when I tried to increase the number of pages, it showed all the pages clumped together.

Thanks,
Nishtha

Luca

unread,
Feb 11, 2021, 11:02:48 AM2/11/21
to oTree help & discussion
Hey,

You need to make sure that for each tab you want to include you (1) add an <li> item with the appropriate content to the list that governs the tab navigation and (2) add a <div> where you want the content of the tab to be included. Here is an HTML code example of a page with 6 tabs:

<!-- Tab navigation -->
<ul class="nav nav-tabs   fixed-top navbar-light bg-light justify-content-center" id="myTab" role="tablist">
   <li class="nav-item">
      <a class="nav-link active" id="part1-tab" data-toggle="tab" href="#part1" role="tab" aria-controls="part1" onclick="topFunction()"> Tab 1</a>
   </li>
   <li class="nav-item">
      <a class="nav-link" id="part2-tab" data-toggle="tab" href="#part2" role="tab" aria-controls="part2" onclick="topFunction()">Tab 2</a>
   </li>
   <li class="nav-item">
      <a class="nav-link" id="part3-tab" data-toggle="tab" href="#part3" role="tab" aria-controls="part3" onclick="topFunction()">Tab 3</a>
   </li>
   <li class="nav-item">
      <a class="nav-link" id="part4-tab" data-toggle="tab" href="#part4" role="tab" aria-controls="part4" onclick="topFunction()">Tab 4</a>
   </li>
   <li class="nav-item">
      <a class="nav-link" id="part5-tab" data-toggle="tab" href="#part5" role="tab" aria-controls="part5" onclick="topFunction()">Tab 5</a>
   </li>
   <li class="nav-item">
      <a class="nav-link" id="part6-tab" data-toggle="tab" href="#part6" role="tab" aria-controls="part6" onclick="topFunction()">Tab 6</a>
   </li>
</ul>
<br>
<br>
<!-- Tab content -->
<div class="tab-content" id="myTabContent">
   <div class="tab-pane show active" id="part1" role="tabpanel" aria-labelledby="part1-tab">
      Page 1
      <button onclick="topFunction()" type="button" class="nexttab btn-primary btn next">Next</button>
   </div>
   <div class="tab-pane" id="part2" role="tabpanel" aria-labelledby="part2-tab">
      Page 2
      <button onclick="topFunction()" type="button" class="prevtab btn-primary btn back">Back</button>
      <button onclick="topFunction()" type="button" class="nexttab btn-primary btn next">Next</button>
   </div>
   <div class="tab-pane" id="part3" role="tabpanel" aria-labelledby="part3-tab">
      Page 3
      <button onclick="topFunction()" type="button" class="prevtab btn-primary btn back">Back</button>
      <button onclick="topFunction()" type="button" class="nexttab btn-primary btn next">Next</button>
   </div>
   <div class="tab-pane" id="part4" role="tabpanel" aria-labelledby="part4-tab">
      Page 4
      <button onclick="topFunction()" type="button" class="prevtab btn-primary btn back">Back</button>
      <button onclick="topFunction()" type="button" class="nexttab btn-primary btn next">Next</button>
   </div>
   <div class="tab-pane" id="part5" role="tabpanel" aria-labelledby="part5-tab">
      Page 5
      <button onclick="topFunction()" type="button" class="prevtab btn-primary btn back">Back</button>
      <button onclick="topFunction()" type="button" class="nexttab btn-primary btn next">Next</button>
   </div>
   <div class="tab-pane" id="part6" role="tabpanel" aria-labelledby="part6-tab">
      Page 6
      <button onclick="topFunction()" type="button" class="prevtab btn-primary btn back">Back</button>
      <button class="nexttab btn-primary btn next">Next</button>
   </div>
</div>
</body>

Best,
Luca

Nishtha Sharma

unread,
Feb 11, 2021, 12:38:55 PM2/11/21
to oTree help & discussion

Thank you so much Luca!
I did exactly that. But I still cannot see pages 4 to 9 (in the attached html file). Can you please take a quick look at my file and let me know if you spot what I am doing wrong.
It seems correct when I only look at the html file but pages 4 to 9 do not show up while running the otree app.
Thanks a lot for the help!

This is the page setting in pages.py

class Block1(Page):
def is_displayed(self):
return self.round_number == 1

def vars_for_template(self):
return {
'showup_fee': self.session.config['participation_fee'],
'population': self.session.config['population'],
'per_employee_profit': self.session.config['employee_profit'],
'separation_probability': self.session.config['separation_probability'],
'separation_percent': 100 * self.session.config['separation_probability'],
'retention_probability': 1 - self.session.config['separation_probability'],
'vacancy_cost': self.session.config['posting_cost']
}

Nishtha
Block1.html

Luca

unread,
Feb 11, 2021, 12:47:22 PM2/11/21
to oTree help & discussion
The problem is that the "next" button of your tab 3 is a proper oTree next button. You need to replace it with <button onclick="topFunction()" type="button" class="nexttab btn-primary btn next">Next</button> in order to get to the next tab. Same for page 6. Only the button on the last tab should be a proper next button.

Best,
Luca

Nishtha Sharma

unread,
Feb 12, 2021, 7:13:42 AM2/12/21
to oTree help & discussion
Yes!!! Thank you so so much! 

Nishtha

Gergely Horváth

unread,
Mar 6, 2021, 5:02:32 AM3/6/21
to oTree help & discussion

Dear Luca,
Thank you so much for posting this. I have encountered a small problem, the code works fine but when I open the page for the first time, I see 3 tabs below each other, then as I click through the tabs and return to the first tab, I see everything fine (only 1 tab per subpage). So when the page appears first time, it shows several tabs, later as i click through them, it "corrects" itself. Any idea what can be the problem?
Best,
Gergely
Message has been deleted

Shiyu ZHANG

unread,
Mar 6, 2021, 7:56:16 AM3/6/21
to oTree help & discussion
Dear Gergely,

  Quite a coincidence, I encountered such an issue just as described by you. 

  For my case, I realized it happens when I created one more tab and create the div element by copy and paste the code of the first tab, so instead of creating one new tab with
"<div class="tab-pane show active" id="part4" role="tabpanel" aria-labelledby="part4-tab">" I use “<div class="tab-pane" id="part4" role="tabpanel" aria-labelledby="part4-tab">”. It then solves the problem.

  Hope that helps.

Best,
Jake ZHANG

Gergely Horváth

unread,
Mar 6, 2021, 8:15:17 AM3/6/21
to Shiyu ZHANG, ot...@googlegroups.com
Dear Jake,

Thanks a lot for this input, it indeed solved the problem! 
Best,
Gergely

--
You received this message because you are subscribed to the Google Groups "oTree help & discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to otree+un...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/otree/91d11858-5aa1-467b-9095-e7595835cf82n%40googlegroups.com.

Gergely Horváth

unread,
Apr 29, 2021, 6:38:30 AM4/29/21
to oTree help & discussion
Is there any issue with using these tabs under newer otree versions? I encountered the issue that my code works when run it on my own computer but the tabs do not work when I upload the code to Heroku. In particular the tabs appear but when I click on them, nothing happens.

This is my code:
<ul class="nav nav-tabs fixed-top navbar-light bg-light justify-content-center " id="myTab" role="tablist">

<li class="nav-item" >
<a class="nav-link active" id="part0-tab" data-toggle="tab" href="#part0" role="tab" aria-controls="part0" onclick="topFunction()"> Painting Pair 6: Questions</a>
</li>

<li class="nav-item" >
<a class="nav-link" id="part1-tab" data-toggle="tab" href="#part1" role="tab" aria-controls="part1" onclick="topFunction()"> Painting Pair 1</a>
</li>

<li class="nav-item">
<a class="nav-link" id="part2-tab" data-toggle="tab" href="#part2" role="tab" aria-controls="part2" onclick="topFunction()">Painting Pair 2</a>
</li>

<li class="nav-item">
<a class="nav-link" id="part3-tab" data-toggle="tab" href="#part3" role="tab" aria-controls="part3" onclick="topFunction()">Painting Pair 3</a>
</li>

<li class="nav-item">
<a class="nav-link" id="part4-tab" data-toggle="tab" href="#part4" role="tab" aria-controls="part4" onclick="topFunction()">Painting Pair 4</a>
</li>

<li class="nav-item">
<a class="nav-link" id="part5-tab" data-toggle="tab" href="#part5" role="tab" aria-controls="part5" onclick="topFunction()">Painting Pair 5</a>
</li>

</ul>

Luca

unread,
Apr 29, 2021, 9:01:13 AM4/29/21
to oTree help & discussion
Hi,

I'm working with the newest oTree 3.xx version, and it is working fine. I have not tested it using oTree Lite, though. If I understand it correctly, oTree Lite uses bootstrap 5, so maybe some bootstrap commands have a different name or functionality there.

Best,
Luca

Chris @ oTree

unread,
Apr 29, 2021, 10:37:14 AM4/29/21
to oTree help & discussion
Yes that's right, in Bootstrap 5 data-toggle was renamed to data-bs-toggle. That's probably the reason.

June Nguyen

unread,
May 13, 2021, 11:25:32 AM5/13/21
to oTree help & discussion
Hi,

I got the same problem. Did you manage to fix the code?

Thanks,
June

Gergely Horváth

unread,
May 14, 2021, 12:04:14 AM5/14/21
to June Nguyen, oTree help & discussion
Hi June,

I just went around the problem by putting all tabs' contents on one page. Sorry that i can't help more.
Best,
Gergely

You received this message because you are subscribed to a topic in the Google Groups "oTree help & discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/otree/0UvDG8mhhcs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to otree+un...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/otree/dd55820c-4d4c-49c9-bd4d-97f538603431n%40googlegroups.com.

Chris @ oTree

unread,
May 14, 2021, 11:16:09 PM5/14/21
to oTree help & discussion
Did you try renaming data-toggle to data-bs-toggle in the code?

xiaogen...@gmail.com

unread,
Jun 4, 2021, 4:33:19 PM6/4/21
to oTree help & discussion
Thank you very much for the great contribution! I find it very helpful! One comment, I found that if I need error checks for some pages/nav-tabs where people need to answer questions correctly before they can proceed, the error message popping and returning the same page are different from the usual way in oTree. I did the error check with Javascript and changed a bit in prev_next_button.js. Is there straightforward way to do error check in a nav-tab page? Thank you!  
Reply all
Reply to author
Forward
0 new messages