Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * Contain the logic for the question bank modal.
18
 *
19
 * @module     mod_quiz/modal_quiz_question_bank
20
 * @copyright  2018 Ryan Wyllie <ryan@moodle.com>
21
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
 
24
import Modal from './add_question_modal';
25
import * as Fragment from 'core/fragment';
26
import * as FormChangeChecker from 'core_form/changechecker';
27
import * as ModalEvents from 'core/modal_events';
1441 ariadna 28
import * as Notification from 'core/notification';
1 efrain 29
 
30
const SELECTORS = {
31
    ADD_TO_QUIZ_CONTAINER: 'td.addtoquizaction',
32
    ANCHOR: 'a[href]',
33
    PREVIEW_CONTAINER: 'td.previewquestionaction',
34
    ADD_QUESTIONS_FORM: 'form#questionsubmit',
35
    SORTERS: '.sorters',
1441 ariadna 36
    SWITCH_TO_OTHER_BANK: 'button[data-action="switch-question-bank"]',
37
    NEW_BANKMOD_ID: 'data-newmodid',
38
    BANK_SEARCH: '#searchbanks',
39
    GO_BACK_BUTTON: 'button[data-action="go-back"]',
40
    ADD_ON_PAGE_FORM_ELEMENT: 'input[name="addonpage"]',
41
    CMID_FORM_ELEMENT: 'form#questionsubmit input[name="cmid"]',
1 efrain 42
};
43
 
