View Issue Details

IDProjectCategoryView StatusLast Update
04643User patchesSurvey Takingpublic2010-12-14 13:02
Reporteruser9586Assigned Toc_schmitz 
PrioritynormalSeverityminor 
Status closedResolutionfixed 
Product Version1.90 
Target VersionFixed in Version1.91 
Summary04643: Implement questionnaire navigation/jumping.
Description

This patch implements 'questionnaire navigation/jumping', by showing a sidebar containing a question index of the current survey.

The premise of the patch was discussed here:

http://sourceforge.net/mailarchive/message.php?msg_name=20100908124843.af9a493a.yuri.delia%40eurac.edu

In short: users should be able to skip questions and return to them later, quickly.

This patch adds a new per-survey setting called "Show Question Index / Allow jumping".

In question-by-question mode, the question index shows a row for each question. The current question is highlighted, while skipped questions are shown in red. Only questions up to the current one are shown (that is, unseen questions are not shown in the index), to avoid users seeing conditional questions. The question text is truncated via CSS, but it is available entirely by hovering in the tooltip.

The user can click any question to go back&forth the questionnaire. Mandatory questions cannot be skipped, unless the mandatory question is the last one being shown (in that case you can still go back). When jumping, the group introduction page is not shown. On group introductions the index itself is also not shown.

In group-by-group mode, each row contains a group. Navigation works the same as in question-by-question. In this mode, however, a group is red if any of the questions is left unanswered.

In both modes, when the last question/group is shown, the "Submit" button appears at the bottom of the index, allowing to submit the questionnaire instantly instead of requiring users to go to the last question.

The question index is scrollable vertically and synced using javascript. It can be customized easily via css.

The 'Show [<< Prev] button' setting is obviously overridden by this setting.

You can see a screenshot here:

http://www.thregr.org/~wavexx/tmp/limeindex.png

Additional Information

This patch adds a new 'allowjmp' column to the survey table, and changes (albeit only slightly) the start/stoppage template to make room for the question index (an extra div is inserted before the "outframe" table).

The CSS is changed on-the-fly by injecting some javascript in the page when the question index is shown. This allows the index width to be completely specified in the CSS.

The changes are implemented only for mysql, the default template and in english language.

The diff was run against my local copy, which has

http://bugs.limesurvey.org/view.php?id=4594#attachments

applied (which bumps the DB version and handles the DB upgrade process).

TagsNo tags attached.
Complete LimeSurvey version number (& build)9114

Activities

user9586

2010-10-02 19:53

  ~12976

Revised patch also highlights (via CSS) missing questions in group-by-group mode.

Mazi

Mazi

2010-10-03 19:50

partner   ~12981

Carsten, can you discuss details with Thibault and check the patch?!

DenisChenu

DenisChenu

2010-10-04 21:08

developer   ~12987

I think jumping are good only for administrator .

I think jumping is bad for surveyor , no ?

user9586

2010-10-05 10:19

  ~12997

Please read the message in the mailing-list.
This feature was requested by surveyors themselves during a comparative study between paper/electronic surveys.

c_schmitz

c_schmitz

2010-10-11 23:55

administrator   ~13091

Can you please provide the patch as a subversion patch (svn diff) against our 1.91 development version at the subversion branch at :
https://limesurvey.svn.sourceforge.net/svnroot/limesurvey/source/limesurvey_dev

Thank you!

user9586

2010-11-11 16:05

  ~13502

Next patch. This time I (hopefully) added all the SQL changes required for all the databases.

Like I said in earlier comments, the most significant impact of this patch is an additional DIV in the main starttemplate, which takes the place of the "outerframe" class. The main table is now of "innerframe" class. This contraption is needed to center the table when the question index is visible.

The other templates work unchanged if no question index is visible. Without the changes to the CSS/template, the question index appears after the navigation controls.

As usual, I'm available for any question or changes.

c_schmitz

c_schmitz

2010-11-15 02:31

administrator   ~13524

Last edited: 2010-11-15 02:33

View 2 revisions

This patch does not seem to be based on limesurvey_dev branch?

user9586

2010-11-15 11:14

  ~13525

It is. limesurvey_dev#9469

c_schmitz

c_schmitz

2010-11-15 16:28

administrator   ~13526

Last edited: 2010-11-15 16:28

View 2 revisions

Ok, here some feedback for the patch:

General problems with the patch:

  • A user changes the answer on an already answered question and then tries to directly go to question which had a condition depending on the first one and that condition means it is not shown anymore after changing the answer.
    On a first test it looks like it is hanging in an endless loop because clicking a link in the index submits the answers on the current page and the new destination does not exist anymore (because it is hidden).
    Please check and test this thoroughly - it is most important that this works with conditions flawlessly.

  • Jumping should not be activatable when survey is in 'all-in-mode' and should be deactivated (with a hint to the user) if all-in-one mode is activated.

  • All templates need to be adjusted. Did you test it with different browsers (IE6 and up)?

General source code problems:

  • function array_invert is IMHO not needed because there is a function named array_flip in PHP.

  • Your functions are missing proper comment sections explaining the params in PHPDoc style.

  • Variables and functions have to be named according to coding guidelines: http://docs.limesurvey.org/tiki-index.php?page=Coding+Rules&amp;structure=LimeSurvey+development

  • Field should have a proper long name not a shortcut name: 'allowjumps' instead of 'allowjmp'

  • Wherever it makes sense please insert comments so other devs in the future know what you inteded at certain locations in the source code, epsically index.php, group.php, question.php

user9586

2010-11-15 20:26

  ~13527

I remember trying the first case. The code should not hang of course: it should skip to the first visible question. I remember checking this in the "limesurvey" branch but will check that again.

By all-in-mode you mean all-in-one-page mode? In that case, jumping is implicitly disabled. I will add an hint.

I only changed the default template, but I tested it against IE7 and onward. I will try to see if I've got an IE6 around to test.

array_invert is necessary because it preserves multiple keys/values during the inversion, whereas array_flip flattens the structure.

c_schmitz

c_schmitz

2010-11-15 20:47

administrator   ~13528

Reminder sent to: lemeur

Thibault, can you have a look at this too and give some feedback, please?

user9586

2010-11-22 19:48

  ~13571

Here's the updated patch. I've followed your advice, but still didn't update all the templates. If you can comment on the patch first, I can finish the changes for all the remaining templates.

I took the liberty of re-indenting a somewhat large chunk on question.php (around line 105) which was completely messed up. There are only two lines affected besides in indent.

lemeur

lemeur

2010-11-22 21:19

developer   ~13572

I've done only a quick review so far, I think it's a rather clean patch.
I vote for integrating it to the _dev branch.

Thibault

c_schmitz

c_schmitz

2010-11-23 18:32

administrator   ~13594

Patch looks good. Please finish the other templates.

c_schmitz

c_schmitz

2010-11-23 18:32

administrator   ~13595

Do you want me to apply the patch so far and you do only a small one for the templates?

user9586

2010-11-24 17:04

 

patch-svn-3.diff (55,529 bytes)
Index: group.php
===================================================================
--- group.php	(revision 9507)
+++ group.php	(working copy)
@@ -17,15 +17,24 @@
 
 if (!isset($homedir) || isset($_REQUEST['$homedir'])) {die("Cannot run this script directly");}
 
-//Move current step ###########################################################################
 if (!isset($_SESSION['step'])) {$_SESSION['step']=0;}
 if (!isset($_SESSION['totalsteps'])) {$_SESSION['totalsteps']=0;}
+if (!isset($_SESSION['maxstep'])) {$_SESSION['maxstep']=0;}
 if (!isset($gl)) {$gl=array('null');}
