MDL-48771 quiz edit: delete mulitiple tidy up & Behat tests

This commit is contained in:
Colin Chambers 2017-02-02 14:36:34 +00:00 committed by Tim Hunt
parent 5d803e5395
commit f37cffb6a5
14 changed files with 746 additions and 334 deletions

View File

@ -59,26 +59,24 @@ class edit_renderer extends \plugin_renderer_base {
// Information at the top.
$output .= $this->quiz_state_warnings($structure);
$output .= html_writer::start_div('mod_quiz-edit-top-controls');
$output .= $this->quiz_information($structure);
$output .= $this->maximum_grade_input($structure, $pageurl);
$output .= html_writer::start_div('mod_quiz-edit-action-buttons btn-group edit-toolbar', ['role' => 'group']);
$output .= $this->repaginate_button($structure, $pageurl);
$output .= $this->bulkaction_button($structure);
$output .= $this->selectmultiple_button($structure);
$output .= html_writer::end_tag('div');
$output .= $this->total_marks($quizobj->get_quiz());
$output .= $this->selectmultiple_controls($structure);
$output .= html_writer::end_tag('div');
// Show the questions organised into sections and pages.
$output .= $this->start_section_list($structure);
// Bulk action button delete and bulk action button cancel.
$output .= html_writer::tag('div', html_writer::empty_tag('input', array('type' => 'button',
'id' => 'bulkactionsdeletecommand', 'value' => get_string('delete', 'moodle'))) . " " .
html_writer::empty_tag('input', array('type' => 'button', 'id' => 'bulkactionscancelcommand',
'value' => get_string('cancel', 'moodle'))), array('class' => 'bulkactioncommand actions'));
// Select all/deselect all questions.
$output .= html_writer::tag('div', html_writer::link('#', get_string('selectall', 'quiz'),
array('id' => 'questionselectall')) . " / " . html_writer::link('#', get_string('selectnone', 'quiz'),
array('id' => 'questiondeselectall')), array('class' => 'bulkactioncommandbuttons'));
foreach ($structure->get_sections() as $section) {
$output .= $this->start_section($structure, $section);
$output .= $this->questions_in_section($structure, $section, $contexts, $pagevars, $pageurl);
@ -199,12 +197,6 @@ class edit_renderer extends \plugin_renderer_base {
$header = html_writer::tag('span', get_string('repaginatecommand', 'quiz'), array('class' => 'repaginatecommand'));
$form = $this->repaginate_form($structure, $pageurl);
$containeroptions = array(
'class' => 'rpcontainerclass',
'cmid' => $structure->get_cmid(),
'header' => $header,
'form' => $form,
);
$buttonoptions = array(
'type' => 'submit',
@ -212,6 +204,8 @@ class edit_renderer extends \plugin_renderer_base {
'id' => 'repaginatecommand',
'value' => get_string('repaginatecommand', 'quiz'),
'class' => 'btn btn-secondary m-b-1',
'data-header' => $header,
'data-form' => $form,
);
if (!$structure->can_be_repaginated()) {
$buttonoptions['disabled'] = 'disabled';
@ -219,26 +213,89 @@ class edit_renderer extends \plugin_renderer_base {
$this->page->requires->yui_module('moodle-mod_quiz-repaginate', 'M.mod_quiz.repaginate.init');
}
return html_writer::start_tag('div', $containeroptions) .
html_writer::empty_tag('input', $buttonoptions);
return html_writer::empty_tag('input', $buttonoptions);
}
/**
* Generate the bulk action button
* Generate the bulk action button.
*
* @param structure $structure the structure of the quiz being edited.
* @return string HTML to output.
*/
protected function bulkaction_button(structure $structure) {
protected function selectmultiple_button(structure $structure) {
$buttonoptions = array(
'type' => 'button',
'name' => 'repaginate',
'id' => 'bulkactionscommand',
'value' => get_string('bulkactions', 'quiz'),
'name' => 'selectmultiple',
'id' => 'selectmultiplecommand',
'value' => get_string('selectmultipleitems', 'quiz'),
'class' => 'btn btn-secondary m-b-1'
);
if (!$structure->can_be_repaginated()) {
if (!$structure->can_be_edited()) {
$buttonoptions['disabled'] = 'disabled';
}
return html_writer::empty_tag('input', $buttonoptions) . html_writer::end_tag('div');
return html_writer::tag('button', get_string('selectmultipleitems', 'quiz'), $buttonoptions);
}
/**
* Generate the controls that appear when the bulk action button is pressed.
*
* @param structure $structure the structure of the quiz being edited.
* @return string HTML to output.
*/
protected function selectmultiple_controls(structure $structure) {
$output = '';
// Bulk action button delete and bulk action button cancel.
$buttondeleteoptions = array(
'type' => 'button',
'id' => 'selectmultipledeletecommand',
'value' => get_string('deleteselected', 'mod_quiz'),
'class' => 'btn btn-secondary'
);
$buttoncanceloptions = array(
'type' => 'button',
'id' => 'selectmultiplecancelcommand',
'value' => get_string('cancel', 'moodle'),
'class' => 'btn btn-secondary'
);
$groupoptions = array(
'class' => 'btn-group selectmultiplecommand actions',
'role' => 'group'
);
$output .= html_writer::tag('div',
html_writer::tag('button', get_string('deleteselected', 'mod_quiz'), $buttondeleteoptions) .
" " .
html_writer::tag('button', get_string('cancel', 'moodle'),
$buttoncanceloptions), $groupoptions);
$toolbaroptions = array(
'class' => 'btn-toolbar',
'role' => 'toolbar',
'aria-label' => get_string('selectmultipletoolbar', 'quiz'),
);
// Select all/deselect all questions.
$buttonselectalloptions = array(
'role' => 'button',
'id' => 'questionselectall',
'class' => 'btn btn-link'
);
$buttondeselectalloptions = array(
'role' => 'button',
'id' => 'questiondeselectall',
'class' => 'btn btn-link'
);
$output .= html_writer::tag('div',
html_writer::tag('div',
html_writer::link('#', get_string('selectall', 'quiz'), $buttonselectalloptions) .
html_writer::tag('span', "/", ['class' => 'separator']) .
html_writer::link('#', get_string('selectnone', 'quiz'), $buttondeselectalloptions),
array('class' => 'btn-group selectmultiplecommandbuttons')),
$toolbaroptions);
return $output;
}
/**
@ -672,7 +729,7 @@ class edit_renderer extends \plugin_renderer_base {
$output .= html_writer::start_div('mod-indent-outer');
$output .= html_writer::tag('input', '', array('id' => 'selectquestion-' .
$structure->get_displayed_number_for_slot($slot), 'name' => 'selectquestion[]',
'type' => 'checkbox', 'class' => 'quiz-question-bulk-selector',
'type' => 'checkbox', 'class' => 'select-multiple-checkbox',
'value' => $structure->get_displayed_number_for_slot($slot)));
$output .= $this->question_number($structure->get_displayed_number_for_slot($slot));

View File

@ -47,7 +47,7 @@ $maxmark = optional_param('maxmark', '', PARAM_FLOAT);
$newheading = optional_param('newheading', '', PARAM_TEXT);
$shuffle = optional_param('newshuffle', 0, PARAM_INT);
$page = optional_param('page', '', PARAM_INT);
$bulkslots = optional_param('slots', '', PARAM_SEQUENCE);
$ids = optional_param('ids', '', PARAM_SEQUENCE);
$PAGE->set_url('/mod/quiz/edit-rest.php',
array('quizid' => $quizid, 'class' => $class));
@ -63,6 +63,9 @@ $modcontext = context_module::instance($cm->id);
echo $OUTPUT->header(); // Send headers.
// All these AJAX actions should be logically atomic.
$transaction = $DB->start_delegated_transaction();
// OK, now let's process the parameters and do stuff
// MDL-10221 the DELETE method is not allowed on some web servers,
// so we simulate it with the action URL param.
@ -71,6 +74,8 @@ if ($pageaction == 'DELETE') {
$requestmethod = 'DELETE';
}
$result = null;
switch($requestmethod) {
case 'POST':
case 'GET': // For debugging.
@ -81,17 +86,17 @@ switch($requestmethod) {
switch ($field) {
case 'getsectiontitle':
require_capability('mod/quiz:manage', $modcontext);
echo json_encode(array('instancesection' => $section->heading));
$result = array('instancesection' => $section->heading);
break;
case 'updatesectiontitle':
require_capability('mod/quiz:manage', $modcontext);
$structure->set_section_heading($id, $newheading);
echo json_encode(array('instancesection' => format_string($newheading)));
$result = array('instancesection' => format_string($newheading));
break;
case 'updateshufflequestions':
require_capability('mod/quiz:manage', $modcontext);
$structure->set_section_shuffle($id, $shuffle);
echo json_encode(array('instanceshuffle' => $section->shufflequestions));
$result = array('instanceshuffle' => $section->shufflequestions);
break;
}
break;
@ -109,14 +114,13 @@ switch($requestmethod) {
}
$structure->move_slot($id, $previousid, $page);
quiz_delete_previews($quiz);
echo json_encode(array('visible' => true));
$result = array('visible' => true);
break;
case 'getmaxmark':
require_capability('mod/quiz:manage', $modcontext);
$slot = $DB->get_record('quiz_slots', array('id' => $id), '*', MUST_EXIST);
echo json_encode(array('instancemaxmark' =>
quiz_format_question_grade($quiz, $slot->maxmark)));
$result = array('instancemaxmark' => quiz_format_question_grade($quiz, $slot->maxmark));
break;
case 'updatemaxmark':
@ -130,8 +134,8 @@ switch($requestmethod) {
quiz_update_all_final_grades($quiz);
quiz_update_grades($quiz, 0, true);
}
echo json_encode(array('instancemaxmark' => quiz_format_question_grade($quiz, $maxmark),
'newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades)));
$result = array('instancemaxmark' => quiz_format_question_grade($quiz, $maxmark),
'newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades));
break;
case 'updatepagebreak':
@ -142,24 +146,25 @@ switch($requestmethod) {
$json[$slot->slot] = array('id' => $slot->id, 'slot' => $slot->slot,
'page' => $slot->page);
}
echo json_encode(array('slots' => $json));
$result = array('slots' => $json);
break;
case 'bulkdelete':
case 'deletemultiple':
require_capability('mod/quiz:manage', $modcontext);
$bulkslots = explode(',', $bulkslots);
rsort($bulkslots); // Work backwards, since removing a question renumbers following slots.
foreach ($bulkslots as $slot) {
if (quiz_has_question_use($quiz, $slot)) {
$structure->remove_slot($slot);
$ids = explode(',', $ids);
foreach ($ids as $id) {
$slot = $DB->get_record('quiz_slots', array('quizid' => $quiz->id, 'id' => $id),
'*', MUST_EXIST);
if (quiz_has_question_use($quiz, $slot->slot)) {
$structure->remove_slot($slot->slot);
}
}
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
echo json_encode(array('deleted' => true));
$result = array('newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades),
'deleted' => true, 'newnumquestions' => $structure->get_question_count());
break;
case 'updatedependency':
@ -167,7 +172,7 @@ switch($requestmethod) {
$slot = $structure->get_slot_by_id($id);
$value = (bool) $value;
$structure->update_question_dependency($slot->id, $value);
echo json_encode(array('requireprevious' => $value));
$result = array('requireprevious' => $value);
break;
}
break;
@ -179,7 +184,7 @@ switch($requestmethod) {
case 'section':
require_capability('mod/quiz:manage', $modcontext);
$structure->remove_section_heading($id);
echo json_encode(array('deleted' => true));
$result = array('deleted' => true);
break;
case 'resource':
@ -190,9 +195,12 @@ switch($requestmethod) {
$structure->remove_slot($slot->slot);
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
echo json_encode(array('newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades),
'deleted' => true, 'newnumquestions' => $structure->get_question_count()));
$result = array('newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades),
'deleted' => true, 'newnumquestions' => $structure->get_question_count());
break;
}
break;
}
$transaction->allow_commit();
echo json_encode($result);

View File

@ -121,7 +121,6 @@ $string['browsersecurity_help'] = 'If "Full screen pop-up with some JavaScript s
* The quiz will only start if the student has a JavaScript-enabled web-browser
* The quiz appears in a full screen popup window that covers all the other windows and has no navigation controls
* Students are prevented, as far as is possible, from using facilities like copy and paste';
$string['bulkactions'] = 'Bulk actions';
$string['calculated'] = 'Calculated';
$string['calculatedquestion'] = 'Calculated question not supported at line {$a}. The question will be ignored';
$string['cannotcreatepath'] = 'Path cannot be created ({$a})';
@ -817,6 +816,8 @@ $string['select'] = 'Select';
$string['selectall'] = 'Select all';
$string['selectcategory'] = 'Select category';
$string['selectedattempts'] = 'Selected attempts...';
$string['selectmultipleitems'] = 'Select multiple items';
$string['selectmultipletoolbar'] = 'Select multiple toolbar';
$string['selectnone'] = 'Deselect all';
$string['selectquestiontype'] = '-- Select question type --';
$string['serveradded'] = 'Server added';

View File

@ -633,10 +633,18 @@ table.quizreviewsummary td.cell {
margin: 4px 0;
}
#page-mod-quiz-edit .mod_quiz-edit-top-controls {
position: relative;
}
#page-mod-quiz-edit .mod_quiz-edit-action-buttons {
display: block;
min-height: 2.85em;
}
#page-mod-quiz-edit .maxgrade,
#page-mod-quiz-edit .totalpoints {
display: block;
float: right;
position: absolute;
right: 0;
margin: -2.85em 0 0;
padding: .2em;
}
@ -644,6 +652,9 @@ table.quizreviewsummary td.cell {
#page-mod-quiz-edit .maxgrade label {
display: inline;
}
#page-mod-quiz-edit .maxgrade input[type="submit"] {
margin: 0;
}
#page-mod-quiz-edit li.activity > div,
#page-mod-quiz-edit li.pagenumber {
@ -879,6 +890,10 @@ table.quizreviewsummary td.cell {
width: 100%;
}
#page-mod-quiz-edit ul.slots li.section li.activity .mod-indent-outer {
padding-left: 22px;
}
#page-mod-quiz-edit ul.slots .activityinstance form {
display: inline;
}
@ -1115,58 +1130,72 @@ table#categoryquestions {
/* Bulk edit actions */
.bulkactioncommandbuttons {
.selectmultiplecommandbuttons {
margin: 0.6em 0.4em;
}
.bulkactioncommand,
.bulkactioncommandbuttons,
.quiz-question-bulk-selector {
.btn-group.selectmultiplecommand,
.btn-group.selectmultiplecommandbuttons,
.select-multiple-checkbox {
display: none;
}
body.quiz-bulk-action-mode .bulkactioncommand,
body.quiz-bulk-action-mode .bulkactioncommandbuttons,
body.quiz-bulk-action-mode .quiz-question-bulk-selector {
#page-mod-quiz-edit.select-multiple .selectmultiplecommand,
#page-mod-quiz-edit.select-multiple .selectmultiplecommandbuttons,
#page-mod-quiz-edit.select-multiple .select-multiple-checkbox {
display: inherit;
}
body.quiz-bulk-action-mode input.quiz-question-bulk-selector[type="checkbox"] {
#page-mod-quiz-edit.select-multiple .selectmultiplecommandbuttons .separator {
position: relative;
float: left;
padding: .5rem 0;
}
#page-mod-quiz-edit #questionselectall {
padding-right: .1rem;
}
#page-mod-quiz-edit #questiondeselectall {
padding-left: .1rem;
}
#page-mod-quiz-edit.select-multiple input.select-multiple-checkbox[type="checkbox"] {
display: inline;
}
body.quiz-bulk-action-mode .mod-quiz-edit-content .section .activity .editing_move,
body.quiz-bulk-action-mode .mod-quiz-edit-content .section .activity .commands {
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section .activity .editing_move,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section .activity .commands {
display: none;
}
body.quiz-bulk-action-mode .mod-quiz-edit-content .section .page_split_join_wrapper {
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section .page_split_join_wrapper {
display: none;
}
body.quiz-bulk-action-mode .mod-quiz-edit-content .section .activity .actions {
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section .activity .actions .editing_delete,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section .activity .actions .editing_maxmark {
display: none;
}
body.quiz-bulk-action-mode#page-mod-quiz-edit .maxgrade,
body.quiz-bulk-action-mode#page-mod-quiz-edit .totalpoints,
body.quiz-bulk-action-mode .mod-quiz-edit-content .last-add-menu {
#page-mod-quiz-edit.select-multiple#page-mod-quiz-edit .maxgrade,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .last-add-menu {
display: none;
}
body.quiz-bulk-action-mode .mod-quiz-edit-content .section-heading,
body.quiz-bulk-action-mode .mod-quiz-edit-content .section-heading form,
body.quiz-bulk-action-mode .mod-quiz-edit-content .section-heading .instancesectioncontainer,
body.quiz-bulk-action-mode .mod-quiz-edit-content .section-heading .instanceshufflequestions,
body.quiz-bulk-action-mode .mod-quiz-edit-content .section-heading .instancesectioncontainer h3 {
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading form,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading .instancesectioncontainer,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading .instanceshufflequestions,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading .instancesectioncontainer h3 {
display: none;
}
body.quiz-bulk-action-mode .mod-quiz-edit-content .rpcontainerclass {
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .edit-toolbar .m-b-1 {
display: none;
}
body.quiz-bulk-action-mode#page-mod-quiz-edit ul.slots li.section li.activity .mod-indent-outer {
#page-mod-quiz-edit.select-multiple#page-mod-quiz-edit ul.slots li.section li.activity .mod-indent-outer {
padding-left: 3px;
}
@ -1236,18 +1265,3 @@ body.quiz-bulk-action-mode#page-mod-quiz-edit ul.slots li.section li.activity .m
page-break-inside: avoid;
}
}
/* Ajustments for mobile devices */
@media only screen and (max-width: 565px) {
#page-mod-quiz-edit .rpcontainerclass {
margin-top: 3em;
}
#page-mod-quiz-edit .maxgrade {
margin-top: 0.1em;
}
#page-mod-quiz-edit .statusbar {
padding: 0;
}
}

View File

@ -0,0 +1,170 @@
@mod @mod_quiz
Feature: Edit quiz page - remove multiple questions
In order to change the layout of a quiz I built efficiently
As a teacher
I need to be able to delete many questions questions.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | T1 | Teacher1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "activities" exist:
| activity | name | course | idnumber |
| quiz | Quiz 1 | C1 | quiz1 |
And I log in as "teacher1"
And I follow "Course 1"
And I follow "Quiz 1"
@javascript
Scenario: Delete selected question using select multiple items feature.
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | Question A | This is question 01 |
| Test questions | truefalse | Question B | This is question 02 |
| Test questions | truefalse | Question C | This is question 03 |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Question A | 1 |
| Question B | 1 |
| Question C | 2 |
And I navigate to "Edit quiz" in current page administration
# Confirm the starting point.
Then I should see "Question A" on quiz page "1"
And I should see "Question B" on quiz page "1"
And I should see "Question C" on quiz page "2"
And I should see "Total of marks: 3.00"
And I should see "Questions: 3"
And I should see "This quiz is open"
# Delete last question in last page. Page contains multiple questions. No reordering.
When I click on "Select multiple items" "button"
Then I click on "selectquestion-3" "checkbox"
And I click on "Delete selected" "button"
And I click on "Yes" "button" in the "Confirm" "dialogue"
Then I should see "Question A" on quiz page "1"
And I should see "Question B" on quiz page "1"
And I should not see "Question C" on quiz page "2"
And I should see "Total of marks: 2.00"
And I should see "Questions: 2"
@javascript
Scenario: Delete first selected question using select multiple items feature.
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | Question A | This is question 01 |
| Test questions | truefalse | Question B | This is question 02 |
| Test questions | truefalse | Question C | This is question 03 |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Question A | 1 |
| Question B | 2 |
| Question C | 2 |
And I navigate to "Edit quiz" in current page administration
# Confirm the starting point.
Then I should see "Question A" on quiz page "1"
And I should see "Question B" on quiz page "2"
And I should see "Question C" on quiz page "2"
And I should see "Total of marks: 3.00"
And I should see "Questions: 3"
And I should see "This quiz is open"
# Delete first question in first page. Page contains multiple questions. No reordering.
When I click on "Select multiple items" "button"
Then I click on "selectquestion-1" "checkbox"
And I click on "Delete selected" "button"
And I click on "Yes" "button" in the "Confirm" "dialogue"
Then I should not see "Question A" on quiz page "1"
And I should see "Question B" on quiz page "1"
And I should see "Question C" on quiz page "1"
And I should see "Total of marks: 2.00"
And I should see "Questions: 2"
@javascript
Scenario: Can delete the last question in a quiz.
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | Question A | This is question 01 |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Question A | 1 |
When I navigate to "Edit quiz" in current page administration
And I click on "Select multiple items" "button"
And I click on "selectquestion-1" "checkbox"
And I click on "Delete selected" "button"
And I click on "Yes" "button" in the "Confirm" "dialogue"
Then I should see "Questions: 0"
@javascript
Scenario: Delete all questions by checking select all.
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | Question A | This is question 01 |
| Test questions | truefalse | Question B | This is question 02 |
| Test questions | truefalse | Question C | This is question 03 |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Question A | 1 |
| Question B | 1 |
| Question C | 2 |
And I navigate to "Edit quiz" in current page administration
# Confirm the starting point.
Then I should see "Question A" on quiz page "1"
And I should see "Question B" on quiz page "1"
And I should see "Question C" on quiz page "2"
And I should see "Total of marks: 3.00"
And I should see "Questions: 3"
And I should see "This quiz is open"
# Delete all questions in page. Page contains multiple questions
When I click on "Select multiple items" "button"
Then I click on "Select all" "link"
And I click on "Delete selected" "button"
And I click on "Yes" "button" in the "Confirm" "dialogue"
Then I should not see "Question A" on quiz page "1"
And I should not see "Question B" on quiz page "1"
And I should not see "Question C" on quiz page "2"
And I should see "Total of marks: 0.00"
And I should see "Questions: 0"
@javascript
Scenario: Deselect all questions by checking deselect all.
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | Question A | This is question 01 |
| Test questions | truefalse | Question B | This is question 02 |
| Test questions | truefalse | Question C | This is question 03 |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Question A | 1 |
| Question B | 1 |
| Question C | 2 |
And I navigate to "Edit quiz" in current page administration
# Confirm the starting point.
Then I should see "Question A" on quiz page "1"
And I should see "Question B" on quiz page "1"
And I should see "Question C" on quiz page "2"
# Delete last question in last page. Page contains multiple questions
When I click on "Select multiple items" "button"
And I click on "Select all" "link"
Then the field "selectquestion-3" matches value "1"
When I click on "Deselect all" "link"
Then the field "selectquestion-3" matches value "0"

View File

@ -25,7 +25,6 @@ YUI.add('moodle-mod_quiz-repaginate', function (Y, NAME) {
*/
var CSS = {
REPAGINATECONTAINERCLASS: '.rpcontainerclass',
REPAGINATECOMMAND: '#repaginatecommand'
};
@ -44,12 +43,12 @@ Y.extend(POPUP, Y.Base, {
body: null,
initializer: function() {
var rpcontainerclass = Y.one(CSS.REPAGINATECONTAINERCLASS);
var repaginatebutton = Y.one(CSS.REPAGINATECOMMAND);
// Set popup header and body.
this.header = rpcontainerclass.getAttribute(PARAMS.HEADER);
this.body = rpcontainerclass.getAttribute(PARAMS.FORM);
Y.one(CSS.REPAGINATECOMMAND).on('click', this.display_dialog, this);
this.header = repaginatebutton.getData(PARAMS.HEADER);
this.body = repaginatebutton.getData(PARAMS.FORM);
repaginatebutton.on('click', this.display_dialog, this);
},
display_dialog: function(e) {

View File

@ -1 +1 @@
YUI.add("moodle-mod_quiz-repaginate",function(e,t){var n={REPAGINATECONTAINERCLASS:".rpcontainerclass",REPAGINATECOMMAND:"#repaginatecommand"},r={CMID:"cmid",HEADER:"header",FORM:"form"},i=function(){i.superclass.constructor.apply(this,arguments)};e.extend(i,e.Base,{header:null,body:null,initializer:function(){var t=e.one(n.REPAGINATECONTAINERCLASS);this.header=t.getAttribute(r.HEADER),this.body=t.getAttribute(r.FORM),e.one(n.REPAGINATECOMMAND).on("click",this.display_dialog,this)},display_dialog:function(e){e.preventDefault();var t={headerContent:this.header,bodyContent:this.body,draggable:!0,modal:!0,zIndex:1e3,context:[n.REPAGINATECOMMAND,"tr","br",["beforeShow"]],centered:!1,width:"30em",visible:!1,postmethod:"form",footerContent:null},r={dialog:null};r.dialog=new M.core.dialogue(t),r.dialog.show()}}),M.mod_quiz=M.mod_quiz||{},M.mod_quiz.repaginate=M.mod_quiz.repaginate||{},M.mod_quiz.repaginate.init=function(){return new i}},"@VERSION@",{requires:["base","event","node","io","moodle-core-notification-dialogue"]});
YUI.add("moodle-mod_quiz-repaginate",function(e,t){var n={REPAGINATECOMMAND:"#repaginatecommand"},r={CMID:"cmid",HEADER:"header",FORM:"form"},i=function(){i.superclass.constructor.apply(this,arguments)};e.extend(i,e.Base,{header:null,body:null,initializer:function(){var t=e.one(n.REPAGINATECOMMAND);this.header=t.getData(r.HEADER),this.body=t.getData(r.FORM),t.on("click",this.display_dialog,this)},display_dialog:function(e){e.preventDefault();var t={headerContent:this.header,bodyContent:this.body,draggable:!0,modal:!0,zIndex:1e3,context:[n.REPAGINATECOMMAND,"tr","br",["beforeShow"]],centered:!1,width:"30em",visible:!1,postmethod:"form",footerContent:null},r={dialog:null};r.dialog=new M.core.dialogue(t),r.dialog.show()}}),M.mod_quiz=M.mod_quiz||{},M.mod_quiz.repaginate=M.mod_quiz.repaginate||{},M.mod_quiz.repaginate.init=function(){return new i}},"@VERSION@",{requires:["base","event","node","io","moodle-core-notification-dialogue"]});

View File

@ -25,7 +25,6 @@ YUI.add('moodle-mod_quiz-repaginate', function (Y, NAME) {
*/
var CSS = {
REPAGINATECONTAINERCLASS: '.rpcontainerclass',
REPAGINATECOMMAND: '#repaginatecommand'
};
@ -44,12 +43,12 @@ Y.extend(POPUP, Y.Base, {
body: null,
initializer: function() {
var rpcontainerclass = Y.one(CSS.REPAGINATECONTAINERCLASS);
var repaginatebutton = Y.one(CSS.REPAGINATECOMMAND);
// Set popup header and body.
this.header = rpcontainerclass.getAttribute(PARAMS.HEADER);
this.body = rpcontainerclass.getAttribute(PARAMS.FORM);
Y.one(CSS.REPAGINATECOMMAND).on('click', this.display_dialog, this);
this.header = repaginatebutton.getData(PARAMS.HEADER);
this.body = repaginatebutton.getData(PARAMS.FORM);
repaginatebutton.on('click', this.display_dialog, this);
},
display_dialog: function(e) {

View File

@ -28,6 +28,7 @@ var CSS = {
PAGE: 'page',
SECTIONHIDDENCLASS: 'hidden',
SECTIONIDPREFIX: 'section-',
SELECTMULTIPLE: 'select-multiple',
SLOT: 'slot',
SHOW: 'editing_show',
TITLEEDITOR: 'titleeditor'
@ -45,7 +46,8 @@ var CSS = {
COMMANDSPAN: '.commands',
CONTENTAFTERLINK: 'div.contentafterlink',
CONTENTWITHOUTLINK: 'div.contentwithoutlink',
DELETESECTIONICON: 'a.editing_delete .icon',
DELETESECTIONICON: 'a.editing_delete img',
DESELECTALL: '#questiondeselectall',
EDITMAXMARK: 'a.editing_maxmark',
EDITSECTION: 'a.editing_section',
EDITSECTIONICON: 'a.editing_section .icon',
@ -65,6 +67,11 @@ var CSS = {
SECTIONUL: 'ul.section',
SECTIONFORM: '.instancesectioncontainer form',
SECTIONINPUT: 'input[name=section]',
SELECTMULTIPLEBUTTON: '#selectmultiplecommand',
SELECTMULTIPLECANCELBUTTON: '#selectmultiplecancelcommand',
SELECTMULTIPLECHECKBOX: '.select-multiple-checkbox',
SELECTMULTIPLEDELETEBUTTON: '#selectmultipledeletecommand',
SELECTALL: '#questionselectall',
SHOW: 'a.' + CSS.SHOW,
SLOTLI: 'li.slot',
SUMMARKS: '.mod_quiz_summarks'
@ -103,6 +110,7 @@ Y.extend(TOOLBOX, Y.Base, {
if (!data) {
data = {};
}
// Handle any variables which we must pass back through to
var pageparams = this.get('config').pageparams,
varname;
@ -289,6 +297,52 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
M.mod_quiz.quizbase.register_module(this);
Y.delegate('click', this.handle_data_action, BODY, SELECTOR.ACTIVITYACTION, this);
Y.delegate('click', this.handle_data_action, BODY, SELECTOR.DEPENDENCY_LINK, this);
this.initialise_select_multiple();
},
/**
* Initialize the select multiple options
*
* Add actions to the buttons that enable multiple slots to be selected and managed at once.
*
* @method initialise_select_multiple
* @protected
*/
initialise_select_multiple: function() {
// Click select multiple button to show the select all options.
Y.one(SELECTOR.SELECTMULTIPLEBUTTON).on('click', function(e) {
e.preventDefault();
Y.one('body').addClass(CSS.SELECTMULTIPLE);
});
// Click cancel button to show the select all options.
Y.one(SELECTOR.SELECTMULTIPLECANCELBUTTON).on('click', function(e) {
e.preventDefault();
Y.one('body').removeClass(CSS.SELECTMULTIPLE);
});
// Click select all link to check all the checkboxes.
Y.one(SELECTOR.SELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX).set('checked', 'checked');
});
// Click deselect all link to show the select all checkboxes.
Y.one(SELECTOR.DESELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX).set('checked', '');
});
// Disable delete multiple button by default.
Y.one(SELECTOR.SELECTMULTIPLEDELETEBUTTON).setAttribute('disabled', 'disabled');
// Assign the delete method to the delete multiple button.
Y.delegate('click', this.delete_multiple_with_confirmation, BODY, SELECTOR.SELECTMULTIPLEDELETEBUTTON, this);
// Enable the delete all button only when at least one slot is selected.
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.SELECTMULTIPLECHECKBOX, this);
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.SELECTALL, this);
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.DESELECTALL, this);
},
/**
@ -361,6 +415,22 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
return null;
},
/**
* If a select multiple checkbox is checked enable the buttons in the select multiple
* toolbar otherwise disable it.
*
* @method toggle_select_all_buttons_enabled
*/
toggle_select_all_buttons_enabled: function() {
var checked = Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked');
var deletebutton = Y.one(SELECTOR.SELECTMULTIPLEDELETEBUTTON);
if (checked && !checked.isEmpty()) {
deletebutton.removeAttribute('disabled');
} else {
deletebutton.setAttribute('disabled', 'disabled');
}
},
/**
* Deletes the given activity or resource after confirmation.
*
@ -391,7 +461,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
// If it is confirmed.
confirm.on('complete-yes', function() {
var spinner = this.add_spinner(element);
var data = {
'class': 'resource',
@ -410,10 +479,66 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
});
}, this);
return this;
},
/**
* Deletes the given activities or resources after confirmation.
*
* @protected
* @method delete_multiple_with_confirmation
* @param {EventFacade} ev The event that was fired.
* @chainable
*/
delete_multiple_with_confirmation: function(ev) {
ev.preventDefault();
var ids = '';
var slots = [];
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked').each(function(node) {
var slot = Y.Moodle.mod_quiz.util.slot.getSlotFromComponent(node);
ids += ids === '' ? '' : ',';
ids += Y.Moodle.mod_quiz.util.slot.getId(slot);
slots.push(slot);
});
var element = Y.one('div.mod-quiz-edit-content');
// Do nothing if no slots are selected.
if (!slots || !slots.length) {
return;
}
// Create the confirmation dialogue.
var confirm = new M.core.confirm({
question: M.util.get_string('areyousureremoveselected', 'quiz'),
modal: true
});
// If it is confirmed.
confirm.on('complete-yes', function() {
var spinner = this.add_spinner(element);
var data = {
'class': 'resource',
field: 'deletemultiple',
ids: ids
};
// Delete items on server.
this.send_request(data, spinner, function(response) {
// Delete locally if deleted on server.
if (response.deleted) {
// Actually remove the element.
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked').each(function(node) {
Y.Moodle.mod_quiz.util.slot.remove(node.ancestor('li.activity'));
});
// Update the page numbers and sections.
this.reorganise_edit_page();
// Remove the select multiple options.
Y.one('body').removeClass(CSS.SELECTMULTIPLE);
}
});
}, this);
},
/**
* Edit the maxmark for the resource
@ -671,82 +796,12 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
'value': 0
}
}
});
M.mod_quiz.resource_toolbox = null;
M.mod_quiz.init_resource_toolbox = function(config) {
M.mod_quiz.resource_toolbox = new RESOURCETOOLBOX(config);
var bulkactions = function() {
var CSS = {
QUIZBULKACTIONMODE: 'quiz-bulk-action-mode'
},
SELECTOR = {
BULKACTIONS: '#bulkactionscommand',
CANCELBULKACTIONS: '#bulkactionscancelcommand',
SELECTALL: '#questionselectall',
DELETEACTION: '#bulkactionsdeletecommand',
DESELECTALL: '#questiondeselectall',
CHECKBOXES: '.quiz-question-bulk-selector'
};
Y.one(SELECTOR.BULKACTIONS).on('click', function(e) {
e.preventDefault();
Y.one('body').addClass(CSS.QUIZBULKACTIONMODE);
});
Y.one(SELECTOR.CANCELBULKACTIONS).on('click', function(e) {
e.preventDefault();
Y.one('body').removeClass(CSS.QUIZBULKACTIONMODE);
});
Y.one(SELECTOR.SELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.CHECKBOXES).set('checked', 'checked');
});
Y.one(SELECTOR.DESELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.CHECKBOXES).set('checked', '');
});
var submitdeletion = function() {
var slots = '';
Y.all(SELECTOR.CHECKBOXES + ':checked').each(function(node) {
slots += slots === '' ? '' : ',';
slots += node.get('value');
});
var spinnercont = Y.one('div.mod-quiz-edit-content'),
spinner = M.mod_quiz.resource_toolbox.add_spinner(spinnercont),
data = {
'class': 'resource',
field: 'bulkdelete',
slots: slots
};
M.mod_quiz.resource_toolbox.send_request(data, spinner, function() {
Y.all(SELECTOR.CHECKBOXES + ':checked').each(function(node) {
node.ancestor('li.activity').remove(true);
});
});
};
Y.one(SELECTOR.DELETEACTION).on('click', function(e) {
e.preventDefault();
// Create the confirmation dialogue.
var confirm = new M.core.confirm({
question: M.util.get_string('areyousureremoveselected', 'quiz'),
modal: true
});
// If it is confirmed.
confirm.on('complete-yes', function() {
submitdeletion();
}, self);
});
};
bulkactions();
return M.mod_quiz.resource_toolbox;
};
/* global TOOLBOX, BODY, SELECTOR */

File diff suppressed because one or more lines are too long

View File

@ -28,6 +28,7 @@ var CSS = {
PAGE: 'page',
SECTIONHIDDENCLASS: 'hidden',
SECTIONIDPREFIX: 'section-',
SELECTMULTIPLE: 'select-multiple',
SLOT: 'slot',
SHOW: 'editing_show',
TITLEEDITOR: 'titleeditor'
@ -45,7 +46,8 @@ var CSS = {
COMMANDSPAN: '.commands',
CONTENTAFTERLINK: 'div.contentafterlink',
CONTENTWITHOUTLINK: 'div.contentwithoutlink',
DELETESECTIONICON: 'a.editing_delete .icon',
DELETESECTIONICON: 'a.editing_delete img',
DESELECTALL: '#questiondeselectall',
EDITMAXMARK: 'a.editing_maxmark',
EDITSECTION: 'a.editing_section',
EDITSECTIONICON: 'a.editing_section .icon',
@ -65,6 +67,11 @@ var CSS = {
SECTIONUL: 'ul.section',
SECTIONFORM: '.instancesectioncontainer form',
SECTIONINPUT: 'input[name=section]',
SELECTMULTIPLEBUTTON: '#selectmultiplecommand',
SELECTMULTIPLECANCELBUTTON: '#selectmultiplecancelcommand',
SELECTMULTIPLECHECKBOX: '.select-multiple-checkbox',
SELECTMULTIPLEDELETEBUTTON: '#selectmultipledeletecommand',
SELECTALL: '#questionselectall',
SHOW: 'a.' + CSS.SHOW,
SLOTLI: 'li.slot',
SUMMARKS: '.mod_quiz_summarks'
@ -103,6 +110,7 @@ Y.extend(TOOLBOX, Y.Base, {
if (!data) {
data = {};
}
// Handle any variables which we must pass back through to
var pageparams = this.get('config').pageparams,
varname;
@ -289,6 +297,52 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
M.mod_quiz.quizbase.register_module(this);
Y.delegate('click', this.handle_data_action, BODY, SELECTOR.ACTIVITYACTION, this);
Y.delegate('click', this.handle_data_action, BODY, SELECTOR.DEPENDENCY_LINK, this);
this.initialise_select_multiple();
},
/**
* Initialize the select multiple options
*
* Add actions to the buttons that enable multiple slots to be selected and managed at once.
*
* @method initialise_select_multiple
* @protected
*/
initialise_select_multiple: function() {
// Click select multiple button to show the select all options.
Y.one(SELECTOR.SELECTMULTIPLEBUTTON).on('click', function(e) {
e.preventDefault();
Y.one('body').addClass(CSS.SELECTMULTIPLE);
});
// Click cancel button to show the select all options.
Y.one(SELECTOR.SELECTMULTIPLECANCELBUTTON).on('click', function(e) {
e.preventDefault();
Y.one('body').removeClass(CSS.SELECTMULTIPLE);
});
// Click select all link to check all the checkboxes.
Y.one(SELECTOR.SELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX).set('checked', 'checked');
});
// Click deselect all link to show the select all checkboxes.
Y.one(SELECTOR.DESELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX).set('checked', '');
});
// Disable delete multiple button by default.
Y.one(SELECTOR.SELECTMULTIPLEDELETEBUTTON).setAttribute('disabled', 'disabled');
// Assign the delete method to the delete multiple button.
Y.delegate('click', this.delete_multiple_with_confirmation, BODY, SELECTOR.SELECTMULTIPLEDELETEBUTTON, this);
// Enable the delete all button only when at least one slot is selected.
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.SELECTMULTIPLECHECKBOX, this);
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.SELECTALL, this);
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.DESELECTALL, this);
},
/**
@ -361,6 +415,22 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
return null;
},
/**
* If a select multiple checkbox is checked enable the buttons in the select multiple
* toolbar otherwise disable it.
*
* @method toggle_select_all_buttons_enabled
*/
toggle_select_all_buttons_enabled: function() {
var checked = Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked');
var deletebutton = Y.one(SELECTOR.SELECTMULTIPLEDELETEBUTTON);
if (checked && !checked.isEmpty()) {
deletebutton.removeAttribute('disabled');
} else {
deletebutton.setAttribute('disabled', 'disabled');
}
},
/**
* Deletes the given activity or resource after confirmation.
*
@ -391,7 +461,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
// If it is confirmed.
confirm.on('complete-yes', function() {
var spinner = this.add_spinner(element);
var data = {
'class': 'resource',
@ -410,10 +479,66 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
});
}, this);
return this;
},
/**
* Deletes the given activities or resources after confirmation.
*
* @protected
* @method delete_multiple_with_confirmation
* @param {EventFacade} ev The event that was fired.
* @chainable
*/
delete_multiple_with_confirmation: function(ev) {
ev.preventDefault();
var ids = '';
var slots = [];
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked').each(function(node) {
var slot = Y.Moodle.mod_quiz.util.slot.getSlotFromComponent(node);
ids += ids === '' ? '' : ',';
ids += Y.Moodle.mod_quiz.util.slot.getId(slot);
slots.push(slot);
});
var element = Y.one('div.mod-quiz-edit-content');
// Do nothing if no slots are selected.
if (!slots || !slots.length) {
return;
}
// Create the confirmation dialogue.
var confirm = new M.core.confirm({
question: M.util.get_string('areyousureremoveselected', 'quiz'),
modal: true
});
// If it is confirmed.
confirm.on('complete-yes', function() {
var spinner = this.add_spinner(element);
var data = {
'class': 'resource',
field: 'deletemultiple',
ids: ids
};
// Delete items on server.
this.send_request(data, spinner, function(response) {
// Delete locally if deleted on server.
if (response.deleted) {
// Actually remove the element.
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked').each(function(node) {
Y.Moodle.mod_quiz.util.slot.remove(node.ancestor('li.activity'));
});
// Update the page numbers and sections.
this.reorganise_edit_page();
// Remove the select multiple options.
Y.one('body').removeClass(CSS.SELECTMULTIPLE);
}
});
}, this);
},
/**
* Edit the maxmark for the resource
@ -671,82 +796,12 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
'value': 0
}
}
});
M.mod_quiz.resource_toolbox = null;
M.mod_quiz.init_resource_toolbox = function(config) {
M.mod_quiz.resource_toolbox = new RESOURCETOOLBOX(config);
var bulkactions = function() {
var CSS = {
QUIZBULKACTIONMODE: 'quiz-bulk-action-mode'
},
SELECTOR = {
BULKACTIONS: '#bulkactionscommand',
CANCELBULKACTIONS: '#bulkactionscancelcommand',
SELECTALL: '#questionselectall',
DELETEACTION: '#bulkactionsdeletecommand',
DESELECTALL: '#questiondeselectall',
CHECKBOXES: '.quiz-question-bulk-selector'
};
Y.one(SELECTOR.BULKACTIONS).on('click', function(e) {
e.preventDefault();
Y.one('body').addClass(CSS.QUIZBULKACTIONMODE);
});
Y.one(SELECTOR.CANCELBULKACTIONS).on('click', function(e) {
e.preventDefault();
Y.one('body').removeClass(CSS.QUIZBULKACTIONMODE);
});
Y.one(SELECTOR.SELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.CHECKBOXES).set('checked', 'checked');
});
Y.one(SELECTOR.DESELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.CHECKBOXES).set('checked', '');
});
var submitdeletion = function() {
var slots = '';
Y.all(SELECTOR.CHECKBOXES + ':checked').each(function(node) {
slots += slots === '' ? '' : ',';
slots += node.get('value');
});
var spinnercont = Y.one('div.mod-quiz-edit-content'),
spinner = M.mod_quiz.resource_toolbox.add_spinner(spinnercont),
data = {
'class': 'resource',
field: 'bulkdelete',
slots: slots
};
M.mod_quiz.resource_toolbox.send_request(data, spinner, function() {
Y.all(SELECTOR.CHECKBOXES + ':checked').each(function(node) {
node.ancestor('li.activity').remove(true);
});
});
};
Y.one(SELECTOR.DELETEACTION).on('click', function(e) {
e.preventDefault();
// Create the confirmation dialogue.
var confirm = new M.core.confirm({
question: M.util.get_string('areyousureremoveselected', 'quiz'),
modal: true
});
// If it is confirmed.
confirm.on('complete-yes', function() {
submitdeletion();
}, self);
});
};
bulkactions();
return M.mod_quiz.resource_toolbox;
};
/* global TOOLBOX, BODY, SELECTOR */

