From 31dec565b720eba68e6dd48738d8be6bc962d352 Mon Sep 17 00:00:00 2001 From: Patrick Donelan Date: Tue, 25 Nov 2008 06:33:55 +0000 Subject: [PATCH] Refactored JS to use module pattern for proper encapsulation Extensive jslinting to improve cross-browser support Added some debugging statements Fixed redirection to exitUrl when survey complete Added www_deleteResponses Added security restrictions on www_ methods --- lib/WebGUI/Asset/Wobject/Survey.pm | 105 ++- .../Asset/Wobject/Survey/ResponseJSON.pm | 4 +- www/extras/wobject/Survey/administersurvey.js | 863 ++++++++++-------- .../wobject/Survey/administersurvey/comm.js | 117 +-- 4 files changed, 595 insertions(+), 494 deletions(-) diff --git a/lib/WebGUI/Asset/Wobject/Survey.pm b/lib/WebGUI/Asset/Wobject/Survey.pm index 44b3d5c59..38497bb40 100644 --- a/lib/WebGUI/Asset/Wobject/Survey.pm +++ b/lib/WebGUI/Asset/Wobject/Survey.pm @@ -21,7 +21,6 @@ use WebGUI::Asset::Wobject::Survey::ResponseJSON; use Data::Dumper; -# #------------------------------------------------------------------- sub definition { my $class = shift; @@ -130,21 +129,21 @@ sub definition { sectionEditTemplateId => { tab => 'display', fieldType => 'template', - label => "Section Edit Template", + label => "Section Edit Tempalte", defaultValue => '1oBRscNIcFOI-pETrCOspA', namespace => 'Survey/Edit', }, questionEditTemplateId => { tab => 'display', fieldType => 'template', - label => "Question Edit Template", + label => "Question Edit Tempalte", defaultValue => 'wAc4azJViVTpo-2NYOXWvg', namespace => 'Survey/Edit', }, answerEditTemplateId => { tab => 'display', fieldType => 'template', - label => "Answer Edit Template", + label => "Answer Edit Tempalte", defaultValue => 'AjhlNO3wZvN5k4i4qioWcg', namespace => 'Survey/Edit', }, @@ -261,6 +260,9 @@ Loads the initial edit survey page. All other edit actions are JSON calls from sub www_editSurvey { my $self = shift; + + return $self->session->privilege->insufficient() + unless ($self->session->user->isInGroup($self->get('groupToEditSurvey'))); my %var; my $out = $self->processTemplate( \%var, $self->get("surveyEditTemplateId") ); @@ -271,6 +273,9 @@ sub www_editSurvey { #------------------------------------------------------------------- sub www_submitObjectEdit { my $self = shift; + + return $self->session->privilege->insufficient() + unless ($self->session->user->isInGroup($self->get('groupToEditSurvey'))); # my $ref = @{decode_json($self->session->form->process("data"))}; my $responses = $self->session->form->paramsHashRef(); @@ -334,6 +339,10 @@ sub deleteObject { #------------------------------------------------------------------- sub www_newObject { my $self = shift; + + return $self->session->privilege->insufficient() + unless ($self->session->user->isInGroup($self->get('groupToEditSurvey'))); + my $ref; my $ids = $self->session->form->process("data"); @@ -354,6 +363,10 @@ sub www_newObject { #------------------------------------------------------------------- sub www_dragDrop { my $self = shift; + + return $self->session->privilege->insufficient() + unless ($self->session->user->isInGroup($self->get('groupToEditSurvey'))); + my $p = decode_json( $self->session->form->process("data") ); my @tid = split /-/, $p->{target}->{id}; @@ -598,31 +611,47 @@ sub www_takeSurvey { my $self = shift; my %var; - my $out = $self->processTemplate( \%var, $self->get("surveyTakeTemplateId") ); - eval { my $responseId = $self->getResponseId(); if ( !$responseId ) { - return $self->surveyEnd(); + $self->session->log->debug('No responseId, surveyEnd'); +# return $self->surveyEnd(); # disabled. let the js handle the exitUrl redirection + } else { + $self->session->log->debug("ResponseId: $responseId"); } }; + + my $out = $self->processTemplate( \%var, $self->get("surveyTakeTemplateId") ); return $self->session->style->process($out,$self->get("styleTemplateId")); } +#------------------------------------------------------------------- +sub www_deleteResponses { + my $self = shift; + + return $self->session->privilege->insufficient() + unless ($self->session->user->isInGroup($self->get('groupToEditSurvey'))); + + $self->session->db->write('delete from Survey_response'); + + return; +} + #handles questions that were submitted #------------------------------------------------------------------- sub www_submitQuestions { my $self = shift; - #can user take survey if ( !$self->canTakeSurvey() ) { - - # return encode_json({"type","FAIL LOGIN"}); + $self->session->log->debug('canTakeSurvey false, surveyEnd'); return $self->surveyEnd(); } my $responseId = $self->getResponseId(); - if ( !$responseId ) { return $self->surveyEnd(); } + if ( !$responseId ) { + $self->session->log->debug('No response id, surveyEnd'); + return $self->surveyEnd(); + } my $responses = $self->session->form->paramsHashRef(); delete $$responses{'func'}; @@ -631,11 +660,12 @@ sub www_submitQuestions { $self->loadBothJSON(); - my $termInfo = $self->response->recordResponses($responses); + my $termInfo = $self->response->recordResponses($self->session, $responses); $self->saveResponseJSON(); if ( $termInfo->[0] ) { + $self->session->log->debug('Terminal, surveyEnd'); return $self->surveyEnd( $termInfo->[1] ); } @@ -679,18 +709,24 @@ sub www_loadQuestions { my $self = shift; if ( !$self->canTakeSurvey() ) { + $self->session->log->debug('canTakeSurvey false, surveyEnd'); return $self->surveyEnd(); } my $responseId = $self->getResponseId(); #also loads the survey and response if ( !$responseId ) { + $self->session->log->debug('No responseId, surveyEnd'); return $self->surveyEnd(); } if($self->response->hasTimedOut()){ + $self->session->log->debug('Response hasTimedOut, surveyEnd'); return $self->surveyEnd(); } - return $self->surveyEnd() if ( $self->response->surveyEnd() ); + if ( $self->response->surveyEnd() ) { + $self->session->log->debug('Response surveyEnd, so calling surveyEnd'); + return $self->surveyEnd(); + } my $questions; eval { $questions = $self->response->nextQuestions(); }; @@ -708,17 +744,18 @@ sub www_loadQuestions { sub surveyEnd { my $self = shift; my $url = shift; - my $responseId = $self->getResponseId(); #also loads the survey and response - - # $self->session->db->write("update Survey_response set endDate = ? and isComplete = 1 where Survey_responseId = ?",[WebGUI::DateTime->now->toDatabase,$responseId]); - $self->session->db->setRow( - "Survey_response", - "Survey_responseId", { - Survey_responseId => $responseId, - endDate => time(),#WebGUI::DateTime->now->toDatabase, - isComplete => 1 - } - ); + + if (my $responseId = $self->getResponseId()) { #also loads the survey and response + # $self->session->db->write("update Survey_response set endDate = ? and isComplete = 1 where Survey_responseId = ?",[WebGUI::DateTime->now->toDatabase,$responseId]); + $self->session->db->setRow( + "Survey_response", + "Survey_responseId", { + Survey_responseId => $responseId, + endDate => time(),#WebGUI::DateTime->now->toDatabase, + isComplete => 1 + } + ); + } if ( $url !~ /\w/ ) { $url = 0; } if ( $url eq "undefined" ) { $url = 0; } if ( !$url ) { @@ -730,8 +767,8 @@ sub surveyEnd { $url = "/"; } } - $self->session->http->setMimeType('application/json'); - return encode_json( { "type", "forward", "url", $url } ); +# $self->session->http->setRedirect($url); + return encode_json({ "type", "forward", "url", $url }); } ## end sub surveyEnd #------------------------------------------------------------------- @@ -844,7 +881,6 @@ sub response { sub getResponseId { my $self = shift; - return $self->{responseId} if ( defined $self->{responseId} ); my $ip = $self->session->env->getIp; @@ -925,6 +961,7 @@ sub getResponseId { } ## end if ( $haveTaken < $allowedTakes) else { + $self->session->log->debug("haveTaken ($haveTaken) >= allowedTakes ($allowedTakes)"); } } ## end if ( !$responseId ) $self->{responseId} = $responseId; @@ -974,9 +1011,12 @@ sub canTakeSurvey { #------------------------------------------------------------------- sub www_viewGradeBook{ my $self = shift; - $self->loadTempReportTable(); - return "" + + return $self->session->privilege->insufficient() unless ( $self->session->user->isInGroup( $self->get("groupToViewReports") ) ); + + $self->loadTempReportTable(); + my @peoples = $self->session->db->quickArray("SELECT UNIQUE(Survey_responseId) from Survey_tempReport where assetId = ?",[$self->getId()]); for my $people(@peoples){ #my $ @@ -988,9 +1028,12 @@ sub www_viewGradeBook{ #------------------------------------------------------------------- sub www_exportSimpleResults{ my $self = shift; - $self->loadTempReportTable(); - return "" + + return $self->session->privilege->insufficient() unless ( $self->session->user->isInGroup( $self->get("groupToViewReports") ) ); + + $self->loadTempReportTable(); + my $filename = $self->session->url->escape( $self->get("title") . "_results.tab" ); my $content = $self->session->db->quickTab( diff --git a/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm index fd4a8cbd7..f5981080b 100644 --- a/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm +++ b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm @@ -130,9 +130,9 @@ sub currentSection { sub recordResponses { my $self = shift; - my $responses = shift; my $session = shift; - + my $responses = shift; + my %mcTypes = ( 'Agree/Disagree', 1, 'Certainty', 1, 'Concern', 1, 'Confidence', 1, 'Education', 1, 'Effectiveness', 1, 'Gender', 1, 'Ideology', 1, 'Importance', 1, 'Likelihood', 1, diff --git a/www/extras/wobject/Survey/administersurvey.js b/www/extras/wobject/Survey/administersurvey.js index 73c7400a1..76bd29cc1 100644 --- a/www/extras/wobject/Survey/administersurvey.js +++ b/www/extras/wobject/Survey/administersurvey.js @@ -1,453 +1,508 @@ -if (typeof Survey == "undefined") { +/*global Survey, YAHOO */ +if (typeof Survey === "undefined") { var Survey = {}; } -Survey.Form = new function() { - - var multipleChoice = {'Multiple Choice':1,'Gender':1,'Yes/No':1,'True/False':1,'Ideology':1, 'Race':1,'Party':1,'Education':1 - ,'Scale':1,'Agree/Disagree':1,'Oppose/Support':1,'Importance':1, - 'Likelihood':1,'Certainty':1,'Satisfaction':1,'Confidence':1,'Effectiveness':1,'Concern':1,'Risk':1,'Threat':1,'Security':1}; - var text = {'Text':1, 'Email':1, 'Phone Number':1, 'Text Date':1, 'Currency':1}; - var slider = {'Slider':1, 'Dual Slider - Range':1, 'Multi Slider - Allocate':1}; - var dateType = {'Date':1,'Date Range':1}; - var fileUpload = {'File Upload':1}; - var hidden = {'Hidden':1}; +(function(){ + var multipleChoice = { + 'Multiple Choice': 1, + 'Gender': 1, + 'Yes/No': 1, + 'True/False': 1, + 'Ideology': 1, + 'Race': 1, + 'Party': 1, + 'Education': 1, + 'Scale': 1, + 'Agree/Disagree': 1, + 'Oppose/Support': 1, + 'Importance': 1, + 'Likelihood': 1, + 'Certainty': 1, + 'Satisfaction': 1, + 'Confidence': 1, + 'Effectiveness': 1, + 'Concern': 1, + 'Risk': 1, + 'Threat': 1, + 'Security': 1 + }; + var text = { + 'Text': 1, + 'Email': 1, + 'Phone Number': 1, + 'Text Date': 1, + 'Currency': 1 + }; + var slider = { + 'Slider': 1, + 'Dual Slider - Range': 1, + 'Multi Slider - Allocate': 1 + }; + var dateType = { + 'Date': 1, + 'Date Range': 1 + }; + var fileUpload = { + 'File Upload': 1 + }; + var hidden = { + 'Hidden': 1 + }; + var hasFile; - var verb = 0; + var verb = 0; var lastSection = 'first'; - + var toValidate; - var sliderWidth = 500; - var sliders; -// this.submittimer; - - - this.displayQuestions = function(params){ - toValidate = new Array();//clear array - var qs = params.questions; - var s = params.section; - sliders = new Array(); - - //What to show and where - document.getElementById('survey').innerHTML = params.html; -//var te = document.createElement('span'); -//te.innerHTML = ""; -//document.getElementById('survey').appendChild(te); -//YAHOO.util.Event.addListener("testB", "click", function(){Survey.Comm.callServer('','loadQuestions');}); - - if(qs[0] != undefined){ - if(lastSection != s.id|| s.everyPageTitle > 0){ - document.getElementById('headertitle').style.display='block'; - } - if(lastSection != s.id|| s.everyPageText > 0){ - document.getElementById('headertext').style.display = 'block'; - } - - if(lastSection != s.id && s.questionsOnSectionPage != '1'){ - var span = document.createElement("div"); - span.innerHTML = ""; - span.style.display = 'block'; - - document.getElementById('survey-header').appendChild(span); - YAHOO.util.Event.addListener("showQuestionsButton", "click", - function(){ - document.getElementById('showQuestionsButton').style.display = 'none'; - if(s.everyPageTitle == 0){ - document.getElementById('headertitle').style.display = 'none'; - } - if(s.everyPageText == 0){ - document.getElementById('headertext').style.display = 'none'; - } - document.getElementById('questions').style.display='inline'; - Survey.Form.addWidgets(qs); - }); - }else{ - document.getElementById('questions').style.display='inline'; - Survey.Form.addWidgets(qs); - } - lastSection = s.id; - }else{ - document.getElementById('headertitle').style.display='block'; - document.getElementById('headertext').style.display = 'block'; - document.getElementById('questions').style.display='inline'; - Survey.Form.addWidgets(qs); - } - } - - - - - //Display questions - this.addWidgets = function(qs){ - hasFile = false; - for(var i = 0; i < qs.length; i++){ - var q = qs[i]; - var verts = ''; - var verte = ''; - for(var x in q.answers){ - for(var y in q.answers[x]){ - if(q.answers[x][y] == undefined){q.answers[x][y] = '';} - } - } - - //Check if this question should be validated - if(q.required == 1){ - toValidate[q.id] = new Array(); - toValidate[q.id]['type'] = q.questionType; - toValidate[q.id]['answers'] = new Array(); - } - - - if(multipleChoice[q.questionType]){ - var butts = new Array(); - verb = 0; - for(var x = 0; x < q.answers.length; x++){ - var a = q.answers[x]; - if(toValidate[q.id]){ - toValidate[q.id]['answers'][a.id] = 1; - } - var b = document.getElementById(a.id+'button'); - /* - b = new YAHOO.widget.Button({ type: "checkbox", label: a.answerText, id: a.id+'button', name: a.id+'button', - value: a.id, - container: a.id+"container", checked: false }); - */ -// b.on("click", this.buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); -// YAHOO.util.Event.addListener(a.id+'button', "click", this.buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); - if(a.verbatim == 1){ - verb = 1; - } - YAHOO.util.Event.addListener(a.id+'button', "click", this.buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); - b.hid = a.id; - butts.push(b); - } - } - else if(dateType[q.questionType]){ - for(var x = 0; x < q.answers.length; x++){ - var a = q.answers[x]; - if(toValidate[q.id]){ - toValidate[q.id]['answers'][a.id] = 1; - } - var calid = a.id+'container'; - var c = new YAHOO.widget.Calendar(calid,{title:'Choose a date:', close:true}); - c.selectEvent.subscribe(this.selectCalendar,[c,a.id],true); - c.render(); - c.hide(); - var b = new YAHOO.widget.Button({ label:"Select Date", id:"pushbutton"+a.id, container:a.id+'button' }); - b.on("click", this.showCalendar,[c]); - } - } - else if(slider[q.questionType]){ - //First run through and put up the span placeholders and find the max value for an answer, to know how big the allocation points will be. - var max = 0; - if(q.questionType == 'Dual Slider - Range'){ - new this.dualSliders(q); - }else{ - for(var s in q.answers){ - var a = q.answers[s]; - YAHOO.util.Event.addListener(a.id, "blur", this.sliderTextSet); - if(a.max - a.min > max){max = a.max - a.min;} - } - } - if(q.questionType == 'Multi Slider - Allocate'){ - //sliderManagers[sliderManagers.length] = new this.sliderManager(q,max); - for(var x = 0; x < q.answers.length; x++){ - var a = q.answers[x]; - if(toValidate[q.id]){ - toValidate[q.id]['total'] = a.max; - toValidate[q.id]['answers'][a.id] = 1; - } - } - new this.sliderManager(q,max); - } - else if(q.questionType == 'Slider'){ - new this.sliders(q); - } - } - - else if(fileUpload[q.questionType]){ - hasFile = true; - } - - else if(text[q.questionType]){ - var a = q.answers[x]; - if(toValidate[q.id]){ - toValidate[q.id]['answers'][a.id] = 1; - } - } - } - YAHOO.util.Event.addListener("submitbutton", "click", this.formsubmit); - } - - - this.formsubmit = function(event){ + function formsubmit(event){ var submit = 1;//boolean for if all was good or not - for(var i in toValidate){ - var answered = 0; - if(toValidate[i]['type'] == 'Multi Slider - Allocate'){ - var total = 0; - for(var z in toValidate[i]['answers']){ - total += Math.round(document.getElementById(z).value); - } - if(total == toValidate[i]['total']){answered = 1;} - else{ - var amountLeft = toValidate[i]['total']-total; - alert("Please allocate the remaining "+amountLeft+ "."); - } - }else{ - for(var z in toValidate[i]['answers']){ - var v = document.getElementById(z).value; - if(v != '' && v != undefined){ + for (var i in toValidate) { + if (YAHOO.lang.hasOwnProperty(toValidate, i)) { + var answered = 0; + if (toValidate[i].type === 'Multi Slider - Allocate') { + var total = 0; + for (var z in toValidate[i].answers) { + if (YAHOO.lang.hasOwnProperty(toValidate[i].answers, z)) { + total += Math.round(document.getElementById(z).value); + } + } + if (total === toValidate[i].total) { answered = 1; - break; + } + else { + var amountLeft = toValidate[i].total - total; + alert("Please allocate the remaining " + amountLeft + "."); } } - } - if(answered == 0){ - submit = 0; - document.getElementById(i+'required').innerHTML = "*"; - }else{ - document.getElementById(i+'required').innerHTML = ""; + else { + for (var z1 in toValidate[i].answers) { + if (YAHOO.lang.hasOwnProperty(toValidate[i].answers, z1)) { + var v = document.getElementById(z1).value; + if (YAHOO.lang.isValue(v) && v !== '') { + answered = 1; + break; + } + } + } + } + if (!answered) { + submit = 0; + document.getElementById(i + 'required').innerHTML = "*"; + } + else { + document.getElementById(i + 'required').innerHTML = ""; + } } } - if(submit == 1){ -YAHOO.log("Submitting"); - Survey.Comm.callServer('','submitQuestions','surveyForm',hasFile); - } - } - - - - - this.dualSliders = function(q){ - var total = sliderWidth; -// var sliders = new Array(); - var a1 = q.answers[0]; - var a2 = q.answers[1]; - var scale = sliderWidth/a1.max; - - var id = q.id; - var a1id = a1.id; - var a2id = a2.id; - - var a1h = document.getElementById(a1id); - var a2h = document.getElementById(a2id); - var a1s = document.getElementById(a1id+'show'); - var a2s = document.getElementById(a2id+'show'); - var s = YAHOO.widget.Slider.getHorizDualSlider(id+'slider-bg', - a1id+"slider-min-thumb", a2id+"slider-max-thumb", - sliderWidth, 1*scale, [1,sliderWidth]); - sliders[id] = s; -//YAHOO.log(1); - - s.minRange = 4; - var updateUI = function () { - var min = Math.round(s.minVal/scale), - max = Math.round(s.maxVal/scale); - a1h.value = min; - a1s.innerHTML = min; - a2h.value = max; - a2s.innerHTML = max; - }; - - // Subscribe to the dual thumb slider's change and ready events to - // report the state. -// s.subscribe('ready', updateUI); - //s.subscribe('change', updateUI); - s.subscribe('slideEnd', updateUI); - } - this.sliders = function(q){ - var total = sliderWidth; - for(var i in q.answers){ - var a = q.answers[i]; - var step = Math.round(q.answers[i].step); - var min = Math.round(parseFloat(q.answers[i].min)); - var distance = Math.round(parseFloat(q.answers[i].max) + (-1 * min)); - var scale = Math.round(sliderWidth/distance); - var lang = YAHOO.lang; - var id = a.id; - var s = YAHOO.widget.Slider.getHorizSlider(id+'slider-bg', id+'slider-thumb', - 0, sliderWidth, (scale*step)); - s.scale = scale; - sliders[q.Survey_questionid] = new Array(); - sliders[q.Survey_questionid][id] = s; - s.input = a.id; - s.scale = scale; - document.getElementById(id).value = a.min; - var check = function() { - var t = document.getElementById(this.input); - t.value = this.getRealValue(); - }; - s.getRealValue = function() { - return Math.round(parseFloat(( (this.getValue() / total) * distance) + min )); - } - s.subscribe("slideEnd", check); + if (submit) { + YAHOO.log("Submitting"); + Survey.Comm.callServer('', 'submitQuestions', 'surveyForm', hasFile); } } + //an object which creates sliders for allocation type questions and then manages their events and keeps them from overallocating - this.sliderManager = function(q,t){ - var total = sliderWidth; - var step = Math.round(parseFloat(q.answers[0].step)); + function sliderManager(q, t){ + var total = sliderWidth; + var step = Math.round(parseFloat(q.answers[0].step)); var min = Math.round(parseFloat(q.answers[0].min)); var distance = Math.round(parseFloat(q.answers[0].max) + (-1 * min)); - var scale = Math.round(sliderWidth/distance); - for(var i in q.answers){ - var a = q.answers[i]; - var Event = YAHOO.util.Event; - var lang = YAHOO.lang; - var id = a.id+'slider-bg'; - var s = YAHOO.widget.Slider.getHorizSlider(id, a.id+'slider-thumb', - 0, sliderWidth, scale*step); - s.animate = false; - if(sliders[q.id] == undefined){ - sliders[q.id] = new Array(); - } - sliders[q.id][a.id] = s; - s.input = a.id; - s.lastValue = 0; - var check = function() { - var t = 0; - for(var x in sliders[q.id]){ - t+= sliders[q.id][x].getValue(); + var scale = Math.round(sliderWidth / distance); + for (var i in q.answers) { + if (YAHOO.lang.hasOwnProperty(q.answers, i)) { + var a = q.answers[i]; + var Event = YAHOO.util.Event; + var lang = YAHOO.lang; + var id = a.id + 'slider-bg'; + var s = YAHOO.widget.Slider.getHorizSlider(id, a.id + 'slider-thumb', 0, sliderWidth, scale * step); + s.animate = false; + if (YAHOO.lang.isUndefined(sliders[q.id])) { + sliders[q.id] = []; } - if(t > total){ - t -= this.getValue(); - t = Math.round(t); - this.setValue(total-t);// + (scale*step)); - document.getElementById(this.input).value = Math.round(parseFloat(( ((total-t) / total) * distance) + min )); - }else{ - this.lastValue = this.getValue(); - document.getElementById(this.input).value = this.getRealValue(); - } - }; - s.subscribe("change", check); - s.subscribe("slideEnd", check); - var manualEntry = function(e){ - // set the value when the 'return' key is detected - if (Event.getCharCode(e) === 13 || e.type == 'blur') { - var v = parseFloat(this.value, 10); - v = (lang.isNumber(v)) ? v : 0; -// v *= scale; - v = ( ( (v-min) / distance))*total; - // convert the real value into a pixel offset - for(var sl in sliders[q.id]){ - if(sliders[q.id][sl].input == this.id){ - sliders[q.id][sl].setValue(Math.round(v)); + sliders[q.id][a.id] = s; + s.input = a.id; + s.lastValue = 0; + var check = function(){ + var t = 0; + for (var x in sliders[q.id]) { + if (YAHOO.lang.hasOwnProperty(sliders[q.id], x)) { + t += sliders[q.id][x].getValue(); + } } - } - } + if (t > total) { + t -= this.getValue(); + t = Math.round(t); + this.setValue(total - t);// + (scale*step)); + document.getElementById(this.input).value = Math.round(parseFloat((((total - t) / total) * distance) + min)); + } + else { + this.lastValue = this.getValue(); + document.getElementById(this.input).value = this.getRealValue(); + } + }; + s.subscribe("change", check); + s.subscribe("slideEnd", check); + var manualEntry = function(e){ + // set the value when the 'return' key is detected + if (Event.getCharCode(e) === 13 || e.type === 'blur') { + var v = parseFloat(this.value, 10); + v = (lang.isNumber(v)) ? v : 0; + // v *= scale; + v = (((v - min) / distance)) * total; + // convert the real value into a pixel offset + for (var sl in sliders[q.id]) { + if (sliders[q.id][sl].input === this.id) { + sliders[q.id][sl].setValue(Math.round(v)); + } + } + } + }; + Event.on(document.getElementById(s.input), "blur", manualEntry); + Event.on(document.getElementById(s.input), "keypress", manualEntry); + + s.getRealValue = function(){ + return Math.round(parseFloat(((this.getValue() / total) * distance) + min)); + }; + document.getElementById(s.input).value = s.getRealValue(); } - Event.on(document.getElementById(s.input), "blur", manualEntry); - Event.on(document.getElementById(s.input), "keypress", manualEntry); - - s.getRealValue = function() { - return Math.round(parseFloat(( (this.getValue() / total) * distance) + min )); - } - document.getElementById(s.input).value = s.getRealValue(); } } - - this.selectCalendar = function(event,args,obj){ + + function sliderTextSet(event, objs){ + this.value = this.value * 1; + if (this.value === 'NaN') { + this.value = 0; + } + sliders[this.id].setValue(Math.round(this.value * sliders[this.id].scale)); + } + + function handleDualSliders(q){ + var a1 = q.answers[0]; + var a2 = q.answers[1]; + var scale = sliderWidth / a1.max; + + var id = q.id; + var a1id = a1.id; + var a2id = a2.id; + + var a1h = document.getElementById(a1id); + var a2h = document.getElementById(a2id); + var a1s = document.getElementById(a1id + 'show'); + var a2s = document.getElementById(a2id + 'show'); + var s = YAHOO.widget.Slider.getHorizDualSlider(id + 'slider-bg', a1id + "slider-min-thumb", a2id + "slider-max-thumb", sliderWidth, 1 * scale, [1, sliderWidth]); + sliders[id] = s; + + s.minRange = 4; + var updateUI = function(){ + var min = Math.round(s.minVal / scale), max = Math.round(s.maxVal / scale); + a1h.value = min; + a1s.innerHTML = min; + a2h.value = max; + a2s.innerHTML = max; + }; + + // Subscribe to the dual thumb slider's change and ready events to + // report the state. + // s.subscribe('ready', updateUI); + //s.subscribe('change', updateUI); + s.subscribe('slideEnd', updateUI); + } + + function handleSliders(q){ + var total = sliderWidth; + for (var i in q.answers) { + if (YAHOO.lang.hasOwnProperty(q.answers, i)) { + var a = q.answers[i]; + var step = Math.round(q.answers[i].step); + var min = Math.round(parseFloat(q.answers[i].min)); + var distance = Math.round(parseFloat(q.answers[i].max) + (-1 * min)); + var scale = Math.round(sliderWidth / distance); + var id = a.id; + var s = YAHOO.widget.Slider.getHorizSlider(id + 'slider-bg', id + 'slider-thumb', 0, sliderWidth, (scale * step)); + s.scale = scale; + sliders[q.Survey_questionid] = []; + sliders[q.Survey_questionid][id] = s; + s.input = a.id; + s.scale = scale; + document.getElementById(id).value = a.min; + var check = function(){ + var t = document.getElementById(this.input); + t.value = this.getRealValue(); + }; + s.getRealValue = function(){ + return Math.round(parseFloat(((this.getValue() / total) * distance) + min)); + }; + s.subscribe("slideEnd", check); + } + } + } + + function showCalendar(event, objs){ + objs[0].show(); + } + + function selectCalendar(event, args, obj){ var id = obj[1]; - var selected = args[0]; + var selected = args[0]; var date = selected[0]; var year = date[0], month = date[1], day = date[2]; var input = document.getElementById(id); input.value = month + "/" + day + "/" + year; obj[0].hide(); } - - - this.showCalendar = function(event,objs){ - objs[0].show(); - } - - this.sliderTextSet = function(event,objs){ - this.value = this.value * 1; - if(this.value == 'NaN'){this.value = 0;} - sliders[this.id].setValue(Math.round(this.value * sliders[this.id].scale)); - } - - this.buttonChanged = function(event,objs){ + + function buttonChanged(event, objs){ var b = objs[0]; var qid = objs[1]; var maxA = objs[2]; var butts = objs[3]; var qsize = objs[4]; var aid = objs[5]; - max = parseFloat(max); -// clearTimeout(Survey.Form.submittimer); - if(maxA == 1){ - if(b.className == 'mcbutton-selected'){ + //max = parseFloat(max); + // clearTimeout(Survey.Form.submittimer); + if (maxA) { + if (b.className === 'mcbutton-selected') { document.getElementById(b.hid).value = 0; - b.className='mcbutton'; - }else{ - document.getElementById(b.hid).value = 1; - b.className='mcbutton-selected'; + b.className = 'mcbutton'; } - for(var i in butts){ - if(butts[i] != b){ - butts[i].className='mcbutton'; - document.getElementById(butts[i].hid).value = ''; + else { + document.getElementById(b.hid).value = 1; + b.className = 'mcbutton-selected'; + } + for (var i in butts) { + if (YAHOO.lang.hasOwnProperty(butts, i)) { + if (butts[i] !== b) { + butts[i].className = 'mcbutton'; + document.getElementById(butts[i].hid).value = ''; + } } } - } - else if(b.className == 'mcbutton'){ - var bscount = 0;//button selected count - for(var i in butts){ - if(butts[i].className == 'mcbutton-selected'){bscount++;} - } - var max = maxA - bscount;//= parseFloat(document.getElementById(qid+'max').innerHTML); - if(max == 0){ - b.className='mcbutton'; + } + else + if (b.className === 'mcbutton') { + var bscount = 0;//button selected count + for (var ib in butts) { + if (butts[ib].className === 'mcbutton-selected') { + bscount++; + } + } + var max = maxA - bscount;//= parseFloat(document.getElementById(qid+'max').innerHTML); + if (max === 0) { + b.className = 'mcbutton'; //warn that options used up + } + else { + b.className = 'mcbutton-selected'; + //document.getElementById(qid+'max').innerHTML = parseFloat(max-1); + document.getElementById(b.hid).value = 1; + } } - else{ - b.className='mcbutton-selected'; - //document.getElementById(qid+'max').innerHTML = parseFloat(max-1); - document.getElementById(b.hid).value = 1; + else { + b.className = 'mcbutton'; + var bscount1 = 0;//button selected count + for (var ibb in butts) { + if (butts[ibb].className === 'mcbutton-selected') { + bscount1++; + } + } + //var max = maxA - bscount1;//= parseFloat(document.getElementById(qid+'max').innerHTML); + // document.getElementById(qid+'max').innerHTML = parseFloat(max+1); + document.getElementById(b.hid).value = ''; } - }else{ - b.className='mcbutton'; - var bscount = 0;//button selected count - for(var i in butts){ - if(butts[i].className == 'mcbutton-selected'){bscount++;} + /* + if(qsize == 1 && b.className == 'mcbutton-selected'){ + if(! document.getElementById(aid+'verbatim')){ + Survey.Form.submittimer=setTimeout("Survey.Form.formsubmit()",500); + } + } + */ + } + + // Public API + Survey.Form = { + displayQuestions: function(params){ + toValidate = []; + var qs = params.questions; + var s = params.section; + sliders = []; + + //What to show and where + document.getElementById('survey').innerHTML = params.html; + //var te = document.createElement('span'); + //te.innerHTML = ""; + //document.getElementById('survey').appendChild(te); + //YAHOO.util.Event.addListener("testB", "click", function(){Survey.Comm.callServer('','loadQuestions');}); + + if (qs[0]) { + if (lastSection !== s.id || s.everyPageTitle > 0) { + document.getElementById('headertitle').style.display = 'block'; + } + if (lastSection !== s.id || s.everyPageText > 0) { + document.getElementById('headertext').style.display = 'block'; + } + + if (lastSection !== s.id && s.questionsOnSectionPage !== 1) { + var span = document.createElement("div"); + span.innerHTML = ""; + span.style.display = 'block'; + + document.getElementById('survey-header').appendChild(span); + YAHOO.util.Event.addListener("showQuestionsButton", "click", function(){ + document.getElementById('showQuestionsButton').style.display = 'none'; + if (s.everyPageTitle === 0) { + document.getElementById('headertitle').style.display = 'none'; + } + if (s.everyPageText === 0) { + document.getElementById('headertext').style.display = 'none'; + } + document.getElementById('questions').style.display = 'inline'; + Survey.Form.addWidgets(qs); + }); + } + else { + document.getElementById('questions').style.display = 'inline'; + Survey.Form.addWidgets(qs); + } + lastSection = s.id; } - var max = maxA - bscount;//= parseFloat(document.getElementById(qid+'max').innerHTML); -// document.getElementById(qid+'max').innerHTML = parseFloat(max+1); - document.getElementById(b.hid).value = ''; + else { + document.getElementById('headertitle').style.display = 'block'; + document.getElementById('headertext').style.display = 'block'; + document.getElementById('questions').style.display = 'inline'; + Survey.Form.addWidgets(qs); + } + }, + + addWidgets: function(qs){ + hasFile = false; + for (var i = 0; i < qs.length; i++) { + var q = qs[i]; + var verts = ''; + for (var x in q.answers) { + if (YAHOO.lang.hasOwnProperty(q.answers, x)) { + for (var y in q.answers[x]) { + if (YAHOO.lang.hasOwnProperty(q.answers[x], y)) { + if (YAHOO.lang.isUndefined(q.answers[x][y])) { + q.answers[x][y] = ''; + } + } + } + } + } + + //Check if this question should be validated + if (q.required) { + toValidate[q.id] = []; + toValidate[q.id].type = q.questionType; + toValidate[q.id].answers = []; + } + + + if (multipleChoice[q.questionType]) { + var butts = []; + verb = 0; + for (var j = 0; j < q.answers.length; j++) { + var a = q.answers[j]; + if (toValidate[q.id]) { + toValidate[q.id].answers[a.id] = 1; + } + var b = document.getElementById(a.id + 'button'); + /* + b = new YAHOO.widget.Button({ type: "checkbox", label: a.answerText, id: a.id+'button', name: a.id+'button', + value: a.id, + container: a.id+"container", checked: false }); + */ + // b.on("click", buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); + // YAHOO.util.Event.addListener(a.id+'button', "click", buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); + if (a.verbatim) { + verb = 1; + } + YAHOO.util.Event.addListener(a.id + 'button', "click", buttonChanged, [b, a.id, q.maxAnswers, butts, qs.length, a.id]); + b.hid = a.id; + butts.push(b); + } + } + else + if (dateType[q.questionType]) { + for (var k = 0; k < q.answers.length; k++) { + var ans = q.answers[k]; + if (toValidate[q.id]) { + toValidate[q.id].answers[ans.id] = 1; + } + var calid = ans.id + 'container'; + var c = new YAHOO.widget.Calendar(calid, { + title: 'Choose a date:', + close: true + }); + c.selectEvent.subscribe(selectCalendar, [c, ans.id], true); + c.render(); + c.hide(); + var btn = new YAHOO.widget.Button({ + label: "Select Date", + id: "pushbutton" + ans.id, + container: ans.id + 'button' + }); + btn.on("click", showCalendar, [c]); + } + } + else + if (slider[q.questionType]) { + //First run through and put up the span placeholders and find the max value for an answer, to know how big the allocation points will be. + var max = 0; + if (q.questionType === 'Dual Slider - Range') { + handleDualSliders(q); + } + else { + for (var s in q.answers) { + if (YAHOO.lang.hasOwnProperty(q.answers, s)) { + var a1 = q.answers[s]; + YAHOO.util.Event.addListener(a1.id, "blur", sliderTextSet); + if (a1.max - a1.min > max) { + max = a1.max - a1.min; + } + } + } + } + if (q.questionType === 'Multi Slider - Allocate') { + //sliderManagers[sliderManagers.length] = new this.sliderManager(q,max); + for (var x1 = 0; x1 < q.answers.length; x1++) { + if (toValidate[q.id]) { + toValidate[q.id].total = q.answers[x1].max; + toValidate[q.id].answers[q.answers[x1].id] = 1; + } + } + sliderManager(q, max); + } + else + if (q.questionType === 'Slider') { + handleSliders(q); + } + } + + else + if (fileUpload[q.questionType]) { + hasFile = true; + } + + else + if (text[q.questionType]) { + if (toValidate[q.id]) { + toValidate[q.id].answers[q.answers[x].id] = 1; + } + } + } + YAHOO.util.Event.addListener("submitbutton", "click", formsubmit); } -/* - if(qsize == 1 && b.className == 'mcbutton-selected'){ - if(! document.getElementById(aid+'verbatim')){ - Survey.Form.submittimer=setTimeout("Survey.Form.formsubmit()",500); - } - } -*/ - } -}(); + }; + + +})(); - - - -//---------------------------------------------------------------- -// -// Initialize survey -// -//---------------------------------------------------------------- -Survey.OnLoad = new function() { - var e = YAHOO.util.Event; - this.init = function() { - e.onDOMReady(this.initHandler); - } - this.initHandler = function(){ - Survey.Comm.setUrl('/'+document.getElementById('assetPath').value); - Survey.Comm.callServer('','loadQuestions'); - } -}(); - -Survey.OnLoad.init(); +YAHOO.util.Event.onDOMReady(function(){ + // Survey.Comm.setUrl('/' + document.getElementById('assetPath').value); + Survey.Comm.callServer('', 'loadQuestions'); +}); \ No newline at end of file diff --git a/www/extras/wobject/Survey/administersurvey/comm.js b/www/extras/wobject/Survey/administersurvey/comm.js index 9947facb4..18d2000aa 100644 --- a/www/extras/wobject/Survey/administersurvey/comm.js +++ b/www/extras/wobject/Survey/administersurvey/comm.js @@ -1,73 +1,76 @@ -if (typeof Survey == "undefined") { + +/*global Survey, YAHOO */ +if (typeof Survey === "undefined") { var Survey = {}; } -Survey.Comm= new function(){ +(function(){ - - this.url = ''; - this.setUrl = function(u){this.url = u;} - var callMade = 0; - var request = function(sUrl,callback,postData,form, hasFile){ - if(form != undefined){ - if(hasFile){ - YAHOO.util.Connect.setForm(form,true); + var callMade = 0; + var request = function(sUrl, callback, postData, form, hasFile){ + if (form) { + if (hasFile) { + YAHOO.util.Connect.setForm(form, true); //YAHOO.log('set file was true'); - }else{ + } + else { //YAHOO.log('set file was false'); YAHOO.util.Connect.setForm(form); } //YAHOO.log('setForm was true'); } - if(callMade == 1){ + if (callMade) { alert("Waiting on previous request"); - }else{ + } + else { callMade = 1; -YAHOO.log(sUrl); + YAHOO.log(sUrl); YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData); } - } - - - this.callback = { - upload:function(o){ - callMade = 0; - Survey.Comm.callServer('','loadQuestions'); - }, - success:function(o){ - window.scrollTo(0,0); - callMade = 0; - var response = ''; - response = YAHOO.lang.JSON.parse(o.responseText); - if(response.type == 'displayquestions'){ - Survey.Form.displayQuestions(response); - }else if(response.type == 'forward'){ -//YAHOO.log("going to "+response.url); - location.href=response.url; - }else{ - alert("bad response"); - } - }, - failure: function(o){ - callMade = 0; - if(o.status == -1){ - alert("Last request timed out, please try again"); - }else{ - alert("Last request failed "+o.statusText); - } - }, }; - - this.callServer = function(data,functionName,form,hasFile){ - var postData; - if(form == undefined){ - postData = "data="+YAHOO.lang.JSON.stringify(data,data); - //YAHOO.log(postData); + + + Survey.Comm = { + callback: { + upload: function(o){ + callMade = 0; + Survey.Comm.callServer('', 'loadQuestions'); + }, + success: function(o){ + window.scrollTo(0, 0); + callMade = 0; + var response = ''; + response = YAHOO.lang.JSON.parse(o.responseText); + if (response.type === 'displayquestions') { + Survey.Form.displayQuestions(response); + } + else + if (response.type === 'forward') { + //YAHOO.log("going to "+response.url); + location.href = response.url; + } + else { + alert("bad response"); + } + }, + failure: function(o){ + callMade = 0; + if (o.status === -1) { + alert("Last request timed out, please try again"); + } + else { + alert("Last request failed " + o.statusText); + } + } + }, + callServer: function(data, functionName, form, hasFile){ + var postData; + if (!form) { + postData = "data=" + YAHOO.lang.JSON.stringify(data, data); + } + //var sUrl = this.url + "?func="+functionName; + var sUrl = "?func=" + functionName; + request(sUrl, this.callback, postData, form, hasFile); } - var sUrl = this.url + "?func="+functionName; - request(sUrl,this.callback,postData,form,hasFile); - } - - - -}(); + }; +})();