Skip to content

Commit

Permalink
MDL-47368 Edit quiz: page should not reload so often
Browse files Browse the repository at this point in the history
The approach is that we have a new JavaScript function
M.mod_quiz.resource_toolbox.reorganise_edit_page which, after a ajax
action, fixes up everything like page breaks, page and question numbers,
that might now be wrong.

We call that function instead of reloading the page.

Also, there are a lot more Behat tests to verify this works correctly.

AMOS BEGIN
 MOV [joinpages,mod_quiz],[removepagebreak,mod_quiz]
 MOV [splitpages,mod_quiz],[addpagebreak,mod_quiz]
AMOS END
  • Loading branch information
Colin Chambers authored and timhunt committed Oct 28, 2014
1 parent d63a81c commit a69f81f
Show file tree
Hide file tree
Showing 25 changed files with 1,842 additions and 360 deletions.
136 changes: 111 additions & 25 deletions mod/quiz/classes/output/edit_renderer.php
Expand Up @@ -83,7 +83,8 @@ public function edit_page(\quiz $quizobj, structure $structure,
$output .= $this->end_section_list();

// Inialise the JavaScript.
$this->initialise_editing_javascript($quizobj->get_course(), $quizobj->get_quiz());
$this->initialise_editing_javascript($quizobj->get_course(), $quizobj->get_quiz(),
$structure, $contexts, $pagevars, $pageurl);

// Include the contents of any other popups required.
if ($structure->can_be_edited()) {
Expand Down Expand Up @@ -361,6 +362,38 @@ public function questions_in_section(structure $structure, $section,
public function question_row(structure $structure, $question, $contexts, $pagevars, $pageurl) {
$output = '';

$output .= $this->page_row($structure, $question, $contexts, $pagevars, $pageurl);

// Page split/join icon.
$joinhtml = '';
if ($structure->can_be_edited() && !$structure->is_last_slot_in_quiz($question->slot)) {
$joinhtml = $this->page_split_join_button($structure->get_quiz(),
$question, !$structure->is_last_slot_on_page($question->slot));
}

// Question HTML.
$questionhtml = $this->question($structure, $question, $pageurl);
$questionclasses = 'activity ' . $question->qtype . ' qtype_' . $question->qtype . ' slot';

$output .= html_writer::tag('li', $questionhtml . $joinhtml,
array('class' => $questionclasses, 'id' => 'slot-' . $question->slotid));

return $output;
}

/**
* Displays one question with the surrounding controls.
*
* @param structure $structure object containing the structure of the quiz.
* @param \stdClass $question data from the question and quiz_slots tables.
* @param \question_edit_contexts $contexts the relevant question bank contexts.
* @param array $pagevars the variables from {@link \question_edit_setup()}.
* @param \moodle_url $pageurl the canonical URL of this page.
* @return string HTML to output.
*/
public function page_row(structure $structure, $question, $contexts, $pagevars, $pageurl) {
$output = '';

// Put page in a span for easier styling.
$page = html_writer::tag('span', get_string('page') . ' ' . $question->page,
array('class' => 'text'));
Expand All @@ -378,20 +411,6 @@ public function question_row(structure $structure, $question, $contexts, $pageva
array('class' => 'pagenumber activity yui3-dd-drop page', 'id' => 'page-' . $question->page));
}

// Page split/join icon.
$joinhtml = '';
if ($structure->can_be_edited() && !$structure->is_last_slot_in_quiz($question->slot)) {
$joinhtml = $this->page_split_join_button($structure->get_quiz(),
$question, !$structure->is_last_slot_on_page($question->slot));
}

// Question HTML.
$questionhtml = $this->question($structure, $question, $pageurl);
$questionclasses = 'activity ' . $question->qtype . ' qtype_' . $question->qtype . ' slot';

$output .= html_writer::tag('li', $questionhtml . $joinhtml,
array('class' => $questionclasses, 'id' => 'slot-' . $question->slotid));

return $output;
}

Expand Down Expand Up @@ -644,22 +663,22 @@ public function question_remove_icon($question, $pageurl) {
*
* @param \stdClass $quiz the quiz settings from the database.
* @param \stdClass $question data from the question and quiz_slots tables.
* @param string $insertpagebreak if true, show an insert page break icon.
* Else show a join pages icon.
* @param bool $insertpagebreak if true, show an insert page break icon.
* else show a join pages icon.
* @return string HTML to output.
*/
public function page_split_join_button($quiz, $question, $insertpagebreak) {
$url = new \moodle_url('repaginate.php', array('cmid' => $quiz->cmid, 'quizid' => $quiz->id,
'slot' => $question->slot, 'repag' => $insertpagebreak ? 2 : 1, 'sesskey' => sesskey()));

if ($insertpagebreak) {
$title = get_string('splitpages', 'quiz');
$title = get_string('addpagebreak', 'quiz');
$image = $this->pix_icon('e/insert_page_break', $title);
$action = 'unlinkpage';
$action = 'addpagebreak';
} else {
$title = get_string('joinpages', 'quiz');
$title = get_string('removepagebreak', 'quiz');
$image = $this->pix_icon('e/remove_page_break', $title);
$action = 'linkpage';
$action = 'removepagebreak';
}

// Disable the link if quiz has attempts.
Expand All @@ -668,7 +687,7 @@ public function page_split_join_button($quiz, $question, $insertpagebreak) {
$disabled = "disabled";
}
return html_writer::span($this->action_link($url, $image, null, array('title' => $title,
'class' => 'page_split_join', 'disabled' => $disabled, 'data-action' => $action)),
'class' => 'page_split_join cm-edit-action', 'disabled' => $disabled, 'data-action' => $action)),
'page_split_join_wrapper');
}

Expand Down Expand Up @@ -837,17 +856,23 @@ protected function random_question_form(\moodle_url $thispageurl, \question_edit
*
* @param \stdClass $course the course settings from the database.
* @param \stdClass $quiz the quiz settings from the database.
* @param structure $structure object containing the structure of the quiz.
* @param \question_edit_contexts $contexts the relevant question bank contexts.
* @param array $pagevars the variables from {@link \question_edit_setup()}.
* @param \moodle_url $pageurl the canonical URL of this page.
* @return bool Always returns true
*/
protected function initialise_editing_javascript($course, $quiz) {
protected function initialise_editing_javascript($course, $quiz, structure $structure,
\question_edit_contexts $contexts, array $pagevars, \moodle_url $pageurl) {

$config = new \stdClass();
$config->resourceurl = '/mod/quiz/edit_rest.php';
$config->sectionurl = '/mod/quiz/edit_rest.php';
$config->pageparams = array();
$config->questiondecimalpoints = $quiz->questiondecimalpoints;
$config->pagehtml = $this->new_page_template($structure, $contexts, $pagevars, $pageurl);
$config->addpageiconhtml = $this->add_page_icon_template($structure, $quiz);

// Include toolboxes.
$this->page->requires->yui_module('moodle-mod_quiz-toolboxes',
'M.mod_quiz.init_resource_toolbox',
array(array(
Expand All @@ -857,6 +882,9 @@ protected function initialise_editing_javascript($course, $quiz) {
'config' => $config,
))
);
unset($config->pagehtml);
unset($config->addpageiconhtml);

$this->page->requires->yui_module('moodle-mod_quiz-toolboxes',
'M.mod_quiz.init_section_toolbox',
array(array(
Expand All @@ -868,7 +896,6 @@ protected function initialise_editing_javascript($course, $quiz) {
))
);

// Include course dragdrop.
$this->page->requires->yui_module('moodle-mod_quiz-dragdrop', 'M.mod_quiz.init_section_dragdrop',
array(array(
'courseid' => $course->id,
Expand Down Expand Up @@ -900,15 +927,19 @@ protected function initialise_editing_javascript($course, $quiz) {
'movecontent',
'moveleft',
'movesection',
'page',
'question',
'selectall',
'show',
'tocontent',
), 'moodle');

$this->page->requires->strings_for_js(array(
'addpagebreak',
'confirmremovequestion',
'dragtoafter',
'dragtostart',
'removepagebreak',
), 'quiz');

foreach (\question_bank::get_all_qtypes() as $qtype => $notused) {
Expand All @@ -918,6 +949,61 @@ protected function initialise_editing_javascript($course, $quiz) {
return true;
}

/**
* HTML for a page, with ids stripped, so it can be used as a javascript template.
*
* @param structure $structure object containing the structure of the quiz.
* @param \question_edit_contexts $contexts the relevant question bank contexts.
* @param array $pagevars the variables from {@link \question_edit_setup()}.
* @param \moodle_url $pageurl the canonical URL of this page.
* @return string HTML for a new page.
*/
protected function new_page_template(structure $structure,
\question_edit_contexts $contexts, array $pagevars, \moodle_url $pageurl) {
if (!$structure->has_questions()) {
return '';
}

$question = $structure->get_question_in_slot(1);
$pagehtml = $this->page_row($structure, $question, $contexts, $pagevars, $pageurl);

// Normalise the page number.
$pagenumber = $question->page;
$strcontexts = array();
$strcontexts[] = 'page-';
$strcontexts[] = get_string('page') . ' ';
$strcontexts[] = 'addonpage%3D';
$strcontexts[] = 'addonpage=';
$strcontexts[] = 'addonpage="';
$strcontexts[] = get_string('addquestionfrombanktopage', 'quiz', '');
$strcontexts[] = 'data-addonpage%3D';
$strcontexts[] = 'action-menu-';

foreach ($strcontexts as $strcontext) {
$pagehtml = str_replace($strcontext . $pagenumber, $strcontext . '%%PAGENUMBER%%', $pagehtml);
}

return $pagehtml;
}

/**
* HTML for a page, with ids stripped, so it can be used as a javascript template.
*
* @param structure $structure object containing the structure of the quiz.
* @param \stdClass $quiz the quiz settings.
* @return string HTML for a new icon
*/
protected function add_page_icon_template(structure $structure, $quiz) {

if (!$structure->has_questions()) {
return '';
}

$question = $structure->get_question_in_slot(1);
$html = $this->page_split_join_button($quiz, $question, true);
return str_replace('&slot=1&', '&slot=%%SLOT%%&', $html);
}

/**
* Return the contents of the question bank, to be displayed in the question-bank pop-up.
*
Expand Down
5 changes: 3 additions & 2 deletions mod/quiz/edit_rest.php
Expand Up @@ -105,7 +105,7 @@
echo json_encode(array('instancemaxmark' => quiz_format_question_grade($quiz, $maxmark),
'newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades)));
break;
case 'linkslottopage':
case 'updatepagebreak':
require_capability('mod/quiz:manage', $modcontext);
$slots = $structure->update_page_break($quiz, $id, $value);
$json = array();
Expand Down Expand Up @@ -133,7 +133,8 @@
$structure->remove_slot($quiz, $slot->slot);
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
echo json_encode(array('newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades)));
echo json_encode(array('newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades),
'deleted' => true));
break;
}
break;
Expand Down
6 changes: 3 additions & 3 deletions mod/quiz/lang/en/quiz.php
Expand Up @@ -41,6 +41,7 @@
$string['addnewpagesafterselected'] = 'Add new pages after selected questions';
$string['addnewquestionsqbank'] = 'Add questions to the category {$a->catname}: {$a->link}';
$string['addnewuseroverride'] = 'Add user override';
$string['addpagebreak'] = 'Add page break';
$string['addpagehere'] = 'Add page here';
$string['addquestion'] = 'Add question';
$string['addquestionfrombanktopage'] = 'Add from the question bank to page {$a}';
Expand Down Expand Up @@ -431,7 +432,6 @@
$string['invalidsource'] = 'The source is not accepted as valid.';
$string['invalidsourcetype'] = 'Invalid source type.';
$string['invalidstateid'] = 'Invalid state id';
$string['joinpages'] = 'Remove page break';
$string['lastanswer'] = 'Your last answer was';
$string['layout'] = 'Layout';
$string['layoutasshown'] = 'Page layout as shown.';
Expand Down Expand Up @@ -694,6 +694,7 @@
$string['remove'] = 'Remove';
$string['removeallquizattempts'] = 'Delete all quiz attempts';
$string['removeemptypage'] = 'Remove empty page';
$string['removepagebreak'] = 'Remove page break';
$string['removeselected'] = 'Remove selected';
$string['rename'] = 'Rename';
$string['renderingserverconnectfailed'] = 'The server {$a} failed to process an RQP request. Check that the URL is correct.';
Expand Down Expand Up @@ -833,7 +834,6 @@
$string['sorttypealpha'] = 'Sort by type, name';
$string['specificapathnotonquestion'] = 'The specified file path is not on the specified question';
$string['specificquestionnotonquiz'] = 'Specified question is not on the specified quiz';
$string['splitpages'] = 'Add page break';
$string['startagain'] = 'Start again';
$string['startattempt'] = 'Start attempt';
$string['startedon'] = 'Started on';
Expand Down Expand Up @@ -912,7 +912,7 @@
$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}.';

// Deprecated since Moodle 2.8
// Deprecated since Moodle 2.8.

$string['categories'] = 'Categories';
$string['category'] = 'Category';
Expand Down

0 comments on commit a69f81f

Please sign in to comment.