44
export default class ModalQuizQuestionBank extends Modal {
45
    static TYPE = 'mod_quiz-quiz-question-bank';
46
 
47
    /**
48
     * Create the question bank modal.
49
     *
1441 ariadna 50
     * @param {Number} contextId Current module context id.
51
     * @param {Number} bankCmId Current question bank course module id.
52
     * @param {Number} quizCmId Current quiz course module id.
1 efrain 53
     */
1441 ariadna 54
    static init(contextId, bankCmId, quizCmId) {
1 efrain 55
        const selector = '.menu [data-action="questionbank"]';
56
        document.addEventListener('click', (e) => {
57
            const trigger = e.target.closest(selector);
58
            if (!trigger) {
59
                return;
60
            }
61
            e.preventDefault();
62
 
63
            ModalQuizQuestionBank.create({
64
                contextId,
1441 ariadna 65
                quizCmId,
66
                bankCmId,
1 efrain 67
                title: trigger.dataset.header,
68
                addOnPage: trigger.dataset.addonpage,
69
                templateContext: {
70
                    hidden: true,
71
                },
72
                large: true,
73
            });
74
        });
75
    }
76
 
77
    /**
78
     * Override the parent show function.
79
     *
80
     * Reload the body contents when the modal is shown. The current
81
     * window URL is used to inform the new content that should be
82
     * displayed.
83
     *
84
     * @method show
85
     * @return {void}
86
     */
87
    show() {
88
        this.reloadBodyContent(window.location.search);
89
        return super.show(this);
90
    }
91
 
92
    /**
93
     * Replaces the current body contents with a new version of the question
94
     * bank.
95
     *
96
     * The contents of the question bank are generated using the provided
97
     * query string.
98
     *
99
     * @method reloadBodyContent
100
     * @param {string} querystring URL encoded string.
101
     */
102
    reloadBodyContent(querystring) {
1441 ariadna 103
        // Load the question bank fragment to be displayed in the modal and hide the 'go back' button.
104
        this.hideFooter();
105
        this.setTitle(this.originalTitle);
1 efrain 106
        this.setBody(Fragment.loadFragment(
107
            'mod_quiz',
108
            'quiz_question_bank',
109
            this.getContextId(),
110
            {
111
                querystring,
1441 ariadna 112
                quizcmid: this.quizCmId,
113
                bankcmid: this.bankCmId,
1 efrain 114
            }
115
        ));
116
    }
117
 
118
    /**
119
     * Update the URL of the anchor element that the user clicked on to make
120
     * sure that the question is added to the correct page.
121
     *
122
     * @method handleAddToQuizEvent
123
     * @param {event} e A JavaScript event
124
     * @param {object} anchorElement The anchor element that was triggered
125
     */
126
    handleAddToQuizEvent(e, anchorElement) {
127
        // If the user clicks the plus icon to add the question to the page
128
        // directly then we need to intercept the click in order to adjust the
1441 ariadna 129
        // href and include the correct add on page id and cmid before the page is
1 efrain 130
        // redirected.
1441 ariadna 131
        const href = new URL(anchorElement.getAttribute('href'));
1 efrain 132
        href.searchParams.set('addonpage', this.getAddOnPageId());
1441 ariadna 133
        href.searchParams.set('cmid', this.quizCmId);
134
        anchorElement.setAttribute('href', href);
1 efrain 135
    }
136
 
137
    /**
138
     * Set up all of the event handling for the modal.
139
     *
140
     * @method registerEventListeners
141
     */
142
    registerEventListeners() {
143
        // Apply parent event listeners.
144
        super.registerEventListeners(this);
145
 
146
        this.getModal().on('submit', SELECTORS.ADD_QUESTIONS_FORM, (e) => {
147
            // If the user clicks on the "Add selected questions to the quiz" button to add some questions to the page
1441 ariadna 148
            // then we need to intercept the submit in order to include the correct "add on page id"
149
            // and the quizmod id before the form is submitted.
150
            const formElement = e.currentTarget;
151
            document.querySelector(SELECTORS.ADD_ON_PAGE_FORM_ELEMENT).setAttribute('value', this.getAddOnPageId());
1 efrain 152
 
1441 ariadna 153
            // We also need to set the form cmid & action as the quiz modid as this could be coming from a module that isn't a quiz.
154
            document.querySelector(SELECTORS.CMID_FORM_ELEMENT).setAttribute('value', this.quizCmId);
155
            const actionUrl = new URL(formElement.getAttribute('action'));
156
            actionUrl.searchParams.set('cmid', this.quizCmId);
157
            formElement.setAttribute('action', actionUrl.toString());
1 efrain 158
        });
159
 
1441 ariadna 160
        this.getModal().on('click', SELECTORS.SWITCH_TO_OTHER_BANK, () => {
161
            this.handleSwitchBankContentReload(SELECTORS.BANK_SEARCH)
162
                .then(function(ModalQuizQuestionBank) {
163
                        document.querySelector(SELECTORS.BANK_SEARCH)?.addEventListener('change', (e) => {
164
                            const bankCmId = e.currentTarget.value;
165
                            if (bankCmId > 0) {
166
                                ModalQuizQuestionBank.bankCmId = bankCmId;
167
                                ModalQuizQuestionBank.reloadBodyContent(window.location.search);
168
                            }
169
                        });
170
                        document.querySelector(SELECTORS.GO_BACK_BUTTON).addEventListener('click', (e) => {
171
                            ModalQuizQuestionBank.bankCmId = e.currentTarget.value;
172
                            ModalQuizQuestionBank.reloadBodyContent(window.location.search);
173
                        });
174
                    }
175
                )
176
                .catch(Notification.exception);
177
        });
178
 
1 efrain 179
        this.getModal().on('click', SELECTORS.ANCHOR, (e) => {
1441 ariadna 180
            const anchorElement = e.currentTarget;
1 efrain 181
 
182
            // If the anchor element was the add to quiz link.
1441 ariadna 183
            if (anchorElement.closest(SELECTORS.ADD_TO_QUIZ_CONTAINER)) {
1 efrain 184
                this.handleAddToQuizEvent(e, anchorElement);
185
                return;
186
            }
187
 
188
            // If the anchor element was a preview question link.
1441 ariadna 189
            if (anchorElement.closest(SELECTORS.PREVIEW_CONTAINER)) {
1 efrain 190
                return;
191
            }
192
 
193
            // Sorting links have their own handler.
1441 ariadna 194
            if (anchorElement.closest(SELECTORS.SORTERS)) {
1 efrain 195
                return;
196
            }
197
 
1441 ariadna 198
            if (anchorElement.closest('a[' + SELECTORS.NEW_BANKMOD_ID + ']')) {
199
                this.bankCmId = anchorElement.getAttribute(SELECTORS.NEW_BANKMOD_ID);
200
 
201
                // We need to clear the filter as we are about to reload the content.
202
                const url = new URL(location.href);
203
                url.searchParams.delete('filter');
204
                history.pushState({}, '', url);
205
            }
206
 
1 efrain 207
            // Anything else means reload the pop-up contents.
208
            e.preventDefault();
1441 ariadna 209
            this.reloadBodyContent(anchorElement.search);
1 efrain 210
        });
211
 
212
        // Disable the form change checker when the body is rendered.
213
        this.getRoot().on(ModalEvents.bodyRendered, () => {
214
            // Make sure the form change checker is disabled otherwise it'll stop the user from navigating away from the
215
            // page once the modal is hidden.
216
            FormChangeChecker.disableAllChecks();
217
        });
218
    }
219
}
220
 
221
ModalQuizQuestionBank.registerModalType();