+$_SESSION['prevstep']=$_SESSION['step'];
+
+//Move current step ###########################################################################
 if (isset($move) && $move == 'moveprev' && $thissurvey['allowprev']=='Y') {$_SESSION['step'] = $thisstep-1;}
 if (isset($move) && $move == "movenext") {
     if ($_SESSION['step']==$thisstep)
-    $_SESSION['step'] = $thisstep+1;
+        $_SESSION['step'] = $thisstep+1;
 }
+if (isset($move) && bIsNumericInt($move) && $thissurvey['allowjumps']=='Y')
+{
+    $move = (int)$move;
+    if ($move > 0 && (($move <= $_SESSION['step']) || (isset($_SESSION['maxstep']) && $move <= $_SESSION['maxstep'])))
+        $_SESSION['step'] = $move;
+}
 
 // We do not keep the participant session anymore when the same browser is used to answer a second time a survey (let's think of a library PC for instance).
 // Previously we used to keep the session and redirect the user to the
@@ -36,7 +45,9 @@
 
 //CHECK IF ALL MANDATORY QUESTIONS HAVE BEEN ANSWERED ############################################
 //First, see if we are moving backwards or doing a Save so far, and its OK not to check:
-if ($allowmandbackwards==1 && ((isset($move) &&  $move == 'moveprev') || (isset($_POST['saveall']) && $_POST['saveall'] == $clang->gT("Save your responses so far"))))
+if ($allowmandbackwards==1 && (
+    (isset($move) && ($move == "moveprev" || (is_int($move) && $_SESSION['prevstep'] == $_SESSION['maxstep']))) ||
+    (isset($_POST['saveall']) && $_POST['saveall'] == $clang->gT("Save your responses so far"))))
 {
     $backok="Y";
 }
@@ -61,11 +72,11 @@
 {
     while(isset($_SESSION['grouplist'][$_SESSION['step']-1]) && checkgroupfordisplay($_SESSION['grouplist'][$_SESSION['step']-1][0]) === false)
     {
-        if (isset($move) && $move == "moveprev")
+        if ($_SESSION['prevstep'] <= $_SESSION['step'])
         {
             $_SESSION['step']=$_SESSION['step']-1;
         }
-        if (isset($move) && $move == "movenext")
+        else
         {
             $_SESSION['step']=$_SESSION['step']+1;
         }
@@ -337,6 +348,13 @@
     exit;
 }
 
+//Setup an inverted fieldnamesInfo for quick lookup of field answers.
+$aFieldnamesInfoInv = aArrayInvert($_SESSION['fieldnamesInfo']);
+if ($_SESSION['step'] > $_SESSION['maxstep'])
+{
+    $_SESSION['maxstep'] = $_SESSION['step'];
+}
+
 //******************************************************************************************************
 //PRESENT SURVEY
 //******************************************************************************************************
@@ -1193,6 +1211,13 @@
         {
             $man_class = '';
         }
+
+        if (!bCheckQuestionForAnswer($qa[7], $aFieldnamesInfoInv) &&
+                $_SESSION['maxstep'] != $_SESSION['step'])
+        {
+            $man_class .= ' missing';
+        }
+
         if ($qa[3] != 'Y') {$n_q_display = '';} else { $n_q_display = ' style="display: none;"';}
 
         $question= $qa[0];
@@ -1246,6 +1271,63 @@
     echo "<center><font color='red' size='2'>".$clang->gT("This survey is not currently active. You will not be able to save your responses.")."</font></center>\n";
 }
 
+
+if($thissurvey['allowjumps']=='Y')
+{
+    echo "\n\n<!-- PRESENT THE INDEX -->\n";
+
+    echo '<div id="index"><div class="container"><h2>' . $clang->gT("Question index") . '</h2>';
+    for($v = 0, $n = 0; $n != $_SESSION['maxstep']; ++$n)
+    {
+        $g = $_SESSION['grouplist'][$n];
+        if(!checkgroupfordisplay($g[0]))
+            continue;
+
+        $sText = FlattenText($g[1]);
+
+        $bGAnsw = true;
+        foreach($_SESSION['fieldarray'] as $ia)
+        {
+            if($ia[5] != $g[0])
+                continue;
+
+            $qidattributes=getQuestionAttributes($ia[0]);
+            if($qidattributes['hidden']==1 || !checkquestionfordisplay($ia[0]))
+                continue;
+
+            if (!bCheckQuestionForAnswer($ia[1], $aFieldnamesInfoInv))
+            {
+                $bGAnsw = false;
+                break;
+            }
+        }
+
+        ++$v;
+
+        $class = ($n == $_SESSION['step'] - 1? 'current': ($bGAnsw? 'answer': 'missing'));
+        if($v % 2) $class .= " odd";
+
+        $s = $n + 1;
+        echo "<div class=\"row $class\" onclick=\"javascript:document.limesurvey.move.value = '$s'; document.limesurvey.submit();\"><span class=\"hdr\">$v</span><span title=\"$sText\">$sText</span></div>";
+    }
+
+    if($_SESSION['maxstep'] == $_SESSION['totalsteps'])
+    {
+        echo "<input class='submit' type='submit' accesskey='l' onclick=\"javascript:document.limesurvey.move.value = 'movesubmit';\" value=' "
+            . $clang->gT("Submit")." ' name='move2' />\n";
+    }
+
+    echo '</div></div>';
+
+    echo "<script type=\"text/javascript\">\n"
+    . "  $(\".outerframe\").addClass(\"withindex\");\n"
+    . "  var idx = $(\"#index\");\n"
+    . "  var row = $(\"#index .row.current\");\n"
+    . "  idx.scrollTop(row.position().top - idx.height() / 2 - row.height() / 2);\n"
+    . "</script>\n";
+    echo "\n";
+}
+
 echo "<!-- group2.php -->\n"; //This can go eventually - it's redundent for debugging
 
 if (isset($conditions) && is_array($conditions) && count($conditions) != 0)
Index: question.php
===================================================================
--- question.php	(revision 9507)
+++ question.php	(working copy)
@@ -18,15 +18,24 @@
 
 if (!isset($homedir) || isset($_REQUEST['$homedir'])) {die("Cannot run this script directly");}
 
-//Move current step
 if (!isset($_SESSION['step'])) {$_SESSION['step']=0;}
 if (!isset($_SESSION['totalsteps'])) {$_SESSION['totalsteps']=0;}
-if (isset($move) && $move == "moveprev" && $thissurvey['allowprev']=='Y' && $_SESSION['step'] > 0) {$_SESSION['step'] = $thisstep-1;}
+if (!isset($_SESSION['maxstep'])) {$_SESSION['maxstep']=0;}
+$_SESSION['prevstep']=$_SESSION['step'];
+
+//Move current step
+if (isset($move) && $move == "moveprev" && ($thissurvey['allowprev']=='Y' || $thissurvey['allowjumps']=='Y') && $_SESSION['step'] > 0) {$_SESSION['step'] = $thisstep-1;}
 if (isset($move) && $move == "movenext")
 {
     if ($_SESSION['step']==$thisstep)
-    $_SESSION['step'] = $thisstep+1;
+        $_SESSION['step'] = $thisstep+1;
 }
+if (isset($move) && bIsNumericInt($move) && $thissurvey['allowjumps']=='Y')
+{
+    $move = (int)$move;
+    if ($move > 0 && (($move <= $_SESSION['step']) || (isset($_SESSION['maxstep']) && $move <= $_SESSION['maxstep'])))
+        $_SESSION['step'] = $move;
+}
 
 
 // We do not keep the participant session anymore when the same browser is used to answer a second time a survey (let's think of a library PC for instance).
