Merge branch 'MDL-47603' of git://github.com/timhunt/moodle
[moodle.git] / mod / quiz / yui / src / quizquestionbank / js / quizquestionbank.js
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/>.
17 /**
18  * Add questions from question bank functionality for a popup in quiz editing page.
19  *
20  * @package   mod_quiz
21  * @copyright 2014 The Open University
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 var CSS = {
26         QBANKLOADING:       'div.questionbankloading',
27         ADDQUESTIONLINKS:   'ul.menu a.questionbank',
28         ADDTOQUIZCONTAINER: 'td.addtoquizaction',
29         PREVIEWCONTAINER:   'td.previewaction',
30         SEARCHOPTIONS:      '#advancedsearch'
31 };
33 var PARAMS = {
34     PAGE: 'addonpage',
35     HEADER: 'header'
36 };
38 var POPUP = function() {
39     POPUP.superclass.constructor.apply(this, arguments);
40 };
42 Y.extend(POPUP, Y.Base, {
43     loadingDiv: '',
44     dialogue: null,
45     addonpage: 0,
46     searchRegionInitialised: false,
48     create_dialogue: function() {
49         // Create a dialogue on the page and hide it.
50         config = {
51             headerContent : '',
52             bodyContent : Y.one(CSS.QBANKLOADING),
53             draggable : true,
54             modal : true,
55             centered: true,
56             width: null,
57             visible: false,
58             postmethod: 'form',
59             footerContent: null,
60             extraClasses: ['mod_quiz_qbank_dialogue']
61         };
62         this.dialogue = new M.core.dialogue(config);
63         this.dialogue.bodyNode.delegate('click', this.link_clicked, 'a[href]', this);
64         this.dialogue.hide();
66         this.loadingDiv = this.dialogue.bodyNode.getHTML();
68         Y.later(100, this, function() {this.load_content(window.location.search);});
69     },
71     initializer : function() {
72         if (!Y.one(CSS.QBANKLOADING)) {
73             return;
74         }
75         this.create_dialogue();
76         Y.one('body').delegate('click', this.display_dialogue, CSS.ADDQUESTIONLINKS, this);
77     },
79     display_dialogue : function (e) {
80         e.preventDefault();
81         this.dialogue.set('headerContent', e.currentTarget.getData(PARAMS.HEADER));
83         this.addonpage = e.currentTarget.getData(PARAMS.PAGE);
84         var controlsDiv = this.dialogue.bodyNode.one('.modulespecificbuttonscontainer');
85         if (controlsDiv) {
86             var hidden = controlsDiv.one('input[name=addonpage]');
87             if (!hidden) {
88                 hidden = controlsDiv.appendChild('<input type="hidden" name="addonpage">');
89             }
90             hidden.set('value', this.addonpage);
91         }
93         this.initialiseSearchRegion();
94         this.dialogue.show();
95     },
97     load_content : function(queryString) {
98         Y.log('Starting load.', 'debug', 'moodle-mod_quiz-quizquestionbank');
99         this.dialogue.bodyNode.append(this.loadingDiv);
101         // If to support old IE.
102         if (window.history.replaceState) {
103             window.history.replaceState(null, '', M.cfg.wwwroot + '/mod/quiz/edit.php' + queryString);
104         }
106         Y.io(M.cfg.wwwroot + '/mod/quiz/questionbank.ajax.php' + queryString, {
107             method: 'GET',
108             on: {
109                 success: this.load_done,
110                 failure: this.load_failed
111             },
112             context: this
113         });
115         Y.log('Load request sent.', 'debug', 'moodle-mod_quiz-quizquestionbank');
116     },
118     load_done: function(transactionid, response) {
119         var result = JSON.parse(response.responseText);
120         if (!result.status || result.status !== 'OK') {
121             // Because IIS is useless, Moodle can't send proper HTTP response
122             // codes, so we have to detect failures manually.
123             this.load_failed(transactionid, response);
124             return;
125         }
127         Y.log('Load completed.', 'debug', 'moodle-mod_quiz-quizquestionbank');
129         this.dialogue.bodyNode.setHTML(result.contents);
130         Y.use('moodle-question-chooser', function() {M.question.init_chooser({});});
131         this.dialogue.bodyNode.one('form').delegate('change', this.options_changed, '.searchoptions', this);
133         if (this.dialogue.visible) {
134             Y.later(0, this.dialogue, this.dialogue.centerDialogue);
135         }
136         M.question.qbankmanager.init();
138         this.searchRegionInitialised = false;
139         if (this.dialogue.get('visible')) {
140             this.initialiseSearchRegion();
141         }
143         this.dialogue.fire('widget:contentUpdate');
144         // TODO MDL-47602 really, the base class should listen for the even fired
145         // on the previous line, and fix things like makeResponsive.
146         // However, it does not. So the next two lines are a hack to fix up
147         // display issues (e.g. overall scrollbars on the page). Once the base class
148         // is fixed, this comment and the following four lines should be deleted.
149         if (this.dialogue.get('visible')) {
150             this.dialogue.hide();
151             this.dialogue.show();
152         }
153     },
155     load_failed: function() {
156         Y.log('Load failed.', 'debug', 'moodle-mod_quiz-quizquestionbank');
157     },
159     link_clicked: function(e) {
160         // Add question to quiz. mofify the URL, then let it work as normal.
161         if (e.currentTarget.ancestor(CSS.ADDTOQUIZCONTAINER)) {
162             e.currentTarget.set('href', e.currentTarget.get('href') + '&addonpage=' + this.addonpage);
163             return;
164         }
166         // Question preview. Needs to open in a pop-up.
167         if (e.currentTarget.ancestor(CSS.PREVIEWCONTAINER)) {
168             openpopup(e, {
169                 url: e.currentTarget.get('href'),
170                 name: 'questionpreview',
171                 options: 'height=600,width=800,top=0,left=0,menubar=0,location=0,scrollbars,resizable,toolbar,status,directories=0,fullscreen=0,dependent'
172             });
173             return;
174         }
176         // Click on expand/collaspse search-options. Has its own handler.
177         // We should not interfere.
178         if (e.currentTarget.ancestor(CSS.SEARCHOPTIONS)) {
179             return;
180         }
182         // Anything else means reload the pop-up contents.
183         e.preventDefault();
184         this.load_content(e.currentTarget.get('search'));
185     },
187     options_changed: function(e) {
188         e.preventDefault();
189         this.load_content('?' + Y.IO.stringify(e.currentTarget.get('form')));
190     },
192     initialiseSearchRegion: function() {
193         if (this.searchRegionInitialised === true) {
194             return;
195         }
196         if (!Y.one(CSS.SEARCHOPTIONS)) {
197             return;
198         }
200         M.util.init_collapsible_region(Y, "advancedsearch", "question_bank_advanced_search",
201                 M.util.get_string('clicktohideshow', 'moodle'));
202         this.searchRegionInitialised = true;
203     }
204 });
206 M.mod_quiz = M.mod_quiz || {};
207 M.mod_quiz.quizquestionbank = M.mod_quiz.quizquestionbank || {};
208 M.mod_quiz.quizquestionbank.init = function() {
209     return new POPUP();
210 };