oTree Forum >

Raw HTML example: custom user interface with JavaScript

#1 by Arsil

Hi Everyone,

I am trying to calculate the time spend on a calculator page. For this purpose, I get the help from the following document.

https://otree.readthedocs.io/en/latest/forms.html

However, it did not work. 

MODELS:
Class Player (BasePlayer):
     timeJS1 = models.FloatField()
     
PAGES:
class Cal(Page):
    form_model = 'player'
    form_fields = ['a', 'b', 'timeJS1']
    # Where a and b are calculator fields.
    

HTML:
Enter Value of A:
{% form.a %}
<br>
Enter value of B:
{% form.b %}

<input type="hidden" name="timeJS1" id="timeJS1" />

<div style="text-align: right;">
    <button class="btn-primary btn" style = "font-size: 85%;" id="Next">
        NEXT
    </button>
</div>

The following script is copied from otree discussion forum: https://groups.google.com/g/otree/c/uobj5Yat8tE
<script>
window.onload = function() { var startTime = Date.now(); };
function doTimeStuff(){
console.log("dotimestuff started");
var timeSpent = Date.now() - startTime;
console.log("timeSpent calculated:");
console.log(timeSpent);
// save the number in the hidden field
console.log("writing to hidden field");
console.log("hidden field value before: " + document.getElementById('timeJS1').value);
document.getElementById('timeJS1').value = timeSpent;
console.log("hidden field value after: " + document.getElementById('timeJS1').value);
}
</script>

However, I still get the following error.
The form field timeJS1 has errors, but its error message is not being displayed, possibly because you did not include the field in the template. There are 2 ways to fix this:

Include the field with the formfield tag, e.g. {{ formfield "timeJS1" }}
If you are not using formfield but are instead writing the raw HTML for the form input, remember to include {{ formfield_errors 'timeJS1' }} somewhere in your page's HTML.

However, I cannot see any error on the Pyecharm console. I have tried to include {{ formfield_errors 'timeJS1' }} but then it shows an error that this field is required. 

Can anyone help me to resolve this issue.

#2 by Chris_oTree

oTree automatically records timestamps for each page. That is available in the data export section: https://otree.readthedocs.io/en/latest/admin.html#export-data

However, if you need to use the time spent on a page as part of your game logic (e.g. determining a user's payoff by how quickly they do a task), the much better way is to calculate it on the server.


class Player(BasePlayer):
    calc_page_start = models.IntegerField()
    calc_page_duration = models.IntegerField()


on the previous page:

@staticmethod
def before_next_page(player, timeout_happened):
    import time
    player.calc_page_start = time.time()
    
on the calc page:    

@staticmethod
def before_next_page(player, timeout_happened):
    import time
    player.calc_page_duration = time.time() - player.calc_page_start

#3 by Arsil (edited )

Thank you Chris for helping me out in a very detailed manner. I have tried this approach however I got the following error:

Application error (500)
TypeError: cal1_page_start should be set to int, not float.

It appeared on the previous page. However, I used the following

Class Player(BasePlayer):
     cal1_page_start = models.IntegerField()
     
I am not sure what could be the reason for this error.

#4 by Arsil

Finally, I have changed the fields to floatField and it worked. Thank you for the help.

Write a reply

Set forum username