/* MouselabWEB this script contains functions to display MouselabWEB content v 1.00b2, May 14, 2010 improvement from v1.00b: updated reorder function to fixed the problem that the overlay images did not resize with the counterbalancing (c) 2003-2010 Martijn C. Willemsen and Eric J. Johnson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ dtNewDate = new Date(); starttime = dtNewDate.getTime(); // abs. starttime of experiment // set vars for delay prevtime = 0; // memory in timefunction to compensate for delay dtime=0; prevCell = -1; // delay lag memory (-1 means first cell is not delayable loaded = false; // flag to test whether page has been loaded 9is set to true in reorder boxOpen = false; // flag to test whether box is already open (using in showCont and hideCont) chkFrm = false // flag to test whether additional form elements have to be checked on submission warningTxt = "Some questions have not been answered. Please answer all questions before continuing!"; CBpreset = false; // flag to set CB order fixed by a matrix on forehand: default is set to false prevfieldname = ""; // default for switching clicks transpImg = new Image() tempImg = new Image() previousSrc=""; // default values mlweb_outtype="XML"; mlweb_fname=0; masterCond = 1; // number of master conditions randomOrder = false; // force randomize of counterbalancing order subject=""; evtOpen = 0; evtClose = 0; tmDirectStart = false; tmTimeUp = false; tmActive = false; tmCurTime = 0; // get source transparant image transpImg.src="transp.gif" function abc_num(str) { out=str.toUpperCase().charCodeAt(0)-65; return out } function fac(x) { // Faculty: x!=x(x-1)...1 var outp=1; for (var i=1; i<=x; i++) {outp=outp*i} return outp } function CountBal(subjnr, num) { // counterbalance based on subj number. // first subject is 0 // Num is number of options to counterbalance // (number of orders is Num!) var numOrd=fac(num); start = subjnr - numOrd*Math.floor((subjnr-1)/numOrd) orderstr="" for (var i=0;i0; i--) { var den=fac(i-1); pos = Math.floor((start-1)/den)+1 outstr+=orderstr.charAt(pos-1)+"," orderstr = orderstr.substring(0,pos-1)+orderstr.substr(pos) start=start-(pos-1)*den } outstr=outstr.substr(0,outstr.length-1) return outstr.split(",") } function ExpMatrix(M) { // expand data matrices var Mrows=M.split("`"); var outM = new Array(); for (rowcount=0;rowcount0) {tempstyle= loc.className.substring(0,loc.className.indexOf(" "));} } else {tempstyle=loc.className + ' btnhov';} loc.className=tempstyle; } function timefunction(event,name,value) { // Record proc data in form element mlweb_form=document.forms[mlweb_fname].elements['procdata'] dtNewDate = new Date(); eventtime = dtNewDate.getTime(); var curtime = eventtime-starttime-dtime; // dtime is to compensate for delay time (failed openings have negative time! // if (prevtime>curtime) {curtime=prevtime;} else {prevtime=curtime}; // check with previous event time: if smaller, then delay was not finished: set curtime to prevtime so event has duration 0; dtime=0; // reset dtime if (mlweb_outtype=="XML") { var str=""+event+""+name+""+value+""; var headerstr="" } else { var str="\""+event+"\",\""+name+"\",\""+value+"\",\""+curtime+"\"\n" var headerstr="\"event\",\"name\",\"value\",\"time\"\n" }; if(mlweb_form.value=='') { mlweb_form.value=headerstr; } mlweb_form.value+=str; if (event=="onload") {reorder();} return true; } // convert event to eventdata and call save function function RecordEventData(objActionElement, objEvent) { var strName, strEventType, strFormValue; strName = objActionElement.name; strFormValue = (objActionElement.value) ? objActionElement.value : ""; strEventType = objEvent.type; //call timefunction timefunction(strEventType,strName, strFormValue) return false; } function checkForm(formHandle) { if (chkFrm) { noElm = document.forms[mlweb_fname].elements.length; var filled=true; for (i=0;i/Mozilla HandleTxt = document.getElementById(fieldname+"_txt"); HandleBox = document.getElementById(fieldname+"_box"); } else if (document.all) { //IE4/5 HandleTxt=eval("document.all['"+fieldname+"_txt"+"']"); HandleBox=eval("document.all['"+fieldname+"_box"+"']"); } // delay currCell = -1; for (var i=0;i/Mozilla HandleTxt = document.getElementById(fieldname+"_txt"); HandleBox = document.getElementById(fieldname+"_box"); } else if (document.all) { //IE4/5 HandleTxt=eval("document.all['"+fieldname+"_txt"+"']"); HandleBox=eval("document.all['"+fieldname+"_box"+"']"); } HandleTxt.style.visibility='hidden';HandleBox.style.visibility='visible'; } function SwitchCont(fieldname, objEvent) { // special function for clicking tasks if (!loaded) {return;} // do not open boxes when page is loading if (!tmDirectStart & tmActive & tmCurTime==0) {startTmBar();} if (tmTimeUp) {return;} // check if a click on a link (A) occurred. this happens for example // when a mlweb A link gets a focus (due to clicking the box) and a subject presses enter // this is to prevent enters from generating events when in click (rather than mouseover) mode if (objEvent.srcElement) { if (objEvent.srcElement.nodeName=="A") {return} } else if (objEvent.target) { if (objEvent.target.nodeName=="A") {return} } thisElem = new objElem var row = abc_num(fieldname); var col = parseInt(fieldname.substr(1)); // check if open cell should be recorded if ((statecont[RowOut[row]][ColOut[col]]=="0") & !(recOpenCells)) {return;} if (fieldname==prevfieldname) { // just close current box if box is same as previous window.clearTimeout(delay); var row = abc_num(fieldname); var col = parseInt(fieldname.substr(1)); thisElem.name = tagcont[RowOut[row]][ColOut[col]]; // save procesdata RecordEventData(thisElem, objEvent) if (document.getElementById) { // IE6/NS6>/Mozilla HandleTxt = document.getElementById(fieldname+"_txt"); HandleBox = document.getElementById(fieldname+"_box"); } else if (document.all) { //IE4/5 HandleTxt=eval("document.all['"+fieldname+"_txt"+"']"); HandleBox=eval("document.all['"+fieldname+"_box"+"']"); } HandleTxt.style.visibility='hidden';HandleBox.style.visibility='visible'; prevfieldname=""; } else { if ((prevfieldname!="")&(evtClose==1)) { // first close prev box if box is not same as previous window.clearTimeout(delay); var row = abc_num(prevfieldname); var col = parseInt(prevfieldname.substr(1)); thisElem.name = tagcont[RowOut[row]][ColOut[col]]; // save procesdata RecordEventData(thisElem, objEvent) if (document.getElementById) { // IE6/NS6>/Mozilla HandleTxt = document.getElementById(prevfieldname+"_txt"); HandleBox = document.getElementById(prevfieldname+"_box"); } else if (document.all) { //IE4/5 HandleTxt=eval("document.all['"+prevfieldname+"_txt"+"']"); HandleBox=eval("document.all['"+prevfieldname+"_box"+"']"); } HandleTxt.style.visibility='hidden';HandleBox.style.visibility='visible'; } if ((prevfieldname=="")|(evtClose==1)) { // only if any box may be opened or there as no previous box open, show content var row = abc_num(fieldname); var col = parseInt(fieldname.substr(1)); thisElem.name = tagcont[RowOut[row]][ColOut[col]]; thisElem.value = txtcont[RowOut[row]][ColOut[col]]; RecordEventData(thisElem, objEvent); if (document.getElementById) { // IE6/NS6>/Mozilla HandleTxt = document.getElementById(fieldname+"_txt"); HandleBox = document.getElementById(fieldname+"_box"); } else if (document.all) { //IE4/5 HandleTxt=eval("document.all['"+fieldname+"_txt"+"']"); HandleBox=eval("document.all['"+fieldname+"_box"+"']"); } // delay currCell = -1; for (var i=0;i0 ? fac(c1.length) : 1)*(r1.length>0 ? fac(r1.length) : 1); if (subjnr==-1) {subjnr=Math.floor(Math.random()*numCond)} //alert("total cond:" + numCond+"\nsubject: "+subjnr); // counterbalance col groups if (c1.length>0) {c1_order=CountBal(subjnr/subjDen+1,c1.length); subjDen = subjDen*fac(c1.length);} var c1count=0; ColOut = new Array(); for (var i=0; i0) {r1_order=CountBal(subjnr/subjDen+1,r1.length); subjDen = subjDen * fac(r1.length);} var r1count=0; RowOut = new Array(); for (var i=0; i/Mozilla HandleCont = document.getElementById(label+"_cont"); HandleTxt = document.getElementById(label+"_txt"); HandleBox = document.getElementById(label+"_box"); HandleTD = document.getElementById(label+"_td"); HandleTDbox = document.getElementById(label+"_tdbox"); HandleImgBox = document.getElementById(label+"_img"); HandleImg = eval("document.images."+label); pxstr="px"; } else if (document.all) { //IE4/5 HandleCont=eval("document.all['"+label+"_cont"+"']"); HandleTxt=eval("document.all['"+label+"_txt"+"']"); HandleTD=eval("document.all['"+label+"_td"+"']"); HandleBox=eval("document.all['"+label+"_box"+"']"); HandleTDbox=eval("document.all['"+label+"_tdbox"+"']"); HandleImgbox=eval("document.all['"+label+"_img"+"']"); HandleImg = eval("document.images."+label); pxstr="px"; } // set txt HandleTD.innerHTML =""; // empty for IE5 on mac bug // if txtcont is empty or only contains spaces then replace by nbsp to keep TD layout if (txtcont[RowOut[j]][ColOut[i]].replace(/[\x20]/gi, "")=="") {HandleTD.innerHTML = " "} else { // if boxes are non-active and labels are fixed, header rows should also be fixed if (statecont[RowOut[j]][ColOut[i]]=="0") { if (colFix) {tempcol = i} else {tempcol=ColOut[i]}; if (rowFix) {temprow = j} else {temprow = RowOut[j]}; HandleTD.innerHTML = txtcont[temprow][tempcol]; } else {HandleTD.innerHTML = txtcont[RowOut[j]][ColOut[i]]}; }; HandleTDbox.innerHTML =""; // empty for IE5 on mac bug // if boxcont is empty or only contains spaces then replace by nbsp to keep TD layout if (boxcont[RowOut[j]][ColOut[i]].replace(/[\x20]/gi, "")=="") {HandleTDbox.innerHTML = " "} else { if (colFix) {tempcol = i} else {tempcol=ColOut[i]}; if (rowFix) {temprow = j} else {temprow = RowOut[j]}; HandleTDbox.innerHTML = boxcont[temprow][tempcol]; }; //set sizes HandleTD.width = parseInt(WidthCol[ColOut[i]])-5; HandleTD.height = parseInt(HeightRow[RowOut[j]])-5; HandleTDbox.width = parseInt(WidthCol[ColOut[i]])-5; HandleTDbox.height = parseInt(HeightRow[RowOut[j]])-5; if (statecont[RowOut[j]][ColOut[i]]=="1") {HandleTD.className = activeClass;} else {HandleTD.className = inactiveClass}; HandleCont.style.width = parseInt(WidthCol[ColOut[i]])+pxstr; HandleCont.style.height = parseInt(HeightRow[RowOut[j]])+pxstr; HandleTxt.style.width = parseInt(WidthCol[ColOut[i]])+pxstr; HandleTxt.style.height = parseInt(HeightRow[RowOut[j]])+pxstr; HandleTxt.style.clip = "rect(0px "+ HandleTxt.style.width + " " + HandleTxt.style.height +" 0px)"; HandleBox.style.width = parseInt(WidthCol[ColOut[i]])+pxstr; HandleBox.style.height = parseInt(HeightRow[RowOut[j]])+pxstr; HandleBox.style.clip = "rect(0px "+ HandleBox.style.width + " " + HandleBox.style.height +" 0px)"; HandleImgBox.style.width = parseInt(WidthCol[ColOut[i]])+pxstr; HandleImgBox.style.height = parseInt(HeightRow[RowOut[j]])+pxstr; HandleImg.height = parseInt(HeightRow[RowOut[j]]); HandleImg.width = parseInt(WidthCol[ColOut[i]]); // open state=0 boxes using img names from imgcont matrix if (statecont[RowOut[j]][ColOut[i]] == '0') {HandleBox.style.visibility = "hidden"; HandleTxt.style.visibility = "visible";} else {HandleBox.style.visibility = "visible"; HandleTxt.style.visibility = "hidden";} } } // if there are buttons then reorder the buttons according to the counterbalancing scheme if (btnFlg>0) { btn_inner = new Array() for (bc=0;bc"+btnTxt[txtNum];} else {var functionstr = "onMouseOver=\"btnHover(this,'in');timefunction('mouseover','"+btnTag[realNum]+"','"+btnTxt[realNum]+"')\" onClick=\"recChoice('onclick','"+btnTag[realNum]+"','"+btnTxt[txtNum]+"')\" onMouseOut=\"btnHover(this,'out');timefunction('mouseout','"+btnTag[realNum]+"','"+btnTxt[realNum]+"')\""; btn_inner[bc]="";} } else {btn_inner[bc]=" ";} } for (bc=0;bc/Mozilla HandleTD = document.getElementById("btn_"+bc.toString()); } else if (document.all) { //IE4/5 HandleTD=eval("document.all['"+"btn_"+bc.toString()+"']"); } if (bc==0) {defTDcolor = HandleTD.style.backgroundColor;} docstr=btn_inner[bc]; HandleTD.innerHTML =""; // empty for IE5 on mac bug HandleTD.innerHTML = docstr; } } // send col and row orders as events timefunction("subject", subjtype,subjnr) timefunction("order","col",ColOut.join("_")) timefunction("order","row",RowOut.join("_")) timefunction("events","open_close",evtOpen.toString()+"_"+evtClose.toString()); loaded = true; // set flag that page has been loaded; if (tmActive) { initTmBar(); if (tmDirectStart) {startTmBar();} } return; } function initTmBar() { if (!tmActive) {return false;} if (document.getElementById) { // IE6/NS6>/Mozilla HandleTmCont = document.getElementById("tmCont"); HandleTmBar = document.getElementById("tmBar"); HandleTmTime = document.getElementById("tmTime"); } else if (document.all) { //IE4/5 HandleTmCont =eval("document.all['tmCont']"); HandleTmBar=eval("document.all['tmBar']"); HandleTmTime=eval("document.all['tmTime']"); } HandleTmCont.style.width=parseInt(tmWidthPx+4)+"px"; HandleTmTime.style.width=parseInt(tmWidthPx+4)+"px"; if (tmFill) {HandleTmBar.style.width="0px"; HandleTmTime.innerHTML="0 sec";} else {HandleTmBar.style.width=parseInt(tmWidthPx)+"px"; HandleTmTime.innerHTML=parseInt(tmTotalSec)+" sec";} if (tmShowTime) {HandleTmTime.style.visibility="visible";} else {HandleTmTime.style.visibility="hidden";} } function startTmBar() { if (!tmActive) {return false;} tmCurTime = 0; tmInt = setInterval("refreshTmBar()", tmStepSec*1000); } function refreshTmBar() { if (!tmActive) {return false;} tmCurTime= tmCurTime + tmStepSec*1000; if (tmCurTime>tmTotalSec*1000) {clearInterval(tmInt); tmTimeUp=true; return;} if (tmFill) { HandleTmBar.style.width=parseInt(Math.round(tmCurTime/(tmTotalSec*1000)*tmWidthPx))+"px"; if (tmMinLabel=="false" | tmCurTime <60000) {HandleTmTime.innerHTML=parseInt(Math.round(tmCurTime/1000))+" "+tmSecLabel} else { var mnt = parseInt(Math.floor(tmCurTime/60000)); var secs = parseInt((tmCurTime-mnt*60000)/1000); HandleTmTime.innerHTML=mnt+" "+tmMinLabel+" : "+secs+" "+tmSecLabel} ; } else {HandleTmBar.style.width=parseInt(tmWidthPx-Math.round(tmCurTime/(tmTotalSec*1000)*tmWidthPx))+"px"; HandleTmTime.innerHTML=parseInt(tmTotalSec-Math.round(tmCurTime/1000))+" sec"; if (tmMinLabel=="false" | tmCurTime<60000) {HandleTmTime.innerHTML=parseInt(tmTotalSec-Math.round(tmCurTime/1000))+" "+tmSecLabel} else { var timeleft = tmTotalSec*1000-tmCurTime; var mnt = parseInt(Math.floor(timeleft/60000)); var secs = parseInt((timeleft-mnt*60000)/1000); HandleTmTime.innerHTML=mnt+" "+tmMinLabel+" : "+secs+" "+tmSecLabel} ; } } ///////////////////////// // end of mouselabcode // /////////////////////////