From c78fe6b96e08316edade24d0d3828d22ac7fcebc Mon Sep 17 00:00:00 2001 From: Winter Mason Date: Tue, 19 Feb 2013 10:03:44 -0500 Subject: [PATCH] Added variation that inserts Google Form before results --- core/js/IAT_gform.js | 683 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 683 insertions(+) create mode 100644 core/js/IAT_gform.js diff --git a/core/js/IAT_gform.js b/core/js/IAT_gform.js new file mode 100644 index 0000000..e515a44 --- /dev/null +++ b/core/js/IAT_gform.js @@ -0,0 +1,683 @@ +template = {}; +sub = ''; +clearform = true; + +// replace this with the link to the google form +gframe = 'https://docs.google.com/forms/d/1alFGZ2_tkQTsGf5CXI7dyzQPTipsELUMQU6G1v-pdLE/viewform'; + +function randomString(length) { + var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + var result = ''; + for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))]; + return result; +} + +// Loads the input file and starts introduction +function initialize() +{ + // get active template & load data into global variable + $.getJSON("templates/active.txt", function(input) { + document.title = input.active + " IAT"; + $.getJSON("templates/"+input.active+"/input.txt", function(data) { + template = data; + $.get("core/instruct0.html", function(data) { + $("#instructions").html(data); + $("#subID").val(randomString(10)); + }); + }); + }); +} + +function loadInstructions(stage) +{ + switch(stage) + { + case 'one': + sub = $("#subID").val(); + if(sub.search('/[^a-zA-Z0-9]/g')==-1) + { + $.get("core/instruct1.html", function(data) { + $("#instructions").html(data); + $(".IATname").html(template.name); + if( template.catA.itemtype == "img" || + template.catB.itemtype == "img" || + template.cat1.itemtype == "img" || + template.cat2.itemtype == "img") + { + $("#andpics").html(" and pictures "); + } + }); + } + else + { + alert("Please enter a valid subject ID"); + } + break; + case 'two': + $.get("core/instruct2.html", function(data) { + $("#instructions").html(data); + + $("#clabel1").html(template.cat1.label); + $("#clabel2").html(template.cat2.label); + $("#clabelA").html(template.catA.label); + $("#clabelB").html(template.catB.label); + if (template.cat1.itemtype == "txt") + { $("#citems1").html(template.cat1.items.join(", ")); } + else if (template.cat1.itemtype == "img") + { $("#citems1").html("Images of "+template.cat1.label); } + if (template.cat2.itemtype == "txt") + { $("#citems2").html(template.cat2.items.join(", ")); } + else if (template.cat2.itemtype == "img") + { $("#citems2").html("Images of "+template.cat2.label); } + if (template.catA.itemtype == "txt") + { $("#citemsA").html(template.catA.items.join(", ")); } + else if (template.catA.itemtype == "img") + { $("#citemsA").html("Images of "+template.catA.label); } + if (template.catB.itemtype == "txt") + { $("#citemsB").html(template.catB.items.join(", ")); } + else if (template.catB.itemtype == "img") + { $("#citemsB").html("Images of "+template.catB.label); } + }); + break; + case 'IAT': + $.get("core/IAT.html", function(data) { + $('body').html(data); + document.onkeypress = keyHandler; + startIAT(); + }); + break; + } +} + +// Initialize variables, build page & data object, display instructions +function startIAT() +{ + currentState = "instruction"; + session = 0; + roundnum = 0; + + // default to show results to participant + if (!('showResult' in template)) + { + template.showResult = "show"; + } + + // make the target or association words green + if (Math.random() < 0.5) + { + openA = ""; + closeA = ""; + open1 = ""; + close1 = ""; + } + else + { + open1 = ""; + close1 = ""; + openA = ""; + closeA = ""; + } + buildPage(); + roundArray = initRounds(); + instructionPage(); +} + +// Adds all images to page (initially hidden) so they are pre-loaded for IAT +function buildPage() +{ + if (template.catA.itemtype == "img") + { + for (i in template.catA.items) + { + var itemstr = ''; + $("#exp_instruct").after(itemstr); + } + } + if (template.catB.itemtype == "img") + { + for (i in template.catB.items) + { + var itemstr = ''; + $("#exp_instruct").after(itemstr); + } + } + if (template.cat1.itemtype == "img") + { + for (i in template.cat1.items) + { + var itemstr = ''; + $("#exp_instruct").after(itemstr); + } + } + if (template.cat2.itemtype == "img") + { + for (i in template.cat2.items) + { + var itemstr = ''; + $("#exp_instruct").after(itemstr); + } + } +} + +// Round object +function IATround() +{ + this.starttime = 0; + this.endtime = 0; + this.itemtype = "none"; + this.category = "none"; + this.catIndex = 0; + this.correct = 0; + this.errors = 0; +} + +// Create array for each session & round, with pre-randomized ordering of images +function initRounds() +{ + var roundArray = []; + // for each session + for (var i=0; i<7; i++) + { + roundArray[i] = []; + switch (i) + { + case 0: + case 4: + stype = "target"; + numrounds = 20; + break; + case 1: + stype = "association"; + numrounds = 20; + break; + case 2: + case 3: + case 5: + case 6: + stype = "both"; + numrounds = 40; + break; + + } + prevIndexA = -1; prevIndex1 = -1; + for (var j = 0; jor
'+open1+template.cat1.label+close1); + $("#right_cat").html(openA+template.catB.label+closeA+'
or
'+open1+template.cat2.label+close1); + break; + case 4: + $("#left_cat").html(openA+template.catB.label+closeA); + $("#right_cat").html(openA+template.catA.label+closeA); + break; + case 5: + case 6: + $("#left_cat").html(openA+template.catB.label+closeA+'
or
'+open1+template.cat1.label+close1); + $("#right_cat").html(openA+template.catA.label+closeA+'
or
'+open1+template.cat2.label+close1); + break; + } + if (session == 7) + { + $("#left_cat").html(""); + $("#right_cat").html(""); + $("#exp_instruct").html(""); + WriteFile(); + //if('insertForm' in template) + if(true) + { + resulttext = ''; + $("#experiment_frame").html(resulttext); + } + else + { + if(template.showResult == "show") + { + calculateIAT(); + } + else + { + resulttext = "
Thanks for participating!
"; + $("#picture_frame").html(resulttext); + } + } + } + else + { + $.get("core/gInstruct"+(session+1)+".html", function(data) { $('#exp_instruct').html(data); }); + } +} + +function clearForm(toggle) +{ + clearform = clearform ^ toggle; + if(clearform) + { + $('#experiment_frame').html('
'); + if(template.showResult == "show") + { + calculateIAT(); + } + else + { + resulttext = "
Thanks for participating!
"; + $("#picture_frame").html(resulttext); + } + } +} + +// Calculates estimate of effect size to present results to participant +function calculateIAT() +{ + // calculate mean log(RT) for first key trial + compatible = 0; + for (i=1; i 3000) { score = 3000; } + compatible += Math.log(score); + } + compatible /= (roundArray[3].length - 1); + + // calculate mean log(RT) for second key trial + incompatible = 0; + for (i=1; i 3000) { score = 3000; } + incompatible += Math.log(score); + } + incompatible /= (roundArray[6].length - 1); + + // calculate variance log(RT) for first key trial + cvar = 0; + for (i=1; i 3000) { score = 3000; } + cvar += Math.pow((Math.log(score) - compatible),2); + } + + // calculate variance log(RT) for second key trial + ivar = 0; + for (i=1; i 3000) { score = 3000; } + ivar += Math.pow((Math.log(score) - incompatible),2); + } + + // calculate t-value + tvalue = (incompatible - compatible) / Math.sqrt(((cvar/39) + (ivar/39))/40); + + // determine effect size from t-value and create corresponding text + if (Math.abs(tvalue) > 2.89) { severity = " much more than "; } + else if (Math.abs(tvalue) > 2.64) { severity = " more than "; } + else if (Math.abs(tvalue) > 1.99) { severity = " a little more than "; } + else if (Math.abs(tvalue) > 1.66) { severity = " just slightly more than "; } + else { severity = ""; } + + // put together feedback based on direction & magnitude + if (tvalue < 0 && severity != "") + { + resulttext = "
You associate "+openA+template.catB.label+closeA+" with "+open1+template.cat1.label+close1; + resulttext += " and "+openA+template.catA.label+closeA+" with "+open1+template.cat2.label+close1+severity; + resulttext += "you associate "+openA+template.catA.label+closeA+" with "+open1+template.cat1.label+close1; + resulttext += " and "+openA+template.catB.label+closeA+" with "+open1+template.cat2.label+close1+".
"; + // resulttext += "
incompatible: "+incompatible+" ("+(ivar/39)+"); compatible: "+compatible+" ("+(cvar/39)+"); tvalue: "+tvalue+"
"; + } + else if (tvalue > 0 && severity != "") + { + resulttext = "
You associate "+openA+template.catA.label+closeA+" with "+open1+template.cat1.label+close1; + resulttext += " and "+openA+template.catB.label+closeA+" with "+open1+template.cat2.label+close1+severity; + resulttext += "you associate "+openA+template.catB.label+closeA+" with "+open1+template.cat1.label+close1; + resulttext += " and "+openA+template.catA.label+closeA+" with "+open1+template.cat2.label+close1+".
"; + // resulttext += "
incompatible: "+incompatible+" ("+(ivar/39)+"); compatible: "+compatible+" ("+(cvar/39)+"); tvalue: "+tvalue+"
"; + } + else + { + resulttext = "
You do not associate "+openA+template.catA.label+closeA; + resulttext += " with "+open1+template.cat1.label+close1+" any more or less than you associate "; + resulttext += openA+template.catB.label+closeA+" with "+open1+template.cat1.label+close1+".
"; + // resulttext += "
incompatible: "+incompatible+" ("+(ivar/39)+"); compatible: "+compatible+" ("+(cvar/39)+"); tvalue: "+tvalue+"
"; + } + $("#picture_frame").html(resulttext); +} + +// not currently used +function groupEvaluations() +{ + $('#demoglist').after( + "Please rate how warm or cold you feel toward the following groups:\ +
\ + (0 = coldest feelings, 5 = neutral, 10 = warmest feelings)\ +
    \ +
  1. \ +

    "+template.catA.label+"

    \ +

    \ + \ +

    \ +
  2. \ +
  3. \ +

    "+template.catB.label+"

    \ +

    \ + \ +

    \ +
  4. \ +
\ + "); +} + +function IsNumeric(input) +{ + return (input - 0) == input && input.length > 0; +} + +// not currently used +function checkDemographics() +{ + gender = $("input[name=gender]:checked").val(); + age = $("#age option:selected").val(); + loc = $("#loc option:selected").val().replace(/[^A-Za-z0-9,]/g,' '); + races = []; + $("input[name=race]:checked").each(function() { races.push($(this).val()); }); + income = $("#income").val(); + education = $("#edu option:selected").val(); + + // alert(income+"\n"+parseFloat(income)+"\n"); + // $.get('getLocation.php', + // { 'q': loc}, + // function(data) { + // alert(data); + // }); + + // Do validation of input + var error = false; + var errmsg = ""; + + if(gender==null) + { + error=true; + errmsg += "
Please choose an option for gender
"; + } + if(age=="unselected") + { + error=true; + errmsg += "
Please state the year you were born
"; + } + if(loc.length == 0) + { + error=true; + errmsg += "
Please indicate your current location
"; + } + if(races==null) + { + error=true; + errmsg += "
Please indicate your ethnicity
"; + } + if(income==null || $.trim(income) != income.replace(/[^0-9$.,]/g,'') || !IsNumeric(income.replace(/[^0-9.]/g,''))) + { + error=true; + errmsg += "
Please enter a valid number for income
"; + } + if(education=="unselected") + { + error=true; + errmsg += "
Please indicate your highest level of education
"; + } + if(sub.length == 0) + { + error=true; + errmsg += "
Please enter a valid identifier
"; + } + // Output error message if input not valid + if(error==false) + { + subject = sub; + var demos = gender+'\t'; + demos += age+'\t'; + demos += loc+'\t'; + demos += races.join(',')+'\t'; + demos += income.replace(/[^0-9.]/g,'')+'\t'; + demos += education+'\n'; + $.post("core/writeFile.php", { 'subject': subject, 'src': "survey", 'data': demos }, function() {location.href = 'instruct2.php?sub='+sub;}); + } + else + { + $('#error-1').html(errmsg); + } +} + + +// Converts the data for each session and round into a comma-delimited string +// and passes it to writeFile.php to be written by the server +function WriteFile() +{ + var subject = sub; + subject = subject.length==0 ? "unknown" : subject; + var str = ""; + for (i=0; i