@@ -36,7 +45,9 @@
 
 //CHECK IF ALL MANDATORY QUESTIONS HAVE BEEN ANSWERED ############################################
 //First, see if we are moving backwards or doing a Save so far, and its OK not to check:
-if ($allowmandbackwards==1 && ((isset($move) &&  $move == "moveprev") || (isset($_POST['saveall']) && $_POST['saveall'] == $clang->gT("Save your responses so far"))))
+if ($allowmandbackwards==1 && (
+    (isset($move) && ($move == "moveprev" || (is_int($move) && $_SESSION['prevstep'] == $_SESSION['maxstep']))) ||
+    (isset($_POST['saveall']) && $_POST['saveall'] == $clang->gT("Save your responses so far"))))
 {
     $backok="Y";
 }
@@ -70,7 +81,7 @@
 }
 
 //RUN THIS IF THIS IS THE FIRST TIME
-if (!isset($_SESSION['step']) || !$_SESSION['step'])
+if (!$_SESSION['step'])
 {
     $totalquestions = buildsurveysession();
     if(isset($thissurvey['showwelcome']) && $thissurvey['showwelcome'] == 'N') {
@@ -81,6 +92,7 @@
         exit;
     }
 }
+
 //******************************************************************************************************
 //PRESENT SURVEY
 //******************************************************************************************************
@@ -105,63 +117,71 @@
 
 while ($conditionforthisquestion == "Y" || $qidattributes['hidden']==1) //IF CONDITIONAL, CHECK IF CONDITIONS ARE MET; IF HIDDEN MOVE TO NEXT
 {
- // this is a while, not an IF because if we skip the question we loop on the next question, see below
-if (checkquestionfordisplay($ia[0]) === true && $qidattributes['hidden']==0)
-{ // question will be displayed
-// we set conditionforthisquestion to N here because it is used later to select style=display:'' for the question
-$conditionforthisquestion="N";
-}
-else
-{
-    $questionsSkipped++;
-    if (returnglobal('move') == "movenext")
+    // this is a while, not an IF because if we skip the question we loop on the next question, see below
+    if (checkquestionfordisplay($ia[0]) === true && $qidattributes['hidden']==0)
     {
-        $currentquestion++;
-        if(isset($_SESSION['fieldarray'][$currentquestion]))
+        // question will be displayed we set conditionforthisquestion to N here
+        // because it is used later to select style=display:'' for the question
+        $conditionforthisquestion="N";
+    }
+    else
+    {
+        $questionsSkipped++;
+        if ($_SESSION['prevstep'] <= $_SESSION['step'])
         {
-            $ia=$_SESSION['fieldarray'][$currentquestion];
-        }
-        if ($_SESSION['step']>=$_SESSION['totalsteps'])
-        {
-            $move="movesubmit";
-            submitanswer(); // complete this answer (submitdate)
-            break;
-        }
-        $_SESSION['step']++;
-        foreach ($_SESSION['grouplist'] as $gl)
-        {
-            if ($gl[0] == $ia[5])
+            $currentquestion++;
+            if(isset($_SESSION['fieldarray'][$currentquestion]))
             {
-                $gid=$gl[0];
-                $groupname=$gl[1];
-                $groupdescription=$gl[2];
-                if (auto_unescape($_POST['lastgroupname']) != strip_tags($groupname) && $groupdescription) {$newgroup = "Y";} else {$newgroup == "N";}
+                $ia=$_SESSION['fieldarray'][$currentquestion];
             }
+            if ($_SESSION['step']>=$_SESSION['totalsteps'])
+            {
+                $move="movesubmit";
+                submitanswer(); // complete this answer (submitdate)
+                break;
+            }
+            $_SESSION['step']++;
+            foreach ($_SESSION['grouplist'] as $gl)
+            {
+                if ($gl[0] == $ia[5])
+                {
+                    $gid=$gl[0];
+                    $groupname=$gl[1];
+                    $groupdescription=$gl[2];
+                    if (auto_unescape($_POST['lastgroupname']) != strip_tags($groupname) && $groupdescription) {$newgroup = "Y";} else {$newgroup == "N";}
+                }
+            }
         }
-    }
-    elseif (returnglobal('move') == "moveprev")
-    {
-        $currentquestion--; // if we reach -1, this means we must go back to first page
-        if ($currentquestion >= 0)
-        {
-        $ia=$_SESSION['fieldarray'][$currentquestion];
-        $_SESSION['step']--;
-    }
         else
         {
-            $_SESSION['step']=0;
-            display_first_page();
-            exit;
+            $currentquestion--; // if we reach -1, this means we must go back to first page
+            if ($currentquestion >= 0)
+            {
+                $ia=$_SESSION['fieldarray'][$currentquestion];
+                $_SESSION['step']--;
+            }
+            else
+            {
+                $_SESSION['step']=0;
+                display_first_page();
+                exit;
+            }
         }
+        // because we skip this question, we need to loop on the same condition 'check-block'
+        //  with the new question (we have overwritten $ia)
+        $conditionforthisquestion=$ia[7];
+        $qidattributes=getQuestionAttributes($ia[0]);
+        $extendedConditionResult = checkExtendedConditionForQuestion($ia[0]);
     }
-    // because we skip this question, we need to loop on the same condition 'check-block'
-    //  with the new question (we have overwritten $ia)
-    $conditionforthisquestion=$ia[7];
-    $qidattributes=getQuestionAttributes($ia[0]);
-		$extendedConditionResult = checkExtendedConditionForQuestion($ia[0]);
-}
 } // End of while conditionforthisquestion=="Y"
 
