Added Survey back button, with option to turn it on/off, tests, and i18n
Noticed that some Survey tests are broken, will fix tomorrow
This commit is contained in:
parent
9c228e2c83
commit
c3ea6d4683
10 changed files with 294 additions and 81 deletions
|
|
@ -34,6 +34,7 @@
|
||||||
- added: ThingyRecord allows you to sell records in a Thingy (like a classified ad)
|
- added: ThingyRecord allows you to sell records in a Thingy (like a classified ad)
|
||||||
- fixed: #10109: Matrix 2.0 - Updates to product listing by maintainer account require admin approval
|
- fixed: #10109: Matrix 2.0 - Updates to product listing by maintainer account require admin approval
|
||||||
- fixed #10146: Thingy duplicate errors
|
- fixed #10146: Thingy duplicate errors
|
||||||
|
- Added Survey back button
|
||||||
|
|
||||||
7.7.3
|
7.7.3
|
||||||
- fixed #10094: double explanation in thread help
|
- fixed #10094: double explanation in thread help
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -37,7 +37,7 @@ allMaintenanceSingleton($session);
|
||||||
unsetPackageFlags($session);
|
unsetPackageFlags($session);
|
||||||
installThingyRecord( $session );
|
installThingyRecord( $session );
|
||||||
installPluggableTax( $session );
|
installPluggableTax( $session );
|
||||||
|
addSurveyBackButtonColumn( $session );
|
||||||
|
|
||||||
finish($session); # this line required
|
finish($session); # this line required
|
||||||
|
|
||||||
|
|
@ -247,6 +247,12 @@ ENDSQL
|
||||||
print "DONE!\n" unless $quiet;
|
print "DONE!\n" unless $quiet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub addSurveyBackButtonColumn{
|
||||||
|
my $session = shift;
|
||||||
|
print "\tAdding allowBackBtn column to Survey table... " unless $quiet;
|
||||||
|
$session->db->write("alter table Survey add column `allowBackBtn` TINYINT(3)");
|
||||||
|
print "Done.\n" unless $quiet;
|
||||||
|
}
|
||||||
|
|
||||||
# -------------- DO NOT EDIT BELOW THIS LINE --------------------------------
|
# -------------- DO NOT EDIT BELOW THIS LINE --------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,8 +197,6 @@ sub definition {
|
||||||
fieldType => 'workflow',
|
fieldType => 'workflow',
|
||||||
label => 'Survey End Workflow',
|
label => 'Survey End Workflow',
|
||||||
hoverHelp => 'Workflow to run when user completes the Survey',
|
hoverHelp => 'Workflow to run when user completes the Survey',
|
||||||
# label => $i18n->get('editForm workflowIdAddEntry label'),
|
|
||||||
# hoverHelp => $i18n->get('editForm workflowIdAddEntry description'),
|
|
||||||
none => 1,
|
none => 1,
|
||||||
},
|
},
|
||||||
quizModeSummary => {
|
quizModeSummary => {
|
||||||
|
|
@ -207,13 +205,16 @@ sub definition {
|
||||||
tab => 'properties',
|
tab => 'properties',
|
||||||
label => $i18n->get('Quiz mode summaries'),
|
label => $i18n->get('Quiz mode summaries'),
|
||||||
hoverHelp => $i18n->get('Quiz mode summaries help'),
|
hoverHelp => $i18n->get('Quiz mode summaries help'),
|
||||||
}
|
},
|
||||||
|
allowBackBtn => {
|
||||||
|
fieldType => 'yesNo',
|
||||||
|
defaultValue => 0,
|
||||||
|
tab => 'properties',
|
||||||
|
label => $i18n->get('Allow back button'),
|
||||||
|
hoverHelp => $i18n->get('Allow back button help'),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
#my $defaultMC = $session->
|
|
||||||
|
|
||||||
#%properties = ();
|
|
||||||
|
|
||||||
push @{$definition}, {
|
push @{$definition}, {
|
||||||
assetName => $i18n->get('assetName'),
|
assetName => $i18n->get('assetName'),
|
||||||
icon => 'survey.gif',
|
icon => 'survey.gif',
|
||||||
|
|
@ -1154,6 +1155,41 @@ sub www_submitQuestions {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 www_goBack
|
||||||
|
|
||||||
|
Handles the Survey back button
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub www_goBack {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
if ( !$self->canTakeSurvey() ) {
|
||||||
|
$self->session->log->debug('canTakeSurvey false, surveyEnd');
|
||||||
|
return $self->surveyEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
my $responseId = $self->responseId();
|
||||||
|
if ( !$responseId ) {
|
||||||
|
$self->session->log->debug('No response id, surveyEnd');
|
||||||
|
return $self->surveyEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !$self->get('allowBackBtn') ) {
|
||||||
|
$self->session->log->debug('allowBackBtn false, delegating to www_loadQuestions');
|
||||||
|
return $self->www_loadQuestions();
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->responseJSON->pop;
|
||||||
|
$self->persistResponseJSON;
|
||||||
|
|
||||||
|
return $self->www_loadQuestions();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
=head2 getSummary
|
=head2 getSummary
|
||||||
|
|
@ -1305,13 +1341,6 @@ Sends the processed template and questions structure to the client
|
||||||
|
|
||||||
sub prepareShowSurveyTemplate {
|
sub prepareShowSurveyTemplate {
|
||||||
my ( $self, $section, $questions ) = @_;
|
my ( $self, $section, $questions ) = @_;
|
||||||
# my %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
|
|
||||||
# );
|
|
||||||
my %textArea = ( 'TextArea', 1 );
|
my %textArea = ( 'TextArea', 1 );
|
||||||
my %text = ( 'Text', 1, 'Email', 1, 'Phone Number', 1, 'Text Date', 1, 'Currency', 1, 'Number', 1 );
|
my %text = ( 'Text', 1, 'Email', 1, 'Phone Number', 1, 'Text Date', 1, 'Currency', 1, 'Number', 1 );
|
||||||
my %slider = ( 'Slider', 1, 'Dual Slider - Range', 1, 'Multi Slider - Allocate', 1 );
|
my %slider = ( 'Slider', 1, 'Dual Slider - Range', 1, 'Multi Slider - Allocate', 1 );
|
||||||
|
|
@ -1379,6 +1408,7 @@ sub prepareShowSurveyTemplate {
|
||||||
if(scalar @{$questions} == ($section->{totalQuestions} - $section->{questionsAnswered})){
|
if(scalar @{$questions} == ($section->{totalQuestions} - $section->{questionsAnswered})){
|
||||||
$section->{isLastPage} = 1
|
$section->{isLastPage} = 1
|
||||||
}
|
}
|
||||||
|
$section->{allowBackBtn} = $self->get('allowBackBtn');
|
||||||
|
|
||||||
my $out = $self->processTemplate( $section, $self->get('surveyQuestionsId') );
|
my $out = $self->processTemplate( $section, $self->get('surveyQuestionsId') );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ sub value {
|
||||||
if (my $other_instance = $other_instances->{$asset_spec}) {
|
if (my $other_instance = $other_instances->{$asset_spec}) {
|
||||||
my $values = $other_instance->{values};
|
my $values = $other_instance->{values};
|
||||||
my $value = $values->{$key};
|
my $value = $values->{$key};
|
||||||
$session->log->debug("[$asset_spec, $key] resolves to [$value]");
|
$session->log->debug("value($asset_spec, $key) resolves to [$value]");
|
||||||
return $value;
|
return $value;
|
||||||
} else {
|
} else {
|
||||||
# Throw an exception, triggering run() to resolve the external reference and re-run
|
# Throw an exception, triggering run() to resolve the external reference and re-run
|
||||||
|
|
@ -63,7 +63,7 @@ sub value {
|
||||||
}
|
}
|
||||||
my $key = shift;
|
my $key = shift;
|
||||||
my $value = $values->{$key};
|
my $value = $values->{$key};
|
||||||
$session->log->debug("[$key] resolves to [$value]");
|
$session->log->debug("value($key) resolves to [$value]");
|
||||||
return $value; # scalar variable, so no need to clone
|
return $value; # scalar variable, so no need to clone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ sub score {
|
||||||
if (my $other_instance = $other_instances->{$asset_spec}) {
|
if (my $other_instance = $other_instances->{$asset_spec}) {
|
||||||
my $scores = $other_instance->{scores};
|
my $scores = $other_instance->{scores};
|
||||||
my $score = $scores->{$key};
|
my $score = $scores->{$key};
|
||||||
$session->log->debug("[$asset_spec, $key] resolves to [$score]");
|
$session->log->debug("score($asset_spec, $key) resolves to [$score]");
|
||||||
return $score;
|
return $score;
|
||||||
} else {
|
} else {
|
||||||
# Throw an exception, triggering run() to resolve the external reference and re-run
|
# Throw an exception, triggering run() to resolve the external reference and re-run
|
||||||
|
|
@ -94,7 +94,7 @@ sub score {
|
||||||
}
|
}
|
||||||
my $key = shift;
|
my $key = shift;
|
||||||
my $score = $scores->{$key};
|
my $score = $scores->{$key};
|
||||||
$session->log->debug("[$key] resolves to [$score]");
|
$session->log->debug("score($key) resolves to [$score]");
|
||||||
return $score; # scalar variable, so no need to clone
|
return $score; # scalar variable, so no need to clone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,59 +39,6 @@ number of questions answered (L<"questionsAnswered">) and the Survey start time
|
||||||
|
|
||||||
This package is not intended to be used by any other Asset in WebGUI.
|
This package is not intended to be used by any other Asset in WebGUI.
|
||||||
|
|
||||||
=head2 surveyOrder
|
|
||||||
|
|
||||||
This data strucutre is an array (reference) of Survey addresses (see
|
|
||||||
L<WebGUI::Asset::Wobject::Survey::SurveyJSON/Address Parameter>), stored in the order
|
|
||||||
in which items are presented to the user.
|
|
||||||
|
|
||||||
By making use of L<WebGUI::Asset::Wobject::Survey::SurveyJSON> methods which expect address params as
|
|
||||||
arguments, you can access Section/Question/Answer items in order by iterating over surveyOrder.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
# Access sections in order..
|
|
||||||
for my $address (@{ $self->surveyOrder }) {
|
|
||||||
my $section = $self->survey->section( $address );
|
|
||||||
# etc..
|
|
||||||
}
|
|
||||||
|
|
||||||
In general, the surveyOrder data structure looks like:
|
|
||||||
|
|
||||||
[ $sectionIndex, $questionIndex, [ $answerIndex1, $answerIndex2, ....]
|
|
||||||
|
|
||||||
There is one array element for every section and address in the survey. If there are
|
|
||||||
no questions, or no addresses, those array elements will not be present.
|
|
||||||
|
|
||||||
=head2 responses
|
|
||||||
|
|
||||||
This data structure stores a snapshot of all question responses. Both question data and answer data
|
|
||||||
is stored in this hash reference.
|
|
||||||
|
|
||||||
Questions keys are constructed by hypenating the relevant L<"sIndex"> and L<"qIndex">.
|
|
||||||
Answer keys are constructed by hypenating the relevant L<"sIndex">, L<"qIndex"> and L<aIndex|"aIndexes">.
|
|
||||||
|
|
||||||
Question entries only contain a comment field:
|
|
||||||
{
|
|
||||||
...
|
|
||||||
questionId => {
|
|
||||||
comment => "question comment",
|
|
||||||
}
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
Answers entries contain: value (the recorded value), time and comment fields.
|
|
||||||
|
|
||||||
{
|
|
||||||
...
|
|
||||||
answerId => {
|
|
||||||
value => "recorded answer value",
|
|
||||||
time => time(),
|
|
||||||
comment => "answer comment",
|
|
||||||
},
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
|
|
@ -252,7 +199,7 @@ sub hasTimedOut{
|
||||||
|
|
||||||
=head2 lastResponse ([ $responseIndex ])
|
=head2 lastResponse ([ $responseIndex ])
|
||||||
|
|
||||||
Mutator. The lastResponse property represents the index of the most recent surveyOrder entry shown.
|
Mutator. The lastResponse property represents the surveyOrder index of the most recent item shown.
|
||||||
|
|
||||||
This method returns (and optionally sets) the value of lastResponse.
|
This method returns (and optionally sets) the value of lastResponse.
|
||||||
|
|
||||||
|
|
@ -325,8 +272,29 @@ sub startTime {
|
||||||
|
|
||||||
=head2 surveyOrder
|
=head2 surveyOrder
|
||||||
|
|
||||||
Accessor for surveyOrder (see L<"surveyOrder">).
|
Accessor. Initialized on first access via L<"initSurveyOrder">.
|
||||||
Initialized on first access via L<"initSurveyOrder">.
|
|
||||||
|
This data strucutre is an array (reference) of Survey addresses (see
|
||||||
|
L<WebGUI::Asset::Wobject::Survey::SurveyJSON/Address Parameter>), stored in the order
|
||||||
|
in which items are presented to the user.
|
||||||
|
|
||||||
|
In general, the surveyOrder data structure looks like:
|
||||||
|
|
||||||
|
[ $sectionIndex, $questionIndex, [ $answerIndex1, $answerIndex2, ....]
|
||||||
|
|
||||||
|
There is one array element for every section and address in the survey. If there are
|
||||||
|
no questions, or no addresses, those array elements will not be present.
|
||||||
|
|
||||||
|
By making use of L<WebGUI::Asset::Wobject::Survey::SurveyJSON> methods which expect address params as
|
||||||
|
arguments, you can access Section/Question/Answer items in order by iterating over surveyOrder.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
# Access sections in order..
|
||||||
|
for my $address (@{ $self->surveyOrder }) {
|
||||||
|
my $section = $self->survey->section( $address );
|
||||||
|
# etc..
|
||||||
|
}
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
|
|
@ -1242,11 +1210,32 @@ sub response {
|
||||||
return $self->{_response};
|
return $self->{_response};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
=head2 responses
|
=head2 responses
|
||||||
|
|
||||||
Mutator for the L<"responses"> property.
|
Mutator. Note, this is an unsafe reference.
|
||||||
|
|
||||||
Note, this is an unsafe reference.
|
This data structure stores a snapshot of all question responses. Both question data and answer data
|
||||||
|
is stored in this hash reference.
|
||||||
|
|
||||||
|
Questions keys are constructed by hypenating the relevant L<"sIndex"> and L<"qIndex">.
|
||||||
|
Answer keys are constructed by hypenating the relevant L<"sIndex">, L<"qIndex"> and L<aIndex|"aIndexes">.
|
||||||
|
|
||||||
|
{
|
||||||
|
# Question entries only contain a comment field, e.g.
|
||||||
|
'0-0' => {
|
||||||
|
comment => "question comment",
|
||||||
|
},
|
||||||
|
# ...
|
||||||
|
# Answers entries contain: value (the recorded value), time and comment fields.
|
||||||
|
'0-0-0' => {
|
||||||
|
value => "recorded answer value",
|
||||||
|
time => time(),
|
||||||
|
comment => "answer comment",
|
||||||
|
},
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
|
|
@ -1259,6 +1248,62 @@ sub responses {
|
||||||
return $self->response->{responses};
|
return $self->response->{responses};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head2 pop
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub pop {
|
||||||
|
my $self = shift;
|
||||||
|
my %responses = %{ $self->responses };
|
||||||
|
|
||||||
|
# Iterate over responses first time to determine time of most recent response(s)
|
||||||
|
my $lastResponseTime;
|
||||||
|
for my $r ( values %responses ) {
|
||||||
|
if ( $r->{time} ) {
|
||||||
|
$lastResponseTime
|
||||||
|
= !$lastResponseTime || $r->{time} > $lastResponseTime
|
||||||
|
? $r->{time}
|
||||||
|
: $lastResponseTime
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unless $lastResponseTime;
|
||||||
|
|
||||||
|
my $popped;
|
||||||
|
my $poppedQuestions;
|
||||||
|
# Iterate again, removing most recent responses
|
||||||
|
while (my ($address, $r) = each %responses ) {
|
||||||
|
if ( $r->{time} == $lastResponseTime) {
|
||||||
|
$popped->{$address} = $r;
|
||||||
|
delete $self->responses->{$address};
|
||||||
|
|
||||||
|
# Remove associated question/comment entry
|
||||||
|
my ($sIndex, $qIndex, $aIndex) = split /-/, $address;
|
||||||
|
my $qAddress = "$sIndex-$qIndex";
|
||||||
|
$popped->{$qAddress} = $responses{$qAddress};
|
||||||
|
delete $self->responses->{$qAddress};
|
||||||
|
|
||||||
|
# while we're here, build lookup table of popped question ids
|
||||||
|
$poppedQuestions->{$qAddress} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now, nextResponse should be set to index of the first popped question we can find in surveyOrder
|
||||||
|
my $nextResponse = 0;
|
||||||
|
for my $address (@{ $self->surveyOrder }) {
|
||||||
|
my $questionId = "$address->[0]-$address->[1]";
|
||||||
|
if ($poppedQuestions->{$questionId} ) {
|
||||||
|
$self->session->log->debug("setting nextResponse to $nextResponse");
|
||||||
|
$self->nextResponse($nextResponse);
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
$nextResponse++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $popped;
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
=head2 survey
|
=head2 survey
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,8 @@ our $HELP = {
|
||||||
{ 'name' => 'showProgress' },
|
{ 'name' => 'showProgress' },
|
||||||
{ 'name' => 'showTimeLimit' },
|
{ 'name' => 'showTimeLimit' },
|
||||||
{ 'name' => 'minutesLeft' },
|
{ 'name' => 'minutesLeft' },
|
||||||
|
{ 'name' => 'isLastPage' },
|
||||||
|
{ 'name' => 'allowBackBtn' },
|
||||||
{ 'name' => 'questions',
|
{ 'name' => 'questions',
|
||||||
'variables' => [
|
'variables' => [
|
||||||
{ 'name' => 'id' },
|
{ 'name' => 'id' },
|
||||||
|
|
|
||||||
|
|
@ -576,6 +576,16 @@ the time limit for completing the survey. This message is in the 'take survey' t
|
||||||
message => q|The template used to display the Survey Edit screen.|,
|
message => q|The template used to display the Survey Edit screen.|,
|
||||||
lastUpdated => 0,
|
lastUpdated => 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'Allow back button' => {
|
||||||
|
message => q|Allow back button|,
|
||||||
|
lastUpdated => 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
'Allow back button help' => {
|
||||||
|
message => q|Allow the user to navigate backwards in a Survey.|,
|
||||||
|
lastUpdated => 0,
|
||||||
|
},
|
||||||
|
|
||||||
'Max user responses' => {
|
'Max user responses' => {
|
||||||
message => q|Max user responses|,
|
message => q|Max user responses|,
|
||||||
|
|
@ -1380,6 +1390,24 @@ section/answer.|,
|
||||||
context => q|Sub-label for "Year Month" question type|,
|
context => q|Sub-label for "Year Month" question type|,
|
||||||
lastUpdated => 0,
|
lastUpdated => 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'back' => {
|
||||||
|
message => q|Back|,
|
||||||
|
context => q|Back button label on Take Survey page|,
|
||||||
|
lastUpdated => 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
'continue' => {
|
||||||
|
message => q|Continue|,
|
||||||
|
context => q|Continue button label on Take Survey page|,
|
||||||
|
lastUpdated => 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
'finish' => {
|
||||||
|
message => q|Finish|,
|
||||||
|
context => q|Finish button label on Take Survey page|,
|
||||||
|
lastUpdated => 0,
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ my $session = WebGUI::Test->session;
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
# Tests
|
# Tests
|
||||||
my $tests = 64;
|
my $tests = 74;
|
||||||
plan tests => $tests + 1;
|
plan tests => $tests + 1;
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
|
|
@ -561,9 +561,103 @@ cmp_deeply(
|
||||||
'recordResponses: if the answer is all whitespace, it is skipped over'
|
'recordResponses: if the answer is all whitespace, it is skipped over'
|
||||||
);
|
);
|
||||||
is($rJSON->questionsAnswered, 0, 'question was all whitespace, not answered');
|
is($rJSON->questionsAnswered, 0, 'question was all whitespace, not answered');
|
||||||
#delete $rJSON->{_session};
|
|
||||||
#delete $rJSON->survey->{_session};
|
####################################################
|
||||||
#diag(Dumper($rJSON));
|
#
|
||||||
|
# pop
|
||||||
|
#
|
||||||
|
####################################################
|
||||||
|
$rJSON->responses({});
|
||||||
|
$rJSON->lastResponse(2);
|
||||||
|
is($rJSON->pop, undef, 'pop with no responses returns undef');
|
||||||
|
cmp_deeply($rJSON->responses, {}, 'initially no responses');
|
||||||
|
$rJSON->recordResponses({
|
||||||
|
'1-0comment' => 'Section 1, question 0 comment',
|
||||||
|
'1-0-0' => 'First answer',
|
||||||
|
'1-0-0comment' => 'Section 1, question 0, answer 0 comment',
|
||||||
|
'1-1comment' => 'Section 1, question 1 comment',
|
||||||
|
'1-1-0' => 'Second answer',
|
||||||
|
'1-1-0comment' => 'Section 1, question 1, answer 0 comment',
|
||||||
|
|
||||||
|
});
|
||||||
|
my $popped = $rJSON->pop;
|
||||||
|
cmp_deeply($popped, {
|
||||||
|
# the first q answer
|
||||||
|
'1-0-0' => {
|
||||||
|
value => 1,
|
||||||
|
comment => 'Section 1, question 0, answer 0 comment',
|
||||||
|
time => num(time(), 3),
|
||||||
|
},
|
||||||
|
# the second q answer
|
||||||
|
'1-1-0' => {
|
||||||
|
value => 0,
|
||||||
|
comment => 'Section 1, question 1, answer 0 comment',
|
||||||
|
time => num(time(), 3),
|
||||||
|
},
|
||||||
|
# the first question comment
|
||||||
|
'1-0' => {
|
||||||
|
comment => 'Section 1, question 0 comment',
|
||||||
|
},
|
||||||
|
# the second question comment
|
||||||
|
'1-1' => {
|
||||||
|
comment => 'Section 1, question 1 comment',
|
||||||
|
}
|
||||||
|
}, 'pop removes only existing response');
|
||||||
|
cmp_deeply($rJSON->responses, {}, 'and now back to no responses');
|
||||||
|
is($rJSON->pop, undef, 'additional pop has no effect');
|
||||||
|
|
||||||
|
$rJSON->responses({});
|
||||||
|
$rJSON->lastResponse(2);
|
||||||
|
$rJSON->recordResponses({
|
||||||
|
'1-0comment' => 'Section 1, question 0 comment',
|
||||||
|
'1-0-0' => 'First answer',
|
||||||
|
'1-0-0comment' => 'Section 1, question 0, answer 0 comment',
|
||||||
|
'1-1comment' => 'Section 1, question 1 comment',
|
||||||
|
'1-1-0' => 'Second answer',
|
||||||
|
'1-1-0comment' => 'Section 1, question 1, answer 0 comment',
|
||||||
|
});
|
||||||
|
|
||||||
|
# fake time so that pop thinks first response happened earlier
|
||||||
|
$rJSON->responses->{'1-0-0'}->{time} -= 1;
|
||||||
|
cmp_deeply($rJSON->pop, {
|
||||||
|
# the second q answer
|
||||||
|
'1-1-0' => {
|
||||||
|
value => 0,
|
||||||
|
comment => 'Section 1, question 1, answer 0 comment',
|
||||||
|
time => num(time(), 3),
|
||||||
|
},
|
||||||
|
# the second question comment
|
||||||
|
'1-1' => {
|
||||||
|
comment => 'Section 1, question 1 comment',
|
||||||
|
}
|
||||||
|
}, 'pop now only removes the most recent response');
|
||||||
|
cmp_deeply($rJSON->responses, {
|
||||||
|
# the first q answer
|
||||||
|
'1-0-0' => {
|
||||||
|
value => 1,
|
||||||
|
comment => 'Section 1, question 0, answer 0 comment',
|
||||||
|
time => num(time(), 3),
|
||||||
|
},
|
||||||
|
# the first question comment
|
||||||
|
'1-0' => {
|
||||||
|
comment => 'Section 1, question 0 comment',
|
||||||
|
},
|
||||||
|
}, 'and first response left in tact');
|
||||||
|
cmp_deeply($rJSON->pop, {
|
||||||
|
# the first q answer
|
||||||
|
'1-0-0' => {
|
||||||
|
value => 1,
|
||||||
|
comment => 'Section 1, question 0, answer 0 comment',
|
||||||
|
time => num(time(), 3),
|
||||||
|
},
|
||||||
|
# the first question comment
|
||||||
|
'1-0' => {
|
||||||
|
comment => 'Section 1, question 0 comment',
|
||||||
|
},
|
||||||
|
}, 'second pop removes first response');
|
||||||
|
cmp_deeply($rJSON->responses, {}, '..and now responses hash empty again');
|
||||||
|
|
||||||
|
is($rJSON->pop, undef, 'additional pop has no effect');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,11 @@ if (typeof Survey === "undefined") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goBack(event){
|
||||||
|
YAHOO.log("Going back");
|
||||||
|
Survey.Comm.callServer('', 'goBack');
|
||||||
|
}
|
||||||
|
|
||||||
//an object which creates sliders for allocation type questions and then manages their events and keeps them from overallocating
|
//an object which creates sliders for allocation type questions and then manages their events and keeps them from overallocating
|
||||||
function sliderManager(q, t){
|
function sliderManager(q, t){
|
||||||
var total = sliderWidth;
|
var total = sliderWidth;
|
||||||
|
|
@ -527,6 +532,7 @@ if (typeof Survey === "undefined") {
|
||||||
span.style.display = 'block';
|
span.style.display = 'block';
|
||||||
|
|
||||||
document.getElementById('survey-header').appendChild(span);
|
document.getElementById('survey-header').appendChild(span);
|
||||||
|
|
||||||
YAHOO.util.Event.addListener("showQuestionsButton", "click", function(){
|
YAHOO.util.Event.addListener("showQuestionsButton", "click", function(){
|
||||||
document.getElementById('showQuestionsButton').style.display = 'none';
|
document.getElementById('showQuestionsButton').style.display = 'none';
|
||||||
if (s.everyPageTitle !== '1') {
|
if (s.everyPageTitle !== '1') {
|
||||||
|
|
@ -696,6 +702,7 @@ if (typeof Survey === "undefined") {
|
||||||
butts.push(b);
|
butts.push(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
YAHOO.util.Event.addListener("backbutton", "click", goBack);
|
||||||
YAHOO.util.Event.addListener("submitbutton", "click", formsubmit);
|
YAHOO.util.Event.addListener("submitbutton", "click", formsubmit);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue