]> git.mjollnir.org Git - moodle.git/commitdiff
quiz editing: MDL-17285 This is Olli Savolainen's new interface for editing quizzes.
authortjhunt <tjhunt>
Thu, 20 Nov 2008 06:59:11 +0000 (06:59 +0000)
committertjhunt <tjhunt>
Thu, 20 Nov 2008 06:59:11 +0000 (06:59 +0000)
This was started and usability tested as a Finnish Summer of Code project, and then Olli did further work on it in his own time to get it in shape for inclusion in Moodle 2.0. I reviewed all the code. There are a number of minor outstanding issues that will be fixed soon. See the subtasks of MDL-17284 for a list.

The goal of these changes is to:
* help teachers new to Moodle, so when they first see the quiz editing page, they don't go "Huh! What on earth am I supposed to do here?"
* help novice Moodle users understand and learn to use some of the more advanced quiz feature;
* but, without slowing down more experienced quiz users.

Naturally, with ambitous goals like that, we won't have managed to satisy everybody, but I think this change is a big step in the right direction.

There is extensive documentation on this project at http://docs.moodle.org/en/Development:Quiz_UI_redesign.

20 files changed:
lang/en_utf8/help/quiz/editconcepts.html [new file with mode: 0644]
lang/en_utf8/quiz.php
lib/weblib.php
mod/quiz/addrandom.php [new file with mode: 0644]
mod/quiz/edit.js [new file with mode: 0644]
mod/quiz/edit.php
mod/quiz/editcss.js [new file with mode: 0644]
mod/quiz/editlib.php
mod/quiz/locallib.php
mod/quiz/tabs.php
question/category_class.php
question/category_form_randomquestion.php [new file with mode: 0644]
question/editlib.php
question/question.php
question/type/edit_question_form.php
theme/standard/styles_color.css
theme/standard/styles_fonts.css
theme/standard/styles_ie6.css
theme/standard/styles_layout.css
theme/standard/styles_moz.css

diff --git a/lang/en_utf8/help/quiz/editconcepts.html b/lang/en_utf8/help/quiz/editconcepts.html
new file mode 100644 (file)
index 0000000..e48d378
--- /dev/null
@@ -0,0 +1,25 @@
+<h1>Basic ideas of making quizzes</h1>
+<p>The main concepts while managing quiz content (questions) are:</p>
+<ul>
+    <li>Quiz and pages</li>
+    <li>Question bank and its categories</li>
+    <li>Random question</li>
+</ul>
+<p>You can think of a <strong>quiz</strong>, in essence, to be like a
+traditional pen&amp;paper quiz (or an exam/test). It contains questions.
+You can divide the questions in a quiz on several <strong>pages</strong>
+or you can keep them all on one page.
+With Moodle Quiz, you can also give the grading beforehand for the
+questions in a quiz (as well as the total for the entire quiz).</p>
+<p>When you create questions, they are stored in the <strong>Question
+Bank</strong>. In the Question Bank you can create categories, which are similar
+to folders. You can use them to create a hierarchy for organizing
+questions, for example, by topic. When you create a question into
+an exam, a copy of it is stored in the Question Bank. If you decide to
+remove your question from an exam, it will still be intact in the
+question bank until you delete it from there, too.</p>
+<p>You can use <strong>Random Questions</strong>, if you want a question to
+vary between different attempts students make at the quiz (for example,
+to avoid cheating by means of students copying questions to each other).
+Just create a random question in the quiz and add questions in the
+category of the random question.</p>
index de2b29fb8478f9de0c911d3f9c2bd13cfb55b859..41748e573c33b8e8f2ef534325a691024e5c582a 100644 (file)
@@ -678,5 +678,44 @@ $string['youcannotwait'] = 'This quiz closes before you will be allowed to start
 $string['youneedtoenrol'] = 'You need to enrol in this course before you can attempt this quiz';
 $string['yourfinalgradeis'] = 'Your final grade for this quiz is $a.';
 $string['zerosignificantfiguresnotallowed'] = 'The correct answer cannot have zero significant figures!';
-
+$string['totalquestionsinrandomqcategory'] = 'Total of $a questions in category.';
+$string['selectquestiontype'] = ' -- Select question type -- ';
+$string['adddescriptionlabel'] = 'Add description/label';
+$string['addrandomquestion'] = 'Add random question';
+$string['addrandomquestiontoquiz'] = 'Add random question to quiz $a';
+$string['parentcategory'] = 'Parent category';
+$string['selectcategory'] = 'Select category';
+$string['createcategoryfornewrandomquestion'] = 'Create a question category for the new random question';
+$string['qname'] = 'name';
+$string['qtypename'] = 'type, name';
+$string['age'] = 'age';
+$string['sortquestionsbyx'] = 'Sort questions by: $a';
+$string['addpagehere'] = 'Add page here';
+$string['questionbankmanagement'] = 'Question Bank management';
+$string['totalpoints'] = 'Total of grades';
+$string['quizwillopen'] = 'This quiz will open $a';
+$string['quizopenwillclose'] = 'This quiz is open, will close on $a at ';
+$string['basicideasofquiz'] = 'Basic ideas of making quizzes';
+$string['noquestionsinquiz'] = 'There are no questions in this quiz.';
+$string['addquestion'] = 'Add question';
+$string['questiontextisempty'] = '[Empty question text]';
+$string['addrandomfromcategory'] = 'Add random questions from category';
+$string['fromcategory'] = 'from category';
+$string['questionbankcontents'] = 'Question Bank contents';
+$string['quizorderrandom'] = '* Order of quiz is shuffled';
+$string['quizordernotrandom'] = 'Order of quiz not shuffled';
+$string['repaginatecommand'] = 'Repaginate';
+$string['orderandpaging'] = 'Order and paging';
+$string['noquestionsonpage'] = 'Empty page';
+$string['orderingquiz'] = 'Order and paging';
+$string['moveselectedonpage'] = 'Move selected questions to page';
+$string['addnewpagesafterselected'] = 'Add new pages after selected questions';
+$string['reorderquestions'] = 'Reorder questions';
+$string['noquestionsnotinuse'] = 'This random question is not in use, since its category is empty.';
+$string['addnewquestionsqbank'] = 'Add questions to the category $a in the \'Question bank contents\' tool >>';
+$string['empty'] = 'Empty';
+$string['quizopened'] = 'This quiz is open.';
+$string['areyousuredeleteselected'] = 'Are you sure you want to delete the selected questions?';
+$string['questionsperpageselected'] = 'Questions per page has been set so the paging is currently fixed. As a result, the paging controls have been disabled. You can change this in ';
+$string['shufflequestionsselected'] = '* Shuffle questions has been set so question order is random. As a result, the button Reorder questions has been disabled. You can change this in ';
 ?>
index 050e79c0ca94792a76d25e03332d9ffdfba07bbf..d0f99e07b1dd3d04f9bbccbe90613059727a6ef5 100644 (file)
@@ -717,7 +717,7 @@ function close_window($delay=0) {
  * @param mixed $listbox if false, display as a dropdown menu. If true, display as a list box.
  *      By default, the list box will have a number of rows equal to min(10, count($options)), but if
  *      $listbox is an integer, that number is used for size instead.
- * @param 
+ * @param
  */
 function choose_from_menu ($options, $name, $selected='', $nothing='choose', $script='',
                            $nothingvalue='0', $return=false, $disabled=false, $tabindex=0,
@@ -990,26 +990,30 @@ function print_textfield ($name, $value, $alt = '',$size=50,$maxlength=0, $retur
 
 
 /**
- * Implements a complete little popup form
+ * Implements a complete little form with a dropdown menu. When JavaScript is on
+ * selecting an option from the dropdown automatically submits the form (while
+ * avoiding the usual acessibility problems with this appoach). With JavaScript
+ * off, a 'Go' button is printed.
  *
- * @uses $CFG
- * @param string $common  The URL up to the point of the variable that changes
- * @param array $options  Alist of value-label pairs for the popup list
- * @param string $formid Id must be unique on the page (originaly $formname)
- * @param string $selected The option that is already selected
+ * @param string $baseurl The target URL up to the point of the variable that changes
+ * @param array $options A list of value-label pairs for the popup list
+ * @param string $formid id for the control. Must be unique on the page. Used in the HTML.
+ * @param string $selected The option that is initially selected
  * @param string $nothing The label for the "no choice" option
  * @param string $help The name of a help page if help is required
  * @param string $helptext The name of the label for the help button
- * @param boolean $return Indicates whether the function should return the text
+ * @param boolean $return Indicates whether the function should return the HTML
  *         as a string or echo it directly to the page being rendered
  * @param string $targetwindow The name of the target page to open the linked page in.
  * @param string $selectlabel Text to place in a [label] element - preferred for accessibility.
- * @param array $optionsextra TODO, an array?
+ * @param array $optionsextra an array with the same keys as $options. The values are added within the corresponding <option ...> tag.
+ * @param string $submitvalue Optional label for the 'Go' button. Defaults to get_string('go').
+ * @param boolean $disabled If true, the menu will be displayed disabled.
  * @return string If $return is true then the entire form is returned as a string.
  * @todo Finish documenting this function<br>
  */
-function popup_form($common, $options, $formid, $selected='', $nothing='choose', $help='', $helptext='', $return=false,
-$targetwindow='self', $selectlabel='', $optionsextra=NULL) {
+function popup_form($baseurl, $options, $formid, $selected='', $nothing='choose', $help='', $helptext='', $return=false,
+$targetwindow='self', $selectlabel='', $optionsextra=NULL, $submitvalue='', $disabled=false) {
 
     global $CFG, $SESSION;
     static $go, $choose;   /// Locally cached, in case there's lots on a page
@@ -1018,16 +1022,23 @@ $targetwindow='self', $selectlabel='', $optionsextra=NULL) {
         return '';
     }
 
-    if (!isset($go)) {
-        $go = get_string('go');
+    if (empty($submitvalue)){
+        if (!isset($go)) {
+            $go = get_string('go');
+            $submitvalue=$go;
+        }
     }
-
     if ($nothing == 'choose') {
         if (!isset($choose)) {
             $choose = get_string('choose');
         }
         $nothing = $choose.'...';
     }
+    if ($disabled) {
+        $disabled = 'disabled="disabled"';
+    } else {
+        $disabled = '';
+    }
 
     // changed reference to document.getElementById('id_abc') instead of document.abc
     // MDL-7861
@@ -1046,16 +1057,16 @@ $targetwindow='self', $selectlabel='', $optionsextra=NULL) {
         $selectlabel = '<label for="'.$formid.'_jump">'.$selectlabel.'</label>';
     }
 
-    //IE and Opera fire the onchange when ever you move into a dropdwown list with the keyboard.
+    //IE and Opera fire the onchange when ever you move into a dropdown list with the keyboard.
     //onfocus will call a function inside dropdown.js. It fixes this IE/Opera behavior.
     //Note: There is a bug on Opera+Linux with the javascript code (first mouse selection is inactive),
     //so we do not fix the Opera behavior on Linux
     if (check_browser_version('MSIE') || (check_browser_version('Opera') && !check_browser_operating_system("Linux"))) {
-        $output .= '<div>'.$selectlabel.$button.'<select id="'.$formid.'_jump" onfocus="initSelect(\''.$formid.'\','.$targetwindow.')" name="jump">'."\n";
+        $output .= '<div>'.$selectlabel.$button.'<select id="'.$formid.'_jump" onfocus="initSelect(\''.$formid.'\','.$targetwindow.')" name="jump" '.$disabled.'>'."\n";
     }
     //Other browser
     else {
-        $output .= '<div>'.$selectlabel.$button.'<select id="'.$formid.'_jump" name="jump" onchange="'.$targetwindow.'.location=document.getElementById(\''.$formid.'\').jump.options[document.getElementById(\''.$formid.'\').jump.selectedIndex].value;">'."\n";
+        $output .= '<div>'.$selectlabel.$button.'<select id="'.$formid.'_jump" name="jump" onchange="'.$targetwindow.'.location=document.getElementById(\''.$formid.'\').jump.options[document.getElementById(\''.$formid.'\').jump.selectedIndex].value;" '.$disabled.'>'."\n";
     }
 
     if ($nothing != '') {
@@ -1105,10 +1116,10 @@ $targetwindow='self', $selectlabel='', $optionsextra=NULL) {
         } else {
            if (!empty($CFG->usesid) && !isset($_COOKIE[session_name()]))
             {
-                $url = $SESSION->sid_process_url( $common . $value );
+                $url = $SESSION->sid_process_url( $baseurl . $value );
             } else
             {
-                $url=$common . $value;
+                $url=$baseurl . $value;
             }
             $optstr = '   <option value="' . $url . '"';
 
@@ -1144,7 +1155,7 @@ $targetwindow='self', $selectlabel='', $optionsextra=NULL) {
     $output .= '</select>';
     $output .= '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
     $output .= '<div id="noscript'.$formid.'" style="display: inline;">';
-    $output .= '<input type="submit" value="'.$go.'" /></div>';
+    $output .= '<input type="submit" value="'.$submitvalue.'" '.$disabled.' /></div>';
     $output .= '<script type="text/javascript">'.
                "\n//<![CDATA[\n".
                'document.getElementById("noscript'.$formid.'").style.display = "none";'.
@@ -2068,7 +2079,7 @@ function get_emoticons_list_for_help_file(){
         $formname = 'theform';
         $fieldname = 'message';
     }
-    
+
     $output .= print_js_call('emoticons_help.init', array($formname, $fieldname, 'emoticonlist'), true);
     return $output;
 
@@ -2596,7 +2607,7 @@ function print_header ($title='', $heading='', $navigation='', $focus='',
  * require_once in PHP.
  *
  * There are two special-case calls to this function from print_header which are
- * internal to weblib and use the second $extracthtmlparameter:
+ * internal to weblib and use the second $extracthtml parameter:
  * $extracthtml = 1: this is used before printing the header.
  *      It returns the script tag code that should go inside the <head>.
  * $extracthtml = 2: this is used after printing the header and handles any
@@ -2754,7 +2765,7 @@ function print_delayed_js_call($delay, $function, $args = array(), $return = fal
  * variable, and then just output the configuration variables from PHP using
  * this function.
  *
- * For example, look at the code in question_init_qenginejs_script() in 
+ * For example, look at the code in question_init_qenginejs_script() in
  * lib/questionlib.php. It writes out a bunch of $settings like
  * 'pixpath' => $CFG->pixpath, with $prefix = 'qengine_config'. This gets output
  * in print_header, then the code in question/qengine.js can access these variables
diff --git a/mod/quiz/addrandom.php b/mod/quiz/addrandom.php
new file mode 100644 (file)
index 0000000..cdad500
--- /dev/null
@@ -0,0 +1,73 @@
+<?php // $Id$
+/**
+ * Fallback page of /mod/quiz/edit.php add random question dialog,
+ * for users who do not use javascript.
+ *
+ * @author Olli Savolainen, as a part of the Quiz UI Redesign project in Summer 2008
+ *         {@link http://docs.moodle.org/en/Development:Quiz_UI_redesign}.
+ * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
+ * @package quiz
+ */
+    require_once("../../config.php");
+    require_once($CFG->dirroot.'/mod/quiz/editlib.php');
+    require_once($CFG->dirroot."/question/category_class.php");
+
+    list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) = question_edit_setup('editq', true);
+
+    $defaultcategoryobj = question_make_default_categories($contexts->all());
+    $defaultcategoryid=$defaultcategoryobj->id;
+    $defaultcategorycontext=$defaultcategoryobj->contextid;
+    $defaultcategory="$defaultcategoryid,$defaultcategorycontext";
+
+    $qcobject = new question_category_object(
+        $pagevars['cpage'],
+        $thispageurl,
+        $contexts->having_one_edit_tab_cap('categories'),
+        $defaultcategoryid,
+        $defaultcategory,
+        null,
+        $contexts->having_cap('moodle/question:add'));
+
+    //setting the second parameter of process_randomquestion_formdata to true causes it to redirect on success
+    //TODO: process if returns false?
+    quiz_process_randomquestion_formdata($qcobject,true, $cmid);
+
+    //these params are only passed from page request to request while we stay on this page
+    //otherwise they would go in question_edit_setup
+    $quiz_page = optional_param('quiz_page', 0, PARAM_SEQUENCE);
+    $returnurl = optional_param('returnurl', 0, PARAM_LOCALURL);
+
+    $strquizzes = get_string('modulenameplural', 'quiz');
+    $strquiz = get_string('modulename', 'quiz');
+    $streditingquestions = get_string('editquestions', "quiz");
+    $streditingquiz = get_string('editinga', 'moodle', $strquiz);
+
+    // Get the course object and related bits.
+    if (! $course = $DB->get_record("course", array("id"=> $quiz->course))) {
+        error("This course doesn't exist");
+    }
+    // TODO: Log this visit.
+    /*
+    add_to_log($cm->course, 'quiz', 'editquestions',
+            "view.php?id=$cm->id", "$quiz->id", $cm->id);
+    */
+    //you need mod/quiz:manage in addition to question capabilities to access this page.
+    require_capability('mod/quiz:manage', $contexts->lowest());
+    // Print basic page layout.
+
+    $strupdatemodule = has_capability('moodle/course:manageactivities', $contexts->lowest())
+        ? update_module_button($cm->id, $course->id, get_string('modulename', 'quiz'))
+        : "";
+    $navigation = build_navigation($streditingquiz, $cm);
+    print_header_simple($streditingquiz, '', $navigation, "", "", true, $strupdatemodule);
+
+    if (!$quizname = $DB->get_field($cm->modname, 'name', array('id'=> $cm->instance))) {
+                error('Cannot get the module name in build navigation.');
+    }
+
+    print_heading(get_string("addrandomquestiontoquiz","quiz",$quizname), 'left', 2);
+
+    $qcobject->display_randomquestion_user_interface();
+
+    print_footer($course);
+?>
\ No newline at end of file
diff --git a/mod/quiz/edit.js b/mod/quiz/edit.js
new file mode 100644 (file)
index 0000000..10d2c4d
--- /dev/null
@@ -0,0 +1,130 @@
+/** JavaScript for /mod/quiz/edit.php
+ */
+
+YAHOO.namespace("cats.container");
+YAHOO.namespace("quiz.container");
+function init() {
+    YAHOO.util.Dom.setStyle('randomquestiondialog', 'display', 'block');
+    YAHOO.cats.container.module = new YAHOO.widget.Module("module");
+    YAHOO.cats.container.show = new YAHOO.widget.Module("show");
+    YAHOO.cats.container.hide = new YAHOO.widget.Module("hide");
+    YAHOO.cats.container.module.render();
+    YAHOO.util.Event.addListener("show", "click", YAHOO.cats.container.module.show,
+            YAHOO.cats.container.module, true);
+    YAHOO.util.Event.addListener("show", "click",
+            function(e){
+                YAHOO.cats.container.hide.show;
+                // for some reason YUI sets element display "block" so we have to reverse that:
+                hideel.setStyle("display", "inline");
+                //TODO: get sURL from the phpdata object somehow
+                var sUrl="";
+                var transaction = YAHOO.util.Connect.asyncRequest("GET", sUrl, null, null);
+                YAHOO.util.Event.stopEvent(e);
+            }, YAHOO.cats.container.hide, true);
+    YAHOO.util.Event.addListener("show", "click", YAHOO.cats.container.show.hide, YAHOO.cats.container.show, true);
+    YAHOO.util.Event.addListener("hide", "click", YAHOO.cats.container.module.hide, YAHOO.cats.container.module, true);
+    YAHOO.util.Event.addListener("hide", "click",
+            function(e){
+                YAHOO.cats.container.show.show;
+                // for some reason YUI sets element display
+                // to "block" so we have to reverse that:
+                showel.setStyle("display", "inline");
+                var sUrl="$surl";
+                var transaction = YAHOO.util.Connect.asyncRequest("GET", sUrl, null, null);
+                YAHOO.util.Event.stopEvent(e);
+            }, YAHOO.cats.container.show, true);
+
+    YAHOO.util.Event.addListener("hide", "click", YAHOO.cats.container.hide.hide, YAHOO.cats.container.hide, true);
+
+    // Instantiate the Dialog
+    /* zIndex must be way above 99 to be above the active quiz tab*/
+    YAHOO.quiz.container.randomquestiondialog = new YAHOO.widget.Dialog("randomquestiondialog",
+                {
+                  constraintoviewport : true,
+                  visible : false,
+                  modal:true,
+                  width : "100%",
+                  iframe:true,
+                  zIndex:1000,
+                  fixedcenter : true,
+                  close: true,
+                  draggable: true,
+                  dragOnly: true,
+                  postmethod: "form"
+
+                 } );
+    //show the dialog and depending on from which form (corresponding
+    // a specific quiz page) it was triggered, set the value of the form's
+    // rqpage input element to the form number
+    YAHOO.util.Event.addListener(this.dialog_listeners, "click",
+           function(e){
+                   this.show();
+                var rbutton = YAHOO.util.Event.getTarget(e);
+                var rbform = YAHOO.util.Dom.getAncestorByClassName(rbutton,"randomquestionform");
+                //this depends on the fact that the element hierarchy be:
+                // <form class="randomquestionform"><div>[input elements]</div></form>
+                var rbformelements = YAHOO.util.Dom.getChildren
+                (YAHOO.util.Dom.getFirstChild(rbform));
+                var rqpage=YAHOO.util.Dom.get("rform_qpage");
+
+                /*
+                //this should work, it doesn't, no time to debug.
+                var rqpagehiddenel=YAHOO.util.Dom.getFirstChildBy(rbformelements,function(el) {
+                    //alert("infunc");
+                    var result=YAHOO.util.Dom.hasClass(el,"addonpage_formelement");
+                    //if (result) alert ("yes"); else alert("no");
+                    return result;
+                });
+                //no element in rqpagehiddenel
+                //rqpage.value=rqpagehiddenel.value.value;
+                */
+
+                //this works instead
+                for (var i = 0; i < rbformelements.length; i++) {
+                    if(YAHOO.util.Dom.hasClass(rbformelements[i],"addonpage_formelement")){
+                          //why is this not rqpage.value.value, the first "value" being the element property
+                          // and the second the value of that property? I don't understand.
+                          rqpage.value=rbformelements[i].attributes.value.value;
+                    }
+                }
+                YAHOO.util.Event.stopEvent(e);
+            }, YAHOO.quiz.container.randomquestiondialog,
+            YAHOO.quiz.container.randomquestiondialog, true);
+    YAHOO.quiz.container.randomquestiondialog.render();
+// Instantiate the Dialog
+    YAHOO.quiz.container.repaginatedialog = new YAHOO.widget.Dialog("repaginatedialog",
+                {
+                  modal:true,
+                  width : "100%",
+                  iframe:true,
+                  zIndex:1000,
+                  fixedcenter : true,
+                  visible : false,
+                  close: true,
+                  draggable: true,
+                  dragOnly: true,
+                  constraintoviewport : true,
+                  postmethod: "form"
+                 } );
+YAHOO.util.Event.addListener("repaginatecommand", "click",
+            function(e){
+                YAHOO.util.Dom.setStyle('repaginatedialog', 'display', 'block');
+                this.show();
+            }, YAHOO.quiz.container.repaginatedialog,
+            YAHOO.quiz.container.repaginatedialog, true);
+    YAHOO.quiz.container.repaginatedialog.render();
+
+}
+
+
+YAHOO.util.Event.addListener(window, "load", init,phpGenerated,true);
+YAHOO.util.Dom.setStyle('repaginatedialog', 'display', 'block');
+
+//TODO: take this inside the init function to make sure
+//YAHOO.cats.container.module is defined when run
+if (YAHOO.cats.container.module && quiz_qbanktool){
+    YAHOO.cats.container.module.hide();
+    YAHOO.cats.container.show.show();
+    showel.setStyle("display", "inline");
+    YAHOO.cats.container.hide.hide();
+}
index 063756e65d2c813f7f49fb2112777b23a83cc677..56bb9020eefcc1bc1b4a010a5755725fc6b5b5b6 100644 (file)
  *
  * @author Martin Dougiamas and many others. This has recently been extensively
  *         rewritten by Gustav Delius and other members of the Serving Mathematics project
- *         {@link http://maths.york.ac.uk/serving_maths}
+ *         {@link http://maths.york.ac.uk/serving_maths}. The UI and some functionality
+ *         was rewritten as a part of the Quiz UI Redesign project in Summer 2008
+ *         {@link http://docs.moodle.org/en/Development:Quiz_UI_redesign}.
  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  * @package quiz
  */
-    require_once("../../config.php");
-    require_once($CFG->dirroot.'/mod/quiz/editlib.php');
-
-    /**
-     * Callback function called from question_list() function (which is called from showbank())
-     * Displays action icon as first action for each question.
-     */
-    function module_specific_actions($pageurl, $questionid, $cmid, $canuse){
-        global $CFG;
-        if ($canuse){
-                       // for RTL languages: switch right and left arrows /****/
-                       if (right_to_left()) {
-                               $movearrow = 'removeright.gif';
-                       } else {
-                               $movearrow = 'moveleft.gif';
-                       }
-            $straddtoquiz = get_string("addtoquiz", "quiz");
-            $out = "<a title=\"$straddtoquiz\" href=\"edit.php?".$pageurl->get_query_string()."&amp;addquestion=$questionid&amp;sesskey=".sesskey()."\"><img
-                  src=\"$CFG->pixpath/t/$movearrow\" alt=\"$straddtoquiz\" /></a>&nbsp;";
-            return $out;
+require_once("../../config.php");
+require_once($CFG->dirroot.'/mod/quiz/editlib.php');
+require_once($CFG->dirroot."/question/category_class.php");
+require_js(array('yui_yahoo','yui_dom-event', 'yui_container',
+        'yui_element','yui_dragdrop','yui_animation', 'yui_logger'));
+
+/**
+ * Callback function called from question_list() function (which is called
+ * from showbank())
+ * Displays action icon as first action for each question.
+ */
+function module_specific_actions($pageurl, $questionid, $cmid, $canuse, $cmoptions){
+    global $CFG;
+    if ($canuse && !$cmoptions->hasattempts){
+        // for RTL languages: switch right and left arrows /****/
+        if (right_to_left()) {
+            $movearrow = 'removeright.gif';
         } else {
-            return '';
+            $movearrow = 'moveleft.gif';
         }
-    }
-    /**
-     * Callback function called from question_list() function (which is called from showbank())
-     * Displays button in form with checkboxes for each question.
-     */
-    function module_specific_buttons($cmid){
-        global $THEME;
         $straddtoquiz = get_string("addtoquiz", "quiz");
-        $out = "<input type=\"submit\" name=\"add\" value=\"{$THEME->larrow} $straddtoquiz\" />\n";
+        $out = "<a title=\"$straddtoquiz\" href=\"edit.php?".
+                $pageurl->get_query_string().
+                "&amp;addquestion=$questionid&amp;sesskey=".
+                sesskey()."\"><img src=\"$CFG->pixpath/t/$movearrow\"
+                alt=\"$straddtoquiz\" /></a>&nbsp;";
         return $out;
+    } else {
+        return '';
+    }
+}
+/**
+ * Callback function called from question_list() function
+ * (which is called from showbank())
+ * Displays button in form with checkboxes for each question.
+ */
+function module_specific_buttons($cmid,$cmoptions){
+    if($cmoptions->hasattempts){
+        $disabled='disabled="disabled"';
+    }else{
+        $disabled='';
     }
+    global $THEME;
+    $straddtoquiz = get_string("addtoquiz", "quiz");
+    $out = "<input type=\"submit\" name=\"add\"
+            value=\"{$THEME->larrow} $straddtoquiz\" $disabled />\n";
+    return $out;
+}
 
 
-    /**
-     * Callback function called from question_list() function (which is called from showbank())
-     */
-    function module_specific_controls($totalnumber, $recurse, $category, $cmid){
-        global $QTYPES;
-        $out = '';
-        $catcontext = get_context_instance_by_id($category->contextid);
-        if (has_capability('moodle/question:useall', $catcontext)){
-            $randomusablequestions = $QTYPES['random']->get_usable_questions_from_category(
-                    $category->id, $recurse, '0');
-            $maxrand = count($randomusablequestions);
-            if ($maxrand > 0) {
-                for ($i = 1;$i <= min(10, $maxrand); $i++) {
-                    $randomcount[$i] = $i;
-                }
-                for ($i = 20;$i <= min(100, $maxrand); $i += 10) {
-                    $randomcount[$i] = $i;
-                }
-                $out .= '<br />';
-                $out .= get_string('addrandom', 'quiz', choose_from_menu($randomcount, 'randomcount', '1', '', '', '', true));
-                $out .= '<input type="hidden" name="recurse" value="'.$recurse.'" />';
-                $out .= '<input type="hidden" name="categoryid" value="'.$category->id.'" />';
-                $out .= ' <input type="submit" name="addrandom" value="'. get_string('add') .'" />';
-                $out .= helpbutton('random', get_string('random', 'quiz'), 'quiz', true, false, '', true);
+/**
+ * Callback function called from question_list() function
+ * (which is called from showbank())
+ */
+function module_specific_controls($totalnumber, $recurse, $category, $cmid, $cmoptions){
+    global $THEME,$QTYPES;
+    $out = '';
+    $catcontext = get_context_instance_by_id($category->contextid);
+    if (has_capability('moodle/question:useall', $catcontext)){
+        if($cmoptions->hasattempts){
+            $disabled='disabled="disabled"';
+        }else{
+            $disabled='';
+        }
+        $randomusablequestions = $QTYPES['random']->get_usable_questions_from_category(
+                $category->id, $recurse, '0');
+        $maxrand = count($randomusablequestions);
+        if ($maxrand > 0) {
+            for ($i = 1;$i <= min(10, $maxrand); $i++) {
+                $randomcount[$i] = $i;
             }
+            for ($i = 20;$i <= min(100, $maxrand); $i += 10) {
+                $randomcount[$i] = $i;
+            }
+            $straddtoquiz = get_string("addtoquiz", "quiz");
+            $out = '<strong><label for="menurandomcount">'.get_string('addrandomfromcategory','quiz').
+                    '</label>:</strong><br />';
+            $out .= get_string('addrandom', 'quiz', choose_from_menu($randomcount,
+                    'randomcount', '1', '', '', '', true,$cmoptions->hasattempts));
+            $out .= '<input type="hidden" name="recurse" value="'.$recurse.'" />';
+            $out .= "<input type=\"hidden\" name=\"categoryid\"
+                    value=\"$category->id\" />";
+            $out .= ' <input type="submit" name="addrandom" value="'.
+                    $straddtoquiz.'" '.$disabled.' />';
+            $out .= helpbutton('random', get_string('random', 'quiz'), 'quiz',
+                    true, false, '', true);
         }
-        return $out;
     }
+    return $out;
+}
 
-    list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) = question_edit_setup('editq', true);
-
-    //these params are only passed from page request to request while we stay on this page
-    //otherwise they would go in question_edit_setup
-    $quiz_showbreaks = optional_param('showbreaks', -1, PARAM_BOOL);
-    $quiz_reordertool = optional_param('reordertool', 0, PARAM_BOOL);
-    if ($quiz_showbreaks > -1) {
-        $thispageurl->param('showbreaks', $quiz_showbreaks);
-    } else {
-        $quiz_showbreaks = get_config('quiz', 'questionsperpage') > 1;
+/**
+ * Add an arbitrary element to array at a specified index, pushing the rest
+ * back.
+ *
+ * @param array $array The array to operate on
+ * @param mixed $value The element to add
+ * @param integer $at The position at which to add the element
+ * @return array
+ */
+function array_add_at($array,$value,$at){
+    $beginpart=array_slice($array, 0,$at);
+    $endpart=array_slice($array, $at, (count($array)-$at) );
+    $beginpart[]=$value;
+    $result=array_merge($beginpart,$endpart);
+    return $result;
+}
+/**
+ * Just like strpos, but it returns the position
+ * of the nth instance of the needle.
+ * Thanks to chasesan at gmail for strpos2
+ * http://www.php.net/manual/en/function.strpos.php
+ */
+function strpos2($haystack, $needle, $nth = 1)
+{
+    //Fixes a null return if the position is at the beginning of input
+    //It also changes all input to that of a string ^.~
+    $haystack = ' '.$haystack;
+    if (!strpos($haystack, $needle)){
+        return false;
     }
-    if ($quiz_reordertool != 0) {
-        $thispageurl->param('reordertool', $quiz_reordertool);
+    $offset=0;
+    for($i = 1; $i < $nth; $i++){
+        $offset = strpos($haystack, $needle, $offset) + 1;
     }
+    return strpos($haystack, $needle, $offset) - 1;
+}
+/**
+ * Prints the form for setting a quiz' overall grade
+ */
+function quiz_print_grading_form($quiz, $pageurl, $tabindex){
+    global $USER;
+    $strsave=get_string('save',"quiz");
+    echo "<form method=\"post\" action=\"edit.php\"><div>";
+    echo '<fieldset class="invisiblefieldset" style="display: block;">';
+    echo "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />";
+    echo $pageurl->hidden_params_out();
+    echo '<label for="inputmaxgrade">'.get_string("maximumgrade")."</label>: ";
+    echo '<input type="text" id="inputmaxgrade" name="maxgrade" size="' . ($quiz->decimalpoints + 2) . '" tabindex="'.($tabindex)
+         .'" value="'.quiz_format_grade($quiz, $quiz->grade).'" />';
+    echo '<input type="hidden" name="savechanges" value="save" />';
+    echo '<input type="submit" value="'.$strsave.'" />';
+    helpbutton("maxgrade", get_string("maximumgrade"), "quiz");
+    echo '</fieldset>';
+    echo "</div></form>\n";
+}
+/**
+ * Print the status bar
+ *
+ * @param mixed $quiz The quiz object of the quiz in question
+ * @param integer $sumgrades The sum of the grades of the quiz to display
+ */
 
-    $strquizzes = get_string('modulenameplural', 'quiz');
-    $strquiz = get_string('modulename', 'quiz');
-    $streditingquestions = get_string('editquestions', "quiz");
-    $streditingquiz = get_string('editinga', 'moodle', $strquiz);
-
-    // Get the course object and related bits.
-    if (! $course = $DB->get_record('course', array('id' => $quiz->course))) {
-        print_error('invalidcourseid', 'error');
+function quiz_print_status_bar($quiz,$sumgrades){
+    global $CFG;
+    $numberofquestions=quiz_number_of_questions_in_quiz($quiz->questions);
+    ?><div class="statusdisplay"><span class="totalpoints">
+    <?php echo get_string("totalpoints","quiz") ?>:</span>
+    <?php echo $sumgrades; ?>
+    | <span class="numberofquestions">
+    <?php
+    echo get_string("questions","quiz").": $numberofquestions"
+    ?></span>
+    | <span class="quizopeningstatus">
+    <?php
+    print_timing_information($quiz,true);
+    ?></span><?php
+    // If questions are shuffled, notify the user about the
+    // question order not making much sense
+
+    $updateurl=new moodle_url("$CFG->wwwroot/course/mod.php",
+            array("return"=>"true","update"=>$quiz->cmid, "sesskey"=>sesskey()));
+    echo '<br /><strong><a href="'.$updateurl->out().'">';
+    print_string('updatethis', '', get_string('modulename', 'quiz'));
+    echo '</a>:</strong> ';
+    if($quiz->shufflequestions){
+        echo "*";
+    }
+    echo get_string("shufflequestions",'quiz').": ";
+    if($quiz->shufflequestions){
+        echo get_string("yes");
+    }
+    else{
+        echo get_string("no");
+    }
+    echo " | ";
+    print_string("questionsperpage","quiz");
+    $questionsperpagebool = ($quiz->questionsperpage < 1) ? 0 : 1;
+    if($questionsperpagebool){
+        echo ": $quiz->questionsperpage";
+    }else{
+        echo ": ".get_string("unlimited");
     }
 
-    // Log this visit.
-    add_to_log($cm->course, 'quiz', 'editquestions',
+    ?>
+    </div>
+    <?php
+}
+
+
+list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) =
+        question_edit_setup('editq', true);
+
+$defaultcategoryobj = question_make_default_categories($contexts->all());
+$defaultcategoryid=$defaultcategoryobj->id;
+$defaultcategorycontext=$defaultcategoryobj->contextid;
+$defaultcategory="$defaultcategoryid,$defaultcategorycontext";
+//these params are only passed from page request to request while we stay on
+//this page otherwise they would go in question_edit_setup
+$quiz_reordertool = optional_param('reordertool', 0, PARAM_BOOL);
+$quiz_qbanktool = optional_param('qbanktool', -1, PARAM_BOOL);
+if ($quiz_qbanktool > -1) {
+    $thispageurl->param('qbanktool', $quiz_qbanktool);
+    set_user_preference("quiz_qbanktool_open",$quiz_qbanktool);
+} else {
+    $quiz_qbanktool = get_user_preferences("quiz_qbanktool_open",0);
+}
+
+//will be set further down in the code
+$quiz_has_attempts=false;
+
+if ($quiz_reordertool != 0) {
+    $thispageurl->param('reordertool', $quiz_reordertool);
+}
+
+$strquizzes = get_string('modulenameplural', 'quiz');
+$strquiz = get_string('modulename', 'quiz');
+$streditingquestions = get_string('editquestions', "quiz");
+
+//this just does not work for at least finnish, where words are conjugated:
+//$streditingquiz = get_string('editinga', 'moodle', $strquiz);
+$streditingquiz = get_string('editingquiz', 'quiz');
+$strorderingquiz = get_string('orderingquiz', 'quiz');
+$pagetitle=$streditingquiz;
+if($quiz_reordertool){
+    $pagetitle=$strorderingquiz;
+}
+// Get the course object and related bits.
+if (! $course = $DB->get_record('course', array('id' => $quiz->course))) {
+    print_error('invalidcourseid', 'error');
+}
+
+// Log this visit.
+add_to_log($cm->course, 'quiz', 'editquestions',
             "view.php?id=$cm->id", "$quiz->id", $cm->id);
 
-    //you need mod/quiz:manage in addition to question capabilities to access this page.
-    require_capability('mod/quiz:manage', $contexts->lowest());
-
-    if (isset($quiz->instance)
-        && empty($quiz->grades)){  // Construct an array to hold all the grades.
-        $quiz->grades = quiz_get_all_question_grades($quiz);
-    }
+//you need mod/quiz:manage in addition to question capabilities to access
+//this page.
+require_capability('mod/quiz:manage', $contexts->lowest());
 
+if (isset($quiz->instance)
+&& empty($quiz->grades)){  // Construct an array to hold all the grades.
+    $quiz->grades = quiz_get_all_question_grades($quiz);
+}
 
+// SECTION: PROCESS COMMANDS //
 /// Now, check for commands on this page and modify variables as necessary
-    // If any edit action makes a sifnificant change to the structure of the quiz, then we
-    // will need to delete all preview attempts.
-    $significantchangemade = false;
-
-    if (($up = optional_param('up', false, PARAM_INT)) !== false and confirm_sesskey()) { /// Move the given question up a slot
-        $questions = explode(",", $quiz->questions);
-        if ($up > 0 and isset($questions[$up])) {
-            $prevkey = ($questions[$up-1] == 0) ? $up-2 : $up-1;
-            $swap = $questions[$prevkey];
-            $questions[$prevkey] = $questions[$up];
-            $questions[$up]   = $swap;
-            $quiz->questions = implode(",", $questions);
-            // Always have a page break at the end
-            $quiz->questions = $quiz->questions . ',0';
-            // Avoid duplicate page breaks
-            $quiz->questions = str_replace(',0,0', ',0', $quiz->questions);
-            if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->instance))) {
-                print_error('cannotsavequestion', 'quiz');
-            }
-            $significantchangemade = true;
+// If any edit action makes a sifnificant change to the structure of the quiz,
+// then we will need to delete all preview attempts.
+$significantchangemade = false;
+if (($up = optional_param('up', false, PARAM_INT)) !== false and
+        confirm_sesskey()) { /// Move the given question up a slot
+    $questions = explode(",", $quiz->questions);
+    if ($up > 0 and isset($questions[$up])) {
+        //$prevkey = ($questions[$up-1] == 0) ? $up-2 : $up-1;
+        $prevkey = $up-1;
+        $swap = $questions[$prevkey];
+        $questions[$prevkey] = $questions[$up];
+        $questions[$up]   = $swap;
+        $quiz->questions = implode(",", $questions);
+        $quiz->questions=quiz_clean_layout($quiz->questions);
+        if (!$DB->set_field('quiz', 'questions', $quiz->questions,
+                array('id' => $quiz->instance))) {
+            print_error('cannotsavequestion', 'quiz');
         }
+        $significantchangemade = true;
     }
-
-    if (($down = optional_param('down', false, PARAM_INT)) !== false and confirm_sesskey()) { /// Move the given question down a slot
-        $questions = explode(",", $quiz->questions);
-        if ($down < count($questions)) {
-            $nextkey = ($questions[$down+1] == 0) ? $down+2 : $down+1;
-            $swap = $questions[$nextkey];
-            $questions[$nextkey] = $questions[$down];
-            $questions[$down]   = $swap;
-            $quiz->questions = implode(",", $questions);
-            // Avoid duplicate page breaks
-            $quiz->questions = str_replace(',0,0', ',0', $quiz->questions);
-            if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->instance))) {
-                print_error('cannotsavequestion', 'quiz');
-            }
-            $significantchangemade = true;
+}
+
+
+if (($down = optional_param('down', false, PARAM_INT)) !== false and
+        confirm_sesskey()) { /// Move the given question down a slot
+    $questions = explode(",", $quiz->questions);
+    if ($down < count($questions)) {
+        //$nextkey = ($questions[$down+1] == 0) ? $down+2 : $down+1;
+        $nextkey = $down+1;
+        $swap = $questions[$nextkey];
+        $questions[$nextkey] = $questions[$down];
+        $questions[$down]   = $swap;
+        $quiz->questions = implode(",", $questions);
+        $quiz->questions=quiz_clean_layout($quiz->questions);
+        if (!$DB->set_field('quiz', 'questions', $quiz->questions,
+                array('id' => $quiz->instance))) {
+            print_error('cannotsavequestion', 'quiz');
         }
-    }
-
-    if (($addquestion = optional_param('addquestion', 0, PARAM_INT)) and confirm_sesskey()) { /// Add a single question to the current quiz
-        quiz_add_quiz_question($addquestion, $quiz);
         $significantchangemade = true;
     }
-
-    if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) { /// Add selected questions to the current quiz
-        $rawdata = (array) data_submitted();
-        foreach ($rawdata as $key => $value) {    // Parse input for question ids
-            if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
-                $key = $matches[1];
-                quiz_add_quiz_question($key, $quiz);
-            }
+}
+if (($addquestion = optional_param('addquestion', 0, PARAM_INT)) and
+        confirm_sesskey()) { /// Add a single question to the current quiz
+    $addonpage = optional_param('addonpage',0,PARAM_INT);
+    quiz_add_quiz_question($addquestion, $quiz, $addonpage);
+    $significantchangemade = true;
+}
+
+if (optional_param('add', false, PARAM_BOOL) and
+        confirm_sesskey()) { /// Add selected questions to the current quiz
+    $rawdata = (array) data_submitted();
+    foreach ($rawdata as $key => $value) {    // Parse input for question ids
+        if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
+            $key = $matches[1];
+            quiz_add_quiz_question($key, $quiz);
         }
-        $significantchangemade = true;
     }
-
-    if (optional_param('addrandom', false, PARAM_BOOL) and confirm_sesskey()) { /// Add random questions to the quiz
-        $recurse = optional_param('recurse', 0, PARAM_BOOL);
+    $significantchangemade = true;
+}
+
+$qcobject = new question_category_object(
+    $pagevars['cpage'],
+    $thispageurl,
+    $contexts->having_one_edit_tab_cap('categories'),
+    $defaultcategoryid,
+    $defaultcategory,
+    null,
+    $contexts->having_cap('moodle/question:add'));
+
+$newrandomcategory=quiz_process_randomquestion_formdata($qcobject);
+
+if ((optional_param('addrandom', false, PARAM_BOOL) OR $newrandomcategory)
+        and confirm_sesskey()) {
+    /// Add random questions to the quiz
+    $recurse = optional_param('recurse', 0, PARAM_BOOL);
+    $addonpage = optional_param('addonpage',0,PARAM_INT);
+    if($newrandomcategory){
+        $categoryid = $newrandomcategory;
+        $randomcount = optional_param('randomcount',1, PARAM_INT);
+    }else{
         $categoryid = required_param('categoryid', PARAM_INT);
         $randomcount = required_param('randomcount', PARAM_INT);
-        // load category
-        if (! $category = $DB->get_record('question_categories', array('id' => $categoryid))) {
-            print_error('invalidcategoryid', 'error');
-        }
-        $catcontext = get_context_instance_by_id($category->contextid);
-        require_capability('moodle/question:useall', $catcontext);
-        $category->name = $category->name;
-        // Find existing random questions in this category that are not used by any quiz.
-        if ($existingquestions = $DB->get_records_sql(
-                "SELECT * FROM {question} q
-                WHERE qtype = '" . RANDOM . "'
-                    AND category = ?
-                    AND " . $DB->sql_compare_text('questiontext') . " = ?
-                    AND NOT EXISTS (SELECT * FROM {quiz_question_instances} WHERE question = q.id)
-                ORDER BY id", array($category->id, $recurse))) {
-            // Take as many of these as needed.
-            while (($existingquestion = array_shift($existingquestions)) and $randomcount > 0) {
-                quiz_add_quiz_question($existingquestion->id, $quiz);
-                $randomcount--;
-            }
-        }
-
-        // If more are needed, create them.
-        if ($randomcount > 0) {
-            $form->questiontext = $recurse; // we use the questiontext field to store the info
-                                            // on whether to include questions in subcategories
-            $form->questiontextformat = 0;
-            $form->image = '';
-            $form->defaultgrade = 1;
-            $form->hidden = 1;
-            for ($i = 0; $i < $randomcount; $i++) {
-                $form->category = "$category->id,$category->contextid";
-                $form->stamp = make_unique_id_code();  // Set the unique code (not to be changed)
-                $question = new stdClass;
-                $question->qtype = RANDOM;
-                $question = $QTYPES[RANDOM]->save_question($question, $form, $course);
-                if(!isset($question->id)) {
-                    print_error('cannotinsertrandomquestion', 'quiz');
-                }
-                quiz_add_quiz_question($question->id, $quiz);
-            }
+    }
+    // load category
+    if (! $category = $DB->get_record('question_categories', array('id' => $categoryid))) {
+        print_error('invalidcategoryid', 'error');
+    }
+    $catcontext = get_context_instance_by_id($category->contextid);
+    require_capability('moodle/question:useall', $catcontext);
+    $category->name = $category->name;
+    // Find existing random questions in this category that are
+    // not used by any quiz.
+    if ($existingquestions = $DB->get_records_sql(
+            "SELECT * FROM {question} q
+            WHERE qtype = '" . RANDOM . "'
+                AND category = ?
+                AND " . $DB->sql_compare_text('questiontext') . " = ?
+                AND NOT EXISTS (SELECT * FROM {quiz_question_instances} WHERE question = q.id)
+            ORDER BY id", array($category->id, $recurse))) {
+    // Take as many of these as needed.
+        while (($existingquestion = array_shift($existingquestions))
+                and $randomcount > 0) {
+            quiz_add_quiz_question($existingquestion->id, $quiz, $addonpage);
+            $randomcount--;
         }
-        $significantchangemade = true;
     }
 
-    if (optional_param('repaginate', false, PARAM_BOOL) and confirm_sesskey()) { /// Re-paginate the quiz
-        $questionsperpage = optional_param('questionsperpage', $quiz->questionsperpage, PARAM_INT);
-        if ($questionsperpage != $quiz->questionsperpage) {
-            $quiz->questionsperpage = $questionsperpage;
-            if (!$DB->set_field('quiz', 'questionsperpage', $quiz->questionsperpage, array('id' => $quiz->id))) {
-                print_error('cannotsavenumberofquestion', 'quiz');
+    // If more are needed, create them.
+    if ($randomcount > 0) {
+        $form->questiontext = $recurse; // we use the questiontext field
+                // to store the info on whether to include
+                // questions in subcategories
+        $form->questiontextformat = 0;
+        $form->image = '';
+        $form->defaultgrade = 1;
+        $form->hidden = 1;
+        for ($i = 0; $i < $randomcount; $i++) {
+            $form->category = "$category->id,$category->contextid";
+            $form->stamp = make_unique_id_code(); // Set the unique
+                    //code (not to be changed)
+            $question = new stdClass;
+            $question->qtype = RANDOM;
+            $question = $QTYPES[RANDOM]->save_question($question, $form,
+                    $course);
+            if(!isset($question->id)) {
+                print_error('cannotinsertrandomquestion', 'quiz');
             }
+            quiz_add_quiz_question($question->id, $quiz, $addonpage);
         }
-        $quiz->questions = quiz_repaginate($quiz->questions, $quiz->questionsperpage);
-        if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id))) {
-            print_error('cannotsavelayout', 'quiz');
-        }
-        $significantchangemade = true;
-    }
-    if (($delete = optional_param('delete', false, PARAM_INT)) !== false and confirm_sesskey()) { /// Remove a question from the quiz
-        quiz_delete_quiz_question($delete, $quiz);
-        $significantchangemade = true;
     }
 
-    if (optional_param('savechanges', false, PARAM_BOOL) and confirm_sesskey()) {
-    /// We need to save the new ordering (if given) and the new grades
-        $oldquestions = explode(",", $quiz->questions); // the questions in the old order
-        $questions = array(); // for questions in the new order
-        $rawgrades = (array) data_submitted();
-        unset($quiz->grades);
-        foreach ($rawgrades as $key => $value) {
+    $significantchangemade = true;
+}
+$addpagesafterquestions=array();
+if($addnewpagesafterselected=optional_param('addnewpagesafterselected',null)){
+    $rawgrades = (array) data_submitted();
+    foreach ($rawgrades as $key => $value) {
         /// Parse input for question -> grades
-            if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
-                $key = $matches[1];
-                $quiz->grades[$key] = $value;
-                quiz_update_question_instance($quiz->grades[$key], $key, $quiz->instance);
-
-            /// Parse input for ordering info
-            } elseif (preg_match('!^o([0-9]+)$!', $key, $matches)) {
-                $key = $matches[1];
-                // Make sure two questions don't overwrite each other. If we get a second
-                // question with the same position, shift the second one along to the next gap.
-                while (array_key_exists($value, $questions)) {
-                    $value++;
-                }
-                $questions[$value] = $oldquestions[$key];
-            }
+        if (preg_match('!^s([0-9]+)$!', $key, $matches)){
+            $addpagesafterquestions[]=$matches[1];
         }
+    }
+}
 
-        // If ordering info was given, reorder the questions
-        if ($questions) {
-            ksort($questions);
-            // Make sure that the quiz does not start with a page break.
-            while (reset($questions) == '0') {
-                array_shift($questions);
-            }
-            $quiz->questions = implode(",", $questions);
-            // Always have a page break at the end
-            $quiz->questions = $quiz->questions . ',0';
-            // Avoid duplicate page breaks
-            while (strpos($quiz->questions, ',0,0')) {
-                $quiz->questions = str_replace(',0,0', ',0', $quiz->questions);
-            }
-            if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->instance))) {
-                print_error('cannotsavequestion', 'quiz');
-            }
-        }
+if ( (($addpage = optional_param('addpage', false, PARAM_INT)) OR
+        !empty($addpagesafterquestions))
+            and confirm_sesskey() ) { /// Move the given question up a slot
 
-        // If rescaling is required save the new maximum
-        $maxgrade = optional_param('maxgrade', -1, PARAM_NUMBER);
-        if ($maxgrade >= 0) {
-            if (!quiz_set_grade($maxgrade, $quiz)) {
-                print_error('cannotsetgrade', 'quiz');
-            }
-        }
+    $questions = explode(",", $quiz->questions);
+
+    $pagebreakid='0';
+    if ($addpage > 0 and isset($questions[$addpage]) ) {
+        $questions=array_add_at($questions,$pagebreakid,$addpage);
         $significantchangemade = true;
     }
-
-/// Delete any teacher preview attempts if the quiz has been modified
-    if ($significantchangemade) {
-        $previewattempts = $DB->get_records_select('quiz_attempts',
-                'quiz = ? AND preview = 1', array($quiz->id));
-        if ($previewattempts) {
-            foreach ($previewattempts as $attempt) {
-                quiz_delete_attempt($attempt, $quiz);
-            }
+    foreach($addpagesafterquestions as $key=>$questionid){
+        $addpage=array_search($questionid, $questions)+1;
+        if ($addpage > 0 and isset($questions[$addpage]) ) {
+            $pagebreakid='0';
+            $questions=array_add_at($questions,$pagebreakid,$addpage);
+            $significantchangemade = true;
         }
     }
+    $quiz->questions = implode(",", $questions);
+    $quiz->questions=quiz_clean_layout($quiz->questions);
 
-    question_showbank_actions($thispageurl, $cm);
+    if (!$DB->set_field('quiz', 'questions', $quiz->questions,
+            array('id' => $quiz->instance))) {
+        print_error('cannotsavequestion', 'quiz');
+    }
 
-/// all commands have been dealt with, now print the page
+}
+if (optional_param('repaginate', false, PARAM_BOOL) and confirm_sesskey()) {
+    // Re-paginate the quiz
+    $questionsperpage = optional_param('questionsperpage',
+            $quiz->questionsperpage, PARAM_INT);
+    $quiz->questions = quiz_repaginate($quiz->questions,
+            $questionsperpage );
+    if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id))) {
+        print_error('cannotsavelayout', 'quiz');
+    }
+    $significantchangemade = true;
+}
 
-    // Print basic page layout.
-    if (isset($quiz->instance) and $DB->record_exists_select('quiz_attempts', "quiz = ? AND preview = '0'", array($quiz->instance))){
-        // one column layout with table of questions used in this quiz
-        $strupdatemodule = has_capability('moodle/course:manageactivities', $contexts->lowest())
-                    ? update_module_button($cm->id, $course->id, get_string('modulename', 'quiz'))
-                    : "";
-        $navigation = build_navigation($streditingquiz, $cm);
-        print_header_simple($streditingquiz, '', $navigation, "", "",
-                 true, $strupdatemodule);
 
-        $currenttab = 'edit';
-        $mode = 'editq';
+if ((($deleteemptypage = optional_param('deleteemptypage', false, PARAM_INT))
+        !==false) and confirm_sesskey()) {
+    $questions = explode(",", $quiz->questions);
+    if($deleteemptypage>0){
+        //it points to a value one too big due to the display logic
+        $deleteemptypage--;
+    }
+    if( ((int)$questions[$deleteemptypage]) == 0 ){
+        $questions = explode(",", $quiz->questions);
+        $endpart=array_slice($questions,$deleteemptypage+1,null,true);
+        $beginpart=array_slice($questions,0,$deleteemptypage,true);
+        $questions=array_merge($beginpart,$endpart);
+        $quiz->questions = implode(",", $questions);
+        $quiz->questions=quiz_clean_layout($quiz->questions);
+    }
+    if (!$DB->set_field('quiz', 'questions', $quiz->questions,
+            array('id' => $quiz->instance))) {
+        print_error('cannotsavequestion', 'quiz');
+    }
 
-        include('tabs.php');
 
-        print_box_start();
+}
+$deletequestions=array();
+if($quizdeleteselected=optional_param('quizdeleteselected',false)){
+    $rawgrades = (array) data_submitted();
+    foreach ($rawgrades as $key => $value) {
+        /// Parse input for question -> grades
+        if (preg_match('!^s([0-9]+)$!', $key, $matches)){
+            $deletequestions[]=$matches[1];
+        }
+    }
+}
 
-        echo "<div class=\"quizattemptcounts\">\n";
-        echo '<a href="report.php?mode=overview&amp;id=' . $cm->id . '">' .
-                quiz_num_attempt_summary($quiz, $cm) . '</a><br />' .
-                get_string('cannoteditafterattempts', 'quiz');
-        echo "</div>\n";
 
-        $sumgrades = quiz_print_question_list($quiz,  $thispageurl, false, $quiz_showbreaks, $quiz_reordertool);
-        if (!$DB->set_field('quiz', 'sumgrades', $sumgrades, array('id' => $quiz->instance))) {
-            print_error('cannotsetsumgrades', 'quiz');
+if ( (($delete = optional_param('delete', false, PARAM_INT)) !== false OR
+        !empty($deletequestions)) and confirm_sesskey() ) {
+
+    //was:     if ($delete > 0 ) {
+    if ($delete !==false) {
+        quiz_delete_quiz_question($delete, $quiz);
+        $significantchangemade = true;
+    }
+    foreach($deletequestions as $key=>$questionid){
+        $questions = explode(",", $quiz->questions);
+        $delete=array_search($questionid, $questions);
+        if ($delete !== false) {
+            quiz_delete_quiz_question($delete, $quiz);
+            $significantchangemade = true;
         }
+    }
+    $quiz->questions=quiz_clean_layout($quiz->questions);
 
-        print_box_end();
-        print_footer($course);
-        exit;
+    if (!$DB->set_field('quiz', 'questions', $quiz->questions,
+            array('id' => $quiz->instance))) {
+        print_error('cannotsavequestion', 'quiz');
     }
 
-    // two column layout with quiz info in left column
-    $strupdatemodule = has_capability('moodle/course:manageactivities', $contexts->lowest())
-        ? update_module_button($cm->id, $course->id, get_string('modulename', 'quiz'))
-        : "";
-    $navigation = build_navigation($streditingquiz, $cm);
-    print_header_simple($streditingquiz, '', $navigation, "", "", true, $strupdatemodule);
+}
+
+if (optional_param('savechanges', false, PARAM_BOOL) and confirm_sesskey()) {
+    $oldquestions = explode(",", $quiz->questions); // the questions in the old order
+    $questions = array(); // for questions in the new order
+    $rawgrades = (array) data_submitted();
+    $moveonpagequestions = array();
+    $moveselectedonpage=0;
+    //TODO: Tim: since we are not submitting all of the grades at once in quiz
+    // UI redesign, we cannot unset it since then we could not display it.
+    //Is there really a need to get rid of the old data here?
+    //unset($quiz->grades);
+    $moveselectedonpagetop=optional_param("moveselectedonpagetop",0,PARAM_INT);
+    $moveselectedonpagebottom=optional_param("moveselectedonpagebottom",0,
+            PARAM_INT);
+    if($moveselectedonpagetop){
+        $moveselectedonpage=$moveselectedonpagetop;
+    }else if($moveselectedonpagebottom){
+        $moveselectedonpage=$moveselectedonpagebottom;
+    }
 
-    $currenttab = 'edit';
-    $mode = 'editq';
+    foreach ($rawgrades as $key => $value) {
+        if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
+            /// Parse input for question -> grades
+            $key = $matches[1];
+            $quiz->grades[$key] = $value;
+            quiz_update_question_instance($quiz->grades[$key], $key,
+            $quiz->instance);
 
-    include('tabs.php');
+        } elseif (preg_match('!^o([0-9]+)$!', $key, $matches)) {
+            /// Parse input for ordering info
+            $key = $matches[1];
+            // Make sure two questions don't overwrite each other.
+            // If we get a second
+            // question with the same position, shift the second one
+            // along to the next gap.
+            while (array_key_exists($value, $questions)) {
+                $value++;
+            }
+            $questions[$value] = $oldquestions[$key];
+        } elseif (preg_match('!^s([0-9]+)$!', $key, $matches)){
+            // Parse input for selected questions
+            // (add new pages after questions in quiz)
+            $key = $matches[1];
+            if($moveselectedonpage){
+                $moveonpagequestions[]=$key;
+            }
+        }
+    }
+    // If ordering info was given, reorder the questions
+    if ($questions) {
+        ksort($questions);
+        $quiz->questions = implode(",", $questions);
+        $quiz->questions .=",0";
+        $quiz->questions=quiz_clean_layout($quiz->questions);
 
-    echo '<table border="0" style="width:100%" cellpadding="2" cellspacing="0">';
-    echo '<tr><td style="width:50%" valign="top">';
-    print_box_start('generalbox quizquestions');
-    print_heading(get_string('questionsinthisquiz', 'quiz'), '', 2);
+    }
+    //get a list of questions to move, later to be added in the appropriate
+    //place in the string
+    $questionstomove = implode(",", $moveonpagequestions);
+    if($moveonpagequestions){
+        $pagecount=quiz_number_of_pages($quiz->questions);
+        if($moveselectedonpage>quiz_number_of_pages($quiz->questions)){
+            $moveselectedonpage=$pagecount;
+        }
+        $selectedpageend=(strpos2($quiz->questions,",0",$moveselectedonpage));
+        if($selectedpageend!==FALSE){
+            foreach($moveonpagequestions as $page=>$question){
+                $quiz->questions=str_replace("$question,","",$quiz->questions);
+            }
+            if($moveselectedonpage>1){
+                $pagecount=quiz_number_of_pages($quiz->questions);
+                if($moveselectedonpage>quiz_number_of_pages($quiz->questions)){
+                    $moveselectedonpage=$pagecount;
+                }
+                $selectedpageend=(strpos2($quiz->questions,",0",
+                        $moveselectedonpage-1));
+                $start=substr($quiz->questions,0,$selectedpageend+1);
+                $end=substr($quiz->questions,$selectedpageend);
+                $quiz->questions=$start.$questionstomove.$end;
+            }else if ($moveselectedonpage==1){
+                $quiz->questions=$questionstomove.",".$quiz->questions;
+            }
+        }else{
+            //TODO: add alert message
+        }
 
-    $sumgrades = quiz_print_question_list($quiz, $thispageurl, true, $quiz_showbreaks, $quiz_reordertool);
-    if (!$DB->set_field('quiz', 'sumgrades', $sumgrades, array('id' => $quiz->instance))) {
-        print_error('cannotsetsumgrades', 'quiz');
+    }
+    if($moveonpagequestions or $questions){
+        if (!$DB->set_field('quiz', 'questions', $quiz->questions,
+                array('id' => $quiz->instance))) {
+            print_error('cannotsavequestion', 'quiz');
+        }
+    }
+    // If rescaling is required save the new maximum
+    $maxgrade = optional_param('maxgrade', -1, PARAM_NUMBER);
+    if ($maxgrade >= 0) {
+        if (!quiz_set_grade($maxgrade, $quiz)) {
+            print_error('cannotsetgrade', 'quiz');
+        }
     }
 
-    print_box_end();
 
-    echo '</td><td style="width:50%" valign="top">';
 
-    question_showbank('editq', $contexts, $thispageurl, $cm, $pagevars['qpage'], $pagevars['qperpage'], $pagevars['qsortorder'], $pagevars['qsortorderdecoded'],
-                    $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'], $pagevars['showquestiontext']);
+    $significantchangemade = true;
+}
+/// Delete any teacher preview attempts if the quiz has been modified
+if ($significantchangemade) {
+    $previewattempts = $DB->get_records_select('quiz_attempts',
+             'quiz = ? AND preview = 1', array($quiz->id));
+    if ($previewattempts) {
+        foreach ($previewattempts as $attempt) {
+            quiz_delete_attempt($attempt, $quiz);
+        }
+    }
+    redirect($qcobject->pageurl->out());
+}
 
-    echo '</td></tr>';
-    echo '</table>';
+question_showbank_actions($thispageurl, $cm);
 
-    print_footer($course);
+/// all commands have been dealt with, now print the page
+$questionbankmanagement='<a href="'.$CFG->wwwroot.
+        '/question/edit.php?courseid='.$course->id.'">'.
+        get_string("questionbankmanagement","quiz").'</a> ';
+
+if (isset($quiz->instance) and $DB->record_exists_select('quiz_attempts',
+        "quiz = ? AND preview = '0'", array($quiz->instance))){
+    $quiz_has_attempts=true;
+}
+
+
+$strupdatemodule = has_capability('moodle/course:manageactivities',
+        $contexts->lowest()) ?
+        update_module_button($cm->id, $course->id,
+        get_string('modulename', 'quiz')) :
+        "";
+$navigation = build_navigation($pagetitle, $cm);
+$localcss= '<link rel="stylesheet" type="text/css" href="edit_redesign.css" />
+        <link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.
+        '/lib/yui/container/assets/container.css" />';
+
+//Thanks to
+//http://vani.vox.com/library/post/yui-simple-showhide-div-using-module.html
+//as soon as javascript toggling and saving the state to the server as an ajax call
+//has been done, add $quiz_hide_javascript to $localjs
+/*$quiz_hide_javascript="";
+if(!$quiz_qbanktool){
+    $quiz_hide_javascript='var quiz_qbanktool=true;';
+}else{
+    $quiz_hide_javascript='var quiz_qbanktool=false;';
+}*/
+$quiz_randomquestion_dialog_listeners='this.dialog_listeners=[';
+if(($numberoflisteners=quiz_number_of_pages($quiz->questions))==0){
+    $numberoflisteners=1;
+}
+for($page_iter=1;$page_iter<=$numberoflisteners;$page_iter++){
+    if($page_iter!=1){
+        $quiz_randomquestion_dialog_listeners.= ',';
+    }
+    $quiz_randomquestion_dialog_listeners.= '"addrandomdialoglaunch_'.
+            $page_iter.'"';
+}
+$quiz_randomquestion_dialog_listeners.='];';
+$surl=$thispageurl->out(false,array('qbanktool'=>'0'));
+$surl_js="this.sUrl=\"$surl\";";
+$localjs= '<script type="text/javascript" charset="utf-8">
+    function phpdata(){
+        '.$quiz_randomquestion_dialog_listeners.'
+        '.$surl_js.'
+    }
+    var phpGenerated=new phpdata();
+    </script>
+    <script type="text/javascript"  src="'.$CFG->wwwroot.
+            '/mod/quiz/edit.js" charset="utf-8"></script>
+';
+//apply CSS for when javascript is enabled
+require_js('mod/quiz/editcss.js',true);
+print_header_simple($pagetitle, '', $navigation, "", $localcss,true,
+        $questionbankmanagement.$strupdatemodule);
+echo $localjs;
+$mode = 'editq';
+$currenttab="edit";
+if($quiz_reordertool){
+    $mode="reorder";
+}
+include('tabs.php');
+
+if($quiz_qbanktool){
+    $showbank_inlinecss='display: none;';
+    $bank_inlinecss='display: block;';
+    $hidebank_inlinecss='display: inline;';
+    $quizcontents_inlinecss="";
+
+}else{
+    $showbank_inlinecss='display: inline;';
+    $bank_inlinecss='display: none;';
+    $hidebank_inlinecss='display: none;';
+    $quizcontents_inlinecss='width:100%;';
+}
+print_side_block_start(get_string('questionbankcontents','quiz').
+        ' <a href="'.
+$thispageurl->out(false,array('qbanktool'=>'1')).
+       '"  style="'.$showbank_inlinecss.'" >['.get_string("show").
+       ']</a><!-- id="show" -->
+       <a href="'.$thispageurl->out(false,array('qbanktool'=>'0')).
+       '" style="'.$hidebank_inlinecss.'">['.get_string("hide").
+       ']</a><!-- id="hide" -->
+       ', array("class"=>"questionbankwindow"));
+echo '<div class="container" style="'.$bank_inlinecss.'">';
+echo '<div id="module" class="module">';
+echo '<div class="bd">';
+$cmoptions = new stdClass;
+$cmoptions->hasattempts=$quiz_has_attempts;
+quiz_question_showbank('editq', $contexts, $thispageurl, $cm,
+        $pagevars['qpage'],
+        $pagevars['qperpage'], $pagevars['qsortorder'],
+        $pagevars['qsortorderdecoded'],
+        $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'],
+        $pagevars['showquestiontext'],$cmoptions);
+echo '</div> <!-- end .bd -->';
+echo '</div> <!-- end .module -->';
+echo '</div> <!-- end .container -->';
+print_side_block_end();
+
+if (!$quizname = $DB->get_field($cm->modname, 'name', array('id'=>$cm->instance))) {
+    print_error('cannotmodulename');
+}
+
+echo '<div class="quizcontents" id="quizcontentsblock" style="'.$quizcontents_inlinecss.'">';
+$questionsperpagebool = ($quiz->questionsperpage < 1) ? 0 : 1;
+if($questionsperpagebool){
+    $repaginatingdisabledhtml='disabled="disabled"';
+    $repaginatingdisabled=true;
+}else{
+    $repaginatingdisabledhtml='';
+    $repaginatingdisabled=false;
+}
+if($quiz_reordertool){
+    echo '<div class="repaginatecommand"><button id="repaginatecommand" '.$repaginatingdisabledhtml.'>'.
+            get_string("repaginatecommand","quiz").'...</button>';
+    echo '</div>';
+}
+print_heading($pagetitle.": ".$quizname, 'left', 2);
+helpbutton("editconcepts", get_string("basicideasofquiz","quiz"), "quiz",
+        true,get_string("basicideasofquiz","quiz"));
+
+$notifystring="";
+if($quiz_has_attempts){
+    $string=get_string('cannoteditafterattempts', 'quiz');
+    $string.='<br /><a href="report.php?mode=overview&amp;id=' . $cm->id . '">' .
+        quiz_num_attempt_summary($quiz, $cm) . '</a><br />' ;
+    $notifystring.=notify($string,$style='notifyproblem', $align='center', $return=true);
+}
+if($questionsperpagebool && $quiz_reordertool){
+    $string=get_string('questionsperpageselected', 'quiz');
+    $updateurl=new moodle_url("$CFG->wwwroot/course/mod.php",
+            array("return"=>"true","update"=>$quiz->cmid, "sesskey"=>sesskey()));
+    $string.= '<a href="'.$updateurl->out().'">';
+    $string.=get_string('updatethis', '', get_string('modulename', 'quiz'));
+    $string.='</a>.';
+    $notifystring.=notify($string,$style='notifyproblem', $align='center', $return=true);
+}
+if($quiz->shufflequestions && $quiz_reordertool){
+    $string=get_string('shufflequestionsselected', 'quiz');
+    $updateurl=new moodle_url("$CFG->wwwroot/course/mod.php",
+            array("return"=>"true","update"=>$quiz->cmid, "sesskey"=>sesskey()));
+    $string.= '<a href="'.$updateurl->out().'">';
+    $string.=get_string('updatethis', '', get_string('modulename', 'quiz'));
+    $string.='</a>.';
+    $notifystring.=notify($string,$style='notifyproblem', $align='center', $return=true);
+}
+if(!empty($notifystring)){
+    //TODO: make the box closable so it is not in the way
+    print_box_start();
+    echo $notifystring;
+    print_box_end();
+}
+
+if($quiz_reordertool){
+    $perpage= array();
+    $perpage[0] = get_string('allinone', 'quiz');
+    for ($i=1; $i<=50; ++$i) {
+        $perpage[$i] = $i;
+    }
+    $gostring=get_string('go');
+    echo '<div id="repaginatedialog"><div class="hd">';
+    echo get_string("repaginatecommand","quiz");
+    echo '</div><div class="bd">';
+    echo '<form action="edit.php" method="post">';
+    echo '<fieldset class="invisiblefieldset">';
+    echo $thispageurl->hidden_params_out();
+    echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
+    //YUI does not submit the value of the submit button so
+            //we need to add the value:
+    echo '<input type="hidden" name="repaginate" value="'.$gostring.'" />';
+    print_string('repaginate', 'quiz',
+            choose_from_menu($perpage, 'questionsperpage',
+            $quiz->questionsperpage, '', '', '', true,$repaginatingdisabled));
+    echo '<div class="quizquestionlistcontrols">';
+    echo ' <input type="submit" name="repaginate" value="'. $gostring .'" '.$repaginatingdisabledhtml.' />';
+    echo '</div></fieldset></form></div></div>';
+}
+ob_start();
+$sumgrades = quiz_print_question_list($quiz, $thispageurl, true,
+        null,
+        $quiz_reordertool, $quiz_qbanktool, $quiz_has_attempts);
+
+if (!$DB->set_field('quiz', 'sumgrades', $sumgrades, array('id' => $quiz->instance))) {
+    print_error('cannotsetsumgrades', 'quiz');
+}
+
+$question_list=ob_get_contents();
+ob_end_clean();
+$tabindex=0;
+
+if(!$quiz_reordertool){
+    quiz_print_grading_form($quiz,$thispageurl,$tabindex);
+}
+quiz_print_status_bar($quiz,$sumgrades);
 ?>
+<div class="<?php echo $currenttab; ?>">
+<?php echo $question_list; ?>
+</div>
+<?php
+//close <div class="quizcontents">:
+echo '</div>';
+
+if(!$quiz_reordertool){
+    // display category adding UI
+    ?>
+<div id="randomquestiondialog">
+<div class="hd"><?php print_string("addrandomquestiontoquiz","quiz",$quizname); ?>
+<span id="pagenumber"><!-- TODO: insert pagenumber here via javascript -->
+</span>
+</div>
+<div class="bd"><?php
+$qcobject->display_randomquestion_user_interface();
+?></div>
+</div>
+    <?php
+}
+print_footer($course);
+?>
\ No newline at end of file
diff --git a/mod/quiz/editcss.js b/mod/quiz/editcss.js
new file mode 100644 (file)
index 0000000..92bc52f
--- /dev/null
@@ -0,0 +1,7 @@
+/** JavaScript for /mod/quiz/edit.php to be loaded in the header
+ *  Adds a CSS class to display edit.php for users with JavaScript.
+ */
+        YAHOO.util.Event.onDOMReady(
+            function(){
+                YAHOO.util.Dom.addClass('quizcontentsblock', 'usejs');
+           });
\ No newline at end of file
index c969ff93d8e0120c2f8a5c4d6ba8ebf1748c7ea4..cf3c713f22a2ce31f098c0145fe658ae8e54da4b 100644 (file)
@@ -34,14 +34,7 @@ function quiz_delete_quiz_question($id, &$quiz) {
 
     $question = $questions[$id];
     unset($questions[$id]);
-    // If we deleted the question at the top and it was followed by
-    // a page break then delete page break as well
-    if ($id == 0 && count($questions) > 1 && $questions[1] == 0) {
-        unset($questions[1]);
-    }
     $quiz->questions = implode(",", $questions);
-    // Avoid duplicate page breaks
-    $quiz->questions = str_replace(',0,0', ',0', $quiz->questions);
     // save new questionlist in database
     if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->instance))) {
         print_error('cannotsavequestion', 'quiz');
@@ -62,10 +55,9 @@ function quiz_delete_quiz_question($id, &$quiz) {
 * @param object $quiz  The extended quiz object as used by edit.php
 *                         This is updated by this function
 */
-function quiz_add_quiz_question($id, &$quiz) {
+function quiz_add_quiz_question($id, &$quiz, $page=0) {
     global $DB;
     $questions = explode(",", $quiz->questions);
-
     if (in_array($id, $questions)) {
         return false;
     }
@@ -76,14 +68,42 @@ function quiz_add_quiz_question($id, &$quiz) {
         $end = end($breaks);
         $last = prev($breaks);
         $last = $last ? $last : -1;
-        if (!$quiz->questionsperpage or (($end - $last -1) < $quiz->questionsperpage)) {
+        if (!$quiz->questionsperpage or
+                (($end - $last -1) < $quiz->questionsperpage)) {
             array_pop($questions);
         }
     }
-    // add question
-    $questions[] = $id;
-    // add ending page break
-    $questions[] = 0;
+    if(is_int($page) && $page >= 1){
+        $numofpages=quiz_number_of_pages($quiz->questions);
+        if ($numofpages<$page){
+            //the page specified does not exist in quiz
+            $page=0;
+        }else{
+            // add ending page break - the following logic requires doing
+            //this at this point
+            $questions[] = 0;
+            $currentpage=1;
+            $addnow=false;
+            foreach ($questions as $question){
+                if($question==0){
+                    $currentpage++;
+                    //The current page is the one after the one we want to add on,
+                    //so we add the question before adding the current page.
+                    if ($currentpage==$page+1){
+                        $questions_new[]=$id;
+                    }
+                }
+                $questions_new[]=$question;
+            }
+            $questions=$questions_new;
+        }
+    }
+    if ($page==0){
+        // add question
+        $questions[] = $id;
+        // add ending page break
+        $questions[] = 0;
+    }
 
     // Save new questionslist in database
     $quiz->questions = implode(",", $questions);
@@ -125,247 +145,1298 @@ function quiz_update_question_instance($grade, $questionid, $quizid) {
 }
 
 /**
-* Prints a list of quiz questions in a small layout form with knobs
+* Prints a list of quiz questions for the edit.php main view for edit
+* ($reordertool=false) and order and paging ($reordertool=true) tabs
 *
 * @return int sum of maximum grades
 * @param object $quiz This is not the standard quiz object used elsewhere but
 *     it contains the quiz layout in $quiz->questions and the grades in
 *     $quiz->grades
 * @param boolean $allowdelete Indicates whether the delete icons should be displayed
-* @param boolean $showbreaks  Indicates whether the page breaks should be displayed
-* @param boolean $showbreaks  Indicates whether the reorder tool should be displayed
+* @param boolean $reordertool  Indicates whether the reorder tool should be displayed
+* @param boolean $quiz_qbanktool  Indicates whether the question bank should be displayed
+* @param boolean $hasattempts  Indicates whether the quiz has attempts
 */
-function quiz_print_question_list($quiz, moodle_url $pageurl, $allowdelete=true, $showbreaks=true, $reordertool=false) {
+//TODO: Tim? remove showbreaks since it is no longer used
+function quiz_print_question_list($quiz, $pageurl, $allowdelete=true,
+        $showbreaks=true,$reordertool=false, $quiz_qbanktool=false,
+        $hasattempts=false) {
     global $USER, $CFG, $QTYPES, $DB;
 
     $strorder = get_string("order");
     $strquestionname = get_string("questionname", "quiz");
     $strgrade = get_string("grade");
     $strremove = get_string('remove', 'quiz');
+    $stredit = get_string("edit");
+    $strview = get_string("view");
     $straction = get_string("action");
+    $strmove = get_string("move");
     $strmoveup = get_string("moveup");
     $strmovedown = get_string("movedown");
-    $strsavegrades = get_string("savegrades", "quiz");
+    $strsave=get_string('save',"quiz");
+    $strreorderquestions=get_string("reorderquestions","quiz");
+
+    $strselectall = get_string("selectall", "quiz");
+    $strselectnone = get_string("selectnone", "quiz");
     $strtype = get_string("type", "quiz");
     $strpreview = get_string("preview", "quiz");
 
-    if (!$quiz->questions) {
+    /*if (!$quiz->questions) {
         echo "<p class=\"quizquestionlistcontrols\">";
         print_string("noquestions", "quiz");
         echo "</p>";
         return 0;
-    }
-
-    list($usql, $params) = $DB->get_in_or_equal(explode(',', $quiz->questions));
-    if (!$questions = $DB->get_records_sql("SELECT q.*,c.contextid
+    }*/
+    if($quiz->questions){
+        list($usql, $params) = $DB->get_in_or_equal(explode(',', $quiz->questions));
+        $questions = $DB->get_records_sql("SELECT q.*,c.contextid
                               FROM {question} q,
                                    {question_categories} c
                              WHERE q.id $usql
-                               AND q.category = c.id", $params)) {
-        echo "<p class=\"quizquestionlistcontrols\">";
-        print_string("noquestions", "quiz");
-        echo "</p>";
-        return 0;
+                               AND q.category = c.id", $params);
+    }
+    // if user only has empty pages we have to keep that: out with OR (!$questions)
+    if (!$quiz->questions) {
+        $pagecount=1;
+        echo  '<div class="quizpage"><span class="pagetitle">Page&nbsp;'.
+                $pagecount.'</span><div class="pagecontent"><div class="pagestatus">';
+        print_string("noquestionsinquiz", "quiz");
+        echo '</div>';
+        if(!$reordertool){
+            quiz_print_pagecontrols($quiz, $pageurl, $pagecount,$hasattempts);
+        }
+        echo "</div></div></div>";
+        //this is how it worked before summer 2008
+        //OR !$questions
+        if(!isset($questions)){
+            return 0;
+        }
     }
 
-    $count = 0;
-    $qno = 1;
-    $sumgrade = 0;
-    $order = explode(',', $quiz->questions);
+
+    $layout=quiz_clean_layout($quiz->questions);
+    $order = explode(',', $layout);
     $lastindex = count($order)-1;
-    // If the list does not end with a pagebreak then add it on.
-    if ($order[$lastindex] != 0) {
-        $order[] = 0;
-        $lastindex++;
+
+    if ($hasattempts){
+        $disabled='disabled="disabled"';
+        $movedisabled='';
+        $pagingdisabled='';
+    }else{
+        $disabled='';
+        $movedisabled='';
+        $pagingdisabled='';
+    }
+    if($quiz->shufflequestions){
+        $movedisabled='disabled="disabled"';
+    }
+    if($quiz->questionsperpage){
+        $pagingdisabled='disabled="disabled"';
     }
-    echo "<form method=\"post\" action=\"edit.php\">";
-    echo '<fieldset class="invisiblefieldset" style="display: block;">';
-    echo "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />";
-    echo $pageurl->hidden_params_out();
 
-    echo "<table style=\"width:100%;\">\n";
-    echo "<tr><th colspan=\"3\" style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$strorder</th>";
-    echo "<th class=\"header\" scope=\"col\">#</th>";
-    echo "<th align=\"left\" style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$strquestionname</th>";
-    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$strtype</th>";
-    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$strgrade</th>";
-    echo "<th align=\"center\" style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$straction</th>";
-    echo "</tr>\n";
 
-       // for RTL languages: switch right and left arrows /****/
-    if (right_to_left()) {
-        $movearrow = 'moveleft.gif';
-    } else {
-        $movearrow = 'removeright.gif';
+    $reordercontrolssetdefaultsubmit='<div style="display:none;">'.
+        '<input type="submit" name="savechanges" value="'.
+        $strreorderquestions.'" '.$movedisabled.' /></div>';
+    $reordercontrols1='<div class="addnewpagesafterselected">'.
+        '<input type="submit" name="addnewpagesafterselected" value="'.
+        get_string("addnewpagesafterselected","quiz").'"  '.
+        $pagingdisabled.' /></div>';
+    $reordercontrols1.='<div class="quizdeleteselected">'.
+        '<input type="submit" name="quizdeleteselected" '.
+        'onclick=\'return confirm("'.
+        get_string("areyousuredeleteselected","quiz").'")\'; value="'.
+        get_string("deleteselected").'"  '.$disabled.' /></div>';
+
+    $reordercontrols2top='<div class="moveselectedonpage">'.
+        get_string("moveselectedonpage","quiz") .
+        ': <input name="moveselectedonpagetop" type="text" size="2" '.
+        $movedisabled.'  />'.
+        '<input type="submit" name="savechanges" value="'.
+        $strmove.'"  '.$movedisabled.' />'.'
+        <br /><input type="submit" name="savechanges" value="'.
+        $strreorderquestions.'"  '.$movedisabled.' /></div>';
+    $reordercontrols2bottom='<div class="moveselectedonpage">'.
+        '<input type="submit" name="savechanges" value="'.
+        $strreorderquestions.'"  '.$movedisabled.' /><br />'.
+        get_string("moveselectedonpage","quiz") .
+        ': <input name="moveselectedonpagebottom" type="text" size="2"  '.
+        $movedisabled.' />'.'<input type="submit" name="savechanges" value="'.
+        $strmove.'"  '.$movedisabled.' /> '.'</div>';
+
+    $reordercontrols3='<a href="javascript:select_all_in(\'FORM\',null,'.
+            '\'quizquestions\');">'.
+            $strselectall.'</a> /';
+    $reordercontrols3.=    ' <a href="javascript:deselect_all_in(\'FORM\','.
+            'null,\'quizquestions\');">'.
+            $strselectnone.'</a>';
+
+    $reordercontrolstop='<div class="reordercontrols">'.
+            $reordercontrolssetdefaultsubmit.
+            $reordercontrols1.$reordercontrols2top.$reordercontrols3."</div>";
+    $reordercontrolsbottom='<div class="reordercontrols">'.
+            $reordercontrolssetdefaultsubmit.
+            $reordercontrols2bottom.$reordercontrols1.$reordercontrols3."</div>";
+
+    if($reordertool){
+
+        echo '<form method="post" action="edit.php" id="quizquestions"><div>';
+
+        echo $pageurl->hidden_params_out();
+        echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
+
+        echo $reordercontrolstop;
     }
 
+    /* // Tim: is this a separate case from the above "no questions in quiz"? Should it still be done?:
+    if(!$quiz->questions){
+        $pagecount=1;
+        echo  '<div class="quizpage"><span class="pagetitle">Page&nbsp;'.
+                $pagecount.'</span><div class="pagecontent">';
+        print_string("noquestions", "quiz");
+        quiz_print_pagecontrols($quiz, $pageurl, $pagecount);
+        echo "</div></div>";
+
+    }*/
+
+    //the current question ordinal (no descriptions)
+    $qno = 1;
+    //the current question (includes questions and descriptions)
+    $questioncount=0;
+    //the ordinal of current element in the layout
+    //(includes page breaks, questions and descriptions)
+    $count = 0;
+    //the current page number in iteration
+    $pagecount = 0;
+
+    $sumgrade = 0;
+
+    $pageopen=false;
+
+
+    $returnurl = $pageurl->out();
+    $questiontotalcount=count($order);
+
     foreach ($order as $i => $qnum) {
 
+        $reordercheckbox='';
+        $reordercheckboxlabel='';
+        $reordercheckboxlabelclose='';
+
         if ($qnum and empty($questions[$qnum])) {
             continue;
         }
-
         // If the questiontype is missing change the question type
         if ($qnum and !array_key_exists($questions[$qnum]->qtype, $QTYPES)) {
             $questions[$qnum]->qtype = 'missingtype';
         }
+        $deletex="delete.gif";
+        if($qnum!=0 OR ($qnum==0&&!$pageopen)){
+            //this is either a question or a page break after another
+            //        (no page is currently open)
+            if(!$pageopen){
+                //if no page is open, start display of a page
+                $pagecount++;
+                echo  '<div class="quizpage"><span class="pagetitle">'.
+                        get_string('page').'&nbsp;'.$pagecount.
+                        '</span><div class="pagecontent">';
+                $pageopen=true;
+            }
+            if($qnum==0 && $i<$questiontotalcount){
+                //this is a consequent 0 (signaling empty page), tell
+                //        the user the page is empty
+                echo '<div class="pagestatus">';
+                print_string("noquestionsonpage", "quiz");
+                echo '</div>';
+                if ($allowdelete && !$hasattempts) { // remove from quiz, not question delete.
+                    echo '<div class="quizpagedelete">';
+                    echo "<a title=\"$strremove\" href=\"".
+                            $pageurl->out_action(array('deleteemptypage'=>$i)).
+                            "\"><img src=\"$CFG->pixpath/t/delete.gif\" ".
+                            "class=\"iconsmall\"".
+                            " alt=\"$strremove\" /></a>";
+                    echo '</div>';
+                }
+            }
+
+            if($qnum!=0){
+                $question = $questions[$qnum];
+                $questionparams = array('returnurl' => $returnurl,
+                        'cmid'=>$quiz->cmid, 'id' => $question->id);
+                $questionurl = new moodle_url("$CFG->wwwroot/question/question.php",
+                        $questionparams);
+                $questioncount++;
+                //this is an actual question
 
-        // Show the re-ordering field if the tool is turned on.
-        // But don't show it in front of pagebreaks if they are hidden.
-        if ($reordertool) {
-            if ($qnum or $showbreaks) {
-                echo '<tr><td><input type="text" name="o'.$i.'" size="2" value="'.(10*$count+10).'" /></td>';
+
+                /* Display question start */
+?>
+<div class="question">
+    <div class="questioncontainer">
+        <div class="qnum">
+        <?php
+            $reordercheckbox="";
+            $reordercheckboxlabel='';
+            $reordercheckboxlabelclose='';
+            if($reordertool){
+                $reordercheckbox='<input type="checkbox" name="s'.$question->id.
+                    '" id="s'.$question->id.'" />';
+                $reordercheckboxlabel='<label for="s'.$question->id.'">';
+                $reordercheckboxlabelclose='</label>';
+            }
+            if (!$quiz->shufflequestions) {
+                // Print and increment question number
+                $questioncountstring="";
+                if ($questioncount>999 OR ($reordertool && $questioncount>99)){
+                    $questioncountstring=
+                            "$reordercheckboxlabel<small>$questioncount</small>".
+                            $reordercheckboxlabelclose.$reordercheckbox;
+                }else{
+                    $questioncountstring=$reordercheckboxlabel.$questioncount.
+                            $reordercheckboxlabelclose.$reordercheckbox;
+                }
+                echo $questioncountstring;
+                $qno += $question->length;
             } else {
-                echo '<tr><td><input type="hidden" name="o'.$i.'" size="2" value="'.(10*$count+10).'" /></td>';
+                echo "$reordercheckboxlabel * $reordercheckboxlabelclose".
+                        " $reordercheckbox";
             }
-        } else {
-            echo '<tr><td></td>';
-        }
-        if ($qnum == 0) { // This is a page break
-            if ($showbreaks) {
-                echo '<td colspan ="3">&nbsp;</td>';
-                echo '<td><table style="width:100%; line-height:11px; font-size:9px; margin: -5px -5px;"><tr>';
-                echo '<td><hr /></td>';
-                echo '<td style="width:50px;">Page break</td>';
-                echo '<td><hr /></td>';
-                echo '<td style="width:45px;">';
-                if ($count > 1) {
-                    echo "<a title=\"$strmoveup\" href=\"".$pageurl->out_action(array('up'=>$count))."\"><img
-                         src=\"$CFG->pixpath/t/up.gif\" class=\"iconsmall\" alt=\"$strmoveup\" /></a>";
+
+            ?>
+        </div>
+        <div class="content">
+            <div class="questioncontrols">
+                <?php
+            if ($count != 0) {
+                if(!$hasattempts){
+                    $upbuttonclass="";
+                    if (!($count < $lastindex-1)) {
+                        $upbuttonclass="upwithoutdown";
+                    }
+                    echo "<a title=\"$strmoveup\" href=\"".
+                            $pageurl->out_action(array('up'=>$count))."\"><img
+                             src=\"$CFG->pixpath/t/up.gif\" class=\"iconsmall
+                            $upbuttonclass\" alt=\"$strmoveup\" /></a>";
                 }
-                echo '&nbsp;';
-                if ($count < $lastindex) {
-                    echo "<a title=\"$strmovedown\" href=\"".$pageurl->out_action(array('down'=>$count))."\"><img
-                         src=\"$CFG->pixpath/t/down.gif\" class=\"iconsmall\" alt=\"$strmovedown\" /></a>";
 
-                    echo "<a title=\"$strremove\" href=\"".$pageurl->out_action(array('delete'=>$count))."\">
-                          <img src=\"$CFG->pixpath/t/delete.gif\" class=\"iconsmall\" alt=\"$strremove\" /></a>";
+            }
+            if ($count < $lastindex-1) {
+                if(!$hasattempts){
+                    echo "<a title=\"$strmovedown\" href=\"".
+                            $pageurl->out_action(array('down'=>$count))."\"><img
+                            src=\"$CFG->pixpath/t/down.gif\" class=\"iconsmall\"".
+                            " alt=\"$strmovedown\" /></a>";
                 }
-                echo '</td></tr></table></td>';
-                echo '<td colspan="2">&nbsp;</td>';
+            }else{
             }
-            $count++;
-            // missing </tr> here, if loop is broken, need to close the </tr>
-            echo "</tr>";
-            continue;
-        }
-        $question = $questions[$qnum];
+            if ($allowdelete && question_has_capability_on($question, 'use',
+                    $question->category)) { // remove from quiz, not question delete.
+                if(!$hasattempts){
+                    echo "<a title=\"$strremove\" href=\"".
+                            $pageurl->out_action(array('delete'=>$count))."\">
+                            <img src=\"$CFG->pixpath/t/delete.gif\" ".
+                            "class=\"iconsmall\" alt=\"$strremove\" /></a>";
+                }
+            }
+                ?>
+            </div><?php
+            if ($question->qtype != 'description' && !$reordertool) {
+                ?>
+<div class="points">
+<form method="post" action="edit.php"><div>
+    <label for="<?php echo "inputq$qnum" ?>"><?php echo $strgrade; ?></label>:<br />
+    <fieldset class="invisiblefieldset" style="display: block;">
+    <input type="hidden" name="sesskey" value="<?php echo $USER->sesskey ?>" />
+    <?php echo $pageurl->hidden_params_out(); ?>
+    <input type="hidden" name="savechanges" value="save" />
+        <?php
+            echo '<input type="text" name="q'.$qnum.'" size="' . ($quiz->decimalpoints + 2) . '"
+                    value="'.(0 + $quiz->grades[$qnum]).
+                    '" tabindex="'.($lastindex+$qno).'" '.$disabled.' />';
+            ?>
+        <input type="submit" class="pointssubmitbutton" value="<?php echo $strsave; ?>" <?php echo $disabled; ?> />
+    </fieldset>
 
-        echo "<td>";
-        if ($count != 0) {
-            echo "<a title=\"$strmoveup\" href=\"".$pageurl->out_action(array('up'=>$count))."\"><img
-                 src=\"$CFG->pixpath/t/up.gif\" class=\"iconsmall\" alt=\"$strmoveup\" /></a>";
+</div>
+</form>
+
+            </div>
+<?php
+            }else if ($reordertool) {
+                if ($qnum) {
+                ?>
+<div class="qorder">
+        <?php
+                    echo '<input type="text" name="o'.$i.'" size="2" value="'.
+                            (10*$count+10).
+                             '" tabindex="'.($lastindex+$qno).
+                             '" '.$movedisabled.' />';
+        ?>
+<!--         <input type="submit" class="pointssubmitbutton" value="<?php
+        echo $strsave; ?>" /> -->
+</div>
+<?php
+                }
+            }
+?>
+            <div class="questioncontentcontainer">
+ <?php
+            //strcmp returns 0 if equal
+            if (strcmp($question->qtype,'random')===0){ // it is a random question
+                if(!$reordertool){
+                    quiz_print_randomquestion($question, $pageurl, $quiz,
+                            $quiz_qbanktool);
+                }else{
+                    quiz_print_randomquestion_reordertool($question,
+                            $pageurl, $quiz);
+                }
+            }else{ // it is a single question
+                if(!$reordertool){
+                    quiz_print_singlequestion($question, $questionurl, $quiz);
+                }else{
+                    quiz_print_singlequestion_reordertool($question,
+                            $questionurl, $quiz);
+                }
+            }
+                ?>
+            </div>
+        </div>
+    </div>
+</div>
+
+    <?php
+            /* Display question end */
+                $count++;
+                $sumgrade += $quiz->grades[$qnum];
+
+            }
         }
-        echo "</td>";
-        echo "<td>";
-        if ($count < $lastindex-1) {
-            echo "<a title=\"$strmovedown\" href=\"".$pageurl->out_action(array('down'=>$count))."\"><img
-                 src=\"$CFG->pixpath/t/down.gif\" class=\"iconsmall\" alt=\"$strmovedown\" /></a>";
+        //a page break: end the existing page.
+        if($qnum == 0){
+            if($pageopen){
+                if(!$reordertool){
+                    quiz_print_pagecontrols($quiz, $pageurl, $pagecount,
+                            $hasattempts);
+                }else if ($i<$questiontotalcount-1){
+                    //do not include the last page break for reordering
+                    //to avoid creating a new extra page in the end
+                    echo '<input type="hidden" name="o'.$i.'" size="2" value="'.
+                            (10*$count+10).'" />';
+                }
+                echo "</div></div>";
+
+                if(!$reordertool){
+                    echo "<div class=\"addpage\">";
+                    print_single_button($pageurl->out(true),
+                            array("cmid"=>$quiz->cmid,
+                                    "courseid"=>$quiz->course,
+                                    "addpage"=>$count,
+                                    "sesskey"=>sesskey()),
+                            get_string("addpagehere","quiz"),
+                             'get',
+                             '_self',
+                            false,
+                            '',
+                            $hasattempts);
+                    echo "</div>";
+                }
+                $pagecount;
+                $pageopen=false;
+                $count++;
+            }
         }
-        echo "</td>";
 
-        if (!$quiz->shufflequestions) {
-            // Print and increment question number
-            echo '<td>'.($question->length ? $qno : '&nbsp;').'</td>';
-            $qno += $question->length;
+    }
+    if($reordertool){
+        echo $reordercontrolsbottom;
+        echo '</div></form>';
+    }
+
+
+
+    return $sumgrade;
+}
+
+/**
+ * Print all the controls for adding questions directly into the
+ * specific page in the edit tab of edit.php
+ *
+ * @param unknown_type $quiz
+ * @param unknown_type $pageurl
+ * @param unknown_type $page
+ * @param unknown_type $hasattempts
+ */
+function quiz_print_pagecontrols($quiz,$pageurl,$page, $hasattempts){
+    global $CFG;
+    $strcreatenewquestion=get_string("createnewquestion",'quiz');
+    $strselectquestiontype=get_string("selectquestiontype",'quiz');
+    echo '<div class="pagecontrols">';
+    // get the current context
+    $thiscontext = get_context_instance(CONTEXT_COURSE, $quiz->course);
+    $contexts = new question_edit_contexts($thiscontext);
+    // get default category and turn its infor into a string that works in an url
+    $defaultcategory = question_make_default_categories($contexts->all());
+    $categorystring = "$defaultcategory->id,$defaultcategory->contextid";
+    //create the url the question page will return to
+    $returnurl_addtoquiz=new moodle_url($pageurl->out(true),
+            array("addonpage"=>$page));
+    //create the url of the new question page to forward to. return url is given
+    //as a parameter and automatically urlencoded.
+    $newquestionparams = array('returnurl' => $returnurl_addtoquiz->out(false),
+            'cmid'=>$quiz->cmid, "appendqnumstring"=>"addquestion", "category"=>$categorystring);
+    $newquestionurl_object = new moodle_url("$CFG->wwwroot/question/question.php",
+            $newquestionparams);
+    $newquestionurl=$newquestionurl_object->out(false);
+    echo get_string("addquestion","quiz").": ";
+    if ($hasattempts) {
+        $disabled = 'disabled="disabled"';
+    } else {
+        $disabled = '';
+    }
+    popup_form ($newquestionurl.'&amp;qtype=',
+                question_type_menu(),
+                "addquestion_$page",
+                "",
+                $strselectquestiontype,
+                "",
+                "",
+                false,
+                "self",
+                "",
+                null,
+                $strcreatenewquestion, $hasattempts);
+    helpbutton("questiontypes", $strcreatenewquestion, "quiz");
+    echo '<div class="adddescription">';
+    print_single_button($CFG->wwwroot."/question/question.php",
+            array("cmid"=>$quiz->cmid,
+                  "courseid"=>$quiz->course,
+                  "returnurl"=>$returnurl_addtoquiz->out(false),
+                  "appendqnumstring"=>"addquestion",
+                  "category"=>$categorystring,
+                  "qtype"=>"description"),
+            get_string("adddescriptionlabel","quiz"),'get', '_self', false, '',
+                    $hasattempts);
+    echo "\n</div>";
+    ?>
+    <div class="addrandomquestion">
+    <div class="singlebutton">
+        <form class="randomquestionform" action="<?php echo $CFG->wwwroot; ?>/mod/quiz/addrandom.php" method="get">
+            <div>
+                <input type="hidden" class="addonpage_formelement" name="addonpage_form" value="<?php echo $page; ?>" />
+                <input type="hidden" name="cmid" value="<?php echo $quiz->cmid; ?>" />
+                <input type="hidden" name="courseid" value="<?php echo $quiz->course; ?>" />
+                <input type="hidden" name="returnurl" value="<?php echo urlencode($pageurl->out(true)); ?>" />
+                 <input type="submit" id="addrandomdialoglaunch_<?php echo $page; ?>" value="<?php echo get_string("addrandomquestion","quiz"); ?>" <?php echo " $disabled"; ?> />
+                 <!--<a href="#"  id="addrandomdialoglaunch_<?php echo $page; ?>">laa</a>-->
+                 <?php helpbutton('random', get_string('random', 'quiz'), 'quiz', true, false, '');
+                  ?>
+            </div>
+        </form>
+    </div>
+    </div>
+    <?php
+    echo "\n</div>";
+}
+/**
+ * Process submitted form data to create a new category for a random question
+ * This is used by edit.php and addrandom.php
+ * cmid
+ *
+ * @param object $qcobject
+ * @param boolean $redirect if true, redirect to edit.php with GET
+ * parameters to add the question
+ * @param integer $cmid id of the quiz' course module; required if $redirect=true
+ * @return mixed category_id if $redirect==false and operation successfull, returns new category's id. if operation failed, returns false.
+ */
+function quiz_process_randomquestion_formdata(&$qcobject, $redirect=false, $cmid=0){
+    global $CFG,$DB;
+    $newrandomcategory=0;
+    $addonpage=0;
+    if ($redirect && !$cmid){
+        return false;
+    }
+    if ($qcobject->catform_rand->is_cancelled()){
+        return false;
+    }elseif ($catformdata = $qcobject->catform_rand->get_data()) {
+        $addonpage=$catformdata->addonpage;
+        if (!$catformdata->id) {//new category
+            $newrandomcategory=$qcobject->add_category($catformdata->parent,
+                    $catformdata->name, $catformdata->info,true);
+            if(!is_null($newrandomcategory)){
+                if (! $newcategory = $DB->get_record('question_categories',
+                        array('id'=>$newrandomcategory))) {
+                    print_error('invalidcategoryid');
+                }
+            }else{
+                print_error("cannotcreatecategory");
+                return false;
+            }
         } else {
-            echo '<td>&nbsp;</td>';
+            print_error("cannotcreatecategory");
+            return false;
         }
+    }
+    if ($redirect && $newrandomcategory){
+        redirect($CFG->wwwroot."/mod/quiz/edit.php?cmid=$cmid&addonpage=$addonpage&addrandom=1&categoryid=$newrandomcategory&randomcount=1&sesskey=".sesskey());
+    }else{
+        return($newrandomcategory);
 
-        echo '<td>' . format_string($question->name) . '</td>';
-        echo "<td align=\"center\">";
-        print_question_icon($question);
-        echo "</td>";
-        echo '<td align="left">';
-        if ($question->qtype == 'description') {
-            echo "<input type=\"hidden\" name=\"q$qnum\" value=\"0\" /> \n";
-        } else {
-            echo '<input type="text" name="q'.$qnum.'" size="' . ($quiz->decimalpoints + 2) . '" value="'.(0 + $quiz->grades[$qnum]).
-             '" tabindex="'.($lastindex+$qno).'" />';
+    }
+}
+
+
+/**
+ * Print a simple question list of the questions in a question bank category.
+ * Used for random question display in the edit tab of edit.php
+ */
+function quiz_simple_question_list($pageurl, $categorylist, $numbertoshow=3,
+        $showhidden=false, $sortorderdecoded='qtype, name ASC',
+        $showquestiontext = true){
+    global $DB;
+
+    // hide-feature
+    $showhidden = $showhidden ? '' : " AND hidden = '0'";
+    $categorylist_array =  explode(',', $categorylist);
+    list($usql, $params) = $DB->get_in_or_equal($categorylist_array);
+
+    if (!$questions = $DB->get_records_select('question',
+            "category $usql AND parent = '0' $showhidden",
+            $params, $sortorderdecoded, '*', 0, $numbertoshow)) {
+        // There are no questions on the requested page.
+        $page = 0;
+        if (!$questions = $DB->get_records_select('question',
+                "category $usql AND parent = '0' $showhidden",
+                $params, $sortorderdecoded, '*', 0, $numbertoshow)) {
+            // There are no questions at all
+            //TODO: if moodle used PHP exceptions, we would raise one here so that
+            //the main UI would know to display quis status "unfinished".
+            return;
         }
-        echo '</td><td align="center">';
-        echo quiz_question_action_icons($quiz, $quiz->cmid, $question, $pageurl->out());
-        if ($allowdelete && question_has_capability_on($question, 'use', $question->category)) { // remove from quiz, not question delete.
-            echo "<a title=\"$strremove\" href=\"".$pageurl->out_action(array('delete'=>$count))."\">
-                    <img src=\"$CFG->pixpath/t/$movearrow\" class=\"iconsmall\" alt=\"$strremove\" /></a>";
+    }
+    foreach ($questions as $question) {
+        echo "<li>";
+        quiz_question_tostring($question,true, $showquestiontext, false);
+        echo "</li>";
+    }
+}
+/**
+ * Print a given single question in quiz for the edit tab of edit.php.
+ * Meant to be used from quiz_print_question_list()
+ */
+function quiz_print_singlequestion(&$question, &$questionurl, &$quiz){
+    $stredit = get_string("edit");
+    $strview = get_string("view");
+
+    global $COURSE,$QTYPES,$CFG;
+    ?>
+    <div class="singlequestion">
+            <?php
+            $formatoptions = new stdClass;
+            $formatoptions->noclean = false;
+            $formatoptions->para = false;
+            $formatoptions->newlines = false;
+            $questiontext=strip_tags(format_text($question->questiontext,
+                    FORMAT_MOODLE,$formatoptions, $COURSE->id));
+            if (question_has_capability_on($question, 'edit', $question->category)
+                    || question_has_capability_on($question, 'move',
+                    $question->category)) {
+               echo "<a title=\"$stredit\" href=\"".$questionurl->out()."\">".
+                        quiz_question_tostring($question,false).
+                        '<span class="editicon">'.
+                        "<img src=\"$CFG->pixpath/t/edit.gif\" alt=\"".
+                        get_string("edit")."\" /></span>".
+                        "</a>";
+            }
+            elseif (question_has_capability_on($question, 'view',
+                    $question->category)){
+               echo "<a title=\"$strview\" href=\"".
+                           $questionurl->out(false, array('id'=>$question->id))."\">".
+                        quiz_question_tostring($question,false).
+                        '<span class="editicon">'.
+                        "<img src=\"$CFG->pixpath/i/info.gif\" ".
+                        "alt=\"$strview\" /></span>".
+                        "</a>";
+            }else{
+                //TODO: this should be a call to quiz_question_tostring, right?
+                echo $questiontext;
+            }
+            echo '<span class="questiontype">';
+            $namestr = $QTYPES[$question->qtype]->menu_name();
+            print_question_icon($question);
+            echo " $namestr</span>";
+            echo '<span class="questionpreview">'.
+                    quiz_question_preview_button($quiz, $question).'</span>';
+            ?>
+    </div><?php
+}
+/**
+ * Print a given random question in quiz for the edit tab of edit.php.
+ * Meant to be used from quiz_print_question_list()
+ */
+function quiz_print_randomquestion(&$question, &$pageurl, &$quiz,$quiz_qbanktool){
+    global $DB;
+    echo '<div class="quiz_randomquestion">';
+
+    //TODO: Tim? I left this out from the below get_record call:, , 'contextid' => $contextid
+    if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) {
+        notify('Random question category not found!');
+        return;
+    }
+
+    echo '<div class="randomquestionfromcategory">';
+    print_question_icon($question);
+    print_string('random','quiz');
+    echo " ".get_string("fromcategory",'quiz').":</div>";
+
+    echo '<div class="randomquestioncategory">';
+    echo '<a href="'.
+         $pageurl->out(false,array("qbanktool"=>1,
+         "cat"=>$category->id.','.$category->contextid)).
+         '">'.$category->name.'</a>';
+    //TODO: URGENT fix question preview for random questions
+    /*echo '<span class="questionpreview">'.
+        quiz_question_preview_button($quiz, $question).
+        '</span>';
+    */
+
+    echo "</div>";
+
+    $questioncount=$DB->count_records_select('question',
+            "category IN ($category->id) AND parent = '0' ");
+
+    echo '<div class="randomquestionqlist">';
+    $randomquestionlistsize=3;
+    if(!$questioncount){
+        echo '<span class="error">';
+        print_string("noquestionsnotinuse", "quiz");
+        echo '<br />';
+        if(!$quiz_qbanktool){
+            echo '<a href="'.
+                $pageurl->out(false,array("qbanktool"=>1,
+                "cat"=>$category->id.','.$category->contextid)).
+                 '">';
+        }
+        echo get_string("addnewquestionsqbank","quiz",
+                "<strong>$category->name</strong>");
+        if(!$quiz_qbanktool){
+            echo '</a>';
         }
 
-        echo "</td></tr>";
-        $count++;
-        $sumgrade += $quiz->grades[$qnum];
+        echo '</span>';
+    }else{
+        echo "<ul>";
+        quiz_simple_question_list($pageurl, $question->category,
+                $randomquestionlistsize);
+        echo '<li class="totalquestionsinrandomqcategory">';
+        if ($questioncount>$randomquestionlistsize){
+            echo "... ";
+        }
+        print_string("totalquestionsinrandomqcategory","quiz",$questioncount);
+        echo "</li>";
+        echo "</ul>";
     }
 
-    echo "<tr><td colspan=\"6\" align=\"right\">\n";
-    print_string('total');
-    echo ": </td>";
-    echo "<td align=\"left\">\n";
-    echo "<strong>$sumgrade</strong>";
-    echo "</td><td>&nbsp;\n</td></tr>\n";
+    echo "</div>";
 
-    echo "<tr><td colspan=\"6\" align=\"right\">\n";
-    print_string('maximumgrade');
-    echo ": </td>";
-    echo "<td align=\"left\">\n";
-    echo '<input type="text" name="maxgrade" size="' . ($quiz->decimalpoints + 2) . '" tabindex="'.($qno+1)
-     .'" value="'.quiz_format_grade($quiz, $quiz->grade).'" />';
-    echo '</td><td align="left">';
-    helpbutton("maxgrade", get_string("maximumgrade"), "quiz");
-    echo "</td></tr></table>\n";
+    echo '<div class="randomquestioncategorycount">';
+    echo "</div>";
 
-    echo '<div class="quizquestionlistcontrols"><input type="submit" value="'.get_string('savechanges').'" />';
-    echo '<input type="hidden" name="savechanges" value="save" /></div>';
+    echo "</div>";
 
-    echo '</fieldset>';
-    echo "</form>\n";
+}
 
-    if (!$quiz->shufflequestions) {
-        echo '<div id="showhidepagingcontrols">';
+/**
+ * Print a given single question in quiz for the reordertool tab of edit.php.
+ * Meant to be used from quiz_print_question_list()
+ */
+function quiz_print_singlequestion_reordertool(&$question, &$questionurl, &$quiz){
+    $stredit = get_string("edit");
+    $strview = get_string("view");
 
-    /// Button to show or hide pagebreaks.
-        if ($showbreaks) {
-            $newshowbreaks = 0;
-            $caption = get_string('hidebreaks', 'quiz');
-        } else {
-            $newshowbreaks = 1;
-            $caption = get_string('showbreaks', 'quiz');
+    global $COURSE,$QTYPES, $CFG;
+    $reordercheckboxlabel='<label for="s'.$question->id.'">';
+    $reordercheckboxlabelclose='</label>';
+
+    ?>
+    <div class="singlequestion">
+            <?php
+            $formatoptions = new stdClass;
+            $formatoptions->noclean = false;
+            $formatoptions->para = false;
+            $formatoptions->newlines = false;
+            echo $reordercheckboxlabel;
+            print_question_icon($question);
+            echo "$reordercheckboxlabelclose ";
+            $questiontext=strip_tags(format_text($question->questiontext,
+                    FORMAT_MOODLE,$formatoptions, $COURSE->id));
+            $editstring="";
+            if (question_has_capability_on($question, 'edit', $question->category) || question_has_capability_on($question, 'move', $question->category)) {
+                echo "$reordercheckboxlabel ".
+                        quiz_question_tostring($question,false).
+                        $reordercheckboxlabelclose;
+                $editstring="<a title=\"$stredit\" href=\"".
+                        $questionurl->out(false, array('id'=>$question->id)).
+                        "\"><img src=\"$CFG->pixpath/t/edit.gif\" alt=\"".
+                        $stredit."\" /> </a>";
+            } elseif (question_has_capability_on($question, 'view',
+                    $question->category)){
+                echo "$reordercheckboxlabel".
+                        quiz_question_tostring($question,false).
+                        "$reordercheckboxlabelclose";
+                $editstring="<a title=\"$strview\" href=\"".$questionurl->out(false,
+                        array('id'=>$question->id))."\">$questionstring <img
+                        src=\"$CFG->pixpath/i/info.gif\" alt=\"$strview\" /></a>";
+            }else{
+                echo "$reordercheckboxlabel".
+                quiz_question_tostring($question,false).
+                        "$reordercheckboxlabelclose";
+            }
+            echo '<span class="questionpreview">'.$editstring.
+                    quiz_question_preview_button($quiz, $question, false).
+                    '</span>';
+            ?>
+    </div><?php
+}
+/**
+ * Print a given random question in quiz for the reordertool tab of edit.php.
+ * Meant to be used from quiz_print_question_list()
+ */
+
+function quiz_print_randomquestion_reordertool(&$question, &$pageurl, &$quiz){
+    global $CFG,$DB;
+    $stredit = get_string("edit");
+    $strview = get_string("view");
+
+    echo '<div class="quiz_randomquestion">';
+
+    //TODO: Tim? I left this out from the below get_record call:, 'contextid', $contextid
+    if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) {
+        notify('Random question category not found!');
+        return;
+    }
+    echo '<div class="randomquestionfromcategory">';
+    $url=$pageurl->out(false,array("qbanktool"=>1, "cat"=>$category->id.','.
+            $category->contextid));
+    $reordercheckboxlabel='<label for="s'.$question->id.'">';
+    $reordercheckboxlabelclose='</label>';
+
+    echo $reordercheckboxlabel;
+    print_question_icon($question);
+    $editstring= "<a title=\"$stredit\" href=\"".$url.
+            "\"><img src=\"$CFG->pixpath/t/edit.gif\" alt=\"".
+            get_string("edit")."\" /> </a>";
+    $questioncount=$DB->count_records_select('question',
+            "category IN ($category->id) AND parent = '0' ");
+    $randomquestionlistsize=3;
+
+    if(!$questioncount){
+        echo '<span class="error">';
+        print_string("empty", "quiz");
+        echo '</span> ';
+    }
+
+    print_string('random','quiz');
+    echo ": $reordercheckboxlabelclose</div>";
+
+    echo '<div class="randomquestioncategory">';
+    echo '<!--<a href="'.
+            $pageurl->out(false,array("qbanktool"=>1, "cat"=>$category->id.','.
+            $category->contextid)).
+            '">-->'.$reordercheckboxlabel.$category->name.
+            $reordercheckboxlabelclose.'<!--</a>-->';
+    echo '<span class="questionpreview">'.$editstring;
+     //TODO: URGENT fix question preview for random questions
+    /*echo
+        quiz_question_preview_button($quiz, $question);
+    */
+    echo '</span>';
+    echo "</div>";
+
+
+    echo '<div class="randomquestioncategorycount">';
+    echo "</div>";
+
+    echo "</div>";
+
+}
+/**
+ * Creates a textual representation of a question for display.
+ */
+function quiz_question_tostring(&$question,$showicon=false,$showquestiontext=true, $return=true){
+        global $COURSE;
+        $result="";
+        $result.='<span class="questionname">';
+        if($showicon){
+            $result.=print_question_icon($question,true);
+            echo " ";
         }
-        print_single_button($pageurl->out(true),
-                array('showbreaks' => $newshowbreaks) + $pageurl->params(), $caption);
+        $result.=shorten_text(format_string($question->name),200).'</span>';
+        if($showquestiontext){
+            $formatoptions = new stdClass;
+            $formatoptions->noclean = true;
+            $formatoptions->para = false;
+            $questiontext=strip_tags(format_text($question->questiontext,
+                    $question->questiontextformat,
+                    $formatoptions, $COURSE->id));
+            $questiontext=shorten_text($questiontext,200);
+            $result.='<span class="questiontext">';
+            if(!empty($questiontext)){
+                $result.=$questiontext;
+            }else{
+                //TODO: if moodle used PHP exceptions, we would raise one here so that
+                //the main UI would know to display quis status "unfinished".
+                $result.='<span class="error">';
+                $result.= get_string("questiontextisempty","quiz");
+                $result.='</span>';
+            }
+            $result.='</span>';
+        }
+        if($return){
+            return $result;
+        }else{
+            echo $result;
+        }
+}
 
-        echo ' ';
 
-    /// Button to show or hide the reordering tool.
-        if ($reordertool) {
-            $newreordertool = 0;
-            $caption = get_string('hidereordertool', 'quiz');
-        } else {
-            $newreordertool = 1;
-            $caption = get_string('reordertool', 'quiz');
+
+
+
+/**
+ * Shows the question bank editing interface.
+ * A changed copy of the function at question/editlib.php; to be refactored.
+ *
+ * The function also processes a number of actions:
+ *
+ * Actions affecting the question pool:
+ * move           Moves a question to a different category
+ * deleteselected Deletes the selected questions from the category
+ * Other actions:
+ * category      Chooses the category
+ * displayoptions Sets display options
+ *
+ * @author Martin Dougiamas and many others. This has recently been extensively
+ *         rewritten by Gustav Delius and other members of the Serving Mathematics project
+ *         {@link http://maths.york.ac.uk/serving_maths}
+ * @param moodle_url $pageurl object representing this pages url.
+ */
+function quiz_question_showbank($tabname, $contexts, $pageurl, $cm,
+        $page, $perpage, $sortorder, $sortorderdecoded, $cat, $recurse,
+        $showhidden, $showquestiontext, $cmoptions){
+    global $COURSE,$DB;
+
+    if (optional_param('deleteselected', false, PARAM_BOOL)){ // teacher still has to confirm
+        // make a list of all the questions that are selected
+        $rawquestions = $_REQUEST; // This code is called by both POST forms and GET links, so cannot use data_submitted.
+        $questionlist = '';  // comma separated list of ids of questions to be deleted
+        $questionnames = ''; // string with names of questions separated by <br /> with
+                             // an asterix in front of those that are in use
+        $inuse = false;      // set to true if at least one of the questions is in use
+        foreach ($rawquestions as $key => $value) {    // Parse input for question ids
+            if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
+                $key = $matches[1];
+                $questionlist .= $key.',';
+                question_require_capability_on($key, 'edit');
+                if (record_exists('quiz_question_instances', 'question', $key)) {
+                    $questionnames .= '* ';
+                    $inuse = true;
+                }
+                $questionnames .= get_field('question', 'name', 'id', $key).
+                        '<br />';
+            }
+        }
+        if (!$questionlist) { // no questions were selected
+            redirect($pageurl->out());
         }
-        print_single_button($pageurl->out(true),
-                array('reordertool' => $newreordertool) + $pageurl->params(), $caption);
-        helpbutton('reorderingtool', get_string('reordertool', 'quiz'), 'quiz');
+        $questionlist = rtrim($questionlist, ',');
 
-        echo '</div>';
+        // Add an explanation about questions in use
+        if ($inuse) {
+            $questionnames .= '<br />'.get_string('questionsinuse', 'quiz');
+        }
+        notice_yesno(get_string("deletequestionscheck", "quiz", $questionnames),
+                    $pageurl->out_action(array('deleteselected'=>$questionlist,
+                            'confirm'=>md5($questionlist))),
+                    $pageurl->out_action());
+    }else{
+        //actual question bank
+        // starts with category selection form
+        list($categoryid, $contextid)=  explode(',', $cat);
 
-    /// Repaginate form.
-        echo '<form method="post" action="edit.php" id="showbreaks">';
-        echo '<div>';
-        echo $pageurl->hidden_params_out();
-        echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
-        $perpage= array();
-        $perpage[0] = get_string('allinone', 'quiz');
-        for ($i=1; $i<=50; ++$i) {
-            $perpage[$i] = $i;
-        }
-        print_string('repaginate', 'quiz', choose_from_menu($perpage, 'questionsperpage',
-                $quiz->questionsperpage, '', '', '', true));
-        echo ' <input type="submit" name="repaginate" value="'. get_string('go') .'" />';
-        echo '</div>';
-        echo '</form>';
+        if (!$categoryid) {
+            print_box_start('generalbox questionbank');
+            quiz_question_category_form($contexts->having_one_edit_tab_cap($tabname), $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
+            echo "<p style=\"text-align:center;\"><b>";
+            print_string("selectcategoryabove", "quiz");
+            echo "</b></p>";
+            print_box_end();
+            return;
+        }
+
+        if (!$category = $DB->get_record('question_categories',
+                array('id' => $categoryid, 'contextid' => $contextid))) {
+                    print_box_start('generalbox questionbank');
+            notify('Category not found!');
+            print_box_end();
+            return;
+        }
+        $formatoptions = new stdClass;
+        $formatoptions->noclean = true;
+        $strcategory = get_string('category', 'quiz');
+        echo '<div class="categoryinfo"><div class="categorynamefieldcontainer">'.
+                $strcategory;
+        echo ': <span class="categorynamefield">';
+        echo shorten_text(strip_tags(format_text($category->name, FORMAT_MOODLE,
+                $formatoptions, $COURSE->id)),60);
+        echo '</span></div><div class="categoryinfofieldcontainer"><span class="categoryinfofield">';
+        echo shorten_text(strip_tags(format_text($category->info, FORMAT_MOODLE,
+                $formatoptions, $COURSE->id)),200);
+        echo '</span></div></div>';
+
+        print_box_start('generalbox questionbank');
+
+        quiz_question_category_form($contexts->having_one_edit_tab_cap($tabname),
+                $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
+        // continues with list of questions
+
+        quiz_question_list($contexts->having_one_edit_tab_cap($tabname),
+                $pageurl,
+                $cat,
+                isset($cm) ? $cm : null,
+                $recurse,
+                $page,
+                $perpage,
+                $showhidden,
+                $sortorder,
+                $sortorderdecoded,
+                $showquestiontext,
+                $contexts->having_cap('moodle/question:add'),
+                $cmoptions);
+
+        echo '<hr/><form method="get" action="edit.php" id="displayoptions">';
+        echo "<fieldset class='invisiblefieldset'>";
+        echo $pageurl->hidden_params_out(array('recurse', 'showhidden',
+                'showquestiontext'));
+        question_category_form_checkbox('recurse', $recurse);
+        question_category_form_checkbox('showhidden', $showhidden);
+        echo '<noscript><div class="centerpara"><input type="submit" value="'.
+                get_string('go') .'" />';
+        echo '</div></noscript></fieldset></form>';
+
+        print_box_end();
     }
 
-    return $sumgrade;
 }
+/**
+ * prints a form to choose categories
+ * A changed copy of the function at question/editlib.php; to be refactored.
+ *
+ */
+function quiz_question_category_form($contexts, $pageurl, $current, $recurse=1,
+        $showhidden=false, $showquestiontext=false) {
+    global $CFG;
 
-?>
+/// Get all the existing categories now
+    $catmenu = question_category_options($contexts, false, 0, true);
+
+    $strcategory = get_string('category', 'quiz');
+    $strselectcategory = get_string('selectcategory', 'quiz');
+    $strshow = get_string('show', 'quiz');
+    $streditcats = get_string('editcategories', 'quiz');
+
+    popup_form ('edit.php?'.$pageurl->get_query_string().'&amp;category=',
+            $catmenu, 'catmenu', $current, '', '', '', false, 'self',
+            $strselectcategory.":");
+}
+
+
+
+/**
+* Prints the table of questions in a category with interactions
+* A changed copy of the function at question/editlib.php; to be refactored.
+*
+* @param object $course   The course object
+* @param int $categoryid  The id of the question category to be displayed
+* @param int $cm      The course module record if we are in the context of a particular module, 0 otherwise
+* @param int $recurse     This is 1 if subcategories should be included, 0 otherwise
+* @param int $page        The number of the page to be displayed
+* @param int $perpage     Number of questions to show per page
+* @param boolean $showhidden   True if also hidden questions should be displayed
+* @param boolean $showquestiontext whether the text of each question should be shown in the list
+*/
+function quiz_question_list($contexts, $pageurl, $categoryandcontext,
+        $cm = null, $recurse=1, $page=0, $perpage=100, $showhidden=false,
+        $sortorder='typename', $sortorderdecoded='qtype, name ASC',
+        $showquestiontext = false, $addcontexts = array(), $cmoptions) {
+    global $USER, $CFG, $THEME, $COURSE, $DB;
+    list($categoryid, $contextid)=  explode(',', $categoryandcontext);
+
+    $qtypemenu = question_type_menu();
+
+    $strcategory = get_string("category", "quiz");
+    $strquestion = get_string("question", "quiz");
+    $straddquestions = get_string("addquestions", "quiz");
+    $strimportquestions = get_string("importquestions", "quiz");
+    $strexportquestions = get_string("exportquestions", "quiz");
+    $strnoquestions = get_string("noquestions", "quiz");
+    $strselect = get_string("select", "quiz");
+    $strselectall = get_string("selectall", "quiz");
+    $strselectnone = get_string("selectnone", "quiz");
+    $strcreatenewquestion = get_string("createnewquestion", "quiz");
+    $strquestionname = get_string("questionname", "quiz");
+    $strdelete = get_string("delete");
+    $stredit = get_string("edit");
+    $strmove = get_string('moveqtoanothercontext', 'question');
+    $strview = get_string("view");
+    $straction = get_string("action");
+    $strrestore = get_string('restore');
+
+    $strtype = get_string("type", "quiz");
+    $strcreatemultiple = get_string("createmultiple", "quiz");
+    $strpreview = get_string("preview","quiz");
+
+    if (!$categoryid) {
+        echo "<p style=\"text-align:center;\"><b>";
+        print_string("selectcategoryabove", "quiz");
+        echo "</b></p>";
+        return;
+    }
+
+    if (!$category = $DB->get_record('question_categories',
+            array('id' => $categoryid, 'contextid' => $contextid))) {
+        notify('Category not found!');
+        return;
+    }
+
+    $catcontext = get_context_instance_by_id($contextid);
+    $canadd = has_capability('moodle/question:add', $catcontext);
+    //check for capabilities on all questions in category, will also apply to sub cats.
+    $caneditall =has_capability('moodle/question:editall', $catcontext);
+    $canuseall =has_capability('moodle/question:useall', $catcontext);
+    $canmoveall =has_capability('moodle/question:moveall', $catcontext);
+
+    if ($cm AND $cm->modname == 'quiz') {
+        $quizid = $cm->instance;
+    } else {
+        $quizid = 0;
+    }
+    //create the url of the new question page to forward to. return url is given
+    //as a parameter and automatically urlencoded.
+
+
+
+    $returnurl = $pageurl->out();
+    $questionurl = new moodle_url("$CFG->wwwroot/question/question.php",
+                                array('returnurl' => $returnurl));
+    if ($cm!==null){
+        $questionurl->param('cmid', $cm->id);
+    } else {
+        $questionurl->param('courseid', $COURSE->id);
+    }
+    $questionmoveurl = new moodle_url("$CFG->wwwroot/question/contextmoveq.php",
+                                array('returnurl' => $returnurl));
+    if ($cm!==null){
+        $questionmoveurl->param('cmid', $cm->id);
+    } else {
+        $questionmoveurl->param('courseid', $COURSE->id);
+    }
+
+
+    $categorylist = ($recurse) ? question_categorylist($category->id) : $category->id;
+
+    // hide-feature
+    $showhidden = $showhidden ? '' : " AND hidden = '0'";
+    echo '<div class="createnewquestion">';
+    if ($canadd) {
+        popup_form ($questionurl->out(false, array('category' => $category->id)).
+                '&amp;qtype=', $qtypemenu, "addquestion_$page", "", "choose", "",
+                "", false, "self", "<strong>$strcreatenewquestion</strong>");
+        helpbutton("questiontypes", $strcreatenewquestion, "quiz");
+    }
+    else {
+        print_string('nopermissionadd', 'question');
+    }
+    echo '</div>';
+
+
+        $categorylist_array =  explode(',', $categorylist);
+
+    list($usql, $params) = $DB->get_in_or_equal($categorylist_array);
+    if (!$totalnumber = $DB->count_records_select('question',
+            "category $usql AND parent = '0' $showhidden", $params)) {
+        echo '<div class="categoryquestionscontainer noquestionsincategory">';
+        print_string("noquestions", "quiz");
+        echo "</div>";
+        return;
+    }
+
+    if (!$questions = $DB->get_records_select('question',
+                "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded,
+                '*', $page*$perpage, $perpage)) {
+
+        // There are no questions on the requested page.
+        $page = 0;
+        if (!$questionsatall = $DB->get_records_select('question',
+                "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded,
+                '*', 0, $perpage)) {
+            // There are no questions at all
+            echo '<div class="categoryquestionscontainer noquestionsincategory">';
+            print_string("noquestions", "quiz");
+            echo "</div>";
+            return;
+        }
+    }
+
+
+
+    echo '<div class="categorysortopotionscontainer">';
+    echo question_sort_options($pageurl, $sortorder);
+    echo '</div>';
+    echo '<div class="categorypagingbarcontainer">';
+    print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage');
+    echo '</div>';
+
+    echo '<form method="post" action="edit.php">';
+    echo '<fieldset class="invisiblefieldset" style="display: block;">';
+    echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
+    echo $pageurl->hidden_params_out();
+    echo '<div class="categoryquestionscontainer">';
+    echo '<table id="categoryquestions" style="width: 100%"><colgroup><col id="qaction"></col><col id="qname"></col><col id="qextraactions"></col></colgroup><tr>';
+    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$straction</th>";
+
+    echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\">$strquestionname</th>";
+    echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\"></th>";
+    echo "</tr>\n";
+    foreach ($questions as $question) {
+        $nameclass = '';
+        $textclass = '';
+        if ($question->hidden) {
+            $nameclass = 'dimmed_text';
+            $textclass = 'dimmed_text';
+        }
+        if ($showquestiontext) {
+            $nameclass .= ' header';
+        }
+        if ($nameclass) {
+            $nameclass = 'class="' . $nameclass . '"';
+        }
+        if ($textclass) {
+            $textclass = 'class="' . $textclass . '"';
+        }
+
+        echo "<tr>\n<td style=\"white-space:nowrap;\" $nameclass>\n";
+
+        $canuseq = question_has_capability_on($question, 'use',
+                $question->category);
+        if (function_exists('module_specific_actions')) {
+            echo module_specific_actions($pageurl, $question->id, $cm->id,
+            $canuseq,$cmoptions);
+        }
+
+        if ($caneditall || $canmoveall || $canuseall){
+            echo "<input title=\"$strselect\" type=\"checkbox\" name=\"q$question->id\" id=\"checkq$question->id\" value=\"1\" />";
+        }
+        echo "</td>\n";
+
+        echo "<td $nameclass><div>";
+        $questionstring=quiz_question_tostring($question,false,true,true);
+        echo "<label for=\"checkq$question->id\">";
+        print_question_icon($question);
+        echo " $questionstring</label>";
+
+
+
+        echo "</div></td>\n";
+        echo "<td>";
+        // edit, hide, delete question, using question capabilities, not quiz capabilieies
+        if (question_has_capability_on($question, 'edit', $question->category) ||
+                question_has_capability_on($question, 'move',
+                $question->category)) {
+            echo "<a title=\"$stredit\" href=\"".$questionurl->out(false,
+                    array('id'=>$question->id))."\"> <img
+                    src=\"$CFG->pixpath/t/edit.gif\" alt=\"$stredit\" /></a>";
+        } elseif (question_has_capability_on($question, 'view',
+                $question->category)){
+
+            echo "<a title=\"$strview\" href=\"".$questionurl->out(false,
+                    array('id'=>$question->id))."\"><img
+                    src=\"$CFG->pixpath/i/info.gif\" alt=\"$strview\" /></a>";
+        }
+        // preview
+        if ($canuseq) {
+            $quizorcourseid = $quizid?('&amp;quizid=' . $quizid):('&amp;courseid=' .$COURSE->id);
+            link_to_popup_window('/question/preview.php?id=' . $question->id .
+                    $quizorcourseid, 'questionpreview',
+                    "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" />",
+                    0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS);
+        }
+        echo "</td>";
+
+        echo "</tr>\n";
+        if($showquestiontext){
+            echo '<tr><td colspan="3" ' . $textclass . '>';
+            $formatoptions = new stdClass;
+            $formatoptions->noclean = true;
+            $formatoptions->para = false;
+            echo format_text($question->questiontext,
+                    $question->questiontextformat,
+                    $formatoptions, $COURSE->id);
+            echo "</td></tr>\n";
+        }
+    }
+    echo "</table></div>\n";
+
+
+
+
+    echo '<div class="categorypagingbarcontainer pagingbottom">';
+    $paging = print_paging_bar($totalnumber, $page, $perpage,
+            $pageurl, 'qpage', false, true);
+    if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
+        if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
+            $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>1000)).'">'.get_string('showall', 'moodle', $totalnumber).'</a>';
+        } else {
+            $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>DEFAULT_QUESTIONS_PER_PAGE)).'">'.get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE).'</a>';
+        }
+        if ($paging) {
+            $paging = substr($paging, 0, strrpos($paging, '</div>'));
+            $paging .= "<br />$showall</div>";
+        } else {
+            $paging = "<div class='paging'>$showall</div>";
+        }
+    }
+    echo $paging;
+    echo '</div>';
+    echo '<div class="categoryselectallcontainer">';
+    if ($caneditall || $canmoveall || $canuseall){
+        echo '<a href="javascript:select_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectall.'</a> /'.
+         ' <a href="javascript:deselect_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectnone.'</a>';
+        echo '<br />';
+    }
+    echo "</div>\n";
+    echo '<div class="modulespecificbuttonscontainer">';
+    if ($caneditall || $canmoveall || $canuseall){
+        echo '<strong>&nbsp;'.get_string('withselected', 'quiz').':</strong><br />';
+        if (function_exists('module_specific_buttons')) {
+            echo module_specific_buttons($cm->id,$cmoptions);
+        }
+        // print delete and move selected question
+        if ($caneditall) {
+            echo '<input type="submit" name="deleteselected" value="'.
+                    $strdelete."\" />\n";
+        }
+        if (function_exists('module_specific_controls') && $canuseall) {
+            $modulespecific=module_specific_controls($totalnumber, $recurse, $category,
+                    $cm->id,$cmoptions);
+            if(!empty($modulespecific)){
+                echo "<hr />$modulespecific";
+            }
+        }
+    }
+    echo "</div>\n";
+
+    echo '</fieldset>';
+    echo "</form>\n";
+}
+
+?>
\ No newline at end of file
index 68d5042f0d97e8642115eeffede70402b378b1cc..29ec7d023234a97a7cb82c76abcbda3c7d45c62b 100644 (file)
@@ -81,9 +81,9 @@ function quiz_create_attempt($quiz, $attemptnumber, $lastattempt, $timenow, $isp
         $attempt->userid = $USER->id;
         $attempt->preview = 0;
         if ($quiz->shufflequestions) {
-            $attempt->layout = quiz_repaginate($quiz->questions, $quiz->questionsperpage, true);
+            $attempt->layout = quiz_clean_layout(quiz_repaginate($quiz->questions, $quiz->questionsperpage, true),true);
         } else {
-            $attempt->layout = $quiz->questions;
+            $attempt->layout = quiz_clean_layout($quiz->questions,true);
         }
     } else {
     /// Build on last attempt.
@@ -229,7 +229,15 @@ function quiz_questions_on_page($layout, $page) {
  *                        So 5,2,0,3,0 means questions 5 and 2 on page 1 and question 3 on page 2
  */
 function quiz_questions_in_quiz($layout) {
-    return str_replace(',0', '', $layout);
+    if($layout){
+        $layout=str_replace(',0', '', $layout);
+        //remove also the zero in the beginning, if any
+        if(isset($layout[0]) && $layout[0]=="0" &&
+                isset($layout[1]) && $layout[1]==","){
+            $layout=substr($layout,2);
+        }
+    }
+    return $layout;
 }
 
 /**
@@ -239,7 +247,31 @@ function quiz_questions_in_quiz($layout) {
  * @param string $layout  The string representing the quiz layout.
  */
 function quiz_number_of_pages($layout) {
-    return substr_count($layout, ',0');
+    $count=0;
+    if($layout){
+        //if the first page is empty, include it, too
+        if (strcmp($layout[0],"0")===0){
+            $count++;
+        }
+        $count+=substr_count($layout, ',0');
+    }
+    return $count;
+}
+/**
+ * Returns the number of questions in the quiz layout
+ *
+ * @return integer         Comma separated list of question ids
+ * @param string $layout  The string representing the quiz layout.
+ */
+function quiz_number_of_questions_in_quiz($layout) {
+    //TODO: clean layout before counting
+    //TODO: remove page breaks
+    $layout=quiz_questions_in_quiz($layout);
+    $count=substr_count($layout, ',');
+    if($count>0){
+        $count++;
+    }
+    return $count;
 }
 
 /**
@@ -275,6 +307,10 @@ function quiz_first_questionnumber($quizlayout, $pagelayout) {
 function quiz_repaginate($layout, $perpage, $shuffle=false) {
     $layout = str_replace(',0', '', $layout); // remove existing page breaks
     $questions = explode(',', $layout);
+    //remove empty pages from beginning
+    while (reset($questions) == '0') {
+        array_shift($questions);
+    }
     if ($shuffle) {
         srand((float)microtime() * 1000000); // for php < 4.2
         shuffle($questions);
@@ -705,7 +741,7 @@ function quiz_question_action_icons($quiz, $cmid, $question, $returnurl){
         $stredit = get_string('edit');
         $strview = get_string('view');
     }
-    $html =''; 
+    $html ='';
     if (($question->qtype != 'random')){
         $html .= quiz_question_preview_button($quiz, $question);
     }
@@ -727,15 +763,19 @@ function quiz_question_action_icons($quiz, $cmid, $question, $returnurl){
  * @param object $question the question
  * @return the HTML for a preview question icon.
  */
-function quiz_question_preview_button($quiz, $question) {
+function quiz_question_preview_button($quiz, $question, $label=true) {
     global $CFG, $COURSE;
     if (!question_has_capability_on($question, 'use', $question->category)){
         return '';
     }
     $strpreview = get_string('previewquestion', 'quiz');
+    $strpreviewlabel="";
+    if($label){
+        $strpreviewlabel = " ".get_string('preview', 'quiz');
+    }
     $quizorcourseid = $quiz->id?('&amp;quizid=' . $quiz->id):('&amp;courseid=' .$COURSE->id);
     return link_to_popup_window('/question/preview.php?id=' . $question->id . $quizorcourseid, 'questionpreview',
-            "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" />",
+            "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" />$strpreviewlabel",
             0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS, true);
 }
 
@@ -1085,7 +1125,78 @@ function quiz_send_notification_emails($course, $quiz, $attempt, $context, $cm)
     // return the number of successfully sent emails
     return $emailresult['good'];
 }
+function print_timing_information($quiz,$showopenstatus=false){
+        $timenow = time();
+        $available = ($quiz->timeopen < $timenow and ($timenow < $quiz->timeclose or !$quiz->timeclose));
+        if ($available) {
+            if ($quiz->timelimit) {
+                echo get_string("quiztimelimit","quiz", format_time($quiz->timelimit * 60))."</p>";
+            }
+            if ($quiz->timeopen) {
+                echo get_string('quizopens', 'quiz'), ': ', userdate($quiz->timeopen);
+            }
+            if ($quiz->timeclose) {
+                echo get_string('quizcloses', 'quiz'), ': ', userdate($quiz->timeclose);
+            }
+            if($showopenstatus){
+                if(!$quiz->timelimit && !$quiz->timeopen && !$quiz->timeclose){
+                    echo get_string('quizopened', 'quiz');
+                }
+            }
+        } else if ($timenow < $quiz->timeopen) {
+            echo get_string("quiznotavailable", "quiz", userdate($quiz->timeopen));
+        } else {
+            echo get_string("quizclosed", "quiz", userdate($quiz->timeclose));
+        }
+        return $available;
+
+}
 
+function quiz_clean_layout($layout,$removeemptypages=false){
+    //remove duplicate "," (or triple, or...)
+    while(strstr($layout,",,")){
+        $layout = str_replace(',,', ',', $layout);
+    }
+    //remove duplicate question ids
+    $layout_arr=explode(",",$layout);
+    $new_arr=array();
+    $seen=array();
+    //remove duplicate questions
+    foreach($layout_arr as $key=>$value){
+         if(!in_array($value,$seen) && $value!=0){
+             $new_arr[]=$value;
+             $seen[]=$value;
+         }else if($value==0){
+             $new_arr[]=0;
+         }
+    }
+    if($removeemptypages){
+        // Avoid duplicate page breaks
+        // Go through all the array keys
+        for($i=0;$i<count($new_arr);$i++){
+            //check if the current position and the one after are both zeros
+            //remove the one after until they are not both zeros
+                while(isset($new_arr[$i+1]) &&
+                        $new_arr[$i]==0 &&
+                        $new_arr[$i+1]==0){
+                    print_r($new_arr);
+                    array_splice($new_arr,$i+1,1);
+                }
+        }
+    }
+    $layout=implode(",",$new_arr);
+    //remove extra "," from beginning and end
+    $layout=trim($layout, ",");
+    //add a ",0" (page break) at the end if there is none
+    $layoutlength=strlen($layout);
+    $last=(strlen($layout)-1);
+    if($layoutlength>1 AND
+            !($layout[$last-1] == ',' AND $layout[$last] == '0')){
+        $layout .= ',0';
+    }
+
+    return $layout;
+}
 /**
  * Print a quiz error message. This is a thin wrapper around print_error, for convinience.
  *
index aa6b1b961edcb4180e7f7ec55c57cbc1721c02a9..1f49a514d99fa0bebc113f5e568c2fa7e229f3cc 100644 (file)
@@ -31,7 +31,7 @@ $tabs = array();
 $row  = array();
 $inactive = array();
 $activated = array();
-
+$stredit=get_string('edit');
 if (has_capability('mod/quiz:view', $context)) {
     $row[] = new tabobject('info', "$CFG->wwwroot/mod/quiz/view.php?id=$cm->id", get_string('info', 'quiz'));
 }
@@ -39,10 +39,11 @@ if (has_capability('mod/quiz:viewreports', $context)) {
     $row[] = new tabobject('reports', "$CFG->wwwroot/mod/quiz/report.php?q=$quiz->id", get_string('results', 'quiz'));
 }
 if (has_capability('mod/quiz:preview', $context)) {
-    $row[] = new tabobject('preview', "$CFG->wwwroot/mod/quiz/startattempt.php?cmid=$cm->id&amp;sesskey=" . sesskey(), get_string('preview', 'quiz'));
+    $strpreview = get_string('preview', 'quiz');
+    $row[] = new tabobject('preview', "$CFG->wwwroot/mod/quiz/startattempt.php?cmid=$cm->id&amp;sesskey=" . sesskey(), "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" /> $strpreview", $strpreview);
 }
 if (has_capability('mod/quiz:manage', $context)) {
-    $row[] = new tabobject('edit', "$CFG->wwwroot/mod/quiz/edit.php?cmid=$cm->id", get_string('edit'));
+    $row[] = new tabobject('edit', "$CFG->wwwroot/mod/quiz/edit.php?cmid=$cm->id", "<img src=\"$CFG->pixpath/t/edit.gif\" class=\"iconsmall\" alt=\"$stredit\" /> $stredit",$stredit);
 }
 
 if ($currenttab == 'info' && count($row) == 1) {
@@ -101,9 +102,11 @@ if ($currenttab == 'edit' and isset($mode)) {
     $streditingquiz = get_string("editinga", "moodle", $strquiz);
 
     if (has_capability('mod/quiz:manage', $context) && $contexts->have_one_edit_tab_cap('editq')) {
-        $row[] = new tabobject('editq', "$CFG->wwwroot/mod/quiz/edit.php?".$thispageurl->get_query_string(), $strquiz, $streditingquiz);
+        //TODO: ensure that removing get_query_string here won't hurt
+        $row[] = new tabobject('editq', "$CFG->wwwroot/mod/quiz/edit.php?cmid=$cm->id", $stredit, $streditingquiz);
+        $row[] = new tabobject('reorder', "$CFG->wwwroot/mod/quiz/edit.php?reordertool=1&amp;cmid=$cm->id", get_string('orderandpaging','quiz'), $streditingquiz);
     }
-    questionbank_navigation_tabs($row, $contexts, $thispageurl->get_query_string());
+    //questionbank_navigation_tabs($row, $contexts, $thispageurl->get_query_string());
     $tabs[] = $row;
 
 }
index c6ef91ddbf35a9062a1f7f11ab03a8c050036a10..f9277024632473e02869e46ceb679d3f8aace186 100644 (file)
@@ -12,6 +12,7 @@ define("QUESTION_PAGE_LENGTH", 25);
 
 require_once("$CFG->libdir/listlib.php");
 require_once("$CFG->dirroot/question/category_form.php");
+require_once("$CFG->dirroot/question/category_form_randomquestion.php");
 require_once('move_form.php');
 
 class question_category_list extends moodle_list {
@@ -135,6 +136,10 @@ class question_category_object {
      * @var question_category_edit_form Object representing form for adding / editing categories.
      */
     var $catform;
+    /**
+     * @var question_category_edit_form_randomquestion Object representing simplified form for adding a category in order to add it into a quiz as a random question.
+     */
+    var $catform_rand;
 
     /**
      * Constructor
@@ -197,8 +202,10 @@ class question_category_object {
             list($paged, $count) = $this->editlists[$key]->list_from_records($paged, $count);
         }
         $this->catform = new question_category_edit_form($this->pageurl, compact('contexts', 'currentcat'));
+        $this->catform_rand = new question_category_edit_form_randomquestion($this->pageurl, compact('contexts', 'currentcat'));
         if (!$currentcat){
             $this->catform->set_data(array('parent'=>$defaultcategory));
+            $this->catform_rand->set_data(array('parent'=>$defaultcategory));
         }
     }
     /**
@@ -216,6 +223,16 @@ class question_category_object {
         $this->output_new_table();
         echo '<br />';
 
+    }
+    /**
+     * Displays the user interface
+     *
+     */
+    function display_randomquestion_user_interface() {
+
+        /// Interface for adding a new category:
+        $this->output_new_randomquestion_table();
+
     }
 
     /**
@@ -225,6 +242,13 @@ class question_category_object {
         $this->catform->display();
     }
 
+    /**
+     * Outputs a table to allow entry of a new category
+     */
+    function output_new_randomquestion_table() {
+        $this->catform_rand->display();
+    }
+
 
     /**
      * Outputs a list to allow editing/rearranging of existing categories
@@ -278,6 +302,8 @@ class question_category_object {
             $category->categoryheader = $this->str->edit;
             $this->catform->set_data($category);
             $this->catform->display();
+            $this->catform_rand->set_data($category);
+            $this->catform_rand->display();
         } else {
             print_error('invalidcategory', '', '', $categoryid);
         }
@@ -369,7 +395,7 @@ class question_category_object {
     /**
      * Creates a new category with given params
      */
-    public function add_category($newparent, $newcategory, $newinfo) {
+    public function add_category($newparent, $newcategory, $newinfo, $return=false) {
         global $DB;
         if (empty($newcategory)) {
             print_error('categorynamecantbeblank', 'quiz');
@@ -391,10 +417,14 @@ class question_category_object {
         $cat->info = $newinfo;
         $cat->sortorder = 999;
         $cat->stamp = make_unique_id_code();
-        if (!$DB->insert_record("question_categories", $cat)) {
+        if (!$categoryid=$DB->insert_record("question_categories", $cat)) {
             print_error('cannotinsertquestioncate', 'question', '', $newcategory);
         } else {
-            redirect($this->pageurl->out());//always redirect after successful action
+            if($return){
+                return $categoryid;
+            }else{
+                redirect($this->pageurl->out());//always redirect after successful action
+            }
         }
     }
 
diff --git a/question/category_form_randomquestion.php b/question/category_form_randomquestion.php
new file mode 100644 (file)
index 0000000..cde516c
--- /dev/null
@@ -0,0 +1,49 @@
+<?php  //$Id$
+
+require_once($CFG->libdir.'/formslib.php');
+
+class question_category_edit_form_randomquestion extends moodleform {
+
+    function definition() {
+        global $CFG, $DB;
+        $mform    =& $this->_form;
+
+        $contexts   = $this->_customdata['contexts'];
+        $currentcat   = $this->_customdata['currentcat'];
+//--------------------------------------------------------------------------------
+        $mform->addElement('header', 'categoryheader', get_string('createcategoryfornewrandomquestion', 'quiz'));
+
+        $questioncategoryel = $mform->addElement('questioncategory', 'parent', get_string('parentcategory', 'quiz'),
+                    array('contexts'=>$contexts, 'top'=>true, 'currentcat'=>$currentcat, 'nochildrenof'=>$currentcat));
+        $mform->setType('parent', PARAM_SEQUENCE);
+        if (1 == $DB->count_records_sql("SELECT count(*)
+                                           FROM {question_categories} c1,
+                                                {question_categories} c2
+                                          WHERE c2.id = ?
+                                            AND c1.contextid = c2.contextid", array($currentcat))){
+            //TODO: Tim? why does the above evaluate true, breaking the form?
+            // and more importantly, if this is a valid situation, how should we react,
+            // that is, what does this mean?
+            //$mform->hardFreeze('parent');
+        }
+        $mform->setHelpButton('parent', array('categoryparent', get_string('parent', 'quiz'), 'question'));
+
+        $mform->addElement('text','name', get_string('name'),'maxlength="254" size="50"');
+        $mform->setDefault('name', '');
+        $mform->addRule('name', get_string('categorynamecantbeblank', 'quiz'), 'required', null, 'client');
+        $mform->setType('name', PARAM_MULTILANG);
+
+        $mform->addElement('hidden', 'info', '');
+        $mform->setType('info', PARAM_MULTILANG);
+
+//--------------------------------------------------------------------------------
+        $this->add_action_buttons(false, get_string('addrandomquestion', 'quiz'));
+//--------------------------------------------------------------------------------
+        $mform->addElement('hidden', 'id', 0);
+        $mform->setType('id', PARAM_INT);
+        //TODO: Tim: is this questionable? to add a hidden field right from a get parameter?
+        $mform->addElement('hidden', 'addonpage', optional_param("addonpage_form", 0, PARAM_SEQUENCE), 'id="rform_qpage"');
+        $mform->setType('addonpage', PARAM_SEQUENCE);
+    }
+}
+?>
index 14d5907df779e3734ec7d8aa1628e0f8a6c00876..50b58d551ca0f97750a4c611247f97ac8f976e59 100644 (file)
@@ -158,7 +158,7 @@ function question_list($contexts, $pageurl, $categoryandcontext, $cm = null,
     $straddquestions = get_string("addquestions", "quiz");
     $strimportquestions = get_string("importquestions", "quiz");
     $strexportquestions = get_string("exportquestions", "quiz");
-    $strnoquestions = get_string("noquestions", "quiz");
+    $strnoquestions = get_string("noquestionsincategory", "quiz");
     $strselect = get_string("select", "quiz");
     $strselectall = get_string("selectall", "quiz");
     $strselectnone = get_string("selectnone", "quiz");
@@ -244,7 +244,7 @@ function question_list($contexts, $pageurl, $categoryandcontext, $cm = null,
     list($usql, $params) = $DB->get_in_or_equal($categorylist_array);
     if (!$totalnumber = $DB->count_records_select('question', "category $usql AND parent = '0' $showhidden", $params)) {
         echo "<p style=\"text-align:center;\">";
-        print_string("noquestions", "quiz");
+        echo $strnoquestions;
         echo "</p>";
         return;
     }
@@ -255,14 +255,13 @@ function question_list($contexts, $pageurl, $categoryandcontext, $cm = null,
         if (!$questions = $DB->get_records_select('question', "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded, '*', 0, $perpage)) {
             // There are no questions at all
             echo "<p style=\"text-align:center;\">";
-            print_string("noquestions", "quiz");
+            echo $strnoquestions;
             echo "</p>";
             return;
         }
     }
 
     print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage');
-
     echo question_sort_options($pageurl, $sortorder);
 
 
@@ -397,15 +396,21 @@ function question_list($contexts, $pageurl, $categoryandcontext, $cm = null,
 function question_sort_options($pageurl, $sortorder){
     global $USER;
     //sort options
-    $html = "<div class=\"mdl-align\">";
-    $html .= '<form method="post" action="edit.php">';
+    $html = "<div class=\"mdl-align questionsortoptions\">";
+    // POST method should only be used for parameters that change data
+    // or if POST method has to be used, the user must be redirected immediately to
+    // non-POSTed page to not break the back button
+    $html .= '<form method="get" action="edit.php">';
     $html .= '<fieldset class="invisiblefieldset" style="display: block;">';
     $html .= '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
     $html .= $pageurl->hidden_params_out(array('qsortorder'));
-    $sortoptions = array('alpha' => get_string("sortalpha", "quiz"),
-                         'typealpha' => get_string("sorttypealpha", "quiz"),
-                         'age' => get_string("sortage", "quiz"));
-    $html .=  choose_from_menu ($sortoptions, 'qsortorder', $sortorder, false, 'this.form.submit();', '0', true);
+    //choose_from_menu concatenates the form name with
+    //"menu" so the label is for menuqsortorder
+    $sortoptions = array('alpha' => get_string("qname", "quiz"),
+                         'typealpha' => get_string("qtypename", "quiz"),
+                         'age' => get_string("age", "quiz"));
+    $a =  choose_from_menu ($sortoptions, 'qsortorder', $sortorder, false, 'this.form.submit();', '0', true);
+    $html .= '<label for="menuqsortorder">'.get_string('sortquestionsbyx', 'quiz', $a).'</label>';
     $html .=  '<noscript><div><input type="submit" value="'.get_string("sortsubmit", "quiz").'" /></div></noscript>';
     $html .= '</fieldset>';
     $html .= "</form>\n";
index 65a60c17372e6184d2021aca801e6cc388e7248e..b763976d3e9db8207bbd27c6152dbd69796e64f2 100644 (file)
@@ -24,6 +24,7 @@ $wizardnow =  optional_param('wizardnow', '', PARAM_ALPHA);
 $movecontext =  optional_param('movecontext', 0, PARAM_BOOL);//switch to make question
                     //uneditable - form is displayed to edit category only
 $returnurl = optional_param('returnurl', 0, PARAM_LOCALURL);
+$appendqnumstring = optional_param('appendqnumstring', '', PARAM_ALPHA);
 
 $inpopup = optional_param('inpopup', 0, PARAM_BOOL);
 
@@ -132,6 +133,8 @@ $toform->category = "$category->id,$category->contextid";
 if ($formeditable && $id){
     $toform->categorymoveto = $toform->category;
 }
+
+$toform->appendqnumstring = $appendqnumstring;
 $toform->returnurl = $returnurl;
 $toform->movecontext = $movecontext;
 if ($cm !== null){
@@ -186,10 +189,14 @@ if ($mform->is_cancelled()){
             notify(get_string('changessaved'), '');
             close_window(3);
         } else {
+            if($appendqnumstring){
+                $returnurl_object=new moodle_url($returnurl);
+                $returnurl=$returnurl_object->out(false,array($appendqnumstring=>($question->id), "sesskey"=>sesskey(), "cmid"=>$cmid));
+            }
             redirect($returnurl);
         }
     } else {
-        $nexturlparams = array('returnurl'=>$returnurl);
+        $nexturlparams = array('returnurl'=>$returnurl, 'appendqnumstring'=>$appendqnumstring);
         if (isset($fromform->nextpageparam) && is_array($fromform->nextpageparam)){
             $nexturlparams += $fromform->nextpageparam;//useful for passing data to the next page which is not saved in the database
         }
index da1a155d325fd27238be341e451b69bdb83470e6..8a51868aaf0feb044317ffe35fc42735ececc493 100644 (file)
@@ -193,6 +193,10 @@ class question_edit_form extends moodleform {
         $mform->setType('returnurl', PARAM_LOCALURL);
         $mform->setDefault('returnurl', 0);
 
+        $mform->addElement('hidden', 'appendqnumstring');
+        $mform->setType('appendqnumstring', PARAM_ALPHA);
+        $mform->setDefault('appendqnumstring', 0);
+
         $buttonarray = array();
         if (!empty($this->question->id)){
             //editing / moving question
@@ -219,17 +223,16 @@ class question_edit_form extends moodleform {
             $mform->hardFreezeAllVisibleExcept(array('categorymoveto', 'buttonar', 'currentgrp'));
         }
     }
-    
+
     function validation($fromform, $files) {
         $errors= parent::validation($fromform, $files);
-        if (empty($fromform->makecopy) && isset($this->question->id) 
-                && ($this->question->formoptions->canedit || $this->question->formoptions->cansaveasnew) 
+        if (empty($fromform->makecopy) && isset($this->question->id)
+                && ($this->question->formoptions->canedit || $this->question->formoptions->cansaveasnew)
                 && empty($fromform->usecurrentcat) && !$this->question->formoptions->canmove){
             $errors['currentgrp'] = get_string('nopermissionmove', 'question');
         }
         return $errors;
     }
-    
 
     /**
      * Add any question-type specific form fields.
index 22f95b5a0d5fe9ae3e9d5ce7e0b449dfd4c044d1..b6c8ef5f174aa276434eefb6c9a7bc7da69e4115 100644 (file)
@@ -1091,6 +1091,73 @@ table.quizreviewsummary td.cell {
 #mod-quiz-report .negcovar{
   border :medium solid pink;
 }
+
+#mod-quiz-edit .questionbankwindow div.header{
+/*this color might need to be theme-specific,
+but in terms of usability, as testing showed,
+//TODO: add url
+it must be ensured that the question
+bank window's title is prominent enough*/
+    background-color:#009;
+    color:#fff;
+    background-image:none;
+}
+
+#mod-quiz-edit div.question div.content div.points,
+        #mod-quiz-edit div.question div.content div.qorder{
+    background-color:#ddf;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent .pagestatus{
+    background-color:#eee;
+}
+#mod-quiz-edit .quizpagedelete img{
+    background-color:#d6d6d6;
+}
+#mod-quiz-edit div.quizpage .pagecontent form#addquestion{
+    background-color:#fff;
+}
+#mod-quiz-edit .questioncontentcontainer div.randomquestionqlist{
+    background-color:#eee;
+    color:#777;
+}
+#mod-quiz-edit .questioncontentcontainer div.randomquestionqlist .totalquestionsinrandomqcategory{
+    color:#000;
+}
+/*TODO: below applies to also question bank, so when
+question bank is adapted to the new UI, add the appropriate
+css id's of question bank*/
+#mod-quiz-edit .categoryinfo{
+    background-color:#eee;
+    border-bottom:1px solid #bbb;
+}
+#mod-quiz-edit .paging{
+    background-color:#ddd;
+}
+#mod-quiz-edit .questionsortoptions{
+    background-color:#ddd;
+}
+
+#mod-quiz-edit .paging a:hover{
+    background-color:#eef;
+}
+#mod-quiz-edit div.questionbank{
+    background-color:#e6e6ff;
+}
+#mod-quiz-edit .questionbank div.categoryquestionscontainer,.questionbank .categorysortopotionscontainer,.questionbank .categorypagingbarcontainer,.questionbank .categoryselectallcontainer{
+    background-color:#FFF;
+}
+#mod-quiz-edit div.question div.content div.questioncontrols{
+    background-color:#FFF;
+}
+#mod-quiz-edit div.editq div.question div.content{
+    background-color:#fff;
+}
+#mod-quiz-edit .questionbankwindow div.header a{
+    color:#FFF;
+}
+
+
 /***
  *** Modules: Resource
  ***/
@@ -1212,3 +1279,4 @@ form.mform .required .fgroup span label {
   color:#000;
 }
 
+
index ea459dd254bab9804208545952b1c104d67af18d..b898103d7c470cb4c3ebb9099aeac46404370829 100644 (file)
@@ -1006,7 +1006,60 @@ body#mod-forum-index .generalbox .cell {
   text-decoration: underline;
 }
 
-/***
+#mod-quiz-edit div.reorder .reordercontrols .moveselectedonpage{
+    text-align:right;
+}
+#mod-quiz-edit div.question div.qnum{
+    text-align:right;
+}
+#mod-quiz-edit div.reorder div.question div.qnum{
+    text-align:right;
+    font-size:1em;
+}
+#mod-quiz-edit div.editq div.question div.qnum{
+    font-size:1.5em;
+}
+#mod-quiz-edit .questionbankwindow div.header a{
+    text-decoration:underline;
+}
+#mod-quiz-edit div.questioncontentcontainer a{
+    text-decoration:underline;
+}
+
+#mod-quiz-edit div.questioncontentcontainer div.singlequestion a{
+    text-decoration:underline;
+}
+#mod-quiz-edit div.editq div.question div.content .singlequestion a .questionname,div.editq div.question div.content .singlequestion a .questiontext{
+    text-decoration:underline;
+}
+#mod-quiz-edit div.question div.content .questiontext,
+#categoryquestions .questiontext{
+    font-weight:bold;
+}
+#mod-quiz-edit div.question div.content div.questioncontrols{
+    text-align:right;
+}
+#mod-quiz-edit div.quizpage .pagecontent .pagestatus{
+    font-weight:bold;
+}
+#mod-quiz-edit div.question div.content .questiontype{
+    font-style:italic;
+}
+#mod-quiz-edit .questioncontentcontainer .randomquestioncategory{
+    font-weight:bold;
+}
+#mod-quiz-edit .categoryinfofield{
+    font-style:italic;
+}
+#mod-quiz-edit .categorynamefield{
+    font-weight:bold;
+}
+#mod-quiz-edit .questionbankwindow div.header{
+    font-weight:bold;
+}
+
+
+    /***
  *** Modules: Resource
  ***/
 
index 95a0de063dc0d526d3ae96fc48d58ffd5360de58..b70aad708500f4c1d4cb39e4599a78c334cc36b0 100755 (executable)
@@ -69,3 +69,22 @@ form.mform textarea {
 #mod-quiz-review #middle-column {
   height: 1%;
 }
+#mod-quiz-edit div.question div.content .questionname,
+#categoryquestions .questionname{
+    /*ie6 shows this as an arrow if this is not specified*/
+    cursor: pointer;
+}
+#mod-quiz-edit #categoryquestions .questiontext{
+    /*ie6 shows this as an arrow if this is not specified*/
+    cursor: pointer;
+}
+#mod-quiz-edit div.tabtree a span img.iconsmall{
+    display:none;
+}
+
+#mod-quiz-edit div.question div.content .questiontext,#categoryquestions .questiontext{
+    width:50%;
+}
+#mod-quiz-edit div.question div.content .questionname,#categoryquestions .questionname{
+    width:20%;
+}
index b7bfbaa398ddd696f9a96be04c94346a92311b5b..4b45755d3483567f354572c25fbcfb224703cda8 100644 (file)
@@ -90,14 +90,6 @@ h6.main {
   text-align: center;
 }
 
-#redirect #message {
-  
-}
-
-#redirect #continue {
-  
-}
-
 /* .clearfix {display: inline-table;} */
 
 /* Hides from IE-mac \*/
@@ -4245,20 +4237,6 @@ table.quizreviewsummary td.cell {
   margin-bottom: 0.5em;
 }
 
-#mod-quiz-edit #page .controls,
-#mod-quiz-edit #page .quizattemptcounts
-{
-  text-align: center;
-}
-#mod-quiz-edit .quizquestions h2 {
-  margin-top: 0;
-}
-#mod-quiz-edit #showhidepagingcontrols {
-  margin-top: 0.7em;
-}
-#mod-quiz-edit #showhidepagingcontrols .singlebutton {
-  display: inline;
-}
 .quizquestionlistcontrols {
   text-align: center;
 }
@@ -4421,6 +4399,545 @@ table.quizreviewsummary td.cell {
   display: block;
   margin: 0.5em 0;
 }
+#mod-quiz-edit div.sideblock{
+    float:right;
+    width:30%;
+    right:0.3em;
+    padding-bottom:0.5em;
+    display:block;
+}
+
+#mod-quiz-edit div.quizcontents{
+    float:left;
+    width:70%;
+    display:block;
+}
+
+#mod-quiz-edit div.quizcontents,h2.main{
+    clear:left;
+}
+
+#mod-quiz-edit .addpage{
+    clear:both;
+    padding-top:0.3em;
+    float:right;
+    margin-right:2em;
+}
+
+#mod-quiz-edit h2.main{
+    display:inline;
+    padding-right:1em;
+}
+
+#mod-quiz-edit .statusdisplay{
+    clear:both;
+    display:block;
+    border:0.2em #FFF solid;
+    margin-bottom:0.3em;
+    margin-right:1em;
+    margin-top:0.3em;
+    padding:0.1em;
+}
+#mod-quiz-edit div.quizpage{
+    display:block;
+    clear:both;
+    width:100%;
+}
+
+#mod-quiz-edit div.quizpage span.pagetitle{
+    margin-top:0.3em;
+    float:left;
+    display:block;
+}
+
+#mod-quiz-edit div.reorder .reordercontrols .moveselectedonpage{
+    clear:right;
+    float:right;
+    padding:0.5em 0.3em;
+}
+
+#mod-quiz-edit div.reorder .reordercontrols .addnewpagesafterselected,#mod-quiz-edit .repaginatecommand{
+    float:right;
+    clear:right;
+    padding-right:1em;
+}
+
+#mod-quiz-edit div.reorder .reordercontrols .deleteselected{
+    float:right;
+    margin-right:1em;
+}
+
+#mod-quiz-edit div.reorder .reordercontrols{
+    clear:both;
+    padding-right:1em;
+    margin-top:0.5em;
+    padding-top:0.5em;
+    padding-bottom:0.5em;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent{
+    margin-top:0.3em;
+    display:block;
+    float:left;
+    position:relative;
+    margin-left:0.3em;
+    border-left:solid #777 thin;
+    line-height:1.3em;
+    -webkit-border-radius:0.6em;
+    -webkit-border-radius-bottomleft:0;
+    -webkit-border-radius-topleft:0;
+    border-radius:0.6em;
+    border-radius-bottomleft:0;
+    border-radius-topleft:0;
+    width:88%;
+    padding:0 0 0.5em;
+}
+
+#mod-quiz-edit div.question{
+    clear:left;
+    width:100%;
+}
+
+#mod-quiz-edit div.question div.qnum{
+    display:block;
+    float:left;
+    width:1.4em;
+    padding-right:0.3em;
+    padding-left:0;
+    z-index:99;
+}
+
+#mod-quiz-edit div.reorder div.question div.qnum{
+    width:2.9em;
+    padding-top:0.1em;
+}
+/*edit tab*/
+#mod-quiz-edit div.editq div.question div.qnum{
+    padding-top:0.2em;
+}
+
+#mod-quiz-edit div.editq div.question{
+    padding-top:0.3em;
+}
+
+#mod-quiz-edit div.reorder div.question{
+    padding-top:0.2em;
+}
+
+#mod-quiz-edit div.question div.questioncontainer{
+    background-color:#ffc;
+}
+
+#mod-quiz-edit div.editq div.question div.content{
+    width:87%;
+    float:left;
+    position:relative;
+    -webkit-border-radius:0.6em;
+    -webkit-border-radius-bottomleft:0;
+    -webkit-border-radius-topleft:0;
+    border-radius:0.6em;
+    border-radius-bottomleft:0;
+    border-radius-topleft:0;
+    line-height:1.4em;
+    padding:0.5em;
+}
+
+#mod-quiz-edit .reorder div.question div.content{
+    width:87%;
+    float:left;
+    background-color:#fff;
+    position:relative;
+    -webkit-border-radius:0.3em;
+    -webkit-border-radius-bottomleft:0;
+    -webkit-border-radius-topleft:0;
+    border-radius:0.3em;
+    border-radius-bottomleft:0;
+    border-radius-topleft:0;
+    line-height:1.2em;
+    padding:0.1em;
+}
+
+#mod-quiz-edit div.question div.content div.points{
+    top:0.5em;
+    border-left:#FFF solid 0.4em;
+    width:7.5em;
+    padding:0.2em;
+}
+
+#mod-quiz-edit .questionbankwindow select#catmenu_jump{
+    /* In Opera9, IE6 the width of the 
+    select obeys the width of its content 
+    by default. This prevents that. */
+    width:100%;
+}
+
+#mod-quiz-edit .questionbankwindow div.header{
+    padding-top:0.2em;
+}
+
+#randomquestiondialog_c select{
+    width:100%;
+}
+
+
+#mod-quiz-edit div.question div.content div.points, 
+        #mod-quiz-edit div.question div.content div.qorder{
+    line-height:1em;
+    float:right;
+    max-width:30%;
+    position:absolute;
+    right:50px;
+    -webkit-border-radius:0.2em;
+    -webkit-border-radius-bottomleft:0;
+    -webkit-border-radius-topleft:0;
+    border-radius:0.2em;
+    border-radius-bottomleft:0;
+    border-radius-topleft:0;
+    z-index:999;
+    display:block;
+    margin:0;
+}
+
+
+#mod-quiz-edit div.question div.content .editicon{
+    width:15px;
+}
+
+#mod-quiz-edit .editq div.questioncontentcontainer  div.singlequestion img{
+    float:left;
+    padding-top:0.3em;
+    padding-right:0.3em;
+}
+
+
+#mod-quiz-edit div.question div.content .questionname,
+#categoryquestions .questionname{
+    white-space:nowrap;
+    text-overflow:ellipsis;
+    overflow:hidden;
+    zoom:1;    
+    position:relative;
+    max-width:20%;
+    /*ie-only:*/
+    text-overflow:ellipsis;
+    /*opera-only*/
+    -o-text-overflow:ellipsis;
+}
+#mod-quiz-edit div.question div.content .singlequestion .questionname,
+#mod-quiz-edit div.question div.content .singlequestion .questiontext{
+    display:inline-block;
+}
+
+#mod-quiz-edit div.editq div.question div.content .singlequestion a .questionname,
+#mod-quiz-edit div.editq div.question div.content .singlequestion a .questiontext{
+    float:left;
+}
+
+#mod-quiz-edit .quizquestionlistcontrols{
+    display:inline;
+}
+
+#mod-quiz-edit div.question div.content .questiontext,
+#categoryquestions .questiontext{
+    -o-text-overflow:ellipsis;
+    text-overflow:ellipsis;
+    position:relative;
+    zoom:1;    
+    padding-left:0.3em;
+    max-width:50%;
+    overflow:hidden;
+    white-space:nowrap;
+    text-overflow:ellipsis;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent .pagestatus{
+    -webkit-border-radius-bottomright:0.3em;
+    -webkit-border-radius-topright:0.3em;
+    border-radius-bottomright:0.3em;
+    border-radius-topright:0.3em;
+    margin:0.3em;
+    padding:0.1em 0.1em 0.1em 0.3em;
+}
+
+#mod-quiz-edit div.question div.content .questiontype{
+    display:block;
+    clear:left;
+    float:left;
+}
+
+#mod-quiz-edit div.question div.content .questionpreview{
+    display:block;
+    float:left;
+    margin-left:0.3em;
+    padding-left:0.2em;
+    padding-right:0.2em;
+    background-color:#eee;
+}
+
+#mod-quiz-edit div.question div.content div.quiz_randomquestion .questionpreview{
+    display:inline;
+    float:none;
+}
+
+#mod-quiz-edit div.question div.content div.questioncontrols{
+    float:right;
+    width:45px;
+    position:absolute;
+    right:0.3em;
+    top:0;
+    z-index:999;
+    display:block;
+    padding:0.2em;
+}
+
+#mod-quiz-edit div.question div.content div.questioncontrols img.upwithoutdown{
+    padding-right:12px;
+    display:inline;
+}
+
+#mod-quiz-edit .quizpagedelete{
+    position:absolute;
+    top:0.2em;
+    right:0.2em;
+    display:inline;
+    z-index:999;
+}
+
+#mod-quiz-edit .quizpagedelete img{
+    background-color:#d6d6d6;
+    padding:0.5em;
+}
+
+#mod-quiz-edit .pagecontrols{
+    clear:both;
+    margin-left:0.5em;
+    padding-top:0.5em;
+}
+
+#mod-quiz-edit .pagecontrols .singlebutton{
+    float:left;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent form#addquestion{
+    margin-right:1em;
+    -webkit-border-radius:0.2em;
+    border-radius:0.2em;
+    padding:0.3em;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent form.randomquestionform{
+    padding-left:1em;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent form.randomquestionform div{
+    /* it is a mystery why this has to be inline-table but
+       otherwise the layout gets screwed, even if
+       it is "inline" */
+    display:inline-table;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent form.randomquestionform div input{
+    display:inline;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent .adddescription{
+    clear:left;
+    margin-top:0.3em;
+}
+
+#mod-quiz-edit div.quizpage .pagecontent .addrandomquestion{
+    margin-top:0.3em;
+}
+
+/* a CSS class YUI container creates on the fly: */
+#mod-quiz-edit div#randomquestiondialog_c{
+    width:90%;
+}
+
+#mod-quiz-edit #repaginatedialog .hd{
+    display:none;
+}
+
+#mod-quiz-edit div#randomquestiondialog{
+    display:none;
+}
+
+#mod-quiz-edit div#randomquestiondialog_c .mform,
+#mod-quiz-edit div#repaginatedialog .mform{
+    margin-left:auto;
+    margin-right:auto;
+}
+
+#mod-quiz-edit div.container div.generalbox{
+    position:relative;
+    display:block;
+    border:0 none;
+    margin:0;
+    padding:0;
+}
+
+#mod-quiz-edit .questioncontentcontainer div.randomquestionqlist{
+    padding-left:0.2em;
+    padding-right:0.2em;
+    clear:both;
+    margin:0.5em;
+}
+
+
+#mod-quiz-edit .questioncontentcontainer div.randomquestionqlist ul{
+    list-style-type:none;
+    margin:0;
+    padding:0;
+}
+
+
+#mod-quiz-edit .reorder .questioncontentcontainer .randomquestioncategory,
+#mod-quiz-edit .reorder .questioncontentcontainer .randomquestionfromcategory,
+#mod-quiz-edit .reorder div.question div.content .questionpreview{
+    display:inline;
+    float:none;
+}
+
+#mod-quiz-edit .reorder .questioncontentcontainer{
+    position:relative;
+    overflow:hidden;
+    white-space:nowrap;
+}
+
+#mod-quiz-edit .reorder .questioncontentcontainer .randomquestioncategory{
+    overflow:hidden;
+    white-space:nowrap;
+}
+
+#mod-quiz-edit .reorder fieldset{
+    display:inline;
+}
+
+#mod-quiz-edit .questioncontentcontainer div.randomquestionqlist ul li{
+    clear:left;
+    width:100%;
+    overflow:hidden;
+    white-space:nowrap;
+}
+
+#mod-quiz-edit .questioncontentcontainer div.randomquestionqlist ul li span{
+    display:inline;
+}
+
+/*start question bank*/
+
+/*TODO: below applies to also question bank, so when
+question bank is adapted to the new UI, add the appropriate
+css id's of question bank*/
+#mod-quiz-edit .questionbankwindow .createnewquestion select,
+#mod-quiz-edit .questionbankwindow  #catmenu select{
+    width:80%;
+}
+#mod-quiz-edit table#categoryquestions{
+    width:100%;
+    overflow:hidden;
+    table-layout:fixed;
+}
+
+#mod-quiz-edit table#categoryquestions td,#mod-quiz-edit table#categoryquestions th{
+    overflow:hidden;
+    white-space:nowrap;
+}
+
+#mod-quiz-edit table#categoryquestions col#qaction{
+    width:20%;
+}
+
+#mod-quiz-edit table#categoryquestions col#qextraactions{
+    width:40px;
+}
+
+#mod-quiz-edit table#categoryquestions .iconsmall{
+    padding-left:5px;
+}
+#mod-quiz-edit .categoryinfo{
+    padding:0.3em;
+}
+
+
+
+#mod-quiz-edit .paging{
+    margin-top:0;
+    margin-bottom:0;
+    display:block;
+}
+
+#mod-quiz-edit .questionsortoptions{
+    margin-top:0.3em;
+}
+
+#mod-quiz-edit .pagingbottom{
+    padding-bottom:0.3em;
+}
+
+#mod-quiz-edit div.questionbank form .invisiblefieldset{
+    clear:both;
+}
+
+#mod-quiz-edit div.createnewquestion{
+    padding-top:0.3em;
+    clear:left;
+}
+
+#mod-quiz-edit .sideblock .content{
+    padding:0;
+}
+
+#mod-quiz-edit .questionbank .categorysortopotionscontainer{
+    padding-top:0.5em;
+    margin-top:0.3em;
+}
+
+#mod-quiz-edit .questionbank .categoryselectallcontainer{
+    padding-bottom:0.5em;
+}
+
+#mod-quiz-edit .questionbank div.categoryquestionscontainer,
+#mod-quiz-edit .questionbank .categorysortopotionscontainer,
+#mod-quiz-edit .questionbank .categorypagingbarcontainer,
+#mod-quiz-edit .questionbank .categoryselectallcontainer{
+    padding-left:0.3em;
+    padding-right:0.3em;
+}
+
+#mod-quiz-edit .noquestionsincategory{
+    clear:both;
+    padding-top:1em;
+    padding-bottom:1em;
+}
+
+#mod-quiz-edit .modulespecificbuttonscontainer{
+    padding-left:0.3em;
+    padding-right:0.3em;
+}
+
+#mod-quiz-edit div#footer{
+    clear:both;
+    padding-top:1em;
+}
+
+#mod-quiz-edit #repaginatecommand{
+    display:none;
+}
+
+/*.usejs class is added via javascript so these will toggle if js is enabled*/
+#mod-quiz-edit .usejs #repaginatedialog{
+    display:none;    
+}
+#mod-quiz-edit .usejs #repaginatedialog .hd{
+    display:block;
+}
+#mod-quiz-edit .usejs #repaginatedialog .bd{
+    padding:1em;    
+}
+#mod-quiz-edit .usejs .repaginatecommand #repaginatecommand{
+    display:block;
+}
 
 /***
  *** Modules: Resource
index 5b609f6ddb84aff870d26276f74ccb8e01842fc9..a99f3c729f7f11d96b635596d1014da6e12e154a 100644 (file)
@@ -1,6 +1,6 @@
 /*******************************************************************
  styles_moz.css
-  
+
  This CSS file uses the non-standard Mozilla CSS extensions
  to add round corners to the current theme.
 
@@ -80,7 +80,7 @@
   -moz-border-radius:3px;
 }
 
-.categorybox, .categoryboxcontent, 
+.categorybox, .categoryboxcontent,
 .coursebox {
   -moz-border-radius:10px;
 }
@@ -347,3 +347,32 @@ body#course-user .section {
 #quiznavigation .qnbutton {
   -moz-box-sizing: content-box;
 }
+#mod-quiz-edit div.quizpage .pagecontent{
+    -moz-border-radius:0.6em;
+    -moz-border-radius-bottomleft:0;
+    -moz-border-radius-topleft:0;
+}
+#mod-quiz-edit .reorder div.question div.content{
+
+    -moz-border-radius:0.3em;
+    -moz-border-radius-bottomleft:0;
+    -moz-border-radius-topleft:0;
+}
+#mod-quiz-edit div.editq div.question div.content{
+    -moz-border-radius:0.6em;
+    -moz-border-radius-bottomleft:0;
+    -moz-border-radius-topleft:0;
+}
+#mod-quiz-edit div.question div.content div.points,
+        #mod-quiz-edit div.question div.content div.qorder{
+    -moz-border-radius:0.2em;
+    -moz-border-radius-bottomleft:0;
+    -moz-border-radius-topleft:0;
+}
+#mod-quiz-edit div.quizpage .pagecontent .pagestatus{
+    -moz-border-radius-bottomright:0.3em;
+    -moz-border-radius-topright:0.3em;
+}
+#mod-quiz-edit div.quizpage .pagecontent form#addquestion{
+    -moz-border-radius:0.2em;
+}
\ No newline at end of file