+//Setup an inverted fieldnamesInfo for quick lookup of field answers.
+$aFieldnamesInfoInv = aArrayInvert($_SESSION['fieldnamesInfo']);
+if ($_SESSION['step'] > $_SESSION['maxstep'])
+{
+    $_SESSION['maxstep'] = $_SESSION['step'];
+}
+
 //SUBMIT
 if ((isset($move) && $move == "movesubmit")  && (!isset($notanswered) || !$notanswered)  && (!isset($notvalidated) || !$notvalidated ) && (!isset($filenotvalidated) || !$filenotvalidated))
 {
@@ -328,7 +348,9 @@
 
 //Check if current page is for group description only
 $bIsGroupDescrPage = false;
-if ($newgroup == "Y" && $groupdescription && (isset($move) && $move != "moveprev"))
+if ($newgroup == "Y" && $groupdescription &&
+    (isset($move) && $move != "moveprev" && !is_int($move)) &&
+    $_SESSION['maxstep'] == $_SESSION['step'])
 {
     // This is a group description page
     //  - $ia contains next question description,
@@ -577,6 +599,62 @@
 
 echo "\n";
 
+if($thissurvey['allowjumps']=='Y' && !$bIsGroupDescrPage)
+{
+    echo "\n\n<!-- PRESENT THE INDEX -->\n";
+
+    $iLastGrp = null;
+
+    echo '<div id="index"><div class="container"><h2>' . $clang->gT("Question index") . '</h2>';
+    for($v = 0, $n = 0; $n != $_SESSION['maxstep']; ++$n)
+    {
+        $ia = $_SESSION['fieldarray'][$n];
+        $qidattributes=getQuestionAttributes($ia[0]);
+        if($qidattributes['hidden']==1 || !checkquestionfordisplay($ia[0]))
+            continue;
+
+        $sText = FlattenText($ia[3]);
+        $bAnsw = bCheckQuestionForAnswer($ia[1], $aFieldnamesInfoInv);
+
+        if($iLastGrp != $ia[5])
+        {
+            $iLastGrp = $ia[5];
+            foreach ($_SESSION['grouplist'] as $gl)
+            {
+                if ($gl[0] == $iLastGrp)
+                {
+                    echo '<h3>' . htmlspecialchars(strip_tags($gl[1]),ENT_QUOTES,'UTF-8') . "</h3>";
+                    break;
+                }
+            }
+        }
+
+        ++$v;
+
+        $class = ($n == $_SESSION['step'] - 1? 'current': ($bAnsw? 'answer': 'missing'));
+        if($v % 2) $class .= " odd";
+
+        $s = $n + 1;
+        echo "<div class=\"row $class\" onclick=\"javascript:document.limesurvey.move.value = '$s'; document.limesurvey.submit();\"><span class=\"hdr\">$v</span><span title=\"$sText\">$sText</span></div>";
+    }
+
+    if($_SESSION['maxstep'] == $_SESSION['totalsteps'])
+    {
+        echo "<input class='submit' type='submit' accesskey='l' onclick=\"javascript:document.limesurvey.move.value = 'movesubmit';\" value=' "
+            . $clang->gT("Submit")." ' name='move2' />\n";
+    }
+
+    echo '</div></div>';
+
+    echo "<script type=\"text/javascript\">\n"
+    . "  $(\".outerframe\").addClass(\"withindex\");\n"
+    . "  var idx = $(\"#index\");\n"
+    . "  var row = $(\"#index .row.current\");\n"
+    . "  idx.scrollTop(row.position().top - idx.height() / 2 - row.height() / 2);\n"
+    . "</script>\n";
+    echo "\n";
+}
+
 if (isset($conditions) && is_array($conditions) && count($conditions) != 0)
 {
     //if conditions exist, create hidden inputs for 'previously' answered questions
Index: common_functions.php
===================================================================
--- common_functions.php	(revision 9507)
+++ common_functions.php	(working copy)
@@ -7980,4 +7980,56 @@
 
 
 
+/**
+ * Check if $str is an integer, or string representation of an integer
+ *
+ * @param mixed $mStr
+ */
+function bIsNumericInt($mStr)
+{
+    if(is_int($mStr))
+        return true;
+    elseif(is_string($mStr))
+        return preg_match("/^[0-9]+$/", $mStr);
+    return false;
+}
+
+/**
+ * Invert key/values of an associative array, preserving multiple values in
+ * the source array as a single key with multiple values in the resulting
+ * array.
+ *
+ * This is not the same as array_flip(), which flattens the structure of the
+ * source array.
+ *
+ * @param array $aArr
+ */
+function aArrayInvert($aArr)
+{
+    $aRet = array();
+    foreach($aArr as $k => $v)
+        $aRet[$v][] = $k;
+    return $aRet;
+}
+
+/**
+ * Check if a question was (at least partially) answered in the current session.
+ *
+ * @param integer $q - Question id
+ * @param array $aFieldnamesInfoInv - Inverted fieldnamesInfo
+ */
+function bCheckQuestionForAnswer($q, $aFieldnamesInfoInv)
+{
+    $bAnsw = false;
+    foreach($aFieldnamesInfoInv[$q] as $sField)
+    {
+        if(!empty($_SESSION[$sField]))
+        {
+            $bAnsw = true;
+            break;
+        }
+    }
+    return $bAnsw;
+}
+
 // Closing PHP tag intentionally left out - yes, it is okay
Index: common.php
===================================================================
--- common.php	(revision 9507)
+++ common.php	(working copy)
@@ -316,4 +316,4 @@
 
 
 
-// Closing PHP tag intentionally left out - yes, it is okay
\ No newline at end of file
+// Closing PHP tag intentionally left out - yes, it is okay
Index: admin/html.php
===================================================================
--- admin/html.php	(revision 9507)
+++ admin/html.php	(working copy)
@@ -796,6 +796,11 @@
         if ($surveyinfo['format'] == "S") {$surveysummary2 .= $clang->gT("It is presented question by question.")."<br />\n";}
         elseif ($surveyinfo['format'] == "G") {$surveysummary2 .= $clang->gT("It is presented group by group.")."<br />\n";}
         else {$surveysummary2 .= $clang->gT("It is presented on one single page.")."<br />\n";}
+        if ($surveyinfo['allowjumps'] == "Y")
+        {
+          if ($surveyinfo['format'] == 'A') {$surveysummary2 .= $clang->gT("No question index will be shown with this format.")."<br />\n";}
+          else {$surveysummary2 .= $clang->gT("A question index will be shown; participants will be able to jump between viewed questions.")."<br />\n";}
+        }
         if ($surveyinfo['datestamp'] == "Y") {$surveysummary2 .= $clang->gT("Responses will be date stamped")."<br />\n";}
         if ($surveyinfo['ipaddr'] == "Y") {$surveysummary2 .= $clang->gT("IP Addresses will be logged")."<br />\n";}
         if ($surveyinfo['refurl'] == "Y") {$surveysummary2 .= $clang->gT("Referer-URL will be saved")."<br />\n";}
Index: admin/database.php
===================================================================
--- admin/database.php	(revision 9507)
+++ admin/database.php	(working copy)
@@ -1073,6 +1073,7 @@
                             'shownoanswer'=>$_POST['shownoanswer'],
                             'showwelcome'=>$_POST['showwelcome'],
                             'allowprev'=>$_POST['allowprev'],
+                            'allowjumps'=>$_POST['allowjumps'],
                             'showprogress'=>$_POST['showprogress'],
                             'listpublic'=>$_POST['public'],
                             'htmlemail'=>$_POST['htmlemail'],
@@ -1362,6 +1363,7 @@
                             'shownoanswer'=>$_POST['shownoanswer'],
                             'showwelcome'=>$_POST['showwelcome'],
                             'allowprev'=>$_POST['allowprev'],
+                            'allowjumps'=>$_POST['allowjumps'],
                             'showprogress'=>$_POST['showprogress'],
                             'printanswers'=>$_POST['printanswers'],
         //                            'usetokens'=>$_POST['usetokens'],
Index: admin/install/create-mysql.sql
===================================================================
--- admin/install/create-mysql.sql	(revision 9507)
+++ admin/install/create-mysql.sql	(working copy)
@@ -290,6 +290,7 @@
   `bounceaccountuser` VARCHAR(200),
   `showwelcome` char(1) default 'Y',
   `showprogress` char(1) default 'Y',
+  `allowjumps` char(1) default 'N',
    PRIMARY KEY(`sid`)
 ) ENGINE=$databasetabletype CHARACTER SET utf8 COLLATE utf8_unicode_ci;
 
Index: admin/install/create-mssqlnative.sql
===================================================================
--- admin/install/create-mssqlnative.sql	(revision 9507)
+++ admin/install/create-mssqlnative.sql	(working copy)
@@ -311,6 +311,7 @@
   [bounceaccountpass] varchar(100) default NULL,
   [bounceaccountencryption] varchar(3) default NULL,
   [showprogress] char(1) default 'N',
+  [allowjumps] char(1) default 'N',
   
   PRIMARY KEY  ([sid])
 ) 
Index: admin/install/create-postgres.sql
===================================================================
--- admin/install/create-postgres.sql	(revision 9507)
+++ admin/install/create-postgres.sql	(working copy)
@@ -314,7 +314,8 @@
 	emailresponseto text,
     emailnotificationto text,
 	tokenlength smallint DEFAULT '15',
-    showprogress character(1) DEFAULT 'N'::bpchar
+    showprogress character(1) DEFAULT 'N'::bpchar,
+    allowjumps character(1) DEFAULT 'N'::bpchar
 );
 
 ALTER TABLE ONLY prefix_surveys ADD CONSTRAINT prefix_surveys_pkey PRIMARY KEY (sid);