View File

@ -23,7 +23,6 @@
*/
var CSS = {
REPAGINATECONTAINERCLASS: '.rpcontainerclass',
REPAGINATECOMMAND: '#repaginatecommand'
};
@ -42,12 +41,12 @@ Y.extend(POPUP, Y.Base, {
body: null,
initializer: function() {
var rpcontainerclass = Y.one(CSS.REPAGINATECONTAINERCLASS);
var repaginatebutton = Y.one(CSS.REPAGINATECOMMAND);
// Set popup header and body.
this.header = rpcontainerclass.getAttribute(PARAMS.HEADER);
this.body = rpcontainerclass.getAttribute(PARAMS.FORM);
Y.one(CSS.REPAGINATECOMMAND).on('click', this.display_dialog, this);
this.header = repaginatebutton.getData(PARAMS.HEADER);
this.body = repaginatebutton.getData(PARAMS.FORM);
repaginatebutton.on('click', this.display_dialog, this);
},
display_dialog: function(e) {

View File

@ -64,6 +64,52 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
M.mod_quiz.quizbase.register_module(this);
Y.delegate('click', this.handle_data_action, BODY, SELECTOR.ACTIVITYACTION, this);
Y.delegate('click', this.handle_data_action, BODY, SELECTOR.DEPENDENCY_LINK, this);
this.initialise_select_multiple();
},
/**
* Initialize the select multiple options
*
* Add actions to the buttons that enable multiple slots to be selected and managed at once.
*
* @method initialise_select_multiple
* @protected
*/
initialise_select_multiple: function() {
// Click select multiple button to show the select all options.
Y.one(SELECTOR.SELECTMULTIPLEBUTTON).on('click', function(e) {
e.preventDefault();
Y.one('body').addClass(CSS.SELECTMULTIPLE);
});
// Click cancel button to show the select all options.
Y.one(SELECTOR.SELECTMULTIPLECANCELBUTTON).on('click', function(e) {
e.preventDefault();
Y.one('body').removeClass(CSS.SELECTMULTIPLE);
});
// Click select all link to check all the checkboxes.
Y.one(SELECTOR.SELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX).set('checked', 'checked');
});
// Click deselect all link to show the select all checkboxes.
Y.one(SELECTOR.DESELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX).set('checked', '');
});
// Disable delete multiple button by default.
Y.one(SELECTOR.SELECTMULTIPLEDELETEBUTTON).setAttribute('disabled', 'disabled');
// Assign the delete method to the delete multiple button.
Y.delegate('click', this.delete_multiple_with_confirmation, BODY, SELECTOR.SELECTMULTIPLEDELETEBUTTON, this);
// Enable the delete all button only when at least one slot is selected.
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.SELECTMULTIPLECHECKBOX, this);
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.SELECTALL, this);
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.DESELECTALL, this);
},
/**
@ -136,6 +182,22 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
return null;
},
/**
* If a select multiple checkbox is checked enable the buttons in the select multiple
* toolbar otherwise disable it.
*
* @method toggle_select_all_buttons_enabled
*/
toggle_select_all_buttons_enabled: function() {
var checked = Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked');
var deletebutton = Y.one(SELECTOR.SELECTMULTIPLEDELETEBUTTON);
if (checked && !checked.isEmpty()) {
deletebutton.removeAttribute('disabled');
} else {
deletebutton.setAttribute('disabled', 'disabled');
}
},
/**
* Deletes the given activity or resource after confirmation.
*
@ -166,7 +228,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
// If it is confirmed.
confirm.on('complete-yes', function() {
var spinner = this.add_spinner(element);
var data = {
'class': 'resource',
@ -185,10 +246,66 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
});
}, this);
return this;
},
/**
* Deletes the given activities or resources after confirmation.
*
* @protected
* @method delete_multiple_with_confirmation
* @param {EventFacade} ev The event that was fired.
* @chainable
*/
delete_multiple_with_confirmation: function(ev) {
ev.preventDefault();
var ids = '';
var slots = [];
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked').each(function(node) {
var slot = Y.Moodle.mod_quiz.util.slot.getSlotFromComponent(node);
ids += ids === '' ? '' : ',';
ids += Y.Moodle.mod_quiz.util.slot.getId(slot);
slots.push(slot);
});
var element = Y.one('div.mod-quiz-edit-content');
// Do nothing if no slots are selected.
if (!slots || !slots.length) {
return;
}
// Create the confirmation dialogue.
var confirm = new M.core.confirm({
question: M.util.get_string('areyousureremoveselected', 'quiz'),
modal: true
});
// If it is confirmed.
confirm.on('complete-yes', function() {
var spinner = this.add_spinner(element);
var data = {
'class': 'resource',
field: 'deletemultiple',
ids: ids
};
// Delete items on server.
this.send_request(data, spinner, function(response) {
// Delete locally if deleted on server.
if (response.deleted) {
// Actually remove the element.
Y.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked').each(function(node) {
Y.Moodle.mod_quiz.util.slot.remove(node.ancestor('li.activity'));
});
// Update the page numbers and sections.
this.reorganise_edit_page();
// Remove the select multiple options.
Y.one('body').removeClass(CSS.SELECTMULTIPLE);
}
});
}, this);
},
/**
* Edit the maxmark for the resource
@ -446,81 +563,11 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
'value': 0
}
}
});
M.mod_quiz.resource_toolbox = null;
M.mod_quiz.init_resource_toolbox = function(config) {
M.mod_quiz.resource_toolbox = new RESOURCETOOLBOX(config);
var bulkactions = function() {
var CSS = {
QUIZBULKACTIONMODE: 'quiz-bulk-action-mode'
},
SELECTOR = {
BULKACTIONS: '#bulkactionscommand',
CANCELBULKACTIONS: '#bulkactionscancelcommand',
SELECTALL: '#questionselectall',
DELETEACTION: '#bulkactionsdeletecommand',
DESELECTALL: '#questiondeselectall',
CHECKBOXES: '.quiz-question-bulk-selector'
};
Y.one(SELECTOR.BULKACTIONS).on('click', function(e) {
e.preventDefault();
Y.one('body').addClass(CSS.QUIZBULKACTIONMODE);
});
Y.one(SELECTOR.CANCELBULKACTIONS).on('click', function(e) {
e.preventDefault();
Y.one('body').removeClass(CSS.QUIZBULKACTIONMODE);
});
Y.one(SELECTOR.SELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.CHECKBOXES).set('checked', 'checked');
});
Y.one(SELECTOR.DESELECTALL).on('click', function(e) {
e.preventDefault();
Y.all(SELECTOR.CHECKBOXES).set('checked', '');
});
var submitdeletion = function() {
var slots = '';
Y.all(SELECTOR.CHECKBOXES + ':checked').each(function(node) {
slots += slots === '' ? '' : ',';
slots += node.get('value');
});
var spinnercont = Y.one('div.mod-quiz-edit-content'),
spinner = M.mod_quiz.resource_toolbox.add_spinner(spinnercont),
data = {
'class': 'resource',
field: 'bulkdelete',
slots: slots
};
M.mod_quiz.resource_toolbox.send_request(data, spinner, function() {
Y.all(SELECTOR.CHECKBOXES + ':checked').each(function(node) {
node.ancestor('li.activity').remove(true);
});
});
};
Y.one(SELECTOR.DELETEACTION).on('click', function(e) {
e.preventDefault();
// Create the confirmation dialogue.
var confirm = new M.core.confirm({
question: M.util.get_string('areyousureremoveselected', 'quiz'),
modal: true
});
// If it is confirmed.
confirm.on('complete-yes', function() {
submitdeletion();
}, self);
});
};
bulkactions();
return M.mod_quiz.resource_toolbox;
};

View File

@ -26,6 +26,7 @@ var CSS = {
PAGE: 'page',
SECTIONHIDDENCLASS: 'hidden',
SECTIONIDPREFIX: 'section-',
SELECTMULTIPLE: 'select-multiple',
SLOT: 'slot',
SHOW: 'editing_show',
TITLEEDITOR: 'titleeditor'
@ -43,7 +44,8 @@ var CSS = {
COMMANDSPAN: '.commands',
CONTENTAFTERLINK: 'div.contentafterlink',
CONTENTWITHOUTLINK: 'div.contentwithoutlink',
DELETESECTIONICON: 'a.editing_delete .icon',
DELETESECTIONICON: 'a.editing_delete img',
DESELECTALL: '#questiondeselectall',
EDITMAXMARK: 'a.editing_maxmark',
EDITSECTION: 'a.editing_section',
EDITSECTIONICON: 'a.editing_section .icon',
@ -63,6 +65,11 @@ var CSS = {
SECTIONUL: 'ul.section',
SECTIONFORM: '.instancesectioncontainer form',
SECTIONINPUT: 'input[name=section]',
SELECTMULTIPLEBUTTON: '#selectmultiplecommand',
SELECTMULTIPLECANCELBUTTON: '#selectmultiplecancelcommand',
SELECTMULTIPLECHECKBOX: '.select-multiple-checkbox',
SELECTMULTIPLEDELETEBUTTON: '#selectmultipledeletecommand',
SELECTALL: '#questionselectall',
SHOW: 'a.' + CSS.SHOW,
SLOTLI: 'li.slot',
SUMMARKS: '.mod_quiz_summarks'
@ -101,6 +108,7 @@ Y.extend(TOOLBOX, Y.Base, {
if (!data) {
data = {};
}
// Handle any variables which we must pass back through to
var pageparams = this.get('config').pageparams,
varname;