Skip to content

Commit

Permalink
adding export of questions and options to fix #79
Browse files Browse the repository at this point in the history
  • Loading branch information
vsoch committed Mar 23, 2016
1 parent 63d1542 commit a177d46
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
38 changes: 29 additions & 9 deletions expfactory/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ def get_required_string(required_boolean):
required = "required"
return required

def parse_meta(text,options=None):
'''parse_meta returns fields to include in inputs for question text and options, for export
:param text: the text of the question (required)
:param options: options to include with the data (optional)
'''
text = text.replace('"',"'")
if options!= None:
options_joined = "|".join([x.replace('"',"'") for x in options])
return 'meta-options="%s" meta-text="%s"' %(options_joined,text)
return 'meta-text="%s"' %(text)


def create_radio(text,id_attribute,options,values,classes=None,required=0):
'''create_radio generate a material lite radio button given a text field, and a set of options.
:param text: The text (content) of the question to ask
Expand All @@ -65,11 +77,13 @@ def create_radio(text,id_attribute,options,values,classes=None,required=0):

required = get_required_string(required)

meta = parse_meta(text,options)

if len(options) == len(values):
radio_html = "<p>%s</p>" %(text)
for n in range(len(options)):
option_id = "%s_%s" %(id_attribute,n)
radio_html = '%s\n<label class="%s" for="option-%s">\n<input type="radio" id="option-%s" class="mdl-radio__button %s" name="%s_options" value="%s">\n<span class="mdl-radio__label">%s</span>\n</label>' %(radio_html,classes,option_id,option_id,required,id_attribute,values[n],options[n])
radio_html = '%s\n<label class="%s" for="option-%s">\n<input type="radio" id="option-%s" class="mdl-radio__button %s" name="%s_options" value="%s" %s>\n<span class="mdl-radio__label">%s</span>\n</label>' %(radio_html,classes,option_id,option_id,required,id_attribute,values[n],meta,options[n])
return "%s<br><br><br><br>" %(radio_html)

print "ERROR: %s options provided, and only %s values. Must define one option per value." %(len(options),len(values))
Expand All @@ -88,10 +102,12 @@ def create_checkbox(text,id_attribute,options,classes=None,required=0):

required = get_required_string(required)

meta = parse_meta(text,options)

checkbox_html = "<p>%s</p>" %(text)
for n in range(len(options)):
option_id = "%s_%s" %(id_attribute,n)
checkbox_html = '%s\n<label class="%s" for="checkbox-%s">\n<input type="checkbox" id="checkbox-%s" class="mdl-checkbox__input %s">\n<span class="mdl-checkbox__label">%s</span>\n</label>' %(checkbox_html,classes,option_id,option_id,required,options[n])
checkbox_html = '%s\n<label class="%s" for="checkbox-%s">\n<input type="checkbox" id="checkbox-%s" %s class="mdl-checkbox__input %s">\n<span class="mdl-checkbox__label">%s</span>\n</label>' %(checkbox_html,classes,option_id,option_id,meta,required,options[n])
return "%s<br><br><br>" %(checkbox_html)

def base_textfield(text,box_text=None,classes=None):
Expand Down Expand Up @@ -123,8 +139,9 @@ def create_textfield(text,id_attribute,box_text=None,classes=None,required=0):

textfield_html,box_text = base_textfield(text,box_text)
required = get_required_string(required)
meta = parse_meta(text)

return '%s\n<div class="%s">\n<input class="mdl-textfield__input %s" type="text" id="%s">\n<label class="mdl-textfield__label" for="%s">%s</label>\n</div><br><br><br>' %(textfield_html,classes,required,id_attribute,id_attribute,box_text)
return '%s\n<div class="%s">\n<input class="mdl-textfield__input %s" type="text" id="%s" %s>\n<label class="mdl-textfield__label" for="%s">%s</label>\n</div><br><br><br>' %(textfield_html,classes,required,id_attribute,meta,id_attribute,box_text)


def create_numeric_textfield(text,id_attribute,box_text=None,classes=None,required=0):
Expand All @@ -141,8 +158,9 @@ def create_numeric_textfield(text,id_attribute,box_text=None,classes=None,requir

required = get_required_string(required)
textfield_html,box_text = base_textfield(text,box_text)
meta = parse_meta(text)

return '%s\n<div class="%s">\n<input class="mdl-textfield__input %s" type="text" pattern="-?[0-9]*(\.[0-9]+)?" id="%s">\n<label class="mdl-textfield__label" for="%s">%s</label>\n<span class="mdl-textfield__error">Input is not a number!</span>\n</div><br><br><br>' %(textfield_html,classes,required,id_attribute,id_attribute,box_text)
return '%s\n<div class="%s">\n<input class="mdl-textfield__input %s" type="text" pattern="-?[0-9]*(\.[0-9]+)?" id="%s" %s>\n<label class="mdl-textfield__label" for="%s">%s</label>\n<span class="mdl-textfield__error">Input is not a number!</span>\n</div><br><br><br>' %(textfield_html,classes,required,id_attribute,meta,id_attribute,box_text)


def create_select_table(text,id_attribute,df,classes=None,required=0):
Expand All @@ -160,6 +178,7 @@ def create_select_table(text,id_attribute,df,classes=None,required=0):

required = get_required_string(required)
table_html = '<p>%s</p>\n<table id="%s" class="%s">\n<thead>\n<tr>' %(text,id_attribute,classes)
meta = parse_meta(text)

# Parse column names
column_names = df.columns.tolist()
Expand Down Expand Up @@ -192,10 +211,11 @@ def create_textarea(text,id_attribute,classes=None,rows=3,required=0):
:param required: is the question required? 0=False,1=True, default 0
'''
textfield_html,box_text = base_textfield(text,box_text)
meta = parse_meta(text)

if classes == None:
classes = "mdl-textfield mdl-js-textfield"
return '%s\n<div class="%s"><textarea class="mdl-textfield__input %s" type="text" rows= "%s" id="%s" ></textarea>\n<label class="mdl-textfield__label" for="%s">%s</label></div><br><br><br>' %(textfield_html,classes,required,rows,id_attribute,id_attribute)
return '%s\n<div class="%s"><textarea class="mdl-textfield__input %s" type="text" rows= "%s" id="%s" %s ></textarea>\n<label class="mdl-textfield__label" for="%s">%s</label></div><br><br><br>' %(textfield_html,classes,required,rows,meta,id_attribute,id_attribute)


def parse_questions(question_file,exp_id,delim="\t"):
Expand Down Expand Up @@ -245,10 +265,10 @@ def parse_questions(question_file,exp_id,delim="\t"):
elif question_type == "radio":
if not str(options) == "nan" and not str(values) == "nan":
new_question = create_radio(text=question_text,
options=options.split(","),
values = values.split(","),
required=required,
id_attribute=unique_id)
options=options.split(","),
values = values.split(","),
required=required,
id_attribute=unique_id)
else:
print "Radio question %s found null for options or values, skipping." %(question_text)

Expand Down
19 changes: 17 additions & 2 deletions expfactory/templates/survey.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,22 @@
event.preventDefault();

// Save data to browser
var form = $(document.questions);
var data = "text/json;charset=utf-8," + JSON.stringify(form.serializeArray());
var $elements = $("#questions :input");

var results = []
$elements.each(function(index, element) {
var result = {}

if ($.inArray( $(element).attr("name"), [ "forward", "backward", "process"] ) == -1) {
result.name = $(element).attr("name");
result.value = $(element).attr("value");
result.options = $(element).attr("meta-options");
result.text = $(element).attr("meta-text");
results.push(result);
}
})

var data = "text/json;charset=utf-8," + JSON.stringify(results);
var a = document.createElement('a');
a.title = "Download"
a.id = "download"
Expand All @@ -65,6 +79,7 @@
a.click()
})


// Validation
}).validate({
errorPlacement: function( error, element ) {
Expand Down
2 changes: 1 addition & 1 deletion expfactory/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def get_jspsych_init(experiment,deployment="local",finished_message=None):
default_inits["local"] = {"on_finish":["jsPsych.data.localSave('%s_results.csv', 'csv');\nexpfactory_finished = true;" %(experiment["exp_id"])]}

# Amazon Mechanical Turk
default_inits["docker-mturk"] = {"on_finish":["""finished_message = '<div id="finished_message" style="margin:100px"><h1>Experiment Complete</h1><p>%s</p><button id="next_experiment_button" type="button" class="btn btn-success">Next Experiment</button><button type="button" id="redo_experiment_button" class="btn btn-danger">Redo Experiment</button></div>'\n$("body").append(finished_message)\n$(".display_stage").hide()\n$(".display_stage_background").hide()\n$("#redo_experiment_button").click( function(){\njavascript:window.location.reload();\n})\n$("#next_experiment_button").click( function(){\nexpfactory.djstatus = "FINISHED";\n$.ajax({ type: "POST",\ncontentType: "application/json",\nurl : "/sync/{{result.id}}/",\ndata : JSON.stringify(expfactory),\ndataType: "json",\nerror: function(error){\nconsole.log(error)\n},\nsuccess: function(data){\nconsole.log("Finished!");\nif (data.finished_battery == "FINISHED"){\n$("#turkey_form").submit()\n} else {\ndocument.location = "{{next_page}}";\n}\n}\n});\n});\n""" %finished_message],
default_inits["docker-mturk"] = {"on_finish":["""finished_message = '<div id="finished_message" style="margin:100px"><h1>Experiment Complete</h1><p>%s</p><button id="next_experiment_button" type="button" class="btn btn-success">Next Experiment</button><button type="button" id="redo_experiment_button" class="btn btn-danger">Redo Experiment</button></div>'\n$("body").append(finished_message);\n$(".display_stage").hide();\n$(".display_stage_background").hide();\n$("#redo_experiment_button").click( function(){\njavascript:window.location.reload();\n})\n$("#next_experiment_button").click( function(){\nexpfactory.djstatus = "FINISHED";\n$.ajax({ type: "POST",\ncontentType: "application/json",\nurl : "/sync/{{result.id}}/",\ndata : JSON.stringify(expfactory),\ndataType: "json",\nerror: function(error){\nconsole.log(error)\n},\nsuccess: function(data){\nconsole.log("Finished!");\nif (data.finished_battery == "FINISHED"){\n$("#turkey_form").submit()\n} else {\ndocument.location = "{{next_page}}";\n}\n}\n});\n});\n""" %finished_message],
"on_data_update":["""expfactory.recordTrialData(data);\nexpfactory.djstatus = "UPDATE";\n$.ajax({ type: "POST",\ncontentType: "application/json",\nurl : "/sync/{{result.id}}/",\ndata : JSON.stringify(expfactory),\ndataType: "json",\nsuccess: function(data){\nconsole.log("data update called")\n}\n});\n"""]}

# Local Docker Deployment
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
name="expfactory",

# Version number (initial):
version="2.3.8",
version="2.4.1",

# Application author details:
author="Vanessa Sochat",
Expand Down

0 comments on commit a177d46

Please sign in to comment.