Index: admin/install/create-mssql.sql
===================================================================
--- admin/install/create-mssql.sql	(revision 9507)
+++ admin/install/create-mssql.sql	(working copy)
@@ -302,6 +302,7 @@
   [bounceaccountpass] varchar(100) default NULL,
   [bounceaccountencryption] varchar(3) default NULL,
   [showprogress] char(1) default 'N',
+  [allowjumps] char(1) default 'N',
   
   PRIMARY KEY  ([sid])
 ) 
Index: admin/editsurveysettings.php
===================================================================
--- admin/editsurveysettings.php	(revision 9507)
+++ admin/editsurveysettings.php	(working copy)
@@ -318,6 +318,17 @@
             $editsurvey .= ">".$clang->gT("No")."</option>\n"
             . "</select></li>\n";
 
+        //Show Question Index
+        $editsurvey .= "<li><label for='allowjumps'>".$clang->gT("Show Question Index / Allow jumping")."</label>\n"
+                . "<select id='allowjumps' name='allowjumps'>\n"
+                . "<option value='Y'";
+        if (!isset($esrow['allowjumps']) || !$esrow['allowjumps'] || $esrow['allowjumps'] == "Y") {$editsurvey .= " selected='selected'";}
+        $editsurvey .= ">".$clang->gT("Yes")."</option>\n"
+                . "<option value='N'";
+        if (isset($esrow['allowjumps']) && $esrow['allowjumps'] == "N") {$editsurvey .= " selected='selected'";}
+        $editsurvey .= ">".$clang->gT("No")."</option>\n"
+                . "</select></li>\n";
+
 	//Show Progress
 	$editsurvey .= "<li><label for='showprogress'>".$clang->gT("Show progress bar")."</label>\n"
                 . "<select id='showprogress' name='showprogress'>\n"
Index: admin/update/upgrade-mysql.php
===================================================================
--- admin/update/upgrade-mysql.php	(revision 9507)
+++ admin/update/upgrade-mysql.php	(working copy)
@@ -401,6 +401,7 @@
         modify_database("", "ALTER TABLE `prefix_surveys` ADD `bounceaccountuser` VARCHAR(200) NULL"); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE `prefix_surveys` ADD `showwelcome` CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE `prefix_surveys` ADD `showprogress` char(1) default 'Y'"); echo $modifyoutput; flush();
+        modify_database("", "ALTER TABLE `prefix_surveys` ADD `allowjumps` char(1) default 'N'"); echo $modifyoutput; flush();
         modify_database("", "CREATE TABLE `prefix_survey_permissions` (
                                 `sid` int(10) unsigned NOT NULL,
                                 `uid` int(10) unsigned NOT NULL,
Index: admin/update/upgrade-mssqlnative.php
===================================================================
--- admin/update/upgrade-mssqlnative.php	(revision 9507)
+++ admin/update/upgrade-mssqlnative.php	(working copy)
@@ -423,6 +423,7 @@
         modify_database("", "ALTER TABLE [prefix_surveys] ADD bounceaccountuser VARCHAR(200) NULL "); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE [prefix_surveys] ADD showwelcome CHAR(1) NULL default 'Y' "); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE [prefix_surveys] ADD showprogress CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
+        modify_database("", "ALTER TABLE [prefix_surveys] ADD allowjumps CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
         modify_database("", "CREATE TABLE [prefix_survey_permissions] (
                             [sid] INT NOT NULL,         
                             [uid] INT NOT NULL,         
Index: admin/update/upgrade-postgres.php
===================================================================
--- admin/update/upgrade-postgres.php	(revision 9507)
+++ admin/update/upgrade-postgres.php	(working copy)
@@ -245,6 +245,7 @@
         modify_database("", "ALTER TABLE prefix_surveys ADD bounceaccountuser character varying(200) NULL"); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE prefix_surveys ADD showwelcome CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE prefix_surveys ADD showprogress CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
+        modify_database("", "ALTER TABLE prefix_surveys ADD allowjumps CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
         modify_database("", "CREATE TABLE prefix_survey_permissions (
                             sid integer DEFAULT 0 NOT NULL,
                             uid integer DEFAULT 0 NOT NULL,
Index: admin/update/upgrade-mssql.php
===================================================================
--- admin/update/upgrade-mssql.php	(revision 9507)
+++ admin/update/upgrade-mssql.php	(working copy)
@@ -423,6 +423,7 @@
         modify_database("", "ALTER TABLE [prefix_surveys] ADD bounceaccountuser VARCHAR(200) NULL"); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE [prefix_surveys] ADD showwelcome CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
         modify_database("", "ALTER TABLE [prefix_surveys] ADD showprogress CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
+        modify_database("", "ALTER TABLE [prefix_surveys] ADD allowjumps CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
         modify_database("", "CREATE TABLE [prefix_survey_permissions] (
                             [sid] INT NOT NULL,         
                             [uid] INT NOT NULL,         
Index: index.php
===================================================================
--- index.php	(revision 9507)
+++ index.php	(working copy)
@@ -1487,14 +1487,7 @@
                     {
                         //The number of questions not answered is equal to the number of questions
                         //This section gets used if it is a multiple choice type question
-                        if (isset($move) && $move == "moveprev")
-                        {
-                            $_SESSION['step'] = $thisstep;
-                        }
-                        if (isset($move) && $move == "movenext")
-                        {
-                            $_SESSION['step'] = $thisstep;
-                        }
+                        $_SESSION['step'] = $thisstep;
                         $notanswered[]=substr($multiname, 5, strlen($multiname));
                         $$multiname=0;
                         $$multiname2=0;
@@ -1516,14 +1509,7 @@
             elseif ((!isset($_POST[$multiname]) || !$_POST[$multiname]) && (!isset($_POST[$dtcm]) || $_POST[$dtcm] == "on"))
             {
                 //One of the mandatory questions hasn't been asnwered
-                if (isset($move) && $move == "moveprev")
-                {
-                    $_SESSION['step'] = $thisstep;
-                }
-                if (isset($move) && $move == "movenext")
-                {
-                    $_SESSION['step'] = $thisstep;
-                }
+                $_SESSION['step'] = $thisstep;
                 $notanswered[]=$mfns[$mi];
             }
             else
@@ -1595,14 +1581,7 @@
 
                     {
                         //The number of questions not answered is equal to the number of questions
-                        if (isset($move) && $move == "moveprev")
-                        {
-                            $_SESSION['step'] = $thisstep;
-                        }
-                        if (isset($move) && $move == "movenext")
-                        {
-                            $_SESSION['step'] = $thisstep;
-                        }
+                        $_SESSION['step'] = $thisstep;
                         $notanswered[]=substr($multiname, 5, strlen($multiname));
                         $$multiname=0;
                         $$multiname2=0;
@@ -1850,14 +1829,7 @@
                 //$maxvalue_answername="maxvalue_answer".$maxvalueanswer;
                 if (!empty($_POST['qattribute_answer'.$maxvalueanswer]) && $_POST['display'.$maxvalueanswer] == "on")
                 {
-                    if (isset($move) && $move == "moveprev")
-                    {
-                        $_SESSION['step'] = $thisstep;
-                    }
-                    if (isset($move) && $move == "movenext")
-                    {
-                        $_SESSION['step'] = $thisstep;
-                    }
+                    $_SESSION['step'] = $thisstep;
                     $notvalidated[]=$maxvalueanswer;
                     return $notvalidated;
                 }
@@ -2759,7 +2731,7 @@
         $surveymover = "<input type=\"hidden\" name=\"move\" value=\"movenext\" id=\"movenext\" />";
     }
 
-    if (isset($_SESSION['step']) && $thissurvey['format'] != "A" && $thissurvey['allowprev'] != "N" &&
+    if (isset($_SESSION['step']) && $thissurvey['format'] != "A" && ($thissurvey['allowprev'] != "N" || $thissurvey['allowjumps'] == "Y") &&
 	($_SESSION['step'] > 0 || (!$_SESSION['step'] && $presentinggroupdescription && $thissurvey['showwelcome'] == 'Y')))
     {
         $surveymover .= "<input class='submit' accesskey='p' type='button' onclick=\"javascript:document.limesurvey.move.value = 'moveprev'; $('#limesurvey').submit();\" value=' &lt;&lt; "
Index: templates/basic/template.css
===================================================================
--- templates/basic/template.css	(revision 9507)
+++ templates/basic/template.css	(working copy)
@@ -739,3 +739,58 @@
   font-weight: normal;
   background-color: #efefef;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #eee;
+  border-left: 1px solid #ccc;
+}
+
+#index h2 { 
+  text-align: center;
+  font-weight: normal;
+}
+
+#index h3 { margin: 0.5em 0 0 0.5em; }
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #CCC; }
+#index .container .row.current { background: #000; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/basic/startpage.pstpl
===================================================================
--- templates/basic/startpage.pstpl	(revision 9507)
+++ templates/basic/startpage.pstpl	(working copy)
@@ -23,7 +23,7 @@
 	<link rel="shortcut icon" href="{TEMPLATEURL}favicon.ico" />
 	</head>
 	<body class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
-		<table width="80%" align="center" class="bf" cellpadding="0" cellspacing="11">
-		<tr>
-			<td>
-
+                <div class="outerframe">
+		        <table width="80%" align="center" class="bf" cellpadding="0" cellspacing="11">
+		        <tr>
+		        	<td>
Index: templates/basic/endpage.pstpl
===================================================================
--- templates/basic/endpage.pstpl	(revision 9507)
+++ templates/basic/endpage.pstpl	(working copy)
@@ -1,3 +1,4 @@
-			</td>
-		</tr>
-	</table>
+	        		</td>
+	        	</tr>
+	        </table>
+        </div>
Index: templates/sherpa/template.css
===================================================================
--- templates/sherpa/template.css	(revision 9507)
+++ templates/sherpa/template.css	(working copy)
@@ -938,3 +938,66 @@
   font-weight: bold;
   text-align: right;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #fff;
+  border-left: 4px double #999;
+}
+
+#index h2 { 
+  margin: 0;
+  padding: 3px;
+  height: 23px;
+  background: url("box_bg.gif") repeat-x;
+  text-align: center;
+  font-family: "Verdana,Geneva,Arial,Helvetica,sans-serif";
+  font-size: 13px;
+}
+
+#index h3 {
+  color: #000099;
+  margin: 0.5em 0 0 0.5em;
+}
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #EEE; }
+#index .container .row.current { background: #000099; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/sherpa/startpage.pstpl
===================================================================
--- templates/sherpa/startpage.pstpl	(revision 9507)
+++ templates/sherpa/startpage.pstpl	(working copy)
@@ -24,12 +24,14 @@
 </head>
 	<body class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
 
-	<table align="center" cellpadding="0" cellspacing="0">
-		<tr class="grayboxheader">
-			<td width="14"><img src="{TEMPLATEURL}box_left.gif" border="0" width="14" /></td>
-			<td background="{TEMPLATEURL}box_bg.gif">{SURVEYNAME}</td>
-			<td width="14"><img src="{TEMPLATEURL}box_right.gif" border="0" width="14" /></td>
-		</tr>
-	</table>
+        <div class="outerframe">
 
-	<div class="survey-main">
+	        <table align="center" cellpadding="0" cellspacing="0">
+	        	<tr class="grayboxheader">
+	        		<td width="14"><img src="{TEMPLATEURL}box_left.gif" border="0" width="14" /></td>
+	        		<td background="{TEMPLATEURL}box_bg.gif">{SURVEYNAME}</td>
+	        		<td width="14"><img src="{TEMPLATEURL}box_right.gif" border="0" width="14" /></td>
+	                </tr>
+	        </table>
+
+	        <div class="survey-main">
Index: templates/sherpa/endpage.pstpl
===================================================================
--- templates/sherpa/endpage.pstpl	(revision 9507)
+++ templates/sherpa/endpage.pstpl	(working copy)
@@ -1 +1,2 @@
+                        </div>
 		</div>
Index: templates/default/template.css
===================================================================
--- templates/default/template.css	(revision 9507)
+++ templates/default/template.css	(working copy)
@@ -300,6 +300,10 @@
   margin: 0% 0% 0.5em 0.5em;
 }
 
+.outerframe.withindex div.missing td.questiontext {
+  background: red;
+}
+
 /* END:  General list styles - - - -  - - -  - - - -
 - - - - -  - - -  - - -  - - - - - -  - - -  - - - - */
   /* STYLES NOT YET DEFINED - - - - -
@@ -729,7 +733,9 @@
   font-size: 0.9em;
 }
 
-table.outerframe {
+table.innerframe {
+  width: 75%;
+  text-align: center;
   border-collapse: separate;
   border-spacing: 1px;
   margin: 20px auto 40px auto;
@@ -943,3 +949,59 @@
   font-weight: bold;
   background-color: #D2E0F2;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #fff;
+  border-left: 1px solid #ccc;
+}
+
+#index h2 { 
+  padding: 1em;
+  background: #eef6ff;
+  text-align: center;
+}
+
+#index h3 { margin: 0.5em 0 0 0.5em; }
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #EEF6FF; }
+#index .container .row.current { background: #1D2D45; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/default/startpage.pstpl
===================================================================
--- templates/default/startpage.pstpl	(revision 9507)
+++ templates/default/startpage.pstpl	(working copy)
@@ -22,6 +22,7 @@
 <link rel="shortcut icon" href="{TEMPLATEURL}favicon.ico" />		
 </head>
 <body class="default lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
-<table width="75%" align="center" class="outerframe">
-	<tr>
-		<td>
+    <div class="outerframe">
+        <table class="innerframe">
+            <tr>
+                <td>
Index: templates/default/endpage.pstpl
===================================================================
--- templates/default/endpage.pstpl	(revision 9507)
+++ templates/default/endpage.pstpl	(working copy)
@@ -1,3 +1,4 @@
-		</td>
-	</tr>
-</table>
\ No newline at end of file
+    		</td>
+    	</tr>
+    </table>
+</div>
Index: templates/clear_logo/template.css
===================================================================
--- templates/clear_logo/template.css	(revision 9507)
+++ templates/clear_logo/template.css	(working copy)
@@ -772,3 +772,56 @@
   font-size: 9pt;
   font-family: arial, verdana, sans-serif;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #fff;
+}
+
+#index h2 { 
+  text-align: right;
+}
+
+#index h3 { margin: 0.5em 0 0 0.5em; }
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #EFE5CA; }
+#index .container .row.current { background: #000; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/clear_logo/startpage.pstpl
===================================================================
--- templates/clear_logo/startpage.pstpl	(revision 9507)
+++ templates/clear_logo/startpage.pstpl	(working copy)
@@ -20,4 +20,4 @@
 	<link rel="shortcut icon" href="{TEMPLATEURL}favicon.ico" />
 </head>
 <body class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
-
+        <div class="outerframe">
Index: templates/clear_logo/endpage.pstpl
===================================================================
--- templates/clear_logo/endpage.pstpl	(revision 9507)
+++ templates/clear_logo/endpage.pstpl	(working copy)
@@ -1,13 +1,14 @@
-			</td>
-		</tr>
-	</table>
-	</td>
-	<td width="3" height="3" class="b9"></td>
-</tr>
-<tr><td width="3" class="b3"></td></tr>
-<tr class="b3">
-	<td colspan="2" height="3"><table cellpadding=0 cellspacing=0>
-		<tr><td width="3" height="3" class="b9"></td></tr>
-	</table></td>
-</tr>
-</table>
\ No newline at end of file
+        			</td>
+        		</tr>
+        	</table>
+        	</td>
+        	<td width="3" height="3" class="b9"></td>
+        </tr>
+        <tr><td width="3" class="b3"></td></tr>
+        <tr class="b3">
+        	<td colspan="2" height="3"><table cellpadding=0 cellspacing=0>
+        		<tr><td width="3" height="3" class="b9"></td></tr>
+        	</table></td>
+        </tr>
+        </table>
+</div>
Index: templates/vallendar/template.css
===================================================================
--- templates/vallendar/template.css	(revision 9507)
+++ templates/vallendar/template.css	(working copy)
@@ -756,3 +756,62 @@
 table.statisticstable strong {
   font-weight: bold;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #EDEDED;
+  border-left: 1px solid #000;
+}
+
+#index h2 {
+  color: #17479e;
+  background: #FFF;
+  margin: 0;
+}
+
+#index h3 {
+  margin: 0.5em 0 0 0.5em;
+  color: #17479e;
+}
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #CCC; }
+#index .container .row.current { background: #17479e; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/vallendar/startpage.pstpl
===================================================================
--- templates/vallendar/startpage.pstpl	(revision 9507)
+++ templates/vallendar/startpage.pstpl	(working copy)
@@ -21,6 +21,7 @@
 	<link rel="shortcut icon" href="{TEMPLATEURL}favicon.ico" />    
 </head>
 	<body bgcolor="#C0C0C0" class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
-<table width="75%" align="center" style="border-collapse: collapse;border-color:#333333" bgcolor="#EDEDED" border="1" cellspacing="0">
-	<tr>
-		<td>
+        <div class="outerframe">
+                <table width="75%" align="center" style="border-collapse: collapse;border-color:#333333" bgcolor="#EDEDED" border="1" cellspacing="0">
+                	<tr>
+                		<td>
Index: templates/vallendar/endpage.pstpl
===================================================================
--- templates/vallendar/endpage.pstpl	(revision 9507)
+++ templates/vallendar/endpage.pstpl	(working copy)
@@ -1,3 +1,4 @@
-		</td>
-	</tr>
-</table>
\ No newline at end of file
+        		</td>
+        	</tr>
+        </table>
+</div>
Index: templates/mint_idea/template.css
===================================================================
--- templates/mint_idea/template.css	(revision 9507)
+++ templates/mint_idea/template.css	(working copy)
@@ -1145,3 +1145,57 @@
   /*float:left;*/ /*text-align: left;*/
   
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  border-left: 1px solid #ccc;
+}
+
+#index h2 { 
+  padding: 1em;
+  text-align: center;
+}
+
+#index h3 { margin: 0.5em 0 0 0.5em; }
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #1D2D45; }
+#index .container .row.current { background: #FFF; color: #000; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/mint_idea/startpage.pstpl
===================================================================
--- templates/mint_idea/startpage.pstpl	(revision 9507)
+++ templates/mint_idea/startpage.pstpl	(working copy)
@@ -21,13 +21,15 @@
 </head>
 	<body  class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
 
-    <div id="layout">
-      
-      <div id="header">
-        
-        <h1 id="logo"><a href="./" title="Company">Lime<span class="light">Survey</span><span class="leaf"> </span></a></h1>
-        <hr class="noscreen" />   
-     
-        <p class="noscreen noprint">
-          <em>Skip to <a href="#obsah">content</a>, <a href="#nav">navigation</a>.</em>
-        </p>
+        <div class="outerframe">
+
+          <div id="layout">
+            
+            <div id="header">
+              
+              <h1 id="logo"><a href="./" title="Company">Lime<span class="light">Survey</span><span class="leaf"> </span></a></h1>
+              <hr class="noscreen" />   
+           
+              <p class="noscreen noprint">
+                <em>Skip to <a href="#obsah">content</a>, <a href="#nav">navigation</a>.</em>
+              </p>
Index: templates/mint_idea/endpage.pstpl
===================================================================
--- templates/mint_idea/endpage.pstpl	(revision 9507)
+++ templates/mint_idea/endpage.pstpl	(working copy)
@@ -1,2 +1,3 @@
 </div>
-</div>
\ No newline at end of file
+</div>
+</div>
Index: templates/eirenicon/template.css
===================================================================
--- templates/eirenicon/template.css	(revision 9507)
+++ templates/eirenicon/template.css	(working copy)
@@ -839,3 +839,68 @@
 td.statsImageholder {
   background-color: #FFF;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #E5E5E5;
+  border-left: 1px solid #000;
+}
+
+#index h2 {
+  margin-top: 0;
+  text-align: center;
+  font-weight: bold;
+  color: #FFF;
+  background: #042455;
+  font-family: verdana;
+  font-size: 8pt;
+}
+
+#index h3 {
+  margin: 0.5em 0 0 0.5em;
+  color: #000080;
+  font-family: Verdana;
+  font-size: 120%;
+}
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #CCC; }
+#index .container .row.current { background: #000; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/eirenicon/startpage.pstpl
===================================================================
--- templates/eirenicon/startpage.pstpl	(revision 9507)
+++ templates/eirenicon/startpage.pstpl	(working copy)
@@ -22,6 +22,7 @@
 </head>
 
 	<body bgcolor="#C0C0C0" class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
-<table width="75%" align="center" style="border-collapse: collapse; border-color:#333333" bgcolor="#EDEDED" border="1" cellspacing="0">
-	<tr>
-		<td>
+                <div class="outerframe">
+                        <table width="75%" align="center" style="border-collapse: collapse; border-color:#333333" bgcolor="#EDEDED" border="1" cellspacing="0">
+                        	<tr>
+                        		<td>
Index: templates/eirenicon/endpage.pstpl
===================================================================
--- templates/eirenicon/endpage.pstpl	(revision 9507)
+++ templates/eirenicon/endpage.pstpl	(working copy)
@@ -1,3 +1,4 @@
-		</td>
-	</tr>
-</table>
\ No newline at end of file
+        		</td>
+        	</tr>
+        </table>
+</div>
Index: templates/bluengrey/template.css
===================================================================
--- templates/bluengrey/template.css	(revision 9507)
+++ templates/bluengrey/template.css	(working copy)
@@ -1113,3 +1113,66 @@
  font-weight:bold;
  padding: 0 10px;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #E9E9E9;
+  border-left: 1px solid #000;
+}
+
+#index h2 {
+  text-align: center;
+  font-weight: bold;
+  padding: 1em;
+  color: #FFF;
+  background: #2F5376;
+}
+
+#index h3 {
+  margin: 0.5em 0 0 0.5em;
+  color: #444;
+  font-family: Verdana;
+  font-size: 12px;
+}
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #CCC; }
+#index .container .row.current { background: #444; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/bluengrey/startpage.pstpl
===================================================================
--- templates/bluengrey/startpage.pstpl	(revision 9507)
+++ templates/bluengrey/startpage.pstpl	(working copy)
@@ -25,6 +25,7 @@
 	<script type="text/javascript" src="{TEMPLATEURL}template.js"></script>
     <link rel="shortcut icon" href="{TEMPLATEURL}favicon.ico" />
 	</head>
-	<body class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
-		<br/>
-		<div id="container">
+        <body class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
+            <div class="outerframe">
+                <br/>
+                <div id="container">
Index: templates/bluengrey/endpage.pstpl
===================================================================
--- templates/bluengrey/endpage.pstpl	(revision 9507)
+++ templates/bluengrey/endpage.pstpl	(working copy)
@@ -1,2 +1,3 @@
+    </div>
 </div>
-<br/>
\ No newline at end of file
+<br/>
Index: templates/limespired/template.css
===================================================================
--- templates/limespired/template.css	(revision 9507)
+++ templates/limespired/template.css	(working copy)
@@ -1054,3 +1054,67 @@
 td.statsImageholder {
   background-color: #FFF;
 }
+
+/* Question Index */
+.outerframe.withindex {
+  margin-left: 1em;
+  margin-right: 26em;
+}
+
+#index {
+  position: absolute;
+  right: 0;
+  width: 25em;
+  top: 0;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  height: 100%;
+  background: #F5FEFF;
+  border-left: 1px solid #00677D;
+}
+
+#index h2 { 
+  margin-top: 0;
+  padding: 10px;
+  background: #00677D;
+  color: #fff;
+  text-align: center;
+  font-size: 1.3em;
+  font-weight: normal;
+}
+
+#index h3 {
+  margin: 0.5em 0 0 0.5em;
+  color: #00677D;
+  font-size: 100%;
+}
+
+#index .container {
+  width: 24em;
+}
+
+#index .container .row {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  text-align: left;
+  border-top: 1px solid #fff;
+}
+
+#index .container .row:hover {
+  text-decoration: underline;
+  cursor: pointer;
+  color: blue;
+}
+
+#index .container .row .hdr {
+  width: 3em;
+  text-align: right;
+  display: inline-block;
+  padding: 0 0.5em 0 0;
+}
+
+#index .container .row.odd { background: #FFF; }
+#index .container .row.current { background: #00407A; color: #fff; }
+#index .container .row.missing { background: #CC0000; color: #fff; }
+#index .container input { margin: 1em; }
Index: templates/limespired/startpage.pstpl
===================================================================
--- templates/limespired/startpage.pstpl	(revision 9507)
+++ templates/limespired/startpage.pstpl	(working copy)
@@ -23,14 +23,15 @@
 <link rel="shortcut icon" href="{TEMPLATEURL}favicon.ico" />
 </head>
 	<body id="page_bg"  class="lang-{SURVEYLANGAGE} {SURVEYFORMAT}">
-		<div id="wrapper2">
-			<div id="wrapper">
-				<div id="header">
-					<div class="rk-1">
-						<div class="rk-2">
-							<a href="http://www.limesurvey.org" class="nounder" title="Limesurvey - The free open source survey tool"><img src="{TEMPLATEURL}blank.gif" border="0" alt="" id="logo" /></a>
-						</div>
-					</div>
-				</div>
-				<div class="surveyname">{SURVEYNAME}</div>
-				<div class="survey-main">
+                <div class="outerframe">
+		        <div id="wrapper2">
+		        	<div id="wrapper">
+		        		<div id="header">
+		        			<div class="rk-1">
+		        				<div class="rk-2">
+		        					<a href="http://www.limesurvey.org" class="nounder" title="Limesurvey - The free open source survey tool"><img src="{TEMPLATEURL}blank.gif" border="0" alt="" id="logo" /></a>
+		        				</div>
+		        			</div>
+		        		</div>
+		        		<div class="surveyname">{SURVEYNAME}</div>
+		        		<div class="survey-main">
Index: templates/limespired/endpage.pstpl
===================================================================
--- templates/limespired/endpage.pstpl	(revision 9507)
+++ templates/limespired/endpage.pstpl	(working copy)
@@ -11,3 +11,4 @@
 </div>
 	</div>
 	</div>
+        </div>
patch-svn-3.diff (55,529 bytes)

user9586

2010-11-24 17:05

  ~13601

Not needed. I updated the patch (which fixes a corner cases with conditions), including all the templates.

I tried to match existing color schemes, and existing styles when possible.

c_schmitz

c_schmitz

2010-11-26 01:42

administrator   ~13604

Last edited: 2010-11-26 01:45

View 1 revisions

Great work! Thank you very much. Patch was applied. Next? :-)

user9586

2010-11-26 15:40

  ~13612

Sorry to reopen this, but there's now a conflict in question.php:119

c_schmitz

c_schmitz

2010-11-26 16:16

administrator   ~13613

Fixed.

Issue History

Date Modified Username Field Change
2010-10-01 18:33 user9586 New Issue
2010-10-01 18:33 user9586 File Added: patch.diff
2010-10-02 19:52 user9586 File Added: patch2.diff
2010-10-02 19:53 user9586 Note Added: 12976
2010-10-03 19:50 Mazi Assigned To => c_schmitz
2010-10-03 19:50 Mazi Status new => assigned
2010-10-03 19:50 Mazi Note Added: 12981
2010-10-04 21:08 DenisChenu Note Added: 12987
2010-10-05 10:19 user9586 Note Added: 12997
2010-10-11 23:55 c_schmitz Status assigned => feedback
2010-10-11 23:55 c_schmitz Note Added: 13091
2010-11-11 16:00 user9586 File Added: patch-svn.diff
2010-11-11 16:05 user9586 Note Added: 13502
2010-11-11 16:05 user9586 Status feedback => assigned
2010-11-15 02:29 c_schmitz File Deleted: patch.diff
2010-11-15 02:29 c_schmitz File Deleted: patch2.diff
2010-11-15 02:31 c_schmitz Note Added: 13524
2010-11-15 02:33 c_schmitz Note Edited: 13524 View Revisions
2010-11-15 11:14 user9586 Note Added: 13525
2010-11-15 16:28 c_schmitz Note Added: 13526
2010-11-15 16:28 c_schmitz Note Edited: 13526 View Revisions
2010-11-15 20:26 user9586 Note Added: 13527
2010-11-15 20:47 c_schmitz Note Added: 13528
2010-11-22 19:46 user9586 File Added: patch-svn-2.diff
2010-11-22 19:48 user9586 Note Added: 13571
2010-11-22 21:19 lemeur Note Added: 13572
2010-11-23 18:28 c_schmitz File Deleted: patch-svn.diff
2010-11-23 18:32 c_schmitz Note Added: 13594
2010-11-23 18:32 c_schmitz Note Added: 13595
2010-11-24 17:04 user9586 File Added: patch-svn-3.diff
2010-11-24 17:05 user9586 Note Added: 13601
2010-11-26 01:35 c_schmitz File Deleted: patch-svn-2.diff
2010-11-26 01:42 c_schmitz Note Added: 13604
2010-11-26 01:42 c_schmitz Status assigned => resolved
2010-11-26 01:42 c_schmitz Fixed in Version => 1.91
2010-11-26 01:42 c_schmitz Resolution open => fixed
2010-11-26 01:45 c_schmitz Note Edited: 13604 View Revisions
2010-11-26 01:46 c_schmitz Note Revision Dropped: 13604: 00429
2010-11-26 15:40 user9586 Note Added: 13612
2010-11-26 15:40 user9586 Status resolved => feedback
2010-11-26 15:40 user9586 Resolution fixed => reopened
2010-11-26 16:16 c_schmitz Note Added: 13613
2010-11-26 16:16 c_schmitz Status feedback => resolved
2010-11-26 16:16 c_schmitz Resolution reopened => fixed
2010-12-14 13:02 c_schmitz Status resolved => closed