From 405168f912ec7bcf12b62436bb6e2299b8fa892a Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Tue, 31 May 2022 09:16:23 +0200 Subject: [PATCH 01/23] Replace get_records with SQL query in get_improvised_question_definition The database schema has changed in Moodle 4.0, meaning that the current call to get_records fails because the "question" table no longer contains information about the categories. This information has instead been split off into the "question_bank_entries" table. To get the same information as before, we need to select from this table. Fixes #77 --- classes/improviser.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/classes/improviser.php b/classes/improviser.php index b3847df..962097b 100755 --- a/classes/improviser.php +++ b/classes/improviser.php @@ -88,10 +88,13 @@ private function get_improvised_question_definition(string $name) { if (!$category) { return false; } - $questions = $DB->get_records('question', [ - 'category' => $category->id, - 'name' => '{IMPROV}' . $name - ]); + $sql = "SELECT qbe.id + FROM {question_bank_entries} qbe + JOIN {question} q + ON q.id = qbe.id + WHERE qbe.questioncategoryid = :catid + AND q.name LIKE :name"; + $questions = $DB->get_records_sql($sql, ['catid' => $category->id, 'name' => '{IMPROV}' . $name]); if (!$questions) { return false; } From 6b068181c7940d6db2741b89ba136ef87787f767 Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Tue, 31 May 2022 10:53:28 +0200 Subject: [PATCH 02/23] Update GitHub workflows to test with Moodle 4.0 Since the code I'm writing on this branch is for Moodle 4.0, it should be tested with that version as well. --- .github/workflows/moodle-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 50f9d58..2dc7996 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -28,7 +28,7 @@ jobs: fail-fast: false matrix: php: ['7.2', '7.3', '7.4'] - moodle-branch: ['MOODLE_310_STABLE', 'MOODLE_39_STABLE'] + moodle-branch: ['MOODLE_400_STABLE', 'MOODLE_310_STABLE'] database: [pgsql, mariadb] steps: From 16bc7159066276d3bff7031736263cb528ceb049 Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Tue, 31 May 2022 14:42:32 +0200 Subject: [PATCH 03/23] Specify the entire path to question_edit_contexts The file was moved in Moodle 4.0 causing code to claim that it's received a different type. Fixes #81 --- edit.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/edit.php b/edit.php index f6860c6..dcdd76d 100755 --- a/edit.php +++ b/edit.php @@ -50,14 +50,14 @@ function jazzquiz_session_open($jazzquizid) { /** * Gets the question bank view based on the options passed in at the page setup. - * @param \question_edit_contexts $contexts + * @param \core_question\local\bank\question_edit_contexts $contexts * @param jazzquiz $jazzquiz * @param \moodle_url $url * @param array $pagevars * @return string * @throws \coding_exception */ -function get_qbank_view(\question_edit_contexts $contexts, jazzquiz $jazzquiz, \moodle_url $url, array $pagevars) { +function get_qbank_view(\core_question\local\bank\question_edit_contexts $contexts, jazzquiz $jazzquiz, \moodle_url $url, array $pagevars) { $qperpage = optional_param('qperpage', 10, PARAM_INT); $qpage = optional_param('qpage', 0, PARAM_INT); // Capture question bank display in buffer to have the renderer render output. @@ -69,14 +69,14 @@ function get_qbank_view(\question_edit_contexts $contexts, jazzquiz $jazzquiz, \ /** * Echos the list of questions using the renderer for jazzquiz. - * @param \question_edit_contexts $contexts + * @param \core_question\local\bank\question_edit_contexts $contexts * @param jazzquiz $jazzquiz * @param \moodle_url $url * @param array $pagevars * @throws \coding_exception * @throws \moodle_exception */ -function list_questions(\question_edit_contexts $contexts, jazzquiz $jazzquiz, \moodle_url $url, array $pagevars) { +function list_questions(\core_question\local\bank\question_edit_contexts $contexts, jazzquiz $jazzquiz, \moodle_url $url, array $pagevars) { $qbankview = get_qbank_view($contexts, $jazzquiz, $url, $pagevars); $jazzquiz->renderer->list_questions($jazzquiz, $jazzquiz->questions, $qbankview, $url); } @@ -119,13 +119,13 @@ function jazzquiz_edit_edit_question(jazzquiz $jazzquiz) { /** * @param jazzquiz $jazzquiz - * @param \question_edit_contexts $contexts + * @param \core_question\local\bank\question_edit_contexts $contexts * @param \moodle_url $url * @param $pagevars * @throws \coding_exception * @throws \moodle_exception */ -function jazzquiz_edit_qlist(jazzquiz $jazzquiz, \question_edit_contexts $contexts, \moodle_url $url, array $pagevars) { +function jazzquiz_edit_qlist(jazzquiz $jazzquiz, \core_question\local\bank\question_edit_contexts $contexts, \moodle_url $url, array $pagevars) { $jazzquiz->renderer->header($jazzquiz, 'edit'); list_questions($contexts, $jazzquiz, $url, $pagevars); $jazzquiz->renderer->footer(); From 3a388cd15c588fc271a060dad834a0a7d02df85e Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 09:34:14 +0200 Subject: [PATCH 04/23] Update reference to \core_question\bank\view This class was renamed/moved to \core_question\local\bank\view, so we need to update the path we call it from. --- classes/bank/jazzquiz_question_bank_view.php | 2 +- edit.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index 208b055..07600ed 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -41,7 +41,7 @@ * @copyright 2018 NTNU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class jazzquiz_question_bank_view extends \core_question\bank\view { +class jazzquiz_question_bank_view extends \core_question\local\bank\view { /** * Define the columns we want to be displayed on the question bank diff --git a/edit.php b/edit.php index dcdd76d..65d33af 100755 --- a/edit.php +++ b/edit.php @@ -173,7 +173,7 @@ function jazzquiz_edit() { } // Process moving, deleting and unhiding questions... - $questionbank = new \core_question\bank\view($contexts, $url, $COURSE, $cm); + $questionbank = new \core_question\local\bank\view($contexts, $url, $COURSE, $cm); $questionbank->process_actions(); switch ($action) { From ef15b85cd61d66aa4f78f93e3fd775690508c90a Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 11:11:57 +0200 Subject: [PATCH 05/23] Remove call to process_actions() This function was deprecated in 0805e387b7735d7a599717e1f5c0ff4fabd1a5e0 in the Moodle repository. According to [upgrade.txt][1] any calls to this function can simply be removed. [1]: https://github.com/moodle/moodle/blob/0805e387b7735d7a599717e1f5c0ff4fabd1a5e0/question/upgrade.txt#L78-L80 --- edit.php | 1 - 1 file changed, 1 deletion(-) diff --git a/edit.php b/edit.php index 65d33af..d5fd8a2 100755 --- a/edit.php +++ b/edit.php @@ -174,7 +174,6 @@ function jazzquiz_edit() { // Process moving, deleting and unhiding questions... $questionbank = new \core_question\local\bank\view($contexts, $url, $COURSE, $cm); - $questionbank->process_actions(); switch ($action) { case 'order': From a28a7ab5e9e5485a077cae12b3842a2a4932965a Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 11:24:51 +0200 Subject: [PATCH 06/23] Add array return type to wanted_columns() A return type was added to wanted_columns() in moodle/question/classes/local/bank/view.php in commit dfed4fd040ef874ed355ba621dc3c6d2021ab095. As a result, this overriding method needs to declare the same return type. --- classes/bank/jazzquiz_question_bank_view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index 07600ed..ebedfc2 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -47,7 +47,7 @@ class jazzquiz_question_bank_view extends \core_question\local\bank\view { * Define the columns we want to be displayed on the question bank * @return array */ - protected function wanted_columns() { + protected function wanted_columns(): array { // Full class names for question bank columns. $columns = [ '\\mod_jazzquiz\\bank\\question_bank_add_to_jazzquiz_action_column', From 610cbaa56a0836447c56d5c8e2843b3d7005b30b Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 11:32:36 +0200 Subject: [PATCH 07/23] Update method signature of overridden display() The signature of display() in moodle/question/classes/local/bank/view.php was updated in dfed4fd040ef874ed355ba621dc3c6d2021ab095. As a result, it needs to be changed in here to reflect the method it overrides. --- classes/bank/jazzquiz_question_bank_view.php | 21 ++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index ebedfc2..7dc8de8 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -75,16 +75,21 @@ protected function display_question_bank_header() { /** * Shows the question bank editing interface. * @param string $tabname - * @param int $page - * @param int $perpage - * @param string $cat - * @param bool $recurse - * @param bool $showhidden - * @param bool $showquestiontext - * @param array $tagids + * @param array $pagevars * @throws \coding_exception */ - public function display($tabname, $page, $perpage, $cat, $recurse, $showhidden, $showquestiontext, $tagids = []) { + public function display($pagevars, $tabname): void { + $page = $pagevars['qpage']; + $perpage = $pagevars['qperpage']; + $cat = $pagevars['cat']; + $recurse = $pagevars['recurse']; + $showhidden = $pagevars['showhidden']; + $showquestiontext = $pagevars['qbshowtext']; + $tagids = []; + if (!empty($pagevars['qtagids'])) { + $tagids = $pagevars['qtagids']; + } + global $PAGE; if ($this->process_actions_needing_ui()) { From 98b0fd14e37ec57912173c45ad90a8b49913b4c7 Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 11:37:19 +0200 Subject: [PATCH 08/23] Remove override of display_question_bank_header() As the TODO comment states, this is a fix for Moodle version 3.4 and earlier. Now that we're going to be supporting Moodle 4.0, I feel it's time to drop support for this. Because the overridden method signature has changed, so if we wanted to keep it we would have to update it. --- classes/bank/jazzquiz_question_bank_view.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index 7dc8de8..0c9f6d7 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -62,16 +62,6 @@ protected function wanted_columns(): array { return $this->requiredcolumns; } - /** - * Display the header element for the question bank. - * This is a copy of the super class method in 3.5+, and only exists for compatibility with 3.4 and earlier. - * TODO: This override should be removed in the future. - */ - protected function display_question_bank_header() { - global $OUTPUT; - echo $OUTPUT->heading(get_string('questionbank', 'question'), 2); - } - /** * Shows the question bank editing interface. * @param string $tabname From 9be9d4e4940b12765191fe1711917566adb30280 Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 11:41:20 +0200 Subject: [PATCH 09/23] Update create_new_question_form() signature The method siganture of this method in moodle/question/classes/local/bank/view.php was changed, so we need to update it in our overriding method. --- classes/bank/jazzquiz_question_bank_view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index 0c9f6d7..6e9fea1 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -141,7 +141,7 @@ public function get_add_to_jazzquiz_url($questionid) { * @throws \coding_exception * @throws \moodle_exception */ - protected function create_new_question_form($category, $add) { + protected function create_new_question_form($category, $add): void { echo '
'; if ($add) { $caption = get_string('create_new_question', 'jazzquiz'); From e29d525eba2f9e9a101fd9a8c38fd90d89521975 Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 11:47:02 +0200 Subject: [PATCH 10/23] Update reference to \core_question\bank\action_column_base This file was moved, so we need to change the path we reference. --- classes/bank/question_bank_add_to_jazzquiz_action_column.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/bank/question_bank_add_to_jazzquiz_action_column.php b/classes/bank/question_bank_add_to_jazzquiz_action_column.php index ab92389..a1f5ae2 100755 --- a/classes/bank/question_bank_add_to_jazzquiz_action_column.php +++ b/classes/bank/question_bank_add_to_jazzquiz_action_column.php @@ -34,7 +34,7 @@ * @copyright 2014 University of Wisconsin - Madison * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class question_bank_add_to_jazzquiz_action_column extends \core_question\bank\action_column_base { +class question_bank_add_to_jazzquiz_action_column extends \core_question\local\bank\action_column_base { /** * Get the name of the column. From 9285422f086c1264dfa3a5a59b9996d92fbe3c8d Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 11:47:25 +0200 Subject: [PATCH 11/23] Update get_required_fields() method signature The method signature for get_required_fields() in moodle/question/classes/local/bank/action_column_base.php changed so we need to update it in our code as well. --- classes/bank/question_bank_add_to_jazzquiz_action_column.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/bank/question_bank_add_to_jazzquiz_action_column.php b/classes/bank/question_bank_add_to_jazzquiz_action_column.php index a1f5ae2..e6a501f 100755 --- a/classes/bank/question_bank_add_to_jazzquiz_action_column.php +++ b/classes/bank/question_bank_add_to_jazzquiz_action_column.php @@ -61,7 +61,7 @@ protected function display_content($question, $rowclasses) { * Get the required fields. * @return string[] */ - public function get_required_fields() { + public function get_required_fields(): array { return ['q.id']; } From b570d34408c4b90a13d0db2d566c432599ee6713 Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 12:37:31 +0200 Subject: [PATCH 12/23] Update references to column class names These classes were moved and renamed, so we need to update the paths to them --- classes/bank/jazzquiz_question_bank_view.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index 6e9fea1..8853e84 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -51,10 +51,10 @@ protected function wanted_columns(): array { // Full class names for question bank columns. $columns = [ '\\mod_jazzquiz\\bank\\question_bank_add_to_jazzquiz_action_column', - 'core_question\\bank\\checkbox_column', - 'core_question\\bank\\question_type_column', - 'core_question\\bank\\question_name_column', - 'core_question\\bank\\preview_action_column' + 'core_question\\local\\bank\\checkbox_column', + 'qbank_viewquestiontype\\question_type_column', + 'qbank_viewquestionname\\viewquestionname_column_helper', + 'qbank_previewquestion\\preview_action_column' ]; foreach ($columns as $column) { $this->requiredcolumns[$column] = new $column($this); From 68deae56bd65373768a36f2f50320fabdf0fd354 Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 13:05:37 +0200 Subject: [PATCH 13/23] Correct arguments in call to display() We changed the signature of this method in 610cbaa56a0836447c56d5c8e2843b3d7005b30b but didn't update the places where it was called, so the code currently errors because it's passed a string where it expects an array. --- edit.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/edit.php b/edit.php index d5fd8a2..a046c49 100755 --- a/edit.php +++ b/edit.php @@ -60,10 +60,18 @@ function jazzquiz_session_open($jazzquizid) { function get_qbank_view(\core_question\local\bank\question_edit_contexts $contexts, jazzquiz $jazzquiz, \moodle_url $url, array $pagevars) { $qperpage = optional_param('qperpage', 10, PARAM_INT); $qpage = optional_param('qpage', 0, PARAM_INT); + $new_pagevars = [ + 'qpage' => $qpage, + 'qperpage' => $qperpage, + 'cat' => $pagevars['cat'], + 'recurse' => true, + 'showhidden' => true, + 'qbshowtext' => true + ]; // Capture question bank display in buffer to have the renderer render output. ob_start(); $questionbank = new bank\jazzquiz_question_bank_view($contexts, $url, $jazzquiz->course, $jazzquiz->cm); - $questionbank->display('editq', $qpage, $qperpage, $pagevars['cat'], true, true, true); + $questionbank->display($new_pagevars, 'editq'); return ob_get_clean(); } From debf9c1c5394ec4de72ed69520aa00b41ea7b15e Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 13:21:29 +0200 Subject: [PATCH 14/23] Remove call to process_actions_needing_ui() This function was deprecated in 0805e387b7735d7a599717e1f5c0ff4fabd1a5e0 in the Moodle repository. According to [upgrade.txt][1] any calls to this function can simply be removed. [1]: https://github.com/moodle/moodle/blob/0805e387b7735d7a599717e1f5c0ff4fabd1a5e0/question/upgrade.txt#L78-L80 --- classes/bank/jazzquiz_question_bank_view.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index 8853e84..d698b8b 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -82,9 +82,6 @@ public function display($pagevars, $tabname): void { global $PAGE; - if ($this->process_actions_needing_ui()) { - return; - } $contexts = $this->contexts->having_one_edit_tab_cap($tabname); list($categoryid, $contextid) = explode(',', $cat); $catcontext = \context::instance_by_id($contextid); From 53cf18fe5600fa64796c7b7728acba46934272bb Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Wed, 1 Jun 2022 14:23:52 +0200 Subject: [PATCH 15/23] Update arguments to display_question_list() The parameters of display_question_list() in moodle/question/classes/local/bank/view.php were changed in dfed4fd040ef874ed355ba621dc3c6d2021ab095, so this code no longer runs correctly. --- classes/bank/jazzquiz_question_bank_view.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/classes/bank/jazzquiz_question_bank_view.php b/classes/bank/jazzquiz_question_bank_view.php index d698b8b..e425430 100755 --- a/classes/bank/jazzquiz_question_bank_view.php +++ b/classes/bank/jazzquiz_question_bank_view.php @@ -96,15 +96,11 @@ public function display($pagevars, $tabname): void { // Continues with list of questions. $this->display_question_list( - $this->contexts->having_one_edit_tab_cap($tabname), $this->baseurl, $cat, - $this->cm, null, $page, - $perpage, - $showhidden, - $showquestiontext, + $perpage, $this->contexts->having_cap('moodle/question:add') ); $this->display_add_selected_questions_button(); From f50b19f1f8214b140ce1e68dff5add70fd72512d Mon Sep 17 00:00:00 2001 From: Julian Montague Date: Thu, 2 Jun 2022 15:03:23 +0200 Subject: [PATCH 16/23] Rebuild JavaScript with the latest Grunt version There's a strange error occuring in some of the code generated by Grunt when packaging. This is a hail mary to see if rebuilding with a newer version of grunt fixes anything. After moving the repository to the mod subdirectory in a moodle install, I ran the following commands (because babel apparently isn't installed and I can't be bothered to figure that out right now; Internet Explorer is dead): 1. npm install 2. cd amd 3. grunt amd --force --- amd/build/core.min.js | 12 ++++++++++-- amd/build/core.min.js.map | 2 +- amd/build/edit.min.js | 12 ++++++++++-- amd/build/edit.min.js.map | 2 +- amd/build/instructor.min.js | 12 ++++++++++-- amd/build/instructor.min.js.map | 2 +- amd/build/student.min.js | 12 ++++++++++-- amd/build/student.min.js.map | 2 +- 8 files changed, 44 insertions(+), 12 deletions(-) diff --git a/amd/build/core.min.js b/amd/build/core.min.js index 2927e03..da0b0c1 100644 --- a/amd/build/core.min.js +++ b/amd/build/core.min.js @@ -1,2 +1,10 @@ -function _classCallCheck(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(a,b){for(var c=0,d;c=this.countdownTimeLeft){clearInterval(this.countdownInterval);this.countdownInterval=0;this.startAttempt(a)}else if(0!==this.countdownTimeLeft){setText(Quiz.info,"question_will_start_in_x_seconds","jazzquiz",this.countdownTimeLeft)}else{setText(Quiz.info,"question_will_start_now")}}},{key:"startCountdown",value:function startCountdown(a,b){var c=this;if(0!==this.countdownInterval){return!0}a=parseInt(a);b=parseInt(b);this.countdownTimeLeft=b;if(1>b){if(0this.endTime){this.hideTimer();this.onTimerEnding()}else{var b=parseInt((this.endTime-a)/1e3);this.quiz.role.onTimerTick(b)}}},{key:"startAttempt",value:function startAttempt(a){var b=this;Quiz.hide(Quiz.info);this.refresh();this.isRunning=!0;a=parseInt(a);if(0===a){return}this.quiz.role.onTimerTick(a);this.endTime=new Date().getTime()+1e3*a;this.timerInterval=setInterval(function(){return b.onTimerTick()},1e3)}}],[{key:"box",get:function get(){return $("#jazzquiz_question_box")}},{key:"timer",get:function get(){return $("#jazzquiz_question_timer")}},{key:"form",get:function get(){return $("#jazzquiz_question_form")}},{key:"isLoaded",value:function isLoaded(){return""!==Question.box.html()}}]);return Question}(),Quiz=function(){function a(b){_classCallCheck(this,a);this.state="";this.isNewState=!1;this.question=new Question(this);this.role=new b(this);this.events={notrunning:"onNotRunning",preparing:"onPreparing",running:"onRunning",reviewing:"onReviewing",sessionclosed:"onSessionClosed",voting:"onVoting"}}_createClass(a,[{key:"changeQuizState",value:function changeQuizState(a,b){this.isNewState=this.state!==a;this.state=a;this.role.onStateChange(a);var c=this.events[a];this.role[c](b)}},{key:"poll",value:function poll(a){var b=this;Ajax.get("info",{},function(c){b.changeQuizState(c.status,c);setTimeout(function(){return b.poll(a)},a)})}}],[{key:"main",get:function get(){return $("#jazzquiz")}},{key:"info",get:function get(){return $("#jazzquiz_info_container")}},{key:"responded",get:function get(){return $("#jazzquiz_responded_container")}},{key:"responses",get:function get(){return $("#jazzquiz_responses_container")}},{key:"responseInfo",get:function get(){return $("#jazzquiz_response_info_container")}},{key:"hide",value:function hide(a){a.addClass("hidden")}},{key:"show",value:function show(a){a.removeClass("hidden")}},{key:"uncheck",value:function uncheck(a){a.children(".fa").removeClass("fa-check-square-o").addClass("fa-square-o")}},{key:"check",value:function check(a){a.children(".fa").removeClass("fa-square-o").addClass("fa-check-square-o")}},{key:"renderAllMathjax",value:function renderAllMathjax(){mEvent.notifyFilterContentUpdated(document.getElementsByClassName("jazzquiz-response-container"))}},{key:"addMathjaxElement",value:function addMathjaxElement(b,c){b.html(""+c+"");a.renderAllMathjax()}},{key:"renderMaximaEquation",value:function renderMaximaEquation(b,c){var d=document.getElementById(c);if(null===d){return}if(cache[b]!==void 0){a.addMathjaxElement($("#"+c),cache[b]);return}Ajax.get("stack",{input:encodeURIComponent(b)},function(b){cache[b.original]=b.latex;a.addMathjaxElement($("#"+c),b.latex)})}}]);return a}();function setText(a,b,c,d){c=c!==void 0?c:"jazzquiz";d=d!==void 0?d:[];$.when(mString.get_string(b,c,d)).done(function(b){return Quiz.show(a.html(b))})}return{initialize:function initialize(a,b,c,d,e){session.courseModuleId=a;session.activityId=b;session.sessionId=c;session.attemptId=d;session.sessionKey=e},Quiz:Quiz,Question:Question,Ajax:Ajax,setText:setText}}); -//# sourceMappingURL=core.min.js.map +/** + * @package mod_jazzquiz + * @author Sebastian S. Gundersen + * @copyright 2014 University of Wisconsin - Madison + * @copyright 2018 NTNU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define("mod_jazzquiz/core",["jquery","core/config","core/str","core/yui","core/event"],(function($,mConfig,mString,Y,mEvent){let session={courseModuleId:0,activityId:0,sessionId:0,attemptId:0,sessionKey:""},cache=[];class Ajax{static request(method,url,data,success){return data.id=session.courseModuleId,data.sessionid=session.sessionId,data.attemptid=session.attemptId,data.sesskey=session.sessionKey,$.ajax({type:method,url:url,data:data,dataType:"json",success:success,error:function(xhr,status,error){}}).fail((()=>setText(Quiz.info,"error_with_request")))}static get(action,data,success){return data.action=action,Ajax.request("get","ajax.php",data,success)}static post(action,data,success){return data.action=action,Ajax.request("post","ajax.php",data,success)}}class Question{constructor(quiz){this.quiz=quiz,this.isRunning=!1,this.isSaving=!1,this.endTime=0,this.isVoteRunning=!1,this.hasVotes=!1,this.countdownTimeLeft=0,this.questionTime=0,this.countdownInterval=0,this.timerInterval=0}static get box(){return $("#jazzquiz_question_box")}static get timer(){return $("#jazzquiz_question_timer")}static get form(){return $("#jazzquiz_question_form")}refresh(){Ajax.get("get_question_form",{},(data=>{data.is_already_submitted?setText(Quiz.info,"wait_for_instructor"):(Quiz.show(Question.box.html(data.html)),eval(data.js),data.css.forEach((cssUrl=>{let head=document.getElementsByTagName("head")[0],style=document.createElement("link");style.rel="stylesheet",style.type="text/css",style.href=cssUrl,head.appendChild(style)})),this.quiz.role.onQuestionRefreshed(data),Quiz.renderAllMathjax())}))}hideTimer(){Quiz.hide(Question.timer),clearInterval(this.timerInterval),this.timerInterval=0}onCountdownTick(questionTime){this.countdownTimeLeft--,this.countdownTimeLeft<=0?(clearInterval(this.countdownInterval),this.countdownInterval=0,this.startAttempt(questionTime)):0!==this.countdownTimeLeft?setText(Quiz.info,"question_will_start_in_x_seconds","jazzquiz",this.countdownTimeLeft):setText(Quiz.info,"question_will_start_now")}startCountdown(questionTime,countdownTimeLeft){return 0!==this.countdownInterval||(questionTime=parseInt(questionTime),countdownTimeLeft=parseInt(countdownTimeLeft),this.countdownTimeLeft=countdownTimeLeft,countdownTimeLeft<1?!(questionTime>0&&countdownTimeLeft<-questionTime)&&(questionTime>1?this.startAttempt(questionTime+countdownTimeLeft):this.startAttempt(0),!0):(this.countdownInterval=setInterval((()=>this.onCountdownTick(questionTime)),1e3),!0))}onTimerEnding(){this.isRunning=!1,this.quiz.role.onTimerEnding()}onTimerTick(){const currentTime=(new Date).getTime();if(currentTime>this.endTime)this.hideTimer(),this.onTimerEnding();else{const timeLeft=parseInt((this.endTime-currentTime)/1e3);this.quiz.role.onTimerTick(timeLeft)}}startAttempt(questionTime){Quiz.hide(Quiz.info),this.refresh(),this.isRunning=!0,0!==(questionTime=parseInt(questionTime))&&(this.quiz.role.onTimerTick(questionTime),this.endTime=(new Date).getTime()+1e3*questionTime,this.timerInterval=setInterval((()=>this.onTimerTick()),1e3))}static isLoaded(){return""!==Question.box.html()}}class Quiz{constructor(Role){this.state="",this.isNewState=!1,this.question=new Question(this),this.role=new Role(this),this.events={notrunning:"onNotRunning",preparing:"onPreparing",running:"onRunning",reviewing:"onReviewing",sessionclosed:"onSessionClosed",voting:"onVoting"}}changeQuizState(state,data){this.isNewState=this.state!==state,this.state=state,this.role.onStateChange(state);const event=this.events[state];this.role[event](data)}poll(ms){Ajax.get("info",{},(data=>{this.changeQuizState(data.status,data),setTimeout((()=>this.poll(ms)),ms)}))}static get main(){return $("#jazzquiz")}static get info(){return $("#jazzquiz_info_container")}static get responded(){return $("#jazzquiz_responded_container")}static get responses(){return $("#jazzquiz_responses_container")}static get responseInfo(){return $("#jazzquiz_response_info_container")}static hide($element){$element.addClass("hidden")}static show($element){$element.removeClass("hidden")}static uncheck($element){$element.children(".fa").removeClass("fa-check-square-o").addClass("fa-square-o")}static check($element){$element.children(".fa").removeClass("fa-square-o").addClass("fa-check-square-o")}static renderAllMathjax(){mEvent.notifyFilterContentUpdated(document.getElementsByClassName("jazzquiz-response-container"))}static addMathjaxElement($target,latex){$target.html(''+latex+""),Quiz.renderAllMathjax()}static renderMaximaEquation(input,targetId){null!==document.getElementById(targetId)&&(void 0===cache[input]?Ajax.get("stack",{input:encodeURIComponent(input)},(data=>{cache[data.original]=data.latex,Quiz.addMathjaxElement($("#"+targetId),data.latex)})):Quiz.addMathjaxElement($("#"+targetId),cache[input]))}}function setText($element,key,from,args){from=void 0!==from?from:"jazzquiz",args=void 0!==args?args:[],$.when(mString.get_string(key,from,args)).done((text=>Quiz.show($element.html(text))))}return{initialize:(courseModuleId,activityId,sessionId,attemptId,sessionKey)=>{session.courseModuleId=courseModuleId,session.activityId=activityId,session.sessionId=sessionId,session.attemptId=attemptId,session.sessionKey=sessionKey},Quiz:Quiz,Question:Question,Ajax:Ajax,setText:setText}})); + +//# sourceMappingURL=core.min.js.map \ No newline at end of file diff --git a/amd/build/core.min.js.map b/amd/build/core.min.js.map index 734489b..dc48efc 100644 --- a/amd/build/core.min.js.map +++ b/amd/build/core.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/core.js"],"names":["define","$","mConfig","mString","Y","mEvent","session","courseModuleId","activityId","sessionId","attemptId","sessionKey","cache","Ajax","method","url","data","success","id","sessionid","attemptid","sesskey","ajax","type","dataType","error","fail","setText","Quiz","info","action","request","Question","quiz","isRunning","isSaving","endTime","isVoteRunning","hasVotes","countdownTimeLeft","questionTime","countdownInterval","timerInterval","get","is_already_submitted","show","box","html","eval","js","css","forEach","cssUrl","head","document","getElementsByTagName","style","createElement","rel","href","appendChild","role","onQuestionRefreshed","renderAllMathjax","hide","timer","clearInterval","startAttempt","parseInt","setInterval","onCountdownTick","onTimerEnding","currentTime","Date","getTime","hideTimer","timeLeft","onTimerTick","refresh","Role","state","isNewState","question","events","notrunning","preparing","running","reviewing","sessionclosed","voting","onStateChange","event","ms","changeQuizState","status","setTimeout","poll","$element","addClass","removeClass","children","notifyFilterContentUpdated","getElementsByClassName","$target","latex","input","targetId","target","getElementById","addMathjaxElement","encodeURIComponent","original","key","from","args","when","get_string","done","text","initialize"],"mappings":"0YAuBAA,OAAM,qBAAC,CAAC,QAAD,CAAW,aAAX,CAA0B,UAA1B,CAAsC,UAAtC,CAAkD,YAAlD,CAAD,CAAkE,SAAUC,CAAV,CAAaC,OAAb,CAAsBC,OAAtB,CAA+BC,CAA/B,CAAkCC,MAAlC,CAA0C,IAG1GC,CAAAA,OAAO,CAAG,CACVC,cAAc,CAAE,CADN,CAEVC,UAAU,CAAE,CAFF,CAGVC,SAAS,CAAE,CAHD,CAIVC,SAAS,CAAE,CAJD,CAKVC,UAAU,CAAE,EALF,CAHgG,CAY1GC,KAAK,CAAG,EAZkG,CAexGC,IAfwG,2FAyB1G,iBAAeC,CAAf,CAAuBC,CAAvB,CAA4BC,CAA5B,CAAkCC,CAAlC,CAA2C,CACvCD,CAAI,CAACE,EAAL,CAAUZ,OAAO,CAACC,cAAlB,CACAS,CAAI,CAACG,SAAL,CAAiBb,OAAO,CAACG,SAAzB,CACAO,CAAI,CAACI,SAAL,CAAiBd,OAAO,CAACI,SAAzB,CACAM,CAAI,CAACK,OAAL,CAAef,OAAO,CAACK,UAAvB,CACA,MAAOV,CAAAA,CAAC,CAACqB,IAAF,CAAO,CACVC,IAAI,CAAET,CADI,CAEVC,GAAG,CAAEA,CAFK,CAGVC,IAAI,CAAEA,CAHI,CAIVQ,QAAQ,CAAE,MAJA,CAKVP,OAAO,CAAEA,CALC,CAMVQ,KAAK,CAAE,gBAA8B,CAEpC,CARS,CAAP,EASJC,IATI,CASC,iBAAMC,CAAAA,OAAO,CAACC,IAAI,CAACC,IAAN,CAAY,oBAAZ,CAAb,CATD,CAUV,CAxCyG,mBAiD1G,aAAWC,CAAX,CAAmBd,CAAnB,CAAyBC,CAAzB,CAAkC,CAC9BD,CAAI,CAACc,MAAL,CAAcA,CAAd,CACA,MAAOjB,CAAAA,CAAI,CAACkB,OAAL,CAAa,KAAb,CAAoB,UAApB,CAAgCf,CAAhC,CAAsCC,CAAtC,CACV,CApDyG,oBA6D1G,cAAYa,CAAZ,CAAoBd,CAApB,CAA0BC,CAA1B,CAAmC,CAC/BD,CAAI,CAACc,MAAL,CAAcA,CAAd,CACA,MAAOjB,CAAAA,CAAI,CAACkB,OAAL,CAAa,MAAb,CAAqB,UAArB,CAAiCf,CAAjC,CAAuCC,CAAvC,CACV,CAhEyG,gBAoExGe,QApEwG,YAsE1G,kBAAYC,CAAZ,CAAkB,gCACd,KAAKA,IAAL,CAAYA,CAAZ,CACA,KAAKC,SAAL,IACA,KAAKC,QAAL,IACA,KAAKC,OAAL,CAAe,CAAf,CACA,KAAKC,aAAL,IACA,KAAKC,QAAL,IACA,KAAKC,iBAAL,CAAyB,CAAzB,CACA,KAAKC,YAAL,CAAoB,CAApB,CACA,KAAKC,iBAAL,CAAyB,CAAzB,CACA,KAAKC,aAAL,CAAqB,CACxB,CAjFyG,4CAkG1G,kBAAU,gBACN7B,IAAI,CAAC8B,GAAL,CAAS,mBAAT,CAA8B,EAA9B,CAAkC,SAAA3B,IAAI,CAAI,CACtC,GAAIA,IAAI,CAAC4B,oBAAT,CAA+B,CAC3BjB,OAAO,CAACC,IAAI,CAACC,IAAN,CAAY,qBAAZ,CAAP,CACA,MACH,CACDD,IAAI,CAACiB,IAAL,CAAUb,QAAQ,CAACc,GAAT,CAAaC,IAAb,CAAkB/B,IAAI,CAAC+B,IAAvB,CAAV,EACAC,IAAI,CAAChC,IAAI,CAACiC,EAAN,CAAJ,CACAjC,IAAI,CAACkC,GAAL,CAASC,OAAT,CAAiB,SAAAC,CAAM,CAAI,IACnBC,CAAAA,CAAI,CAAGC,QAAQ,CAACC,oBAAT,CAA8B,MAA9B,EAAsC,CAAtC,CADY,CAEnBC,CAAK,CAAGF,QAAQ,CAACG,aAAT,CAAuB,MAAvB,CAFW,CAGvBD,CAAK,CAACE,GAAN,CAAY,YAAZ,CACAF,CAAK,CAACjC,IAAN,CAAa,UAAb,CACAiC,CAAK,CAACG,IAAN,CAAaP,CAAb,CACAC,CAAI,CAACO,WAAL,CAAiBJ,CAAjB,CACH,CAPD,EAQA,KAAI,CAACvB,IAAL,CAAU4B,IAAV,CAAeC,mBAAf,CAAmC9C,IAAnC,EACAY,IAAI,CAACmC,gBAAL,EACH,CAjBD,CAkBH,CArHyG,yBA0H1G,oBAAY,CACRnC,IAAI,CAACoC,IAAL,CAAUhC,QAAQ,CAACiC,KAAnB,EACAC,aAAa,CAAC,KAAKxB,aAAN,CAAb,CACA,KAAKA,aAAL,CAAqB,CACxB,CA9HyG,+BAoI1G,yBAAgBF,CAAhB,CAA8B,CAC1B,KAAKD,iBAAL,GACA,GAA8B,CAA1B,OAAKA,iBAAT,CAAiC,CAC7B2B,aAAa,CAAC,KAAKzB,iBAAN,CAAb,CACA,KAAKA,iBAAL,CAAyB,CAAzB,CACA,KAAK0B,YAAL,CAAkB3B,CAAlB,CACH,CAJD,IAIO,IAA+B,CAA3B,QAAKD,iBAAT,CAAkC,CACrCZ,OAAO,CAACC,IAAI,CAACC,IAAN,CAAY,kCAAZ,CAAgD,UAAhD,CAA4D,KAAKU,iBAAjE,CACV,CAFM,IAEA,CACHZ,OAAO,CAACC,IAAI,CAACC,IAAN,CAAY,yBAAZ,CACV,CACJ,CA/IyG,8BAyJ1G,wBAAeW,CAAf,CAA6BD,CAA7B,CAAgD,YAC5C,GAA+B,CAA3B,QAAKE,iBAAT,CAAkC,CAC9B,QACH,CACDD,CAAY,CAAG4B,QAAQ,CAAC5B,CAAD,CAAvB,CACAD,CAAiB,CAAG6B,QAAQ,CAAC7B,CAAD,CAA5B,CACA,KAAKA,iBAAL,CAAyBA,CAAzB,CACA,GAAwB,CAApB,CAAAA,CAAJ,CAA2B,CAEvB,GAAmB,CAAf,CAAAC,CAAY,EAAQD,CAAiB,CAAG,CAACC,CAA7C,CAA2D,CACvD,QACH,CAED,GAAmB,CAAf,CAAAA,CAAJ,CAAsB,CAClB,KAAK2B,YAAL,CAAkB3B,CAAY,CAAGD,CAAjC,CACH,CAFD,IAEO,CACH,KAAK4B,YAAL,CAAkB,CAAlB,CACH,CACD,QACH,CACD,KAAK1B,iBAAL,CAAyB4B,WAAW,CAAC,iBAAM,CAAA,CAAI,CAACC,eAAL,CAAqB9B,CAArB,CAAN,CAAD,CAA2C,GAA3C,CAApC,CACA,QACH,CA/KyG,6BAoL1G,wBAAgB,CACZ,KAAKN,SAAL,IACA,KAAKD,IAAL,CAAU4B,IAAV,CAAeU,aAAf,EACH,CAvLyG,2BA4L1G,sBAAc,CACV,GAAMC,CAAAA,CAAW,CAAG,GAAIC,CAAAA,IAAJ,GAAWC,OAAX,EAApB,CACA,GAAIF,CAAW,CAAG,KAAKpC,OAAvB,CAAgC,CAC5B,KAAKuC,SAAL,GACA,KAAKJ,aAAL,EACH,CAHD,IAGO,CACH,GAAMK,CAAAA,CAAQ,CAAGR,QAAQ,CAAC,CAAC,KAAKhC,OAAL,CAAeoC,CAAhB,EAA+B,GAAhC,CAAzB,CACA,KAAKvC,IAAL,CAAU4B,IAAV,CAAegB,WAAf,CAA2BD,CAA3B,CACH,CACJ,CArMyG,4BA2M1G,sBAAapC,CAAb,CAA2B,YACvBZ,IAAI,CAACoC,IAAL,CAAUpC,IAAI,CAACC,IAAf,EACA,KAAKiD,OAAL,GAEA,KAAK5C,SAAL,IACAM,CAAY,CAAG4B,QAAQ,CAAC5B,CAAD,CAAvB,CACA,GAAqB,CAAjB,GAAAA,CAAJ,CAAwB,CAEpB,MACH,CACD,KAAKP,IAAL,CAAU4B,IAAV,CAAegB,WAAf,CAA2BrC,CAA3B,EACA,KAAKJ,OAAL,CAAe,GAAIqC,CAAAA,IAAJ,GAAWC,OAAX,GAAsC,GAAf,CAAAlC,CAAtC,CACA,KAAKE,aAAL,CAAqB2B,WAAW,CAAC,iBAAM,CAAA,CAAI,CAACQ,WAAL,EAAN,CAAD,CAA2B,GAA3B,CACnC,CAxNyG,mBAmF1G,cAAiB,CACb,MAAO5E,CAAAA,CAAC,CAAC,wBAAD,CACX,CArFyG,mBAuF1G,cAAmB,CACf,MAAOA,CAAAA,CAAC,CAAC,0BAAD,CACX,CAzFyG,kBA2F1G,cAAkB,CACd,MAAOA,CAAAA,CAAC,CAAC,yBAAD,CACX,CA7FyG,wBA0N1G,mBAAkB,CACd,MAA+B,EAAxB,GAAA+B,QAAQ,CAACc,GAAT,CAAaC,IAAb,EACV,CA5NyG,uBAgOxGnB,IAhOwG,YAkO1G,WAAYmD,CAAZ,CAAkB,yBACd,KAAKC,KAAL,CAAa,EAAb,CACA,KAAKC,UAAL,IACA,KAAKC,QAAL,CAAgB,GAAIlD,CAAAA,QAAJ,CAAa,IAAb,CAAhB,CACA,KAAK6B,IAAL,CAAY,GAAIkB,CAAAA,CAAJ,CAAS,IAAT,CAAZ,CACA,KAAKI,MAAL,CAAc,CACVC,UAAU,CAAE,cADF,CAEVC,SAAS,CAAE,aAFD,CAGVC,OAAO,CAAE,WAHC,CAIVC,SAAS,CAAE,aAJD,CAKVC,aAAa,CAAE,iBALL,CAMVC,MAAM,CAAE,UANE,CAQjB,CA/OyG,6CAiP1G,yBAAgBT,CAAhB,CAAuBhE,CAAvB,CAA6B,CACzB,KAAKiE,UAAL,CAAmB,KAAKD,KAAL,GAAeA,CAAlC,CACA,KAAKA,KAAL,CAAaA,CAAb,CACA,KAAKnB,IAAL,CAAU6B,aAAV,CAAwBV,CAAxB,EACA,GAAMW,CAAAA,CAAK,CAAG,KAAKR,MAAL,CAAYH,CAAZ,CAAd,CACA,KAAKnB,IAAL,CAAU8B,CAAV,EAAiB3E,CAAjB,CACH,CAvPyG,oBA6P1G,cAAK4E,CAAL,CAAS,YACL/E,IAAI,CAAC8B,GAAL,CAAS,MAAT,CAAiB,EAAjB,CAAqB,SAAA3B,CAAI,CAAI,CACzB,CAAI,CAAC6E,eAAL,CAAqB7E,CAAI,CAAC8E,MAA1B,CAAkC9E,CAAlC,EACA+E,UAAU,CAAC,iBAAM,CAAA,CAAI,CAACC,IAAL,CAAUJ,CAAV,CAAN,CAAD,CAAsBA,CAAtB,CACb,CAHD,CAIH,CAlQyG,oBAoQ1G,cAAkB,CACd,MAAO3F,CAAAA,CAAC,CAAC,WAAD,CACX,CAtQyG,kBAwQ1G,cAAkB,CACd,MAAOA,CAAAA,CAAC,CAAC,0BAAD,CACX,CA1QyG,uBA4Q1G,cAAuB,CACnB,MAAOA,CAAAA,CAAC,CAAC,+BAAD,CACX,CA9QyG,uBAgR1G,cAAuB,CACnB,MAAOA,CAAAA,CAAC,CAAC,+BAAD,CACX,CAlRyG,0BAoR1G,cAA0B,CACtB,MAAOA,CAAAA,CAAC,CAAC,mCAAD,CACX,CAtRyG,oBAwR1G,cAAYgG,CAAZ,CAAsB,CAClBA,CAAQ,CAACC,QAAT,CAAkB,QAAlB,CACH,CA1RyG,oBA4R1G,cAAYD,CAAZ,CAAsB,CAClBA,CAAQ,CAACE,WAAT,CAAqB,QAArB,CACH,CA9RyG,uBAgS1G,iBAAeF,CAAf,CAAyB,CACrBA,CAAQ,CAACG,QAAT,CAAkB,KAAlB,EAAyBD,WAAzB,CAAqC,mBAArC,EAA0DD,QAA1D,CAAmE,aAAnE,CACH,CAlSyG,qBAoS1G,eAAaD,CAAb,CAAuB,CACnBA,CAAQ,CAACG,QAAT,CAAkB,KAAlB,EAAyBD,WAAzB,CAAqC,aAArC,EAAoDD,QAApD,CAA6D,mBAA7D,CACH,CAtSyG,gCA2S1G,2BAA0B,CACtB7F,MAAM,CAACgG,0BAAP,CAAkC/C,QAAQ,CAACgD,sBAAT,CAAgC,6BAAhC,CAAlC,CACH,CA7SyG,iCAoT1G,2BAAyBC,CAAzB,CAAkCC,CAAlC,CAAyC,CACrCD,CAAO,CAACxD,IAAR,CAAa,iDAAiDyD,CAAjD,CAAyD,SAAtE,EACA5E,CAAI,CAACmC,gBAAL,EACH,CAvTyG,oCA8T1G,8BAA4B0C,CAA5B,CAAmCC,CAAnC,CAA6C,CACzC,GAAMC,CAAAA,CAAM,CAAGrD,QAAQ,CAACsD,cAAT,CAAwBF,CAAxB,CAAf,CACA,GAAe,IAAX,GAAAC,CAAJ,CAAqB,CAEjB,MACH,CACD,GAAI/F,KAAK,CAAC6F,CAAD,CAAL,SAAJ,CAAgC,CAC5B7E,CAAI,CAACiF,iBAAL,CAAuB5G,CAAC,CAAC,IAAMyG,CAAP,CAAxB,CAA0C9F,KAAK,CAAC6F,CAAD,CAA/C,EACA,MACH,CACD5F,IAAI,CAAC8B,GAAL,CAAS,OAAT,CAAkB,CAAC8D,KAAK,CAAEK,kBAAkB,CAACL,CAAD,CAA1B,CAAlB,CAAsD,SAAAzF,CAAI,CAAI,CAC1DJ,KAAK,CAACI,CAAI,CAAC+F,QAAN,CAAL,CAAuB/F,CAAI,CAACwF,KAA5B,CACA5E,CAAI,CAACiF,iBAAL,CAAuB5G,CAAC,CAAC,IAAMyG,CAAP,CAAxB,CAA0C1F,CAAI,CAACwF,KAA/C,CACH,CAHD,CAIH,CA5UyG,gBAuV9G,QAAS7E,CAAAA,OAAT,CAAiBsE,CAAjB,CAA2Be,CAA3B,CAAgCC,CAAhC,CAAsCC,CAAtC,CAA4C,CACxCD,CAAI,CAAIA,CAAI,SAAL,CAAuBA,CAAvB,CAA8B,UAArC,CACAC,CAAI,CAAIA,CAAI,SAAL,CAAuBA,CAAvB,CAA8B,EAArC,CACAjH,CAAC,CAACkH,IAAF,CAAOhH,OAAO,CAACiH,UAAR,CAAmBJ,CAAnB,CAAwBC,CAAxB,CAA8BC,CAA9B,CAAP,EAA4CG,IAA5C,CAAiD,SAAAC,CAAI,QAAI1F,CAAAA,IAAI,CAACiB,IAAL,CAAUoD,CAAQ,CAAClD,IAAT,CAAcuE,CAAd,CAAV,CAAJ,CAArD,CACH,CAED,MAAO,CACHC,UAAU,CAAE,oBAAChH,CAAD,CAAiBC,CAAjB,CAA6BC,CAA7B,CAAwCC,CAAxC,CAAmDC,CAAnD,CAAkE,CAC1EL,OAAO,CAACC,cAAR,CAAyBA,CAAzB,CACAD,OAAO,CAACE,UAAR,CAAqBA,CAArB,CACAF,OAAO,CAACG,SAAR,CAAoBA,CAApB,CACAH,OAAO,CAACI,SAAR,CAAoBA,CAApB,CACAJ,OAAO,CAACK,UAAR,CAAqBA,CACxB,CAPE,CAQHiB,IAAI,CAAEA,IARH,CASHI,QAAQ,CAAEA,QATP,CAUHnB,IAAI,CAAEA,IAVH,CAWHc,OAAO,CAAEA,OAXN,CAcV,CA3WK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2014 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/config', 'core/str', 'core/yui', 'core/event'], function ($, mConfig, mString, Y, mEvent) {\n\n // Contains the needed values for using the ajax script.\n let session = {\n courseModuleId: 0,\n activityId: 0, // TODO: Remove activityId? Unsure if used.\n sessionId: 0,\n attemptId: 0,\n sessionKey: ''\n };\n\n // Used for caching the latex of maxima input.\n let cache = [];\n\n // TODO: Migrate to core/ajax module?\n class Ajax {\n\n /**\n * Send a request using AJAX, with method specified.\n * @param {string} method Which HTTP method to use.\n * @param {string} url Relative to root of jazzquiz module. Does not start with /.\n * @param {Object} data Object with parameters as properties. Reserved: id, quizid, sessionid, attemptid, sesskey\n * @param {function} success Callback function for when the request was completed successfully.\n * @return {jqXHR} The jQuery XHR object\n */\n static request(method, url, data, success) {\n data.id = session.courseModuleId;\n data.sessionid = session.sessionId;\n data.attemptid = session.attemptId;\n data.sesskey = session.sessionKey;\n return $.ajax({\n type: method,\n url: url,\n data: data,\n dataType: 'json',\n success: success,\n error: function (xhr, status, error) {\n //console.error('XHR Error: ' + error + '. Status: ' + status);\n }\n }).fail(() => setText(Quiz.info, 'error_with_request'));\n }\n\n /**\n * Send a GET request using AJAX.\n * @param {string} action Which action to query.\n * @param {Object} data Object with parameters as properties. Reserved: id, quizid, sessionid, attemptid, sesskey\n * @param {function} success Callback function for when the request was completed successfully.\n * @return {jqXHR} The jQuery XHR object\n */\n static get(action, data, success) {\n data.action = action;\n return Ajax.request('get', 'ajax.php', data, success);\n }\n\n /**\n * Send a POST request using AJAX.\n * @param {string} action Which action to query.\n * @param {Object} data Object with parameters as properties. Reserved: id, quizid, sessionid, attemptid, sesskey\n * @param {function} success Callback function for when the request was completed successfully.\n * @return {jqXHR} The jQuery XHR object\n */\n static post(action, data, success) {\n data.action = action;\n return Ajax.request('post', 'ajax.php', data, success);\n }\n\n }\n\n class Question {\n\n constructor(quiz) {\n this.quiz = quiz;\n this.isRunning = false;\n this.isSaving = false;\n this.endTime = 0;\n this.isVoteRunning = false;\n this.hasVotes = false;\n this.countdownTimeLeft = 0;\n this.questionTime = 0;\n this.countdownInterval = 0;\n this.timerInterval = 0;\n }\n\n static get box() {\n return $('#jazzquiz_question_box');\n }\n\n static get timer() {\n return $('#jazzquiz_question_timer');\n }\n\n static get form() {\n return $('#jazzquiz_question_form');\n }\n\n /**\n * Request the current question form.\n */\n refresh() {\n Ajax.get('get_question_form', {}, data => {\n if (data.is_already_submitted) {\n setText(Quiz.info, 'wait_for_instructor');\n return;\n }\n Quiz.show(Question.box.html(data.html));\n eval(data.js);\n data.css.forEach(cssUrl => {\n let head = document.getElementsByTagName('head')[0];\n let style = document.createElement('link');\n style.rel = 'stylesheet';\n style.type = 'text/css';\n style.href = cssUrl;\n head.appendChild(style);\n });\n this.quiz.role.onQuestionRefreshed(data);\n Quiz.renderAllMathjax();\n });\n }\n\n /**\n * Hide the question \"ending in\" timer, and clears the interval.\n */\n hideTimer() {\n Quiz.hide(Question.timer);\n clearInterval(this.timerInterval);\n this.timerInterval = 0;\n }\n\n /**\n * Is called for every second of the question countdown.\n * @param {number} questionTime in seconds\n */\n onCountdownTick(questionTime) {\n this.countdownTimeLeft--;\n if (this.countdownTimeLeft <= 0) {\n clearInterval(this.countdownInterval);\n this.countdownInterval = 0;\n this.startAttempt(questionTime);\n } else if (this.countdownTimeLeft !== 0) {\n setText(Quiz.info, 'question_will_start_in_x_seconds', 'jazzquiz', this.countdownTimeLeft);\n } else {\n setText(Quiz.info, 'question_will_start_now');\n }\n }\n\n /**\n * Start a countdown for the question which will eventually start the question attempt.\n * The question attempt might start before this function return, depending on the arguments.\n * If a countdown has already been started, this call will return true and the current countdown will continue.\n * @param {number} questionTime\n * @param {number} countdownTimeLeft\n * @return {boolean} true if countdown is active\n */\n startCountdown(questionTime, countdownTimeLeft) {\n if (this.countdownInterval !== 0) {\n return true;\n }\n questionTime = parseInt(questionTime);\n countdownTimeLeft = parseInt(countdownTimeLeft);\n this.countdownTimeLeft = countdownTimeLeft;\n if (countdownTimeLeft < 1) {\n // Check if the question has already ended.\n if (questionTime > 0 && countdownTimeLeft < -questionTime) {\n return false;\n }\n // No need to start the countdown. Just start the question.\n if (questionTime > 1) {\n this.startAttempt(questionTime + countdownTimeLeft);\n } else {\n this.startAttempt(0);\n }\n return true;\n }\n this.countdownInterval = setInterval(() => this.onCountdownTick(questionTime), 1000);\n return true;\n }\n\n /**\n * When the question \"ending in\" timer reaches 0 seconds, this will be called.\n */\n onTimerEnding() {\n this.isRunning = false;\n this.quiz.role.onTimerEnding();\n }\n\n /**\n * Is called for every second of the \"ending in\" timer.\n */\n onTimerTick() {\n const currentTime = new Date().getTime();\n if (currentTime > this.endTime) {\n this.hideTimer();\n this.onTimerEnding();\n } else {\n const timeLeft = parseInt((this.endTime - currentTime) / 1000);\n this.quiz.role.onTimerTick(timeLeft);\n }\n }\n\n /**\n * Request the current question from the server.\n * @param {number} questionTime\n */\n startAttempt(questionTime) {\n Quiz.hide(Quiz.info);\n this.refresh();\n // Set this to true so that we don't keep calling this over and over.\n this.isRunning = true;\n questionTime = parseInt(questionTime);\n if (questionTime === 0) {\n // 0 means no timer.\n return;\n }\n this.quiz.role.onTimerTick(questionTime); // TODO: Is it worth having this line?\n this.endTime = new Date().getTime() + questionTime * 1000;\n this.timerInterval = setInterval(() => this.onTimerTick(), 1000);\n }\n\n static isLoaded() {\n return Question.box.html() !== '';\n }\n\n }\n\n class Quiz {\n\n constructor(Role) {\n this.state = '';\n this.isNewState = false;\n this.question = new Question(this);\n this.role = new Role(this);\n this.events = {\n notrunning: 'onNotRunning',\n preparing: 'onPreparing',\n running: 'onRunning',\n reviewing: 'onReviewing',\n sessionclosed: 'onSessionClosed',\n voting: 'onVoting'\n };\n }\n\n changeQuizState(state, data) {\n this.isNewState = (this.state !== state);\n this.state = state;\n this.role.onStateChange(state);\n const event = this.events[state];\n this.role[event](data);\n }\n\n /**\n * Initiate the chained session info calls to ajax.php\n * @param {number} ms interval in milliseconds\n */\n poll(ms) {\n Ajax.get('info', {}, data => {\n this.changeQuizState(data.status, data);\n setTimeout(() => this.poll(ms), ms);\n });\n }\n\n static get main() {\n return $('#jazzquiz');\n }\n\n static get info() {\n return $('#jazzquiz_info_container');\n }\n\n static get responded() {\n return $('#jazzquiz_responded_container');\n }\n\n static get responses() {\n return $('#jazzquiz_responses_container');\n }\n\n static get responseInfo() {\n return $('#jazzquiz_response_info_container');\n }\n\n static hide($element) {\n $element.addClass('hidden');\n }\n\n static show($element) {\n $element.removeClass('hidden');\n }\n\n static uncheck($element) {\n $element.children('.fa').removeClass('fa-check-square-o').addClass('fa-square-o');\n }\n\n static check($element) {\n $element.children('.fa').removeClass('fa-square-o').addClass('fa-check-square-o');\n }\n\n /**\n * Triggers a dynamic content update event, which MathJax listens to.\n */\n static renderAllMathjax() {\n mEvent.notifyFilterContentUpdated(document.getElementsByClassName('jazzquiz-response-container'));\n }\n\n /**\n * Sets the body of the target, and triggers an event letting MathJax know about the element.\n * @param {*} $target\n * @param {string} latex\n */\n static addMathjaxElement($target, latex) {\n $target.html('' + latex + '');\n Quiz.renderAllMathjax();\n }\n\n /**\n * Converts the input to LaTeX and renders it to the target with MathJax.\n * @param {string} input\n * @param {string} targetId\n */\n static renderMaximaEquation(input, targetId) {\n const target = document.getElementById(targetId);\n if (target === null) {\n //console.error('Target element #' + targetId + ' not found.');\n return;\n }\n if (cache[input] !== undefined) {\n Quiz.addMathjaxElement($('#' + targetId), cache[input]);\n return;\n }\n Ajax.get('stack', {input: encodeURIComponent(input)}, data => {\n cache[data.original] = data.latex;\n Quiz.addMathjaxElement($('#' + targetId), data.latex);\n });\n }\n\n }\n\n /**\n * Retrieve a language string that was sent along with the page.\n * @param $element\n * @param {string} key Which string in the language file we want.\n * @param {string} [from=jazzquiz] Which language file we want the string from. Default is jazzquiz.\n * @param [args] This is {$a} in the string for the key.\n */\n function setText($element, key, from, args) {\n from = (from !== undefined) ? from : 'jazzquiz';\n args = (args !== undefined) ? args : [];\n $.when(mString.get_string(key, from, args)).done(text => Quiz.show($element.html(text)));\n }\n\n return {\n initialize: (courseModuleId, activityId, sessionId, attemptId, sessionKey) => {\n session.courseModuleId = courseModuleId;\n session.activityId = activityId;\n session.sessionId = sessionId;\n session.attemptId = attemptId;\n session.sessionKey = sessionKey;\n },\n Quiz: Quiz,\n Question: Question,\n Ajax: Ajax,\n setText: setText\n };\n\n});\n"],"file":"core.min.js"} \ No newline at end of file +{"version":3,"file":"core.min.js","sources":["../src/core.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2014 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/config', 'core/str', 'core/yui', 'core/event'], function ($, mConfig, mString, Y, mEvent) {\n\n // Contains the needed values for using the ajax script.\n let session = {\n courseModuleId: 0,\n activityId: 0, // TODO: Remove activityId? Unsure if used.\n sessionId: 0,\n attemptId: 0,\n sessionKey: ''\n };\n\n // Used for caching the latex of maxima input.\n let cache = [];\n\n // TODO: Migrate to core/ajax module?\n class Ajax {\n\n /**\n * Send a request using AJAX, with method specified.\n * @param {string} method Which HTTP method to use.\n * @param {string} url Relative to root of jazzquiz module. Does not start with /.\n * @param {Object} data Object with parameters as properties. Reserved: id, quizid, sessionid, attemptid, sesskey\n * @param {function} success Callback function for when the request was completed successfully.\n * @return {jqXHR} The jQuery XHR object\n */\n static request(method, url, data, success) {\n data.id = session.courseModuleId;\n data.sessionid = session.sessionId;\n data.attemptid = session.attemptId;\n data.sesskey = session.sessionKey;\n return $.ajax({\n type: method,\n url: url,\n data: data,\n dataType: 'json',\n success: success,\n error: function (xhr, status, error) {\n //console.error('XHR Error: ' + error + '. Status: ' + status);\n }\n }).fail(() => setText(Quiz.info, 'error_with_request'));\n }\n\n /**\n * Send a GET request using AJAX.\n * @param {string} action Which action to query.\n * @param {Object} data Object with parameters as properties. Reserved: id, quizid, sessionid, attemptid, sesskey\n * @param {function} success Callback function for when the request was completed successfully.\n * @return {jqXHR} The jQuery XHR object\n */\n static get(action, data, success) {\n data.action = action;\n return Ajax.request('get', 'ajax.php', data, success);\n }\n\n /**\n * Send a POST request using AJAX.\n * @param {string} action Which action to query.\n * @param {Object} data Object with parameters as properties. Reserved: id, quizid, sessionid, attemptid, sesskey\n * @param {function} success Callback function for when the request was completed successfully.\n * @return {jqXHR} The jQuery XHR object\n */\n static post(action, data, success) {\n data.action = action;\n return Ajax.request('post', 'ajax.php', data, success);\n }\n\n }\n\n class Question {\n\n constructor(quiz) {\n this.quiz = quiz;\n this.isRunning = false;\n this.isSaving = false;\n this.endTime = 0;\n this.isVoteRunning = false;\n this.hasVotes = false;\n this.countdownTimeLeft = 0;\n this.questionTime = 0;\n this.countdownInterval = 0;\n this.timerInterval = 0;\n }\n\n static get box() {\n return $('#jazzquiz_question_box');\n }\n\n static get timer() {\n return $('#jazzquiz_question_timer');\n }\n\n static get form() {\n return $('#jazzquiz_question_form');\n }\n\n /**\n * Request the current question form.\n */\n refresh() {\n Ajax.get('get_question_form', {}, data => {\n if (data.is_already_submitted) {\n setText(Quiz.info, 'wait_for_instructor');\n return;\n }\n Quiz.show(Question.box.html(data.html));\n eval(data.js);\n data.css.forEach(cssUrl => {\n let head = document.getElementsByTagName('head')[0];\n let style = document.createElement('link');\n style.rel = 'stylesheet';\n style.type = 'text/css';\n style.href = cssUrl;\n head.appendChild(style);\n });\n this.quiz.role.onQuestionRefreshed(data);\n Quiz.renderAllMathjax();\n });\n }\n\n /**\n * Hide the question \"ending in\" timer, and clears the interval.\n */\n hideTimer() {\n Quiz.hide(Question.timer);\n clearInterval(this.timerInterval);\n this.timerInterval = 0;\n }\n\n /**\n * Is called for every second of the question countdown.\n * @param {number} questionTime in seconds\n */\n onCountdownTick(questionTime) {\n this.countdownTimeLeft--;\n if (this.countdownTimeLeft <= 0) {\n clearInterval(this.countdownInterval);\n this.countdownInterval = 0;\n this.startAttempt(questionTime);\n } else if (this.countdownTimeLeft !== 0) {\n setText(Quiz.info, 'question_will_start_in_x_seconds', 'jazzquiz', this.countdownTimeLeft);\n } else {\n setText(Quiz.info, 'question_will_start_now');\n }\n }\n\n /**\n * Start a countdown for the question which will eventually start the question attempt.\n * The question attempt might start before this function return, depending on the arguments.\n * If a countdown has already been started, this call will return true and the current countdown will continue.\n * @param {number} questionTime\n * @param {number} countdownTimeLeft\n * @return {boolean} true if countdown is active\n */\n startCountdown(questionTime, countdownTimeLeft) {\n if (this.countdownInterval !== 0) {\n return true;\n }\n questionTime = parseInt(questionTime);\n countdownTimeLeft = parseInt(countdownTimeLeft);\n this.countdownTimeLeft = countdownTimeLeft;\n if (countdownTimeLeft < 1) {\n // Check if the question has already ended.\n if (questionTime > 0 && countdownTimeLeft < -questionTime) {\n return false;\n }\n // No need to start the countdown. Just start the question.\n if (questionTime > 1) {\n this.startAttempt(questionTime + countdownTimeLeft);\n } else {\n this.startAttempt(0);\n }\n return true;\n }\n this.countdownInterval = setInterval(() => this.onCountdownTick(questionTime), 1000);\n return true;\n }\n\n /**\n * When the question \"ending in\" timer reaches 0 seconds, this will be called.\n */\n onTimerEnding() {\n this.isRunning = false;\n this.quiz.role.onTimerEnding();\n }\n\n /**\n * Is called for every second of the \"ending in\" timer.\n */\n onTimerTick() {\n const currentTime = new Date().getTime();\n if (currentTime > this.endTime) {\n this.hideTimer();\n this.onTimerEnding();\n } else {\n const timeLeft = parseInt((this.endTime - currentTime) / 1000);\n this.quiz.role.onTimerTick(timeLeft);\n }\n }\n\n /**\n * Request the current question from the server.\n * @param {number} questionTime\n */\n startAttempt(questionTime) {\n Quiz.hide(Quiz.info);\n this.refresh();\n // Set this to true so that we don't keep calling this over and over.\n this.isRunning = true;\n questionTime = parseInt(questionTime);\n if (questionTime === 0) {\n // 0 means no timer.\n return;\n }\n this.quiz.role.onTimerTick(questionTime); // TODO: Is it worth having this line?\n this.endTime = new Date().getTime() + questionTime * 1000;\n this.timerInterval = setInterval(() => this.onTimerTick(), 1000);\n }\n\n static isLoaded() {\n return Question.box.html() !== '';\n }\n\n }\n\n class Quiz {\n\n constructor(Role) {\n this.state = '';\n this.isNewState = false;\n this.question = new Question(this);\n this.role = new Role(this);\n this.events = {\n notrunning: 'onNotRunning',\n preparing: 'onPreparing',\n running: 'onRunning',\n reviewing: 'onReviewing',\n sessionclosed: 'onSessionClosed',\n voting: 'onVoting'\n };\n }\n\n changeQuizState(state, data) {\n this.isNewState = (this.state !== state);\n this.state = state;\n this.role.onStateChange(state);\n const event = this.events[state];\n this.role[event](data);\n }\n\n /**\n * Initiate the chained session info calls to ajax.php\n * @param {number} ms interval in milliseconds\n */\n poll(ms) {\n Ajax.get('info', {}, data => {\n this.changeQuizState(data.status, data);\n setTimeout(() => this.poll(ms), ms);\n });\n }\n\n static get main() {\n return $('#jazzquiz');\n }\n\n static get info() {\n return $('#jazzquiz_info_container');\n }\n\n static get responded() {\n return $('#jazzquiz_responded_container');\n }\n\n static get responses() {\n return $('#jazzquiz_responses_container');\n }\n\n static get responseInfo() {\n return $('#jazzquiz_response_info_container');\n }\n\n static hide($element) {\n $element.addClass('hidden');\n }\n\n static show($element) {\n $element.removeClass('hidden');\n }\n\n static uncheck($element) {\n $element.children('.fa').removeClass('fa-check-square-o').addClass('fa-square-o');\n }\n\n static check($element) {\n $element.children('.fa').removeClass('fa-square-o').addClass('fa-check-square-o');\n }\n\n /**\n * Triggers a dynamic content update event, which MathJax listens to.\n */\n static renderAllMathjax() {\n mEvent.notifyFilterContentUpdated(document.getElementsByClassName('jazzquiz-response-container'));\n }\n\n /**\n * Sets the body of the target, and triggers an event letting MathJax know about the element.\n * @param {*} $target\n * @param {string} latex\n */\n static addMathjaxElement($target, latex) {\n $target.html('' + latex + '');\n Quiz.renderAllMathjax();\n }\n\n /**\n * Converts the input to LaTeX and renders it to the target with MathJax.\n * @param {string} input\n * @param {string} targetId\n */\n static renderMaximaEquation(input, targetId) {\n const target = document.getElementById(targetId);\n if (target === null) {\n //console.error('Target element #' + targetId + ' not found.');\n return;\n }\n if (cache[input] !== undefined) {\n Quiz.addMathjaxElement($('#' + targetId), cache[input]);\n return;\n }\n Ajax.get('stack', {input: encodeURIComponent(input)}, data => {\n cache[data.original] = data.latex;\n Quiz.addMathjaxElement($('#' + targetId), data.latex);\n });\n }\n\n }\n\n /**\n * Retrieve a language string that was sent along with the page.\n * @param $element\n * @param {string} key Which string in the language file we want.\n * @param {string} [from=jazzquiz] Which language file we want the string from. Default is jazzquiz.\n * @param [args] This is {$a} in the string for the key.\n */\n function setText($element, key, from, args) {\n from = (from !== undefined) ? from : 'jazzquiz';\n args = (args !== undefined) ? args : [];\n $.when(mString.get_string(key, from, args)).done(text => Quiz.show($element.html(text)));\n }\n\n return {\n initialize: (courseModuleId, activityId, sessionId, attemptId, sessionKey) => {\n session.courseModuleId = courseModuleId;\n session.activityId = activityId;\n session.sessionId = sessionId;\n session.attemptId = attemptId;\n session.sessionKey = sessionKey;\n },\n Quiz: Quiz,\n Question: Question,\n Ajax: Ajax,\n setText: setText\n };\n\n});\n"],"names":["define","$","mConfig","mString","Y","mEvent","session","courseModuleId","activityId","sessionId","attemptId","sessionKey","cache","Ajax","method","url","data","success","id","sessionid","attemptid","sesskey","ajax","type","dataType","error","xhr","status","fail","setText","Quiz","info","action","request","Question","constructor","quiz","isRunning","isSaving","endTime","isVoteRunning","hasVotes","countdownTimeLeft","questionTime","countdownInterval","timerInterval","box","timer","form","refresh","get","is_already_submitted","show","html","eval","js","css","forEach","cssUrl","head","document","getElementsByTagName","style","createElement","rel","href","appendChild","role","onQuestionRefreshed","renderAllMathjax","hideTimer","hide","clearInterval","this","onCountdownTick","startAttempt","startCountdown","parseInt","setInterval","onTimerEnding","onTimerTick","currentTime","Date","getTime","timeLeft","Role","state","isNewState","question","events","notrunning","preparing","running","reviewing","sessionclosed","voting","changeQuizState","onStateChange","event","poll","ms","setTimeout","main","responded","responses","responseInfo","$element","addClass","removeClass","children","notifyFilterContentUpdated","getElementsByClassName","$target","latex","input","targetId","getElementById","undefined","encodeURIComponent","original","addMathjaxElement","key","from","args","when","get_string","done","text","initialize"],"mappings":"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"} \ No newline at end of file diff --git a/amd/build/edit.min.js b/amd/build/edit.min.js index 2a1372f..d533120 100644 --- a/amd/build/edit.min.js +++ b/amd/build/edit.min.js @@ -1,2 +1,10 @@ -function _createForOfIteratorHelper(a){if("undefined"==typeof Symbol||null==a[Symbol.iterator]){if(Array.isArray(a)||(a=_unsupportedIterableToArray(a))){var b=0,c=function(){};return{s:c,n:function n(){if(b>=a.length)return{done:!0};return{done:!1,value:a[b++]}},e:function e(a){throw a},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var d,e=!0,f=!1,g;return{s:function s(){d=a[Symbol.iterator]()},n:function n(){var a=d.next();e=a.done;return a},e:function e(a){f=!0;g=a},f:function f(){try{if(!e&&null!=d.return)d.return()}finally{if(f)throw g}}}}function _unsupportedIterableToArray(a,b){if(!a)return;if("string"==typeof a)return _arrayLikeToArray(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return _arrayLikeToArray(a,b)}function _arrayLikeToArray(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c + * @copyright 2015 University of Wisconsin - Madison + * @copyright 2018 NTNU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define("mod_jazzquiz/edit",["jquery"],(function($){function submitQuestionOrder(order,courseModuleId){$.post("edit.php",{id:courseModuleId,action:"order",order:JSON.stringify(order)},(()=>location.reload()))}function getQuestionOrder(){let order=[];return $(".questionlist li").each((function(){order.push($(this).data("question-id"))})),order}function offsetQuestion(questionId,offset){let order=getQuestionOrder(),originalIndex=order.indexOf(questionId);if(-1===originalIndex)return order;for(let i=0;i{$(".edit-question-action").on("click",(function(){const action=$(this).data("action"),questionId=$(this).data("question-id");let order=[];switch(action){case"up":order=offsetQuestion(questionId,1);break;case"down":order=offsetQuestion(questionId,-1);break;case"delete":order=getQuestionOrder();const index=order.indexOf(questionId);-1!==index&&order.splice(index,1);break;default:return}submitQuestionOrder(order,courseModuleId)}));let questionList=document.getElementsByClassName("questionlist")[0];Sortable.create(questionList,{handle:".dragquestion",onSort:()=>submitQuestionOrder(getQuestionOrder(),courseModuleId)}),function(courseModuleId){$(".jazzquiz-add-selected-questions").on("click",(function(){const $checkboxes=$("#categoryquestions td input[type=checkbox]:checked");let questionIds="";for(const checkbox of $checkboxes)questionIds+=checkbox.getAttribute("name").slice(1)+",";$.post("edit.php",{id:courseModuleId,action:"addquestion",questionids:questionIds},(()=>location.reload()))}))}(courseModuleId)}}})); + +//# sourceMappingURL=edit.min.js.map \ No newline at end of file diff --git a/amd/build/edit.min.js.map b/amd/build/edit.min.js.map index 42630b1..a48f986 100644 --- a/amd/build/edit.min.js.map +++ b/amd/build/edit.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/edit.js"],"names":["define","$","submitQuestionOrder","order","courseModuleId","post","id","action","JSON","stringify","location","reload","getQuestionOrder","each","push","data","offsetQuestion","questionId","offset","originalIndex","indexOf","i","length","listenAddToQuiz","on","$checkboxes","questionIds","checkbox","getAttribute","slice","questionids","initialize","index","splice","questionList","document","getElementsByClassName","Sortable","create","handle","onSort"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2015 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function ($) {\n\n /**\n * Submit the question order to the server. An empty array will delete all questions.\n * @param {Array.} order\n * @param {number} courseModuleId\n */\n function submitQuestionOrder(order, courseModuleId) {\n $.post('edit.php', {\n id: courseModuleId,\n action: 'order',\n order: JSON.stringify(order)\n }, () => location.reload()); // TODO: Correct locally instead, but for now just refresh.\n }\n\n /**\n * @returns {Array} The current question order.\n */\n function getQuestionOrder() {\n let order = [];\n $('.questionlist li').each(function () {\n order.push($(this).data('question-id'));\n });\n return order;\n }\n\n /**\n * Move a question up or down by a specified offset.\n * @param {number} questionId\n * @param {number} offset Negative to move down, positive to move up\n * @returns {Array}\n */\n function offsetQuestion(questionId, offset) {\n let order = getQuestionOrder();\n let originalIndex = order.indexOf(questionId);\n if (originalIndex === -1) {\n return order;\n }\n for (let i = 0; i < order.length; i++) {\n if (i + offset === originalIndex) {\n order[originalIndex] = order[i];\n order[i] = questionId;\n break;\n }\n }\n return order;\n }\n\n function listenAddToQuiz(courseModuleId) {\n $('.jazzquiz-add-selected-questions').on('click', function () {\n const $checkboxes = $('#categoryquestions td input[type=checkbox]:checked');\n let questionIds = '';\n for (const checkbox of $checkboxes) {\n questionIds += checkbox.getAttribute('name').slice(1) + ',';\n }\n $.post('edit.php', {\n id: courseModuleId,\n action: 'addquestion',\n questionids: questionIds,\n }, () => location.reload());\n });\n }\n\n return {\n initialize: courseModuleId => {\n $('.edit-question-action').on('click', function () {\n const action = $(this).data('action');\n const questionId = $(this).data('question-id');\n let order = [];\n switch (action) {\n case 'up':\n order = offsetQuestion(questionId, 1);\n break;\n case 'down':\n order = offsetQuestion(questionId, -1);\n break;\n case 'delete':\n order = getQuestionOrder();\n const index = order.indexOf(questionId);\n if (index !== -1) {\n order.splice(index, 1);\n }\n break;\n default:\n return;\n }\n submitQuestionOrder(order, courseModuleId);\n });\n let questionList = document.getElementsByClassName('questionlist')[0];\n Sortable.create(questionList, {\n handle: '.dragquestion',\n onSort: () => submitQuestionOrder(getQuestionOrder(), courseModuleId)\n });\n listenAddToQuiz(courseModuleId);\n }\n };\n\n});\n"],"file":"edit.min.js"} \ No newline at end of file +{"version":3,"file":"edit.min.js","sources":["../src/edit.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2015 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function ($) {\n\n /**\n * Submit the question order to the server. An empty array will delete all questions.\n * @param {Array.} order\n * @param {number} courseModuleId\n */\n function submitQuestionOrder(order, courseModuleId) {\n $.post('edit.php', {\n id: courseModuleId,\n action: 'order',\n order: JSON.stringify(order)\n }, () => location.reload()); // TODO: Correct locally instead, but for now just refresh.\n }\n\n /**\n * @returns {Array} The current question order.\n */\n function getQuestionOrder() {\n let order = [];\n $('.questionlist li').each(function () {\n order.push($(this).data('question-id'));\n });\n return order;\n }\n\n /**\n * Move a question up or down by a specified offset.\n * @param {number} questionId\n * @param {number} offset Negative to move down, positive to move up\n * @returns {Array}\n */\n function offsetQuestion(questionId, offset) {\n let order = getQuestionOrder();\n let originalIndex = order.indexOf(questionId);\n if (originalIndex === -1) {\n return order;\n }\n for (let i = 0; i < order.length; i++) {\n if (i + offset === originalIndex) {\n order[originalIndex] = order[i];\n order[i] = questionId;\n break;\n }\n }\n return order;\n }\n\n function listenAddToQuiz(courseModuleId) {\n $('.jazzquiz-add-selected-questions').on('click', function () {\n const $checkboxes = $('#categoryquestions td input[type=checkbox]:checked');\n let questionIds = '';\n for (const checkbox of $checkboxes) {\n questionIds += checkbox.getAttribute('name').slice(1) + ',';\n }\n $.post('edit.php', {\n id: courseModuleId,\n action: 'addquestion',\n questionids: questionIds,\n }, () => location.reload());\n });\n }\n\n return {\n initialize: courseModuleId => {\n $('.edit-question-action').on('click', function () {\n const action = $(this).data('action');\n const questionId = $(this).data('question-id');\n let order = [];\n switch (action) {\n case 'up':\n order = offsetQuestion(questionId, 1);\n break;\n case 'down':\n order = offsetQuestion(questionId, -1);\n break;\n case 'delete':\n order = getQuestionOrder();\n const index = order.indexOf(questionId);\n if (index !== -1) {\n order.splice(index, 1);\n }\n break;\n default:\n return;\n }\n submitQuestionOrder(order, courseModuleId);\n });\n let questionList = document.getElementsByClassName('questionlist')[0];\n Sortable.create(questionList, {\n handle: '.dragquestion',\n onSort: () => submitQuestionOrder(getQuestionOrder(), courseModuleId)\n });\n listenAddToQuiz(courseModuleId);\n }\n };\n\n});\n"],"names":["define","$","submitQuestionOrder","order","courseModuleId","post","id","action","JSON","stringify","location","reload","getQuestionOrder","each","push","this","data","offsetQuestion","questionId","offset","originalIndex","indexOf","i","length","initialize","on","index","splice","questionList","document","getElementsByClassName","Sortable","create","handle","onSort","$checkboxes","questionIds","checkbox","getAttribute","slice","questionids","listenAddToQuiz"],"mappings":";;;;;;;AAuBAA,2BAAO,CAAC,WAAW,SAAUC,YAOhBC,oBAAoBC,MAAOC,gBAChCH,EAAEI,KAAK,WAAY,CACfC,GAAIF,eACJG,OAAQ,QACRJ,MAAOK,KAAKC,UAAUN,SACvB,IAAMO,SAASC,oBAMbC,uBACDT,MAAQ,UACZF,EAAE,oBAAoBY,MAAK,WACvBV,MAAMW,KAAKb,EAAEc,MAAMC,KAAK,mBAErBb,eASFc,eAAeC,WAAYC,YAC5BhB,MAAQS,mBACRQ,cAAgBjB,MAAMkB,QAAQH,gBACX,IAAnBE,qBACOjB,UAEN,IAAImB,EAAI,EAAGA,EAAInB,MAAMoB,OAAQD,OAC1BA,EAAIH,SAAWC,cAAe,CAC9BjB,MAAMiB,eAAiBjB,MAAMmB,GAC7BnB,MAAMmB,GAAKJ,wBAIZf,YAkBJ,CACHqB,WAAYpB,iBACRH,EAAE,yBAAyBwB,GAAG,SAAS,iBAC7BlB,OAASN,EAAEc,MAAMC,KAAK,UACtBE,WAAajB,EAAEc,MAAMC,KAAK,mBAC5Bb,MAAQ,UACJI,YACC,KACDJ,MAAQc,eAAeC,WAAY,aAElC,OACDf,MAAQc,eAAeC,YAAa,aAEnC,SACDf,MAAQS,yBACFc,MAAQvB,MAAMkB,QAAQH,aACb,IAAXQ,OACAvB,MAAMwB,OAAOD,MAAO,wBAMhCxB,oBAAoBC,MAAOC,uBAE3BwB,aAAeC,SAASC,uBAAuB,gBAAgB,GACnEC,SAASC,OAAOJ,aAAc,CAC1BK,OAAQ,gBACRC,OAAQ,IAAMhC,oBAAoBU,mBAAoBR,2BA3CzCA,gBACrBH,EAAE,oCAAoCwB,GAAG,SAAS,iBACxCU,YAAclC,EAAE,0DAClBmC,YAAc,OACb,MAAMC,YAAYF,YACnBC,aAAeC,SAASC,aAAa,QAAQC,MAAM,GAAK,IAE5DtC,EAAEI,KAAK,WAAY,CACfC,GAAIF,eACJG,OAAQ,cACRiC,YAAaJ,cACd,IAAM1B,SAASC,cAkClB8B,CAAgBrC"} \ No newline at end of file diff --git a/amd/build/instructor.min.js b/amd/build/instructor.min.js index 5e36e8f..f8db5a4 100644 --- a/amd/build/instructor.min.js +++ b/amd/build/instructor.min.js @@ -1,2 +1,10 @@ -function _classCallCheck(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(a,b){for(var c=0,d;c").children("h4"),"showing_vote_results");c.responseInfo.append("
");f(a("#review_show_normal_results"),"click_to_show_original_results");e.remove()}}else if("current_response"===b){if(0===e.length){f(c.responseInfo.html("

").children("h4"),"showing_original_results");c.responseInfo.append("
");f(a("#review_show_vote_results"),"click_to_show_vote_results");d.remove()}}}}},{key:"createBarGraph",value:function createBarGraph(b,d,e,f,g){var h=document.getElementById(e);if(null===h){return}for(var k=0,l=0,m=0,n;ml){l=n}}if(0===k){k=1}if(g){h.innerHTML=""}for(var u=0,v;uo){x.classList.add("outside")}var s=""+b[j].count+"",t=x.insertCell(0);t.onclick=function(){a(this).parent().toggleClass("selected-vote-option")};var y=x.insertCell(1);y.classList.add("bar");y.id=d+"_bar_"+p;y.innerHTML="
"+s+"
";var z=d+"_latex_"+p;t.innerHTML="";c.addMathjaxElement(a("#"+z),b[j].response);if("stack"===b[j].qtype){c.renderMaximaEquation(b[j].response,z)}}else{var A=h.rows[q];A.dataset.row_i=p;A.dataset.response_i=j;A.dataset.percent=o;A.dataset.count=b[j].count;var B=A.classList.contains("outside");if(15o&&!B){A.classList.add("outside")}var C=document.getElementById(d+"_count_"+p);if(null!==C){C.innerHTML=b[j].count}var D=document.getElementById(d+"_bar_"+p);if(null!==D){D.firstElementChild.style.width=o+"%"}}}}},{key:"set",value:function set(d,e,g,h,k,l,m){if(g===void 0){return}if(0===g.length){c.show(c.responded);f(c.responded.find("h4"),"a_out_of_b_responded","jazzquiz",{a:0,b:this.totalStudents});return}switch(k){case"shortanswer":for(var p=0;p"))}this.createBarGraph(this.currentResponses,"current_response",e,l,m);b.sortBarGraph(e)}},{key:"refresh",value:function refresh(b){var d=this;e.get("get_results",{},function(e){d.quiz.question.hasVotes=e.has_votes;d.totalStudents=parseInt(e.total_students);d.set("jazzquiz_responses_container","current_responses_wrapper",e.responses,e.responded,e.question_type,"results",b);if(0"))}a.createBarGraph(h,"vote_response",g,"vote",!1);b.sortBarGraph(g)})}}],[{key:"sortBarGraph",value:function sortBarGraph(a){var b=document.getElementById(a);if(null===b){return}var c=!0;while(c){c=!1;for(var f=0;f");c.addMathjaxElement(i,j[k].name);i.data({time:j[k].time,"question-id":j[k].questionid,"jazzquiz-question-id":j[k].jazzquizquestionid});i.data("test",1);i.on("click",function(){var b=a(this).data("question-id"),c=a(this).data("time"),d=a(this).data("jazzquiz-question-id");f.jumpQuestion(b,c,d);e.html("").removeClass("active");g.removeClass("active")});e.append(i)}})}},{key:"runVoting",value:function runVoting(){var a=b.getSelectedAnswersForVote(),c={questions:encodeURIComponent(JSON.stringify(a))};e.post("run_voting",c,function(){})}},{key:"startQuestion",value:function startQuestion(a,b,d,f){var g=this;c.hide(c.info);this.responses.clear();this.hideCorrectAnswer();e.post("start_question",{method:a,questionid:b,questiontime:d,jazzquizquestionid:f},function(a){return g.quiz.question.startCountdown(a.questiontime,a.delay)})}},{key:"jumpQuestion",value:function jumpQuestion(a,b,c){this.startQuestion("jump",a,b,c)}},{key:"repollQuestion",value:function repollQuestion(){this.startQuestion("repoll",0,0,0)}},{key:"nextQuestion",value:function nextQuestion(){this.startQuestion("next",0,0,0)}},{key:"randomQuestion",value:function randomQuestion(){this.startQuestion("random",0,0,0)}},{key:"closeSession",value:function closeSession(){c.hide(a("#jazzquiz_undo_merge"));c.hide(d.box);c.hide(b.controls);f(c.info,"closing_session");e.post("close_session",{},function(){return window.location=location.href.split("&")[0]})}},{key:"hideCorrectAnswer",value:function hideCorrectAnswer(){if(this.isShowingCorrectAnswer){c.hide(b.correctAnswer);c.uncheck(b.control("answer"));this.isShowingCorrectAnswer=!1}}},{key:"showCorrectAnswer",value:function showCorrectAnswer(){var a=this;this.hideCorrectAnswer();e.get("get_right_response",{},function(d){c.show(b.correctAnswer.html(d.right_answer));c.renderAllMathjax();c.check(b.control("answer"));a.isShowingCorrectAnswer=!0})}}],[{key:"addHotkeys",value:function addHotkeys(c){var d=function(d){if(c.hasOwnProperty(d)){c[d]={action:c[d],repeat:!1};a(document).on("keydown",function(e){if(c[d].repeat||e.ctrlKey){return}if(String.fromCharCode(e.which).toLowerCase()!==d){return}var f=a(":focus").prop("tagName");if(f!==void 0){f=f.toLowerCase();if("input"===f||"textarea"===f){return}}e.preventDefault();c[d].repeat=!0;var g=b.control(c[d].action);if(g.length&&!g.prop("disabled")){g.click()}});a(document).on("keyup",function(a){if(String.fromCharCode(a.which).toLowerCase()===d){c[d].repeat=!1}})}};for(var e in c){d(e)}}},{key:"addEvents",value:function addEvents(c){var d=function(d){if(c.hasOwnProperty(d)){a(document).on("click","#jazzquiz_control_"+d,function(){b.enableControls([]);c[d]()})}};for(var e in c){d(e)}}},{key:"controls",get:function get(){return a("#jazzquiz_controls_box")}},{key:"controlButtons",get:function get(){return b.controls.find(".quiz-control-buttons")}},{key:"control",value:function control(b){return a("#jazzquiz_control_"+b)}},{key:"side",get:function get(){return a("#jazzquiz_side_container")}},{key:"correctAnswer",get:function get(){return a("#jazzquiz_correct_answer_container")}},{key:"isMerging",get:function get(){return 0!==a(".merge-from").length}},{key:"getSelectedAnswersForVote",value:function getSelectedAnswersForVote(){var b=[];a(".selected-vote-option").each(function(a,c){b.push({text:c.dataset.response,count:c.dataset.count})});return b}},{key:"enableControls",value:function enableControls(a){b.controlButtons.children("button").each(function(b,c){var d=c.getAttribute("id").replace("jazzquiz_control_","");c.disabled=-1===a.indexOf(d)})}},{key:"showFullscreenView",value:function showFullscreenView(){if(c.main.hasClass("jazzquiz-fullscreen")){b.closeFullscreenView();return}document.documentElement.style.overflowY="hidden";c.main.addClass("jazzquiz-fullscreen")}},{key:"closeFullscreenView",value:function closeFullscreenView(){document.documentElement.style.overflowY="auto";c.main.removeClass("jazzquiz-fullscreen")}},{key:"closeQuestionListMenu",value:function closeQuestionListMenu(c,d){var e="#jazzquiz_"+d+"_menu",f=a(c.target).closest(e);if(!f.length){a(e).html("").removeClass("active");b.control(d).removeClass("active")}}},{key:"addReportEventHandlers",value:function addReportEventHandlers(){a(document).on("click","#report_overview_controls button",function(){var b=a(this).data("action");if("attendance"===b){a("#report_overview_responded").fadeIn();a("#report_overview_responses").fadeOut()}else if("responses"===b){a("#report_overview_responses").fadeIn();a("#report_overview_responded").fadeOut()}})}}]);return b}();return{initialize:function initialize(a,b,d){var e=new c(h);e.role.totalQuestions=a;if(b){h.addReportEventHandlers();e.role.responses.showResponses=!0;d.forEach(function(a){var b="jazzquiz_wrapper_responses_"+a.num,c="responses_wrapper_table_"+a.num,d="report_"+a.num;e.role.responses.set(b,c,a.responses,void 0,a.type,d,!1)})}else{e.poll(500)}}}}); -//# sourceMappingURL=instructor.min.js.map +/** + * @package mod_jazzquiz + * @author Sebastian S. Gundersen + * @copyright 2014 University of Wisconsin - Madison + * @copyright 2018 NTNU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define("mod_jazzquiz/instructor",["jquery","mod_jazzquiz/core"],(function($,Jazz){const Quiz=Jazz.Quiz,Question=Jazz.Question,Ajax=Jazz.Ajax,setText=Jazz.setText;class ResponseView{constructor(quiz){this.quiz=quiz,this.currentResponses=[],this.showVotesUponReview=!1,this.respondedCount=0,this.showResponses=!1,this.totalStudents=0,$(document).on("click","#jazzquiz_undo_merge",(()=>this.undoMerge())),$(document).on("click",(event=>{event.target.classList.contains("bar")?this.startMerge(event.target.id):event.target.parentNode&&event.target.parentNode.classList.contains("bar")&&this.startMerge(event.target.parentNode.id)})),$(document).on("click","#review_show_normal_results",(()=>this.refresh(!1))),$(document).on("click","#review_show_vote_results",(()=>this.refreshVotes()))}clear(){Quiz.responses.html(""),Quiz.responseInfo.html("")}hide(){Quiz.uncheck(Instructor.control("responses")),Quiz.hide(Quiz.responses),Quiz.hide(Quiz.responseInfo)}show(){Quiz.check(Instructor.control("responses")),Quiz.show(Quiz.responses),Quiz.show(Quiz.responseInfo),this.showVotesUponReview?(this.refreshVotes(),this.showVotesUponReview=!1):this.refresh(!1)}toggle(){this.showResponses=!this.showResponses,this.showResponses?this.show():this.hide()}endMerge(){$(".merge-into").removeClass("merge-into"),$(".merge-from").removeClass("merge-from")}undoMerge(){Ajax.post("undo_merge",{},(()=>this.refresh(!0)))}merge(from,into){Ajax.post("merge_responses",{from:from,into:into},(()=>this.refresh(!1)))}startMerge(fromRowBarId){const $barCell=$("#"+fromRowBarId);let $row=$barCell.parent();if($row.hasClass("merge-from"))this.endMerge();else{if($row.hasClass("merge-into")){const $fromRow=$(".merge-from");return this.merge($fromRow.data("response"),$row.data("response")),void this.endMerge()}$row.addClass("merge-from"),$row.parent().parent().find("tr").each((function(){$(this).find("td")[1].id!==$barCell.attr("id")&&$(this).addClass("merge-into")}))}}createControls(name){if(this.quiz.question.hasVotes){if("reviewing"===this.quiz.state){let $showNormalResult=$("#review_show_normal_results"),$showVoteResult=$("#review_show_vote_results");Quiz.show(Quiz.responseInfo),"vote_response"===name?0===$showNormalResult.length&&(setText(Quiz.responseInfo.html('

').children("h4"),"showing_vote_results"),Quiz.responseInfo.append('
'),setText($("#review_show_normal_results"),"click_to_show_original_results"),$showVoteResult.remove()):"current_response"===name&&0===$showVoteResult.length&&(setText(Quiz.responseInfo.html('

').children("h4"),"showing_original_results"),Quiz.responseInfo.append('
'),setText($("#review_show_vote_results"),"click_to_show_vote_results"),$showNormalResult.remove())}}else Quiz.hide(Quiz.responseInfo)}createBarGraph(responses,name,targetId,graphId,rebuild){let target=document.getElementById(targetId);if(null===target)return;let total=0,highestResponseCount=0;for(let i=0;ihighestResponseCount&&(highestResponseCount=count)}0===total&&(total=1),rebuild&&(target.innerHTML="");for(let i=0;i'+responses[i].count+"";let responseCell=row.insertCell(0);responseCell.onclick=function(){$(this).parent().toggleClass("selected-vote-option")};let barCell=row.insertCell(1);barCell.classList.add("bar"),barCell.id=name+"_bar_"+rowIndex,barCell.innerHTML='
'+countHtml+"
";const latexId=name+"_latex_"+rowIndex;responseCell.innerHTML='',Quiz.addMathjaxElement($("#"+latexId),responses[i].response),"stack"===responses[i].qtype&&Quiz.renderMaximaEquation(responses[i].response,latexId)}else{let currentRow=target.rows[currentRowIndex];currentRow.dataset.row_i=rowIndex,currentRow.dataset.response_i=i,currentRow.dataset.percent=percent,currentRow.dataset.count=responses[i].count;const containsOutside=currentRow.classList.contains("outside");percent>15&&containsOutside?currentRow.classList.remove("outside"):percent<15&&!containsOutside&¤tRow.classList.add("outside");let countElement=document.getElementById(name+"_count_"+rowIndex);null!==countElement&&(countElement.innerHTML=responses[i].count);let barElement=document.getElementById(name+"_bar_"+rowIndex);null!==barElement&&(barElement.firstElementChild.style.width=percent+"%")}}}static sortBarGraph(targetId){let target=document.getElementById(targetId);if(null===target)return;let isSorting=!0;for(;isSorting;){isSorting=!1;for(let i=0;i';Quiz.show($("#"+wrapperId).html(html))}this.createBarGraph(this.currentResponses,"current_response",tableId,graphId,rebuild),ResponseView.sortBarGraph(tableId)}}refresh(rebuild){Ajax.get("get_results",{},(data=>{this.quiz.question.hasVotes=data.has_votes,this.totalStudents=parseInt(data.total_students),this.set("jazzquiz_responses_container","current_responses_wrapper",data.responses,data.responded,data.question_type,"results",rebuild),data.merge_count>0?Quiz.show($("#jazzquiz_undo_merge")):Quiz.hide($("#jazzquiz_undo_merge"))}))}refreshVotes(){if(!this.showResponses&&"reviewing"!==this.quiz.state)return Quiz.hide(Quiz.responseInfo),void Quiz.hide(Quiz.responses);Ajax.get("get_vote_results",{},(data=>{const answers=data.answers,targetId="wrapper_vote_responses";let responses=[];this.respondedCount=0,this.totalStudents=parseInt(data.total_students);for(let i in answers)answers.hasOwnProperty(i)&&(responses.push({response:answers[i].attempt,count:answers[i].finalcount,qtype:answers[i].qtype,slot:answers[i].slot}),this.respondedCount+=parseInt(answers[i].finalcount));if(setText(Quiz.responded.find("h4"),"a_out_of_b_voted","jazzquiz",{a:this.respondedCount,b:this.totalStudents}),null===document.getElementById(targetId)){const html='
';Quiz.show(Quiz.responses.html(html))}this.createBarGraph(responses,"vote_response",targetId,"vote",!1),ResponseView.sortBarGraph(targetId)}))}}class Instructor{constructor(quiz){this.quiz=quiz,this.responses=new ResponseView(quiz),this.isShowingCorrectAnswer=!1,this.totalQuestions=0,this.allowVote=!1,$(document).on("keyup",(event=>{27===event.keyCode&&Instructor.closeFullscreenView()})),$(document).on("click",(event=>{Instructor.closeQuestionListMenu(event,"improvise"),Instructor.closeQuestionListMenu(event,"jump")})),Instructor.addEvents({repoll:()=>this.repollQuestion(),vote:()=>this.runVoting(),improvise:()=>this.showQuestionListSetup("improvise"),jump:()=>this.showQuestionListSetup("jump"),next:()=>this.nextQuestion(),random:()=>this.randomQuestion(),end:()=>this.endQuestion(),fullscreen:()=>Instructor.showFullscreenView(),answer:()=>this.showCorrectAnswer(),responses:()=>this.responses.toggle(),exit:()=>this.closeSession(),quit:()=>this.closeSession(),startquiz:()=>this.startQuiz()}),Instructor.addHotkeys({t:"responses",r:"repoll",a:"answer",e:"end",j:"jump",i:"improvise",v:"vote",n:"next",m:"random",f:"fullscreen"})}static addHotkeys(keys){for(let key in keys)keys.hasOwnProperty(key)&&(keys[key]={action:keys[key],repeat:!1},$(document).on("keydown",(event=>{if(keys[key].repeat||event.ctrlKey)return;if(String.fromCharCode(event.which).toLowerCase()!==key)return;let focusedTag=$(":focus").prop("tagName");if(void 0!==focusedTag&&(focusedTag=focusedTag.toLowerCase(),"input"===focusedTag||"textarea"===focusedTag))return;event.preventDefault(),keys[key].repeat=!0;let $control=Instructor.control(keys[key].action);$control.length&&!$control.prop("disabled")&&$control.click()})),$(document).on("keyup",(event=>{String.fromCharCode(event.which).toLowerCase()===key&&(keys[key].repeat=!1)})))}static addEvents(events){for(let key in events)events.hasOwnProperty(key)&&$(document).on("click","#jazzquiz_control_"+key,(()=>{Instructor.enableControls([]),events[key]()}))}static get controls(){return $("#jazzquiz_controls_box")}static get controlButtons(){return Instructor.controls.find(".quiz-control-buttons")}static control(key){return $("#jazzquiz_control_"+key)}static get side(){return $("#jazzquiz_side_container")}static get correctAnswer(){return $("#jazzquiz_correct_answer_container")}static get isMerging(){return 0!==$(".merge-from").length}onNotRunning(data){this.responses.totalStudents=data.student_count,Quiz.hide(Instructor.side),setText(Quiz.info,"instructions_for_instructor"),Instructor.enableControls([]),Quiz.hide(Instructor.controlButtons);let $studentsJoined=Instructor.control("startquiz").next();1===data.student_count?setText($studentsJoined,"one_student_has_joined"):data.student_count>1?setText($studentsJoined,"x_students_have_joined","jazzquiz",data.student_count):setText($studentsJoined,"no_students_have_joined"),Quiz.show(Instructor.control("startquiz").parent())}onPreparing(data){Quiz.hide(Instructor.side),setText(Quiz.info,"instructions_for_instructor");let enabledButtons=["improvise","jump","random","fullscreen","quit"];data.slot0&&data.delay<-data.questiontime&&this.endQuestion(),this.responses.refresh(!Instructor.isMerging);else{this.quiz.question.startCountdown(data.questiontime,data.delay)&&(this.quiz.question.isRunning=!0)}}onReviewing(data){Quiz.show(Instructor.side);let enabledButtons=["answer","repoll","fullscreen","improvise","jump","random","quit"];this.allowVote&&enabledButtons.push("vote"),data.slot$("#jazzquiz_controls").removeClass("btn-hide")))}endQuestion(){this.quiz.question.hideTimer(),Ajax.post("end_question",{},(()=>{"voting"===this.quiz.state?this.responses.showVotesUponReview=!0:(this.quiz.question.isRunning=!1,Instructor.enableControls([]))}))}showQuestionListSetup(name){let $controlButton=Instructor.control(name);$controlButton.hasClass("active")||Ajax.get("list_"+name+"_questions",{},(data=>{let self=this,$menu=$("#jazzquiz_"+name+"_menu");const menuMargin=$controlButton.offset().left-$controlButton.parent().offset().left;$menu.html("").addClass("active").css("margin-left",menuMargin+"px"),$controlButton.addClass("active");const questions=data.questions;for(let i in questions){if(!questions.hasOwnProperty(i))continue;let $questionButton=$('');Quiz.addMathjaxElement($questionButton,questions[i].name),$questionButton.data({time:questions[i].time,"question-id":questions[i].questionid,"jazzquiz-question-id":questions[i].jazzquizquestionid}),$questionButton.data("test",1),$questionButton.on("click",(function(){const questionId=$(this).data("question-id"),time=$(this).data("time"),jazzQuestionId=$(this).data("jazzquiz-question-id");self.jumpQuestion(questionId,time,jazzQuestionId),$menu.html("").removeClass("active"),$controlButton.removeClass("active")})),$menu.append($questionButton)}}))}static getSelectedAnswersForVote(){let result=[];return $(".selected-vote-option").each(((i,option)=>{result.push({text:option.dataset.response,count:option.dataset.count})})),result}runVoting(){const options=Instructor.getSelectedAnswersForVote(),data={questions:encodeURIComponent(JSON.stringify(options))};Ajax.post("run_voting",data,(()=>{}))}startQuestion(method,questionId,questionTime,jazzquizQuestionId){Quiz.hide(Quiz.info),this.responses.clear(),this.hideCorrectAnswer(),Ajax.post("start_question",{method:method,questionid:questionId,questiontime:questionTime,jazzquizquestionid:jazzquizQuestionId},(data=>this.quiz.question.startCountdown(data.questiontime,data.delay)))}jumpQuestion(questionId,questionTime,jazzquizQuestionId){this.startQuestion("jump",questionId,questionTime,jazzquizQuestionId)}repollQuestion(){this.startQuestion("repoll",0,0,0)}nextQuestion(){this.startQuestion("next",0,0,0)}randomQuestion(){this.startQuestion("random",0,0,0)}closeSession(){Quiz.hide($("#jazzquiz_undo_merge")),Quiz.hide(Question.box),Quiz.hide(Instructor.controls),setText(Quiz.info,"closing_session"),Ajax.post("close_session",{},(()=>window.location=location.href.split("&")[0]))}hideCorrectAnswer(){this.isShowingCorrectAnswer&&(Quiz.hide(Instructor.correctAnswer),Quiz.uncheck(Instructor.control("answer")),this.isShowingCorrectAnswer=!1)}showCorrectAnswer(){this.hideCorrectAnswer(),Ajax.get("get_right_response",{},(data=>{Quiz.show(Instructor.correctAnswer.html(data.right_answer)),Quiz.renderAllMathjax(),Quiz.check(Instructor.control("answer")),this.isShowingCorrectAnswer=!0}))}static enableControls(buttons){Instructor.controlButtons.children("button").each(((index,child)=>{const id=child.getAttribute("id").replace("jazzquiz_control_","");child.disabled=-1===buttons.indexOf(id)}))}static showFullscreenView(){Quiz.main.hasClass("jazzquiz-fullscreen")?Instructor.closeFullscreenView():(document.documentElement.style.overflowY="hidden",Quiz.main.addClass("jazzquiz-fullscreen"))}static closeFullscreenView(){document.documentElement.style.overflowY="auto",Quiz.main.removeClass("jazzquiz-fullscreen")}static closeQuestionListMenu(event,name){const menuId="#jazzquiz_"+name+"_menu";$(event.target).closest(menuId).length||($(menuId).html("").removeClass("active"),Instructor.control(name).removeClass("active"))}static addReportEventHandlers(){$(document).on("click","#report_overview_controls button",(function(){const action=$(this).data("action");"attendance"===action?($("#report_overview_responded").fadeIn(),$("#report_overview_responses").fadeOut()):"responses"===action&&($("#report_overview_responses").fadeIn(),$("#report_overview_responded").fadeOut())}))}}return{initialize:function(totalQuestions,reportView,slots){let quiz=new Quiz(Instructor);quiz.role.totalQuestions=totalQuestions,reportView?(Instructor.addReportEventHandlers(),quiz.role.responses.showResponses=!0,slots.forEach((slot=>{const wrapper="jazzquiz_wrapper_responses_"+slot.num,table="responses_wrapper_table_"+slot.num,graph="report_"+slot.num;quiz.role.responses.set(wrapper,table,slot.responses,void 0,slot.type,graph,!1)}))):quiz.poll(500)}}})); + +//# sourceMappingURL=instructor.min.js.map \ No newline at end of file diff --git a/amd/build/instructor.min.js.map b/amd/build/instructor.min.js.map index 3012fcb..697f263 100644 --- a/amd/build/instructor.min.js.map +++ b/amd/build/instructor.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/instructor.js"],"names":["define","$","Jazz","Quiz","Question","Ajax","setText","ResponseView","quiz","currentResponses","showVotesUponReview","respondedCount","showResponses","totalStudents","document","on","undoMerge","event","target","classList","contains","startMerge","id","parentNode","refresh","refreshVotes","responses","html","responseInfo","uncheck","Instructor","control","hide","check","show","removeClass","post","from","into","fromRowBarId","$barCell","$row","parent","hasClass","endMerge","$fromRow","merge","data","addClass","$table","find","each","$cells","attr","name","question","hasVotes","state","$showNormalResult","$showVoteResult","length","children","append","remove","targetId","graphId","rebuild","getElementById","total","highestResponseCount","i","count","parseInt","innerHTML","prune","rows","j","dataset","response","deleteRow","createControls","percent","rowIndex","currentRowIndex","row_i","row","insertRow","response_i","add","countHtml","responseCell","insertCell","onclick","toggleClass","barCell","latexId","addMathjaxElement","qtype","renderMaximaEquation","currentRow","containsOutside","countElement","barElement","firstElementChild","style","width","wrapperId","tableId","responded","questionType","a","b","trim","replace","exists","push","createBarGraph","sortBarGraph","get","has_votes","total_students","set","question_type","merge_count","answers","hasOwnProperty","attempt","finalcount","slot","isSorting","current","next","insertBefore","isShowingCorrectAnswer","totalQuestions","allowVote","keyCode","closeFullscreenView","closeQuestionListMenu","addEvents","repollQuestion","runVoting","showQuestionListSetup","nextQuestion","randomQuestion","endQuestion","showFullscreenView","showCorrectAnswer","toggle","closeSession","startQuiz","addHotkeys","student_count","side","info","enableControls","controlButtons","$studentsJoined","enabledButtons","questionTime","questiontime","isRunning","delay","isMerging","started","startCountdown","isLoaded","isNewState","correctAnswer","clear","css","voteable","timeLeft","timer","hideTimer","$controlButton","$menu","menuMargin","offset","left","questions","$questionButton","time","questionid","jazzquizquestionid","questionId","jazzQuestionId","jumpQuestion","options","getSelectedAnswersForVote","encodeURIComponent","JSON","stringify","method","jazzquizQuestionId","hideCorrectAnswer","startQuestion","box","controls","window","location","href","split","right_answer","renderAllMathjax","keys","key","action","repeat","ctrlKey","String","fromCharCode","which","toLowerCase","focusedTag","prop","preventDefault","$control","click","events","result","option","text","buttons","index","child","getAttribute","disabled","indexOf","main","documentElement","overflowY","menuId","menu","closest","fadeIn","fadeOut","initialize","reportView","slots","role","addReportEventHandlers","forEach","wrapper","num","table","graph","type","poll"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2014 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'mod_jazzquiz/core'], function ($, Jazz) {\n\n const Quiz = Jazz.Quiz;\n const Question = Jazz.Question;\n const Ajax = Jazz.Ajax;\n const setText = Jazz.setText;\n\n class ResponseView {\n\n /**\n * @param {Quiz} quiz\n */\n constructor(quiz) {\n this.quiz = quiz;\n this.currentResponses = [];\n this.showVotesUponReview = false;\n this.respondedCount = 0;\n this.showResponses = false;\n this.totalStudents = 0;\n $(document).on('click', '#jazzquiz_undo_merge', () => this.undoMerge());\n $(document).on('click', event => {\n // Clicking a row to merge.\n if (event.target.classList.contains('bar')) {\n this.startMerge(event.target.id);\n } else if (event.target.parentNode && event.target.parentNode.classList.contains('bar')) {\n this.startMerge(event.target.parentNode.id);\n }\n });\n $(document).on('click', '#review_show_normal_results', () => this.refresh(false));\n $(document).on('click', '#review_show_vote_results', () => this.refreshVotes());\n }\n\n /**\n * Clear, but not hide responses.\n */\n clear() {\n Quiz.responses.html('');\n Quiz.responseInfo.html('');\n }\n\n /**\n * Hides the responses\n */\n hide() {\n Quiz.uncheck(Instructor.control('responses'));\n Quiz.hide(Quiz.responses);\n Quiz.hide(Quiz.responseInfo);\n }\n\n /**\n * Shows the responses\n */\n show() {\n Quiz.check(Instructor.control('responses'));\n Quiz.show(Quiz.responses);\n Quiz.show(Quiz.responseInfo);\n if (this.showVotesUponReview) {\n this.refreshVotes();\n this.showVotesUponReview = false;\n } else {\n this.refresh(false);\n }\n }\n\n /**\n * Toggle whether to show or hide the responses\n */\n toggle() {\n this.showResponses = !this.showResponses;\n if (this.showResponses) {\n this.show();\n } else {\n this.hide();\n }\n }\n\n /**\n * End the response merge.\n */\n endMerge() {\n $('.merge-into').removeClass('merge-into');\n $('.merge-from').removeClass('merge-from');\n }\n\n /**\n * Undo the last response merge.\n */\n undoMerge() {\n Ajax.post('undo_merge', {}, () => this.refresh(true));\n }\n\n /**\n * Merges responses based on response string.\n * @param {string} from\n * @param {string} into\n */\n merge(from, into) {\n Ajax.post('merge_responses', {from: from, into: into}, () => this.refresh(false));\n }\n\n /**\n * Start a merge between two responses.\n * @param {string} fromRowBarId\n */\n startMerge(fromRowBarId) {\n const $barCell = $('#' + fromRowBarId);\n let $row = $barCell.parent();\n if ($row.hasClass('merge-from')) {\n this.endMerge();\n return;\n }\n if ($row.hasClass('merge-into')) {\n const $fromRow = $('.merge-from');\n this.merge($fromRow.data('response'), $row.data('response'));\n this.endMerge();\n return;\n }\n $row.addClass('merge-from');\n let $table = $row.parent().parent();\n $table.find('tr').each(function () {\n const $cells = $(this).find('td');\n if ($cells[1].id !== $barCell.attr('id')) {\n $(this).addClass('merge-into');\n }\n });\n }\n\n /**\n * Create controls to toggle between the responses of the actual question and the vote that followed.\n * @param {string} name Can be either 'vote_response' or 'current_response'\n */\n createControls(name) {\n if (!this.quiz.question.hasVotes) {\n Quiz.hide(Quiz.responseInfo);\n return;\n }\n // Add button for instructor to change what to review.\n if (this.quiz.state === 'reviewing') {\n let $showNormalResult = $('#review_show_normal_results');\n let $showVoteResult = $('#review_show_vote_results');\n Quiz.show(Quiz.responseInfo);\n if (name === 'vote_response') {\n if ($showNormalResult.length === 0) {\n setText(Quiz.responseInfo.html('

').children('h4'), 'showing_vote_results');\n Quiz.responseInfo.append('
');\n setText($('#review_show_normal_results'), 'click_to_show_original_results');\n $showVoteResult.remove();\n }\n } else if (name === 'current_response') {\n if ($showVoteResult.length === 0) {\n setText(Quiz.responseInfo.html('

').children('h4'), 'showing_original_results');\n Quiz.responseInfo.append('
');\n setText($('#review_show_vote_results'), 'click_to_show_vote_results');\n $showNormalResult.remove();\n }\n }\n }\n }\n\n /**\n * Create a new and unsorted response bar graph.\n * @param {Array.} responses\n * @param {string} name\n * @param {string} targetId\n * @param {string} graphId\n * @param {boolean} rebuild If the table should be completely rebuilt or not\n */\n createBarGraph(responses, name, targetId, graphId, rebuild) {\n let target = document.getElementById(targetId);\n if (target === null) {\n return;\n }\n let total = 0;\n let highestResponseCount = 0;\n for (let i = 0; i < responses.length; i++) {\n let count = parseInt(responses[i].count); // In case count is a string.\n total += count;\n if (count > highestResponseCount) {\n highestResponseCount = count;\n }\n\n }\n if (total === 0) {\n total = 1;\n }\n\n // Remove the rows if it should be rebuilt.\n if (rebuild) {\n target.innerHTML = '';\n }\n\n // Prune rows.\n for (let i = 0; i < target.rows.length; i++) {\n let prune = true;\n for (let j = 0; j < responses.length; j++) {\n if (target.rows[i].dataset.response === responses[j].response) {\n prune = false;\n break;\n }\n }\n if (prune) {\n target.deleteRow(i);\n i--;\n }\n }\n\n this.createControls(name);\n\n name += graphId;\n\n // Add rows.\n for (let i = 0; i < responses.length; i++) {\n //const percent = (parseInt(responses[i].count) / total) * 100;\n const percent = (parseInt(responses[i].count) / highestResponseCount) * 100;\n\n // Check if row with same response already exists.\n let rowIndex = -1;\n let currentRowIndex = -1;\n for (let j = 0; j < target.rows.length; j++) {\n if (target.rows[j].dataset.response === responses[i].response) {\n rowIndex = target.rows[j].dataset.row_i;\n currentRowIndex = j;\n break;\n }\n }\n\n if (rowIndex === -1) {\n rowIndex = target.rows.length;\n let row = target.insertRow();\n row.dataset.response_i = i;\n row.dataset.response = responses[i].response;\n row.dataset.percent = percent;\n row.dataset.row_i = rowIndex;\n row.dataset.count = responses[i].count;\n row.classList.add('selected-vote-option');\n if (percent < 15) {\n row.classList.add('outside');\n }\n\n const countHtml = '' + responses[i].count + '';\n let responseCell = row.insertCell(0);\n responseCell.onclick = function () {\n $(this).parent().toggleClass('selected-vote-option');\n };\n\n let barCell = row.insertCell(1);\n barCell.classList.add('bar');\n barCell.id = name + '_bar_' + rowIndex;\n barCell.innerHTML = '
' + countHtml + '
';\n\n const latexId = name + '_latex_' + rowIndex;\n responseCell.innerHTML = '';\n Quiz.addMathjaxElement($('#' + latexId), responses[i].response);\n if (responses[i].qtype === 'stack') {\n Quiz.renderMaximaEquation(responses[i].response, latexId);\n }\n } else {\n let currentRow = target.rows[currentRowIndex];\n currentRow.dataset.row_i = rowIndex;\n currentRow.dataset.response_i = i;\n currentRow.dataset.percent = percent;\n currentRow.dataset.count = responses[i].count;\n const containsOutside = currentRow.classList.contains('outside');\n if (percent > 15 && containsOutside) {\n currentRow.classList.remove('outside');\n } else if (percent < 15 && !containsOutside) {\n currentRow.classList.add('outside');\n }\n let countElement = document.getElementById(name + '_count_' + rowIndex);\n if (countElement !== null) {\n countElement.innerHTML = responses[i].count;\n }\n let barElement = document.getElementById(name + '_bar_' + rowIndex);\n if (barElement !== null) {\n barElement.firstElementChild.style.width = percent + '%';\n }\n }\n }\n };\n\n /**\n * Sort the responses in the graph by how many had the same response.\n * @param {string} targetId\n */\n static sortBarGraph(targetId) {\n let target = document.getElementById(targetId);\n if (target === null) {\n return;\n }\n let isSorting = true;\n while (isSorting) {\n isSorting = false;\n for (let i = 0; i < (target.rows.length - 1); i++) {\n const current = parseInt(target.rows[i].dataset.percent);\n const next = parseInt(target.rows[i + 1].dataset.percent);\n if (current < next) {\n target.rows[i].parentNode.insertBefore(target.rows[i + 1], target.rows[i]);\n isSorting = true;\n break;\n }\n }\n }\n }\n\n /**\n * Create and sort a bar graph based on the responses passed.\n * @param {string} wrapperId\n * @param {string} tableId\n * @param {Array.} responses\n * @param {number|undefined} responded How many students responded to the question\n * @param {string} questionType\n * @param {string} graphId\n * @param {boolean} rebuild If the graph should be rebuilt or not.\n */\n set(wrapperId, tableId, responses, responded, questionType, graphId, rebuild) {\n if (responses === undefined) {\n return;\n }\n\n // Check if any responses to show.\n if (responses.length === 0) {\n Quiz.show(Quiz.responded);\n setText(Quiz.responded.find('h4'), 'a_out_of_b_responded', 'jazzquiz', {\n a: 0,\n b: this.totalStudents\n });\n return;\n }\n\n // Question type specific.\n switch (questionType) {\n case 'shortanswer':\n for (let i = 0; i < responses.length; i++) {\n responses[i].response = responses[i].response.trim();\n }\n break;\n case 'stack':\n // Remove all spaces from responses.\n for (let i = 0; i < responses.length; i++) {\n responses[i].response = responses[i].response.replace(/\\s/g, '');\n }\n break;\n default:\n break;\n }\n\n // Update data.\n this.currentResponses = [];\n this.respondedCount = 0;\n for (let i = 0; i < responses.length; i++) {\n let exists = false;\n let count = 1;\n if (responses[i].count !== undefined) {\n count = parseInt(responses[i].count);\n }\n this.respondedCount += count;\n // Check if response is a duplicate.\n for (let j = 0; j < this.currentResponses.length; j++) {\n if (this.currentResponses[j].response === responses[i].response) {\n this.currentResponses[j].count += count;\n exists = true;\n break;\n }\n }\n // Add element if not a duplicate.\n if (!exists) {\n this.currentResponses.push({\n response: responses[i].response,\n count: count,\n qtype: questionType\n });\n }\n }\n\n // Update responded container.\n if (Quiz.responded.length !== 0 && responded !== undefined) {\n Quiz.show(Quiz.responded);\n setText(Quiz.responded.find('h4'), 'a_out_of_b_responded', 'jazzquiz', {\n a: responded,\n b: this.totalStudents\n });\n }\n\n // Should we show the responses?\n if (!this.showResponses && this.quiz.state !== 'reviewing') {\n Quiz.hide(Quiz.responseInfo);\n Quiz.hide(Quiz.responses);\n return;\n }\n\n if (document.getElementById(tableId) === null) {\n const html = '
';\n Quiz.show($('#' + wrapperId).html(html));\n }\n this.createBarGraph(this.currentResponses, 'current_response', tableId, graphId, rebuild);\n ResponseView.sortBarGraph(tableId);\n }\n\n /**\n * Fetch and show results for the ongoing or previous question.\n * @param {boolean} rebuild If the response graph should be rebuilt or not.\n */\n refresh(rebuild) {\n Ajax.get('get_results', {}, data => {\n this.quiz.question.hasVotes = data.has_votes;\n this.totalStudents = parseInt(data.total_students);\n\n this.set('jazzquiz_responses_container', 'current_responses_wrapper',\n data.responses, data.responded, data.question_type, 'results', rebuild);\n\n if (data.merge_count > 0) {\n Quiz.show($('#jazzquiz_undo_merge'));\n } else {\n Quiz.hide($('#jazzquiz_undo_merge'));\n }\n });\n }\n\n /**\n * refresh() equivalent for votes.\n */\n refreshVotes() {\n // Should we show the results?\n if (!this.showResponses && this.quiz.state !== 'reviewing') {\n Quiz.hide(Quiz.responseInfo);\n Quiz.hide(Quiz.responses);\n return;\n }\n Ajax.get('get_vote_results', {}, data => {\n const answers = data.answers;\n const targetId = 'wrapper_vote_responses';\n let responses = [];\n\n this.respondedCount = 0;\n this.totalStudents = parseInt(data.total_students);\n\n for (let i in answers) {\n if (!answers.hasOwnProperty(i)) {\n continue;\n }\n responses.push({\n response: answers[i].attempt,\n count: answers[i].finalcount,\n qtype: answers[i].qtype,\n slot: answers[i].slot\n });\n this.respondedCount += parseInt(answers[i].finalcount);\n }\n\n setText(Quiz.responded.find('h4'), 'a_out_of_b_voted', 'jazzquiz', {\n a: this.respondedCount,\n b: this.totalStudents\n });\n\n if (document.getElementById(targetId) === null) {\n const html = '
';\n Quiz.show(Quiz.responses.html(html));\n }\n\n this.createBarGraph(responses, 'vote_response', targetId, 'vote', false);\n ResponseView.sortBarGraph(targetId);\n });\n }\n\n }\n\n class Instructor {\n\n /**\n * @param {Quiz} quiz\n */\n constructor(quiz) {\n this.quiz = quiz;\n this.responses = new ResponseView(quiz);\n this.isShowingCorrectAnswer = false;\n this.totalQuestions = 0;\n this.allowVote = false;\n\n $(document).on('keyup', event => {\n if (event.keyCode === 27) { // Escape key.\n Instructor.closeFullscreenView();\n }\n });\n\n $(document).on('click', event => {\n Instructor.closeQuestionListMenu(event, 'improvise');\n Instructor.closeQuestionListMenu(event, 'jump');\n });\n\n Instructor.addEvents({\n 'repoll': () => this.repollQuestion(),\n 'vote': () => this.runVoting(),\n 'improvise': () => this.showQuestionListSetup('improvise'),\n 'jump': () => this.showQuestionListSetup('jump'),\n 'next': () => this.nextQuestion(),\n 'random': () => this.randomQuestion(),\n 'end': () => this.endQuestion(),\n 'fullscreen': () => Instructor.showFullscreenView(),\n 'answer': () => this.showCorrectAnswer(),\n 'responses': () => this.responses.toggle(),\n 'exit': () => this.closeSession(),\n 'quit': () => this.closeSession(),\n 'startquiz': () => this.startQuiz()\n });\n\n Instructor.addHotkeys({\n 't': 'responses',\n 'r': 'repoll',\n 'a': 'answer',\n 'e': 'end',\n 'j': 'jump',\n 'i': 'improvise',\n 'v': 'vote',\n 'n': 'next',\n 'm': 'random',\n 'f': 'fullscreen'\n });\n }\n\n static addHotkeys(keys) {\n for (let key in keys) {\n if (keys.hasOwnProperty(key)) {\n keys[key] = {\n action: keys[key],\n repeat: false // TODO: Maybe event.repeat becomes more standard?\n };\n $(document).on('keydown', event => {\n if (keys[key].repeat || event.ctrlKey) {\n return;\n }\n if (String.fromCharCode(event.which).toLowerCase() !== key) {\n return;\n }\n let focusedTag = $(':focus').prop('tagName');\n if (focusedTag !== undefined) {\n focusedTag = focusedTag.toLowerCase();\n if (focusedTag === 'input' || focusedTag === 'textarea') {\n return;\n }\n }\n event.preventDefault();\n keys[key].repeat = true;\n let $control = Instructor.control(keys[key].action);\n if ($control.length && !$control.prop('disabled')) {\n $control.click();\n }\n });\n $(document).on('keyup', event => {\n if (String.fromCharCode(event.which).toLowerCase() === key) {\n keys[key].repeat = false;\n }\n });\n }\n }\n }\n\n static addEvents(events) {\n for (let key in events) {\n if (events.hasOwnProperty(key)) {\n $(document).on('click', '#jazzquiz_control_' + key, () => {\n Instructor.enableControls([]);\n events[key]();\n });\n }\n }\n }\n\n static get controls() {\n return $('#jazzquiz_controls_box');\n }\n\n static get controlButtons() {\n return Instructor.controls.find('.quiz-control-buttons');\n }\n\n static control(key) {\n return $('#jazzquiz_control_' + key);\n }\n\n static get side() {\n return $('#jazzquiz_side_container');\n }\n\n static get correctAnswer() {\n return $('#jazzquiz_correct_answer_container');\n }\n\n static get isMerging() {\n return $('.merge-from').length !== 0;\n }\n\n onNotRunning(data) {\n this.responses.totalStudents = data.student_count;\n Quiz.hide(Instructor.side);\n setText(Quiz.info, 'instructions_for_instructor');\n Instructor.enableControls([]);\n Quiz.hide(Instructor.controlButtons);\n let $studentsJoined = Instructor.control('startquiz').next();\n if (data.student_count === 1) {\n setText($studentsJoined, 'one_student_has_joined');\n } else if (data.student_count > 1) {\n setText($studentsJoined, 'x_students_have_joined', 'jazzquiz', data.student_count);\n } else {\n setText($studentsJoined, 'no_students_have_joined');\n }\n Quiz.show(Instructor.control('startquiz').parent());\n }\n\n onPreparing(data) {\n Quiz.hide(Instructor.side);\n setText(Quiz.info, 'instructions_for_instructor');\n let enabledButtons = ['improvise', 'jump', 'random', 'fullscreen', 'quit'];\n if (data.slot < this.totalQuestions) {\n enabledButtons.push('next');\n }\n Instructor.enableControls(enabledButtons);\n }\n\n onRunning(data) {\n if (!this.responses.showResponses) {\n this.responses.hide();\n }\n Quiz.show(Instructor.side);\n Instructor.enableControls(['end', 'responses', 'fullscreen']);\n this.quiz.question.questionTime = data.questiontime;\n if (this.quiz.question.isRunning) {\n // Check if the question has already ended.\n // We need to do this because the state does not update unless an instructor is connected.\n if (data.questionTime > 0 && data.delay < -data.questiontime) {\n this.endQuestion();\n }\n // Only rebuild results if we are not merging.\n this.responses.refresh(!Instructor.isMerging);\n } else {\n const started = this.quiz.question.startCountdown(data.questiontime, data.delay);\n if (started) {\n this.quiz.question.isRunning = true;\n }\n }\n }\n\n onReviewing(data) {\n Quiz.show(Instructor.side);\n let enabledButtons = ['answer', 'repoll', 'fullscreen', 'improvise', 'jump', 'random', 'quit'];\n if (this.allowVote) {\n enabledButtons.push('vote');\n }\n if (data.slot < this.totalQuestions) {\n enabledButtons.push('next');\n }\n Instructor.enableControls(enabledButtons);\n\n // In case page was refreshed, we should ensure the question is showing.\n if (!Question.isLoaded()) {\n this.quiz.question.refresh();\n }\n\n // For now, just always show responses while reviewing.\n // In the future, there should be an additional toggle.\n if (this.quiz.isNewState) {\n this.responses.show();\n }\n // No longer in question.\n this.quiz.question.isRunning = false;\n }\n\n onSessionClosed(data) {\n Quiz.hide(Instructor.side);\n Quiz.hide(Instructor.correctAnswer);\n Instructor.enableControls([]);\n this.responses.clear();\n this.quiz.question.isRunning = false;\n }\n\n onVoting(data) {\n if (!this.responses.showResponses) {\n this.responses.hide();\n }\n Quiz.show(Instructor.side);\n Instructor.enableControls(['quit', 'fullscreen', 'answer', 'responses', 'end']);\n this.responses.refreshVotes();\n }\n\n onStateChange(state) {\n $('#region-main').find('ul.nav.nav-tabs').css('display', 'none');\n $('#region-main-settings-menu').css('display', 'none');\n $('.region_main_settings_menu_proxy').css('display', 'none');\n Quiz.show(Instructor.controlButtons);\n Quiz.hide(Instructor.control('startquiz').parent());\n }\n\n onQuestionRefreshed(data) {\n this.allowVote = data.voteable;\n }\n\n onTimerEnding() {\n this.endQuestion();\n }\n\n onTimerTick(timeLeft) {\n setText(Question.timer, 'x_seconds_left', 'jazzquiz', timeLeft);\n }\n\n /**\n * Start the quiz. Does not start any questions.\n */\n startQuiz() {\n Quiz.hide(Instructor.control('startquiz').parent());\n Ajax.post('start_quiz', {}, () => $('#jazzquiz_controls').removeClass('btn-hide'));\n }\n\n /**\n * End the currently ongoing question or vote.\n */\n endQuestion() {\n this.quiz.question.hideTimer();\n Ajax.post('end_question', {}, () => {\n if (this.quiz.state === 'voting') {\n this.responses.showVotesUponReview = true;\n } else {\n this.quiz.question.isRunning = false;\n Instructor.enableControls([]);\n }\n });\n }\n\n /**\n * Show a question list dropdown.\n * @param {string} name\n */\n showQuestionListSetup(name) {\n let $controlButton = Instructor.control(name);\n if ($controlButton.hasClass('active')) {\n // It's already open. Let's not send another request.\n return;\n }\n Ajax.get('list_' + name + '_questions', {}, data => {\n let self = this;\n let $menu = $('#jazzquiz_' + name + '_menu');\n const menuMargin = $controlButton.offset().left - $controlButton.parent().offset().left;\n $menu.html('').addClass('active').css('margin-left', menuMargin + 'px');\n $controlButton.addClass('active');\n const questions = data.questions;\n for (let i in questions) {\n if (!questions.hasOwnProperty(i)) {\n continue;\n }\n let $questionButton = $('');\n Quiz.addMathjaxElement($questionButton, questions[i].name);\n $questionButton.data({\n 'time': questions[i].time,\n 'question-id': questions[i].questionid,\n 'jazzquiz-question-id': questions[i].jazzquizquestionid\n });\n $questionButton.data('test', 1);\n $questionButton.on('click', function () {\n const questionId = $(this).data('question-id');\n const time = $(this).data('time');\n const jazzQuestionId = $(this).data('jazzquiz-question-id');\n self.jumpQuestion(questionId, time, jazzQuestionId);\n $menu.html('').removeClass('active');\n $controlButton.removeClass('active');\n });\n $menu.append($questionButton);\n }\n });\n }\n\n /**\n * Get the selected responses.\n * @returns {Array.} Vote options\n */\n static getSelectedAnswersForVote() {\n let result = [];\n $('.selected-vote-option').each((i, option) => {\n result.push({\n text: option.dataset.response,\n count: option.dataset.count\n });\n });\n return result;\n }\n\n /**\n * Start a vote with the responses that are currently selected.\n */\n runVoting() {\n const options = Instructor.getSelectedAnswersForVote();\n const data = {questions: encodeURIComponent(JSON.stringify(options))};\n Ajax.post('run_voting', data, () => {});\n }\n\n /**\n * Start a new question in this session.\n * @param {string} method\n * @param {number} questionId\n * @param {number} questionTime\n * @param {number} jazzquizQuestionId\n */\n startQuestion(method, questionId, questionTime, jazzquizQuestionId) {\n Quiz.hide(Quiz.info);\n this.responses.clear();\n this.hideCorrectAnswer();\n Ajax.post('start_question', {\n method: method,\n questionid: questionId,\n questiontime: questionTime,\n jazzquizquestionid: jazzquizQuestionId\n }, data => this.quiz.question.startCountdown(data.questiontime, data.delay));\n }\n\n /**\n * Jump to a planned question in the quiz.\n * @param {number} questionId\n * @param {number} questionTime\n * @param {number} jazzquizQuestionId\n */\n jumpQuestion(questionId, questionTime, jazzquizQuestionId) {\n this.startQuestion('jump', questionId, questionTime, jazzquizQuestionId);\n }\n\n /**\n * Repoll the previously asked question.\n */\n repollQuestion() {\n this.startQuestion('repoll', 0, 0, 0);\n }\n\n /**\n * Continue on to the next preplanned question.\n */\n nextQuestion() {\n this.startQuestion('next', 0, 0, 0);\n }\n\n /**\n * Start a random question.\n */\n randomQuestion() {\n this.startQuestion('random', 0, 0, 0);\n }\n\n /**\n * Close the current session.\n */\n closeSession() {\n Quiz.hide($('#jazzquiz_undo_merge'));\n Quiz.hide(Question.box);\n Quiz.hide(Instructor.controls);\n setText(Quiz.info, 'closing_session');\n Ajax.post('close_session', {}, () => window.location = location.href.split('&')[0]);\n }\n\n /**\n * Hide the correct answer if showing.\n */\n hideCorrectAnswer() {\n if (this.isShowingCorrectAnswer) {\n Quiz.hide(Instructor.correctAnswer);\n Quiz.uncheck(Instructor.control('answer'));\n this.isShowingCorrectAnswer = false;\n }\n }\n\n /**\n * Request and show the correct answer for the ongoing or previous question.\n */\n showCorrectAnswer() {\n this.hideCorrectAnswer();\n Ajax.get('get_right_response', {}, data => {\n Quiz.show(Instructor.correctAnswer.html(data.right_answer));\n Quiz.renderAllMathjax();\n Quiz.check(Instructor.control('answer'));\n this.isShowingCorrectAnswer = true;\n });\n }\n\n /**\n * Enables all buttons passed in arguments, but disables all others.\n * @param {Array.} buttons The unique part of the IDs of the buttons to be enabled.\n */\n static enableControls(buttons) {\n Instructor.controlButtons.children('button').each((index, child) => {\n const id = child.getAttribute('id').replace('jazzquiz_control_', '');\n child.disabled = (buttons.indexOf(id) === -1);\n });\n }\n\n /**\n * Enter fullscreen mode for better use with projectors.\n */\n static showFullscreenView() {\n if (Quiz.main.hasClass('jazzquiz-fullscreen')) {\n Instructor.closeFullscreenView();\n return;\n }\n // Hide the scrollbar - remember to always set back to auto when closing.\n document.documentElement.style.overflowY = 'hidden';\n // Sets the quiz view to an absolute position that covers the viewport.\n Quiz.main.addClass('jazzquiz-fullscreen');\n }\n\n /**\n * Exit the fullscreen mode.\n */\n static closeFullscreenView() {\n document.documentElement.style.overflowY = 'auto';\n Quiz.main.removeClass('jazzquiz-fullscreen');\n }\n\n /**\n * Close the dropdown menu for choosing a question.\n * @param {Event} event\n * @param {string} name\n */\n static closeQuestionListMenu(event, name) {\n const menuId = '#jazzquiz_' + name + '_menu';\n // Close the menu if the click was not inside.\n const menu = $(event.target).closest(menuId);\n if (!menu.length) {\n $(menuId).html('').removeClass('active');\n Instructor.control(name).removeClass('active');\n }\n }\n\n static addReportEventHandlers() {\n $(document).on('click', '#report_overview_controls button', function () {\n const action = $(this).data('action');\n if (action === 'attendance') {\n $('#report_overview_responded').fadeIn();\n $('#report_overview_responses').fadeOut();\n } else if (action === 'responses') {\n $('#report_overview_responses').fadeIn();\n $('#report_overview_responded').fadeOut();\n }\n });\n }\n\n }\n\n return {\n initialize: function (totalQuestions, reportView, slots) {\n let quiz = new Quiz(Instructor);\n quiz.role.totalQuestions = totalQuestions;\n if (reportView) {\n Instructor.addReportEventHandlers();\n quiz.role.responses.showResponses = true;\n slots.forEach(slot => {\n const wrapper = 'jazzquiz_wrapper_responses_' + slot.num;\n const table = 'responses_wrapper_table_' + slot.num;\n const graph = 'report_' + slot.num;\n quiz.role.responses.set(wrapper, table, slot.responses, undefined, slot.type, graph, false);\n });\n } else {\n quiz.poll(500);\n }\n }\n }\n\n});\n"],"file":"instructor.min.js"} \ No newline at end of file +{"version":3,"file":"instructor.min.js","sources":["../src/instructor.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2014 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'mod_jazzquiz/core'], function ($, Jazz) {\n\n const Quiz = Jazz.Quiz;\n const Question = Jazz.Question;\n const Ajax = Jazz.Ajax;\n const setText = Jazz.setText;\n\n class ResponseView {\n\n /**\n * @param {Quiz} quiz\n */\n constructor(quiz) {\n this.quiz = quiz;\n this.currentResponses = [];\n this.showVotesUponReview = false;\n this.respondedCount = 0;\n this.showResponses = false;\n this.totalStudents = 0;\n $(document).on('click', '#jazzquiz_undo_merge', () => this.undoMerge());\n $(document).on('click', event => {\n // Clicking a row to merge.\n if (event.target.classList.contains('bar')) {\n this.startMerge(event.target.id);\n } else if (event.target.parentNode && event.target.parentNode.classList.contains('bar')) {\n this.startMerge(event.target.parentNode.id);\n }\n });\n $(document).on('click', '#review_show_normal_results', () => this.refresh(false));\n $(document).on('click', '#review_show_vote_results', () => this.refreshVotes());\n }\n\n /**\n * Clear, but not hide responses.\n */\n clear() {\n Quiz.responses.html('');\n Quiz.responseInfo.html('');\n }\n\n /**\n * Hides the responses\n */\n hide() {\n Quiz.uncheck(Instructor.control('responses'));\n Quiz.hide(Quiz.responses);\n Quiz.hide(Quiz.responseInfo);\n }\n\n /**\n * Shows the responses\n */\n show() {\n Quiz.check(Instructor.control('responses'));\n Quiz.show(Quiz.responses);\n Quiz.show(Quiz.responseInfo);\n if (this.showVotesUponReview) {\n this.refreshVotes();\n this.showVotesUponReview = false;\n } else {\n this.refresh(false);\n }\n }\n\n /**\n * Toggle whether to show or hide the responses\n */\n toggle() {\n this.showResponses = !this.showResponses;\n if (this.showResponses) {\n this.show();\n } else {\n this.hide();\n }\n }\n\n /**\n * End the response merge.\n */\n endMerge() {\n $('.merge-into').removeClass('merge-into');\n $('.merge-from').removeClass('merge-from');\n }\n\n /**\n * Undo the last response merge.\n */\n undoMerge() {\n Ajax.post('undo_merge', {}, () => this.refresh(true));\n }\n\n /**\n * Merges responses based on response string.\n * @param {string} from\n * @param {string} into\n */\n merge(from, into) {\n Ajax.post('merge_responses', {from: from, into: into}, () => this.refresh(false));\n }\n\n /**\n * Start a merge between two responses.\n * @param {string} fromRowBarId\n */\n startMerge(fromRowBarId) {\n const $barCell = $('#' + fromRowBarId);\n let $row = $barCell.parent();\n if ($row.hasClass('merge-from')) {\n this.endMerge();\n return;\n }\n if ($row.hasClass('merge-into')) {\n const $fromRow = $('.merge-from');\n this.merge($fromRow.data('response'), $row.data('response'));\n this.endMerge();\n return;\n }\n $row.addClass('merge-from');\n let $table = $row.parent().parent();\n $table.find('tr').each(function () {\n const $cells = $(this).find('td');\n if ($cells[1].id !== $barCell.attr('id')) {\n $(this).addClass('merge-into');\n }\n });\n }\n\n /**\n * Create controls to toggle between the responses of the actual question and the vote that followed.\n * @param {string} name Can be either 'vote_response' or 'current_response'\n */\n createControls(name) {\n if (!this.quiz.question.hasVotes) {\n Quiz.hide(Quiz.responseInfo);\n return;\n }\n // Add button for instructor to change what to review.\n if (this.quiz.state === 'reviewing') {\n let $showNormalResult = $('#review_show_normal_results');\n let $showVoteResult = $('#review_show_vote_results');\n Quiz.show(Quiz.responseInfo);\n if (name === 'vote_response') {\n if ($showNormalResult.length === 0) {\n setText(Quiz.responseInfo.html('

').children('h4'), 'showing_vote_results');\n Quiz.responseInfo.append('
');\n setText($('#review_show_normal_results'), 'click_to_show_original_results');\n $showVoteResult.remove();\n }\n } else if (name === 'current_response') {\n if ($showVoteResult.length === 0) {\n setText(Quiz.responseInfo.html('

').children('h4'), 'showing_original_results');\n Quiz.responseInfo.append('
');\n setText($('#review_show_vote_results'), 'click_to_show_vote_results');\n $showNormalResult.remove();\n }\n }\n }\n }\n\n /**\n * Create a new and unsorted response bar graph.\n * @param {Array.} responses\n * @param {string} name\n * @param {string} targetId\n * @param {string} graphId\n * @param {boolean} rebuild If the table should be completely rebuilt or not\n */\n createBarGraph(responses, name, targetId, graphId, rebuild) {\n let target = document.getElementById(targetId);\n if (target === null) {\n return;\n }\n let total = 0;\n let highestResponseCount = 0;\n for (let i = 0; i < responses.length; i++) {\n let count = parseInt(responses[i].count); // In case count is a string.\n total += count;\n if (count > highestResponseCount) {\n highestResponseCount = count;\n }\n\n }\n if (total === 0) {\n total = 1;\n }\n\n // Remove the rows if it should be rebuilt.\n if (rebuild) {\n target.innerHTML = '';\n }\n\n // Prune rows.\n for (let i = 0; i < target.rows.length; i++) {\n let prune = true;\n for (let j = 0; j < responses.length; j++) {\n if (target.rows[i].dataset.response === responses[j].response) {\n prune = false;\n break;\n }\n }\n if (prune) {\n target.deleteRow(i);\n i--;\n }\n }\n\n this.createControls(name);\n\n name += graphId;\n\n // Add rows.\n for (let i = 0; i < responses.length; i++) {\n //const percent = (parseInt(responses[i].count) / total) * 100;\n const percent = (parseInt(responses[i].count) / highestResponseCount) * 100;\n\n // Check if row with same response already exists.\n let rowIndex = -1;\n let currentRowIndex = -1;\n for (let j = 0; j < target.rows.length; j++) {\n if (target.rows[j].dataset.response === responses[i].response) {\n rowIndex = target.rows[j].dataset.row_i;\n currentRowIndex = j;\n break;\n }\n }\n\n if (rowIndex === -1) {\n rowIndex = target.rows.length;\n let row = target.insertRow();\n row.dataset.response_i = i;\n row.dataset.response = responses[i].response;\n row.dataset.percent = percent;\n row.dataset.row_i = rowIndex;\n row.dataset.count = responses[i].count;\n row.classList.add('selected-vote-option');\n if (percent < 15) {\n row.classList.add('outside');\n }\n\n const countHtml = '' + responses[i].count + '';\n let responseCell = row.insertCell(0);\n responseCell.onclick = function () {\n $(this).parent().toggleClass('selected-vote-option');\n };\n\n let barCell = row.insertCell(1);\n barCell.classList.add('bar');\n barCell.id = name + '_bar_' + rowIndex;\n barCell.innerHTML = '
' + countHtml + '
';\n\n const latexId = name + '_latex_' + rowIndex;\n responseCell.innerHTML = '';\n Quiz.addMathjaxElement($('#' + latexId), responses[i].response);\n if (responses[i].qtype === 'stack') {\n Quiz.renderMaximaEquation(responses[i].response, latexId);\n }\n } else {\n let currentRow = target.rows[currentRowIndex];\n currentRow.dataset.row_i = rowIndex;\n currentRow.dataset.response_i = i;\n currentRow.dataset.percent = percent;\n currentRow.dataset.count = responses[i].count;\n const containsOutside = currentRow.classList.contains('outside');\n if (percent > 15 && containsOutside) {\n currentRow.classList.remove('outside');\n } else if (percent < 15 && !containsOutside) {\n currentRow.classList.add('outside');\n }\n let countElement = document.getElementById(name + '_count_' + rowIndex);\n if (countElement !== null) {\n countElement.innerHTML = responses[i].count;\n }\n let barElement = document.getElementById(name + '_bar_' + rowIndex);\n if (barElement !== null) {\n barElement.firstElementChild.style.width = percent + '%';\n }\n }\n }\n };\n\n /**\n * Sort the responses in the graph by how many had the same response.\n * @param {string} targetId\n */\n static sortBarGraph(targetId) {\n let target = document.getElementById(targetId);\n if (target === null) {\n return;\n }\n let isSorting = true;\n while (isSorting) {\n isSorting = false;\n for (let i = 0; i < (target.rows.length - 1); i++) {\n const current = parseInt(target.rows[i].dataset.percent);\n const next = parseInt(target.rows[i + 1].dataset.percent);\n if (current < next) {\n target.rows[i].parentNode.insertBefore(target.rows[i + 1], target.rows[i]);\n isSorting = true;\n break;\n }\n }\n }\n }\n\n /**\n * Create and sort a bar graph based on the responses passed.\n * @param {string} wrapperId\n * @param {string} tableId\n * @param {Array.} responses\n * @param {number|undefined} responded How many students responded to the question\n * @param {string} questionType\n * @param {string} graphId\n * @param {boolean} rebuild If the graph should be rebuilt or not.\n */\n set(wrapperId, tableId, responses, responded, questionType, graphId, rebuild) {\n if (responses === undefined) {\n return;\n }\n\n // Check if any responses to show.\n if (responses.length === 0) {\n Quiz.show(Quiz.responded);\n setText(Quiz.responded.find('h4'), 'a_out_of_b_responded', 'jazzquiz', {\n a: 0,\n b: this.totalStudents\n });\n return;\n }\n\n // Question type specific.\n switch (questionType) {\n case 'shortanswer':\n for (let i = 0; i < responses.length; i++) {\n responses[i].response = responses[i].response.trim();\n }\n break;\n case 'stack':\n // Remove all spaces from responses.\n for (let i = 0; i < responses.length; i++) {\n responses[i].response = responses[i].response.replace(/\\s/g, '');\n }\n break;\n default:\n break;\n }\n\n // Update data.\n this.currentResponses = [];\n this.respondedCount = 0;\n for (let i = 0; i < responses.length; i++) {\n let exists = false;\n let count = 1;\n if (responses[i].count !== undefined) {\n count = parseInt(responses[i].count);\n }\n this.respondedCount += count;\n // Check if response is a duplicate.\n for (let j = 0; j < this.currentResponses.length; j++) {\n if (this.currentResponses[j].response === responses[i].response) {\n this.currentResponses[j].count += count;\n exists = true;\n break;\n }\n }\n // Add element if not a duplicate.\n if (!exists) {\n this.currentResponses.push({\n response: responses[i].response,\n count: count,\n qtype: questionType\n });\n }\n }\n\n // Update responded container.\n if (Quiz.responded.length !== 0 && responded !== undefined) {\n Quiz.show(Quiz.responded);\n setText(Quiz.responded.find('h4'), 'a_out_of_b_responded', 'jazzquiz', {\n a: responded,\n b: this.totalStudents\n });\n }\n\n // Should we show the responses?\n if (!this.showResponses && this.quiz.state !== 'reviewing') {\n Quiz.hide(Quiz.responseInfo);\n Quiz.hide(Quiz.responses);\n return;\n }\n\n if (document.getElementById(tableId) === null) {\n const html = '
';\n Quiz.show($('#' + wrapperId).html(html));\n }\n this.createBarGraph(this.currentResponses, 'current_response', tableId, graphId, rebuild);\n ResponseView.sortBarGraph(tableId);\n }\n\n /**\n * Fetch and show results for the ongoing or previous question.\n * @param {boolean} rebuild If the response graph should be rebuilt or not.\n */\n refresh(rebuild) {\n Ajax.get('get_results', {}, data => {\n this.quiz.question.hasVotes = data.has_votes;\n this.totalStudents = parseInt(data.total_students);\n\n this.set('jazzquiz_responses_container', 'current_responses_wrapper',\n data.responses, data.responded, data.question_type, 'results', rebuild);\n\n if (data.merge_count > 0) {\n Quiz.show($('#jazzquiz_undo_merge'));\n } else {\n Quiz.hide($('#jazzquiz_undo_merge'));\n }\n });\n }\n\n /**\n * refresh() equivalent for votes.\n */\n refreshVotes() {\n // Should we show the results?\n if (!this.showResponses && this.quiz.state !== 'reviewing') {\n Quiz.hide(Quiz.responseInfo);\n Quiz.hide(Quiz.responses);\n return;\n }\n Ajax.get('get_vote_results', {}, data => {\n const answers = data.answers;\n const targetId = 'wrapper_vote_responses';\n let responses = [];\n\n this.respondedCount = 0;\n this.totalStudents = parseInt(data.total_students);\n\n for (let i in answers) {\n if (!answers.hasOwnProperty(i)) {\n continue;\n }\n responses.push({\n response: answers[i].attempt,\n count: answers[i].finalcount,\n qtype: answers[i].qtype,\n slot: answers[i].slot\n });\n this.respondedCount += parseInt(answers[i].finalcount);\n }\n\n setText(Quiz.responded.find('h4'), 'a_out_of_b_voted', 'jazzquiz', {\n a: this.respondedCount,\n b: this.totalStudents\n });\n\n if (document.getElementById(targetId) === null) {\n const html = '
';\n Quiz.show(Quiz.responses.html(html));\n }\n\n this.createBarGraph(responses, 'vote_response', targetId, 'vote', false);\n ResponseView.sortBarGraph(targetId);\n });\n }\n\n }\n\n class Instructor {\n\n /**\n * @param {Quiz} quiz\n */\n constructor(quiz) {\n this.quiz = quiz;\n this.responses = new ResponseView(quiz);\n this.isShowingCorrectAnswer = false;\n this.totalQuestions = 0;\n this.allowVote = false;\n\n $(document).on('keyup', event => {\n if (event.keyCode === 27) { // Escape key.\n Instructor.closeFullscreenView();\n }\n });\n\n $(document).on('click', event => {\n Instructor.closeQuestionListMenu(event, 'improvise');\n Instructor.closeQuestionListMenu(event, 'jump');\n });\n\n Instructor.addEvents({\n 'repoll': () => this.repollQuestion(),\n 'vote': () => this.runVoting(),\n 'improvise': () => this.showQuestionListSetup('improvise'),\n 'jump': () => this.showQuestionListSetup('jump'),\n 'next': () => this.nextQuestion(),\n 'random': () => this.randomQuestion(),\n 'end': () => this.endQuestion(),\n 'fullscreen': () => Instructor.showFullscreenView(),\n 'answer': () => this.showCorrectAnswer(),\n 'responses': () => this.responses.toggle(),\n 'exit': () => this.closeSession(),\n 'quit': () => this.closeSession(),\n 'startquiz': () => this.startQuiz()\n });\n\n Instructor.addHotkeys({\n 't': 'responses',\n 'r': 'repoll',\n 'a': 'answer',\n 'e': 'end',\n 'j': 'jump',\n 'i': 'improvise',\n 'v': 'vote',\n 'n': 'next',\n 'm': 'random',\n 'f': 'fullscreen'\n });\n }\n\n static addHotkeys(keys) {\n for (let key in keys) {\n if (keys.hasOwnProperty(key)) {\n keys[key] = {\n action: keys[key],\n repeat: false // TODO: Maybe event.repeat becomes more standard?\n };\n $(document).on('keydown', event => {\n if (keys[key].repeat || event.ctrlKey) {\n return;\n }\n if (String.fromCharCode(event.which).toLowerCase() !== key) {\n return;\n }\n let focusedTag = $(':focus').prop('tagName');\n if (focusedTag !== undefined) {\n focusedTag = focusedTag.toLowerCase();\n if (focusedTag === 'input' || focusedTag === 'textarea') {\n return;\n }\n }\n event.preventDefault();\n keys[key].repeat = true;\n let $control = Instructor.control(keys[key].action);\n if ($control.length && !$control.prop('disabled')) {\n $control.click();\n }\n });\n $(document).on('keyup', event => {\n if (String.fromCharCode(event.which).toLowerCase() === key) {\n keys[key].repeat = false;\n }\n });\n }\n }\n }\n\n static addEvents(events) {\n for (let key in events) {\n if (events.hasOwnProperty(key)) {\n $(document).on('click', '#jazzquiz_control_' + key, () => {\n Instructor.enableControls([]);\n events[key]();\n });\n }\n }\n }\n\n static get controls() {\n return $('#jazzquiz_controls_box');\n }\n\n static get controlButtons() {\n return Instructor.controls.find('.quiz-control-buttons');\n }\n\n static control(key) {\n return $('#jazzquiz_control_' + key);\n }\n\n static get side() {\n return $('#jazzquiz_side_container');\n }\n\n static get correctAnswer() {\n return $('#jazzquiz_correct_answer_container');\n }\n\n static get isMerging() {\n return $('.merge-from').length !== 0;\n }\n\n onNotRunning(data) {\n this.responses.totalStudents = data.student_count;\n Quiz.hide(Instructor.side);\n setText(Quiz.info, 'instructions_for_instructor');\n Instructor.enableControls([]);\n Quiz.hide(Instructor.controlButtons);\n let $studentsJoined = Instructor.control('startquiz').next();\n if (data.student_count === 1) {\n setText($studentsJoined, 'one_student_has_joined');\n } else if (data.student_count > 1) {\n setText($studentsJoined, 'x_students_have_joined', 'jazzquiz', data.student_count);\n } else {\n setText($studentsJoined, 'no_students_have_joined');\n }\n Quiz.show(Instructor.control('startquiz').parent());\n }\n\n onPreparing(data) {\n Quiz.hide(Instructor.side);\n setText(Quiz.info, 'instructions_for_instructor');\n let enabledButtons = ['improvise', 'jump', 'random', 'fullscreen', 'quit'];\n if (data.slot < this.totalQuestions) {\n enabledButtons.push('next');\n }\n Instructor.enableControls(enabledButtons);\n }\n\n onRunning(data) {\n if (!this.responses.showResponses) {\n this.responses.hide();\n }\n Quiz.show(Instructor.side);\n Instructor.enableControls(['end', 'responses', 'fullscreen']);\n this.quiz.question.questionTime = data.questiontime;\n if (this.quiz.question.isRunning) {\n // Check if the question has already ended.\n // We need to do this because the state does not update unless an instructor is connected.\n if (data.questionTime > 0 && data.delay < -data.questiontime) {\n this.endQuestion();\n }\n // Only rebuild results if we are not merging.\n this.responses.refresh(!Instructor.isMerging);\n } else {\n const started = this.quiz.question.startCountdown(data.questiontime, data.delay);\n if (started) {\n this.quiz.question.isRunning = true;\n }\n }\n }\n\n onReviewing(data) {\n Quiz.show(Instructor.side);\n let enabledButtons = ['answer', 'repoll', 'fullscreen', 'improvise', 'jump', 'random', 'quit'];\n if (this.allowVote) {\n enabledButtons.push('vote');\n }\n if (data.slot < this.totalQuestions) {\n enabledButtons.push('next');\n }\n Instructor.enableControls(enabledButtons);\n\n // In case page was refreshed, we should ensure the question is showing.\n if (!Question.isLoaded()) {\n this.quiz.question.refresh();\n }\n\n // For now, just always show responses while reviewing.\n // In the future, there should be an additional toggle.\n if (this.quiz.isNewState) {\n this.responses.show();\n }\n // No longer in question.\n this.quiz.question.isRunning = false;\n }\n\n onSessionClosed(data) {\n Quiz.hide(Instructor.side);\n Quiz.hide(Instructor.correctAnswer);\n Instructor.enableControls([]);\n this.responses.clear();\n this.quiz.question.isRunning = false;\n }\n\n onVoting(data) {\n if (!this.responses.showResponses) {\n this.responses.hide();\n }\n Quiz.show(Instructor.side);\n Instructor.enableControls(['quit', 'fullscreen', 'answer', 'responses', 'end']);\n this.responses.refreshVotes();\n }\n\n onStateChange(state) {\n $('#region-main').find('ul.nav.nav-tabs').css('display', 'none');\n $('#region-main-settings-menu').css('display', 'none');\n $('.region_main_settings_menu_proxy').css('display', 'none');\n Quiz.show(Instructor.controlButtons);\n Quiz.hide(Instructor.control('startquiz').parent());\n }\n\n onQuestionRefreshed(data) {\n this.allowVote = data.voteable;\n }\n\n onTimerEnding() {\n this.endQuestion();\n }\n\n onTimerTick(timeLeft) {\n setText(Question.timer, 'x_seconds_left', 'jazzquiz', timeLeft);\n }\n\n /**\n * Start the quiz. Does not start any questions.\n */\n startQuiz() {\n Quiz.hide(Instructor.control('startquiz').parent());\n Ajax.post('start_quiz', {}, () => $('#jazzquiz_controls').removeClass('btn-hide'));\n }\n\n /**\n * End the currently ongoing question or vote.\n */\n endQuestion() {\n this.quiz.question.hideTimer();\n Ajax.post('end_question', {}, () => {\n if (this.quiz.state === 'voting') {\n this.responses.showVotesUponReview = true;\n } else {\n this.quiz.question.isRunning = false;\n Instructor.enableControls([]);\n }\n });\n }\n\n /**\n * Show a question list dropdown.\n * @param {string} name\n */\n showQuestionListSetup(name) {\n let $controlButton = Instructor.control(name);\n if ($controlButton.hasClass('active')) {\n // It's already open. Let's not send another request.\n return;\n }\n Ajax.get('list_' + name + '_questions', {}, data => {\n let self = this;\n let $menu = $('#jazzquiz_' + name + '_menu');\n const menuMargin = $controlButton.offset().left - $controlButton.parent().offset().left;\n $menu.html('').addClass('active').css('margin-left', menuMargin + 'px');\n $controlButton.addClass('active');\n const questions = data.questions;\n for (let i in questions) {\n if (!questions.hasOwnProperty(i)) {\n continue;\n }\n let $questionButton = $('');\n Quiz.addMathjaxElement($questionButton, questions[i].name);\n $questionButton.data({\n 'time': questions[i].time,\n 'question-id': questions[i].questionid,\n 'jazzquiz-question-id': questions[i].jazzquizquestionid\n });\n $questionButton.data('test', 1);\n $questionButton.on('click', function () {\n const questionId = $(this).data('question-id');\n const time = $(this).data('time');\n const jazzQuestionId = $(this).data('jazzquiz-question-id');\n self.jumpQuestion(questionId, time, jazzQuestionId);\n $menu.html('').removeClass('active');\n $controlButton.removeClass('active');\n });\n $menu.append($questionButton);\n }\n });\n }\n\n /**\n * Get the selected responses.\n * @returns {Array.} Vote options\n */\n static getSelectedAnswersForVote() {\n let result = [];\n $('.selected-vote-option').each((i, option) => {\n result.push({\n text: option.dataset.response,\n count: option.dataset.count\n });\n });\n return result;\n }\n\n /**\n * Start a vote with the responses that are currently selected.\n */\n runVoting() {\n const options = Instructor.getSelectedAnswersForVote();\n const data = {questions: encodeURIComponent(JSON.stringify(options))};\n Ajax.post('run_voting', data, () => {});\n }\n\n /**\n * Start a new question in this session.\n * @param {string} method\n * @param {number} questionId\n * @param {number} questionTime\n * @param {number} jazzquizQuestionId\n */\n startQuestion(method, questionId, questionTime, jazzquizQuestionId) {\n Quiz.hide(Quiz.info);\n this.responses.clear();\n this.hideCorrectAnswer();\n Ajax.post('start_question', {\n method: method,\n questionid: questionId,\n questiontime: questionTime,\n jazzquizquestionid: jazzquizQuestionId\n }, data => this.quiz.question.startCountdown(data.questiontime, data.delay));\n }\n\n /**\n * Jump to a planned question in the quiz.\n * @param {number} questionId\n * @param {number} questionTime\n * @param {number} jazzquizQuestionId\n */\n jumpQuestion(questionId, questionTime, jazzquizQuestionId) {\n this.startQuestion('jump', questionId, questionTime, jazzquizQuestionId);\n }\n\n /**\n * Repoll the previously asked question.\n */\n repollQuestion() {\n this.startQuestion('repoll', 0, 0, 0);\n }\n\n /**\n * Continue on to the next preplanned question.\n */\n nextQuestion() {\n this.startQuestion('next', 0, 0, 0);\n }\n\n /**\n * Start a random question.\n */\n randomQuestion() {\n this.startQuestion('random', 0, 0, 0);\n }\n\n /**\n * Close the current session.\n */\n closeSession() {\n Quiz.hide($('#jazzquiz_undo_merge'));\n Quiz.hide(Question.box);\n Quiz.hide(Instructor.controls);\n setText(Quiz.info, 'closing_session');\n Ajax.post('close_session', {}, () => window.location = location.href.split('&')[0]);\n }\n\n /**\n * Hide the correct answer if showing.\n */\n hideCorrectAnswer() {\n if (this.isShowingCorrectAnswer) {\n Quiz.hide(Instructor.correctAnswer);\n Quiz.uncheck(Instructor.control('answer'));\n this.isShowingCorrectAnswer = false;\n }\n }\n\n /**\n * Request and show the correct answer for the ongoing or previous question.\n */\n showCorrectAnswer() {\n this.hideCorrectAnswer();\n Ajax.get('get_right_response', {}, data => {\n Quiz.show(Instructor.correctAnswer.html(data.right_answer));\n Quiz.renderAllMathjax();\n Quiz.check(Instructor.control('answer'));\n this.isShowingCorrectAnswer = true;\n });\n }\n\n /**\n * Enables all buttons passed in arguments, but disables all others.\n * @param {Array.} buttons The unique part of the IDs of the buttons to be enabled.\n */\n static enableControls(buttons) {\n Instructor.controlButtons.children('button').each((index, child) => {\n const id = child.getAttribute('id').replace('jazzquiz_control_', '');\n child.disabled = (buttons.indexOf(id) === -1);\n });\n }\n\n /**\n * Enter fullscreen mode for better use with projectors.\n */\n static showFullscreenView() {\n if (Quiz.main.hasClass('jazzquiz-fullscreen')) {\n Instructor.closeFullscreenView();\n return;\n }\n // Hide the scrollbar - remember to always set back to auto when closing.\n document.documentElement.style.overflowY = 'hidden';\n // Sets the quiz view to an absolute position that covers the viewport.\n Quiz.main.addClass('jazzquiz-fullscreen');\n }\n\n /**\n * Exit the fullscreen mode.\n */\n static closeFullscreenView() {\n document.documentElement.style.overflowY = 'auto';\n Quiz.main.removeClass('jazzquiz-fullscreen');\n }\n\n /**\n * Close the dropdown menu for choosing a question.\n * @param {Event} event\n * @param {string} name\n */\n static closeQuestionListMenu(event, name) {\n const menuId = '#jazzquiz_' + name + '_menu';\n // Close the menu if the click was not inside.\n const menu = $(event.target).closest(menuId);\n if (!menu.length) {\n $(menuId).html('').removeClass('active');\n Instructor.control(name).removeClass('active');\n }\n }\n\n static addReportEventHandlers() {\n $(document).on('click', '#report_overview_controls button', function () {\n const action = $(this).data('action');\n if (action === 'attendance') {\n $('#report_overview_responded').fadeIn();\n $('#report_overview_responses').fadeOut();\n } else if (action === 'responses') {\n $('#report_overview_responses').fadeIn();\n $('#report_overview_responded').fadeOut();\n }\n });\n }\n\n }\n\n return {\n initialize: function (totalQuestions, reportView, slots) {\n let quiz = new Quiz(Instructor);\n quiz.role.totalQuestions = totalQuestions;\n if (reportView) {\n Instructor.addReportEventHandlers();\n quiz.role.responses.showResponses = true;\n slots.forEach(slot => {\n const wrapper = 'jazzquiz_wrapper_responses_' + slot.num;\n const table = 'responses_wrapper_table_' + slot.num;\n const graph = 'report_' + slot.num;\n quiz.role.responses.set(wrapper, table, slot.responses, undefined, slot.type, graph, false);\n });\n } else {\n quiz.poll(500);\n }\n }\n }\n\n});\n"],"names":["define","$","Jazz","Quiz","Question","Ajax","setText","ResponseView","constructor","quiz","currentResponses","showVotesUponReview","respondedCount","showResponses","totalStudents","document","on","this","undoMerge","event","target","classList","contains","startMerge","id","parentNode","refresh","refreshVotes","clear","responses","html","responseInfo","hide","uncheck","Instructor","control","show","check","toggle","endMerge","removeClass","post","merge","from","into","fromRowBarId","$barCell","$row","parent","hasClass","$fromRow","data","addClass","find","each","attr","createControls","name","question","hasVotes","state","$showNormalResult","$showVoteResult","length","children","append","remove","createBarGraph","targetId","graphId","rebuild","getElementById","total","highestResponseCount","i","count","parseInt","innerHTML","rows","prune","j","dataset","response","deleteRow","percent","rowIndex","currentRowIndex","row_i","row","insertRow","response_i","add","countHtml","responseCell","insertCell","onclick","toggleClass","barCell","latexId","addMathjaxElement","qtype","renderMaximaEquation","currentRow","containsOutside","countElement","barElement","firstElementChild","style","width","isSorting","insertBefore","set","wrapperId","tableId","responded","questionType","undefined","a","b","trim","replace","exists","push","sortBarGraph","get","has_votes","total_students","question_type","merge_count","answers","hasOwnProperty","attempt","finalcount","slot","isShowingCorrectAnswer","totalQuestions","allowVote","keyCode","closeFullscreenView","closeQuestionListMenu","addEvents","repollQuestion","runVoting","showQuestionListSetup","nextQuestion","randomQuestion","endQuestion","showFullscreenView","showCorrectAnswer","closeSession","startQuiz","addHotkeys","keys","key","action","repeat","ctrlKey","String","fromCharCode","which","toLowerCase","focusedTag","prop","preventDefault","$control","click","events","enableControls","controls","controlButtons","side","correctAnswer","isMerging","onNotRunning","student_count","info","$studentsJoined","next","onPreparing","enabledButtons","onRunning","questionTime","questiontime","isRunning","delay","startCountdown","onReviewing","isLoaded","isNewState","onSessionClosed","onVoting","onStateChange","css","onQuestionRefreshed","voteable","onTimerEnding","onTimerTick","timeLeft","timer","hideTimer","$controlButton","self","$menu","menuMargin","offset","left","questions","$questionButton","time","questionid","jazzquizquestionid","questionId","jazzQuestionId","jumpQuestion","result","option","text","options","getSelectedAnswersForVote","encodeURIComponent","JSON","stringify","startQuestion","method","jazzquizQuestionId","hideCorrectAnswer","box","window","location","href","split","right_answer","renderAllMathjax","buttons","index","child","getAttribute","disabled","indexOf","main","documentElement","overflowY","menuId","closest","fadeIn","fadeOut","initialize","reportView","slots","role","addReportEventHandlers","forEach","wrapper","num","table","graph","type","poll"],"mappings":"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"} \ No newline at end of file diff --git a/amd/build/student.min.js b/amd/build/student.min.js index f2493b8..7333d64 100644 --- a/amd/build/student.min.js +++ b/amd/build/student.min.js @@ -1,2 +1,10 @@ -function _classCallCheck(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(a,b){for(var c=0,d;c + * @copyright 2014 University of Wisconsin - Madison + * @copyright 2018 NTNU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define("mod_jazzquiz/student",["jquery","mod_jazzquiz/core"],(function($,Jazz){const Quiz=Jazz.Quiz,Question=Jazz.Question,Ajax=Jazz.Ajax,setText=Jazz.setText;class Student{constructor(quiz){this.quiz=quiz,this.voteAnswer=void 0;let self=this;$(document).on("submit","#jazzquiz_question_form",(function(event){event.preventDefault(),self.submitAnswer()})).on("click","#jazzquiz_save_vote",(function(){self.saveVote()})).on("click",".jazzquiz-select-vote",(function(){self.voteAnswer=this.value}))}onNotRunning(data){setText(Quiz.info,"instructions_for_student")}onPreparing(data){setText(Quiz.info,"wait_for_instructor")}onRunning(data){if(this.quiz.question.isRunning)return;this.quiz.question.startCountdown(data.questiontime,data.delay)||setText(Quiz.info,"wait_for_instructor")}onReviewing(data){this.quiz.question.isVoteRunning=!1,this.quiz.question.isRunning=!1,this.quiz.question.hideTimer(),Quiz.hide(Question.box),setText(Quiz.info,"wait_for_instructor")}onSessionClosed(data){window.location=location.href.split("&")[0]}onVoting(data){if(this.quiz.question.isVoteRunning)return;Quiz.info.html(data.html),Quiz.show(Quiz.info);const options=data.options;for(let i=0;i{data.feedback.length>0?Quiz.show(Quiz.info.html(data.feedback)):setText(Quiz.info,"wait_for_instructor"),this.quiz.question.isSaving=!1,this.quiz.question.isRunning&&(this.quiz.question.isVoteRunning||(Quiz.hide(Question.box),this.quiz.question.hideTimer()))})).fail((()=>{this.quiz.question.isSaving=!1}))}saveVote(){Ajax.post("save_vote",{vote:this.voteAnswer},(data=>{"success"===data.status?setText(Quiz.info,"wait_for_instructor"):setText(Quiz.info,"you_already_voted")}))}}return{initialize:()=>{new Quiz(Student).poll(2e3)}}})); + +//# sourceMappingURL=student.min.js.map \ No newline at end of file diff --git a/amd/build/student.min.js.map b/amd/build/student.min.js.map index 5f1ce01..8ce49a8 100644 --- a/amd/build/student.min.js.map +++ b/amd/build/student.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/student.js"],"names":["define","$","Jazz","Quiz","Question","Ajax","setText","Student","quiz","voteAnswer","self","document","on","event","preventDefault","submitAnswer","saveVote","value","info","data","question","isRunning","started","startCountdown","questiontime","delay","isVoteRunning","hideTimer","hide","box","window","location","href","split","html","show","options","i","length","addMathjaxElement","content_id","text","question_type","renderMaximaEquation","timeLeft","timer","isSaving","tinyMCE","triggerSave","serialized","form","serializeArray","name","hasOwnProperty","post","feedback","fail","vote","status","initialize","poll"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2014 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'mod_jazzquiz/core'], function ($, Jazz) {\n\n const Quiz = Jazz.Quiz;\n const Question = Jazz.Question;\n const Ajax = Jazz.Ajax;\n const setText = Jazz.setText;\n\n class Student {\n\n /**\n * @param {Quiz} quiz\n */\n constructor(quiz) {\n this.quiz = quiz;\n this.voteAnswer = undefined;\n let self = this;\n $(document).on('submit', '#jazzquiz_question_form', function(event) {\n event.preventDefault();\n self.submitAnswer();\n }).on('click', '#jazzquiz_save_vote', function() {\n self.saveVote();\n }).on('click', '.jazzquiz-select-vote', function() {\n self.voteAnswer = this.value;\n });\n }\n\n onNotRunning(data) {\n setText(Quiz.info, 'instructions_for_student');\n }\n\n onPreparing(data) {\n setText(Quiz.info, 'wait_for_instructor');\n }\n\n onRunning(data) {\n if (this.quiz.question.isRunning) {\n return;\n }\n const started = this.quiz.question.startCountdown(data.questiontime, data.delay);\n if (!started) {\n setText(Quiz.info, 'wait_for_instructor');\n }\n }\n\n onReviewing(data) {\n this.quiz.question.isVoteRunning = false;\n this.quiz.question.isRunning = false;\n this.quiz.question.hideTimer();\n Quiz.hide(Question.box);\n setText(Quiz.info, 'wait_for_instructor');\n }\n\n onSessionClosed(data) {\n window.location = location.href.split('&')[0];\n }\n\n onVoting(data) {\n if (this.quiz.question.isVoteRunning) {\n return;\n }\n Quiz.info.html(data.html);\n Quiz.show(Quiz.info);\n const options = data.options;\n for (let i = 0; i < options.length; i++) {\n Quiz.addMathjaxElement($('#' + options[i].content_id), options[i].text);\n if (options[i].question_type === 'stack') {\n Quiz.renderMaximaEquation(options[i].text, options[i].content_id);\n }\n }\n this.quiz.question.isVoteRunning = true;\n }\n\n onStateChange(state) {\n\n }\n\n onQuestionTimerEnding() {\n\n }\n\n onTimerTick(timeLeft) {\n setText(Question.timer, 'question_will_end_in_x_seconds', 'jazzquiz', timeLeft);\n }\n\n onQuestionRefreshed(data) {\n\n }\n\n /**\n * Submit answer for the current question.\n */\n submitAnswer() {\n if (this.quiz.question.isSaving) {\n // Don't save twice.\n return;\n }\n this.quiz.question.isSaving = true;\n if (typeof tinyMCE !== 'undefined') {\n tinyMCE.triggerSave();\n }\n const serialized = Question.form.serializeArray();\n let data = {};\n for (let name in serialized) {\n if (serialized.hasOwnProperty(name)) {\n data[serialized[name].name] = serialized[name].value;\n }\n }\n Ajax.post('save_question', data, data => {\n if (data.feedback.length > 0) {\n Quiz.show(Quiz.info.html(data.feedback));\n } else {\n setText(Quiz.info, 'wait_for_instructor');\n }\n this.quiz.question.isSaving = false;\n if (!this.quiz.question.isRunning) {\n return;\n }\n if (this.quiz.question.isVoteRunning) {\n return;\n }\n Quiz.hide(Question.box);\n this.quiz.question.hideTimer();\n }).fail(() => {\n this.quiz.question.isSaving = false;\n });\n }\n\n saveVote() {\n Ajax.post('save_vote', {vote: this.voteAnswer}, data => {\n if (data.status === 'success') {\n setText(Quiz.info, 'wait_for_instructor');\n } else {\n setText(Quiz.info, 'you_already_voted');\n }\n });\n }\n\n }\n\n return {\n initialize: () => {\n let quiz = new Quiz(Student);\n quiz.poll(2000);\n }\n }\n\n});\n"],"file":"student.min.js"} \ No newline at end of file +{"version":3,"file":"student.min.js","sources":["../src/student.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @package mod_jazzquiz\n * @author Sebastian S. Gundersen \n * @copyright 2014 University of Wisconsin - Madison\n * @copyright 2018 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'mod_jazzquiz/core'], function ($, Jazz) {\n\n const Quiz = Jazz.Quiz;\n const Question = Jazz.Question;\n const Ajax = Jazz.Ajax;\n const setText = Jazz.setText;\n\n class Student {\n\n /**\n * @param {Quiz} quiz\n */\n constructor(quiz) {\n this.quiz = quiz;\n this.voteAnswer = undefined;\n let self = this;\n $(document).on('submit', '#jazzquiz_question_form', function(event) {\n event.preventDefault();\n self.submitAnswer();\n }).on('click', '#jazzquiz_save_vote', function() {\n self.saveVote();\n }).on('click', '.jazzquiz-select-vote', function() {\n self.voteAnswer = this.value;\n });\n }\n\n onNotRunning(data) {\n setText(Quiz.info, 'instructions_for_student');\n }\n\n onPreparing(data) {\n setText(Quiz.info, 'wait_for_instructor');\n }\n\n onRunning(data) {\n if (this.quiz.question.isRunning) {\n return;\n }\n const started = this.quiz.question.startCountdown(data.questiontime, data.delay);\n if (!started) {\n setText(Quiz.info, 'wait_for_instructor');\n }\n }\n\n onReviewing(data) {\n this.quiz.question.isVoteRunning = false;\n this.quiz.question.isRunning = false;\n this.quiz.question.hideTimer();\n Quiz.hide(Question.box);\n setText(Quiz.info, 'wait_for_instructor');\n }\n\n onSessionClosed(data) {\n window.location = location.href.split('&')[0];\n }\n\n onVoting(data) {\n if (this.quiz.question.isVoteRunning) {\n return;\n }\n Quiz.info.html(data.html);\n Quiz.show(Quiz.info);\n const options = data.options;\n for (let i = 0; i < options.length; i++) {\n Quiz.addMathjaxElement($('#' + options[i].content_id), options[i].text);\n if (options[i].question_type === 'stack') {\n Quiz.renderMaximaEquation(options[i].text, options[i].content_id);\n }\n }\n this.quiz.question.isVoteRunning = true;\n }\n\n onStateChange(state) {\n\n }\n\n onQuestionTimerEnding() {\n\n }\n\n onTimerTick(timeLeft) {\n setText(Question.timer, 'question_will_end_in_x_seconds', 'jazzquiz', timeLeft);\n }\n\n onQuestionRefreshed(data) {\n\n }\n\n /**\n * Submit answer for the current question.\n */\n submitAnswer() {\n if (this.quiz.question.isSaving) {\n // Don't save twice.\n return;\n }\n this.quiz.question.isSaving = true;\n if (typeof tinyMCE !== 'undefined') {\n tinyMCE.triggerSave();\n }\n const serialized = Question.form.serializeArray();\n let data = {};\n for (let name in serialized) {\n if (serialized.hasOwnProperty(name)) {\n data[serialized[name].name] = serialized[name].value;\n }\n }\n Ajax.post('save_question', data, data => {\n if (data.feedback.length > 0) {\n Quiz.show(Quiz.info.html(data.feedback));\n } else {\n setText(Quiz.info, 'wait_for_instructor');\n }\n this.quiz.question.isSaving = false;\n if (!this.quiz.question.isRunning) {\n return;\n }\n if (this.quiz.question.isVoteRunning) {\n return;\n }\n Quiz.hide(Question.box);\n this.quiz.question.hideTimer();\n }).fail(() => {\n this.quiz.question.isSaving = false;\n });\n }\n\n saveVote() {\n Ajax.post('save_vote', {vote: this.voteAnswer}, data => {\n if (data.status === 'success') {\n setText(Quiz.info, 'wait_for_instructor');\n } else {\n setText(Quiz.info, 'you_already_voted');\n }\n });\n }\n\n }\n\n return {\n initialize: () => {\n let quiz = new Quiz(Student);\n quiz.poll(2000);\n }\n }\n\n});\n"],"names":["define","$","Jazz","Quiz","Question","Ajax","setText","Student","constructor","quiz","voteAnswer","undefined","self","this","document","on","event","preventDefault","submitAnswer","saveVote","value","onNotRunning","data","info","onPreparing","onRunning","question","isRunning","startCountdown","questiontime","delay","onReviewing","isVoteRunning","hideTimer","hide","box","onSessionClosed","window","location","href","split","onVoting","html","show","options","i","length","addMathjaxElement","content_id","text","question_type","renderMaximaEquation","onStateChange","state","onQuestionTimerEnding","onTimerTick","timeLeft","timer","onQuestionRefreshed","isSaving","tinyMCE","triggerSave","serialized","form","serializeArray","name","hasOwnProperty","post","feedback","fail","vote","status","initialize","poll"],"mappings":";;;;;;;AAuBAA,8BAAO,CAAC,SAAU,sBAAsB,SAAUC,EAAGC,YAE3CC,KAAOD,KAAKC,KACZC,SAAWF,KAAKE,SAChBC,KAAOH,KAAKG,KACZC,QAAUJ,KAAKI,cAEfC,QAKFC,YAAYC,WACHA,KAAOA,UACPC,gBAAaC,MACdC,KAAOC,KACXZ,EAAEa,UAAUC,GAAG,SAAU,2BAA2B,SAASC,OACzDA,MAAMC,iBACNL,KAAKM,kBACNH,GAAG,QAAS,uBAAuB,WAClCH,KAAKO,cACNJ,GAAG,QAAS,yBAAyB,WACpCH,KAAKF,WAAaG,KAAKO,SAI/BC,aAAaC,MACThB,QAAQH,KAAKoB,KAAM,4BAGvBC,YAAYF,MACRhB,QAAQH,KAAKoB,KAAM,uBAGvBE,UAAUH,SACFT,KAAKJ,KAAKiB,SAASC,iBAGPd,KAAKJ,KAAKiB,SAASE,eAAeN,KAAKO,aAAcP,KAAKQ,QAEtExB,QAAQH,KAAKoB,KAAM,uBAI3BQ,YAAYT,WACHb,KAAKiB,SAASM,eAAgB,OAC9BvB,KAAKiB,SAASC,WAAY,OAC1BlB,KAAKiB,SAASO,YACnB9B,KAAK+B,KAAK9B,SAAS+B,KACnB7B,QAAQH,KAAKoB,KAAM,uBAGvBa,gBAAgBd,MACZe,OAAOC,SAAWA,SAASC,KAAKC,MAAM,KAAK,GAG/CC,SAASnB,SACDT,KAAKJ,KAAKiB,SAASM,qBAGvB7B,KAAKoB,KAAKmB,KAAKpB,KAAKoB,MACpBvC,KAAKwC,KAAKxC,KAAKoB,YACTqB,QAAUtB,KAAKsB,YAChB,IAAIC,EAAI,EAAGA,EAAID,QAAQE,OAAQD,IAChC1C,KAAK4C,kBAAkB9C,EAAE,IAAM2C,QAAQC,GAAGG,YAAaJ,QAAQC,GAAGI,MACjC,UAA7BL,QAAQC,GAAGK,eACX/C,KAAKgD,qBAAqBP,QAAQC,GAAGI,KAAML,QAAQC,GAAGG,iBAGzDvC,KAAKiB,SAASM,eAAgB,EAGvCoB,cAAcC,QAIdC,yBAIAC,YAAYC,UACRlD,QAAQF,SAASqD,MAAO,iCAAkC,WAAYD,UAG1EE,oBAAoBpC,OAOpBJ,kBACQL,KAAKJ,KAAKiB,SAASiC,qBAIlBlD,KAAKiB,SAASiC,UAAW,EACP,oBAAZC,SACPA,QAAQC,oBAENC,WAAa1D,SAAS2D,KAAKC,qBAC7B1C,KAAO,OACN,IAAI2C,QAAQH,WACTA,WAAWI,eAAeD,QAC1B3C,KAAKwC,WAAWG,MAAMA,MAAQH,WAAWG,MAAM7C,OAGvDf,KAAK8D,KAAK,gBAAiB7C,MAAMA,OACzBA,KAAK8C,SAAStB,OAAS,EACvB3C,KAAKwC,KAAKxC,KAAKoB,KAAKmB,KAAKpB,KAAK8C,WAE9B9D,QAAQH,KAAKoB,KAAM,4BAElBd,KAAKiB,SAASiC,UAAW,EACzB9C,KAAKJ,KAAKiB,SAASC,YAGpBd,KAAKJ,KAAKiB,SAASM,gBAGvB7B,KAAK+B,KAAK9B,SAAS+B,UACd1B,KAAKiB,SAASO,iBACpBoC,MAAK,UACC5D,KAAKiB,SAASiC,UAAW,KAItCxC,WACId,KAAK8D,KAAK,YAAa,CAACG,KAAMzD,KAAKH,aAAaY,OACxB,YAAhBA,KAAKiD,OACLjE,QAAQH,KAAKoB,KAAM,uBAEnBjB,QAAQH,KAAKoB,KAAM,+BAO5B,CACHiD,WAAY,KACG,IAAIrE,KAAKI,SACfkE,KAAK"} \ No newline at end of file From 455f2ad01f59e9d8a2b61496fffeef6b10a00e94 Mon Sep 17 00:00:00 2001 From: Hans Georg Schaathun Date: Mon, 5 Sep 2022 15:39:23 +0200 Subject: [PATCH 17/23] Fixed a deprecated function call. Removes error message but not the bug --- classes/improviser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/improviser.php b/classes/improviser.php index 962097b..4a36c5f 100755 --- a/classes/improviser.php +++ b/classes/improviser.php @@ -120,7 +120,7 @@ private function get_default_question_category() { $context = \context_module::instance($this->jazzquiz->cm->id); $category = question_get_default_category($context->id); if (!$category) { - $contexts = new \question_edit_contexts($context); + $contexts = new \core_question\local\bank\question_edit_contexts($context); $category = question_make_default_categories($contexts->all()); } return $category; From 959a26f5fb3e88ae312c711e62f9540220127495 Mon Sep 17 00:00:00 2001 From: Hans Georg Schaathun Date: Tue, 6 Sep 2022 08:30:18 +0200 Subject: [PATCH 18/23] Added new functions to create question bank entry and question version for the IMPROV questions. They are now correctly created, but they do not appear in the Improvise drop down menu during the session. --- classes/improviser.php | 67 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/classes/improviser.php b/classes/improviser.php index 4a36c5f..1221852 100755 --- a/classes/improviser.php +++ b/classes/improviser.php @@ -126,6 +126,24 @@ private function get_default_question_category() { return $category; } + /** + * Create a question bank entry for the database. + * @return \stdClass | null + */ + private function make_generic_question_bank_entry() { + $category = $this->get_default_question_category(); + if (!$category) { + return null; + } + + /* debugging( "Making generic question bank entry." ) ; */ + $question = new \stdClass(); + $question->questioncategoryid = $category->id; + $question->ownerid = null; + $question->idnumber = null; + return $question; + } + /** * Create a question database object. * @param string $qtype What question type to create @@ -134,18 +152,15 @@ private function get_default_question_category() { */ private function make_generic_question_definition(string $qtype, string $name) { if (!$this->question_type_exists($qtype)) { + /* debugging( "make_generic_question_definition: question type does not exist" ) ; */ return null; } $existing = $this->get_improvised_question_definition($name); if ($existing !== false) { - return null; - } - $category = $this->get_default_question_category(); - if (!$category) { + /* debugging( "make_generic_question_definition: existing: ".$name ) ; */ return null; } $question = new \stdClass(); - $question->category = $category->id; $question->parent = 0; $question->name = '{IMPROV}' . $name; $question->questiontext = ' '; @@ -157,8 +172,6 @@ private function make_generic_question_definition(string $qtype, string $name) { $question->qtype = $qtype; $question->length = 1; $question->stamp = ''; - $question->version = ''; - $question->hidden = 0; $question->timecreated = time(); $question->timemodified = $question->timecreated; $question->createdby = null; @@ -225,11 +238,19 @@ private function make_generic_question_answer($questionid, string $format, strin */ private function insert_multichoice_question_definition(string $name, array $answers) { global $DB; + /* debugging("insert_multichoice_question_definition: ".$name ) ; */ $question = $this->make_generic_question_definition('multichoice', $name); if (!$question) { return; } + /* debugging("insert_multichoice_question_definition 2") ; */ + $qbankentry = $this->make_generic_question_bank_entry(); + if (!$qbankentry) { + return; + } $question->id = $DB->insert_record('question', $question); + $qbankentry->id = $DB->insert_record('question_bank_entries', $qbankentry); + $this->insert_question_version( $qbankentry->id, $question->id ) ; // Add options. $options = $this->make_multichoice_options($question->id); $DB->insert_record('qtype_multichoice_options', $options); @@ -238,6 +259,23 @@ private function insert_multichoice_question_definition(string $name, array $ans $qanswer = $this->make_generic_question_answer($question->id, 1, $answer); $DB->insert_record('question_answers', $qanswer); } + /* debugging( "Question ID ".$question->id ); */ + } + + /* Create a question version database object, linking the given question + * and question bank entry. + * @param int $qbankid The ID of the question banke entry + * @param int $qid The ID of the question + * @return \stdClass + */ + private function insert_question_version(int $qbankid, int $qid) { + global $DB; + $qv = new \stdClass(); + $qv->questionbankentryid = $qbankid ; + $qv->version = 1 ; + $qv->questionid = $qid ; + $qv->id = $DB->insert_record('question_versions', $qv); + return $qv; } /** @@ -246,11 +284,19 @@ private function insert_multichoice_question_definition(string $name, array $ans */ private function insert_shortanswer_question_definition(string $name) { global $DB; + /* debugging("insert_shortanswer_question_definition: ".$name ) ; */ $question = $this->make_generic_question_definition('shortanswer', $name); if (!$question) { return; } + $qbankentry = $this->make_generic_question_bank_entry(); + if (!$qbankentry) { + return; + } $question->id = $DB->insert_record('question', $question); + $qbankentry->id = $DB->insert_record('question_bank_entries', $qbankentry); + $this->insert_question_version( $qbankentry->id, $question->id ) ; + // Add options. $options = $this->make_shortanswer_options($question->id); $DB->insert_record('qtype_shortanswer_options', $options); @@ -261,11 +307,18 @@ private function insert_shortanswer_question_definition(string $name) { private function insert_shortmath_question_definition(string $name) { global $DB; + /* debugging("insert_shortmath_question_definition: ".$name ) ; */ $question = $this->make_generic_question_definition('shortmath', $name); if (!$question) { return; } + $qbankentry = $this->make_generic_question_bank_entry(); + if (!$qbankentry) { + return; + } $question->id = $DB->insert_record('question', $question); + $qbankentry->id = $DB->insert_record('question_bank_entries', $qbankentry); + $this->insert_question_version( $qbankentry->id, $question->id ) ; // Add options. Important: If shortmath changes options table in the future, this must be changed too. $options = $this->make_shortanswer_options($question->id); $DB->insert_record('qtype_shortmath_options', $options); From 382dfe5d4431b6b8630031ad762e6f0ed9bb4972 Mon Sep 17 00:00:00 2001 From: Hans Georg Schaathun Date: Tue, 6 Sep 2022 14:19:06 +0200 Subject: [PATCH 19/23] Changed the SQL query to find IMPROV questions to match new schema. It seems to work. Not thoroughly tested though. --- ajax.php | 2 ++ classes/improviser.php | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ajax.php b/ajax.php index 15319e9..416a4c5 100755 --- a/ajax.php +++ b/ajax.php @@ -45,7 +45,9 @@ function show_all_improvise_questions(jazzquiz $jazzquiz) { $improviser = new improviser($jazzquiz); $questionrecords = $improviser->get_all_improvised_question_definitions(); + debugging( 'show'.$questionrecords ); if (!$questionrecords) { + debugging( 'No improvisation questions' ); return [ 'status' => 'error', 'message' => 'No improvisation questions' diff --git a/classes/improviser.php b/classes/improviser.php index 1221852..cab8960 100755 --- a/classes/improviser.php +++ b/classes/improviser.php @@ -60,13 +60,19 @@ public function get_all_improvised_question_definitions() { $questions = []; $context = \context_module::instance($this->jazzquiz->cm->id); $parts = explode('/', $context->path); + debugging( "get_all_improvised: ".$parts ) ; foreach ($parts as $part) { // Selecting name first, to prevent duplicate improvise questions. + debugging( "get_all_improvised: ".$part ) ; $sql = "SELECT q.name, q.id FROM {question} q + JOIN {question_versions} qv + ON q.id = qv.questionid + JOIN {question_bank_entries} qbe + ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc - ON qc.id = q.category + ON qc.id = qbe.questioncategoryid JOIN {context} ctx ON ctx.id = qc.contextid AND ctx.path LIKE :path From 7ff471201222f3741db2a8e131d125dde737826d Mon Sep 17 00:00:00 2001 From: Hans Georg Schaathun Date: Tue, 6 Sep 2022 14:25:55 +0200 Subject: [PATCH 20/23] Converted tab character --- reports.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reports.php b/reports.php index 6c76726..79e25a2 100755 --- a/reports.php +++ b/reports.php @@ -136,7 +136,7 @@ function jazzquiz_reports() { if (!$isdownload) { $jazzquiz->renderer->header($jazzquiz, 'reports'); } - $sessionid = optional_param('sessionid', 0, PARAM_INT); + $sessionid = optional_param('sessionid', 0, PARAM_INT); switch ($action) { case 'view': jazzquiz_view_session_report($jazzquiz, $url, $sessionid); From deb37583e0b58f704db367f81e5391978b9459e8 Mon Sep 17 00:00:00 2001 From: Hans Georg Schaathun Date: Tue, 6 Sep 2022 14:31:49 +0200 Subject: [PATCH 21/23] Moved static declaration after visibility --- backup/moodle2/backup_jazzquiz_activity_task.class.php | 2 +- backup/moodle2/restore_jazzquiz_activity_task.class.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backup/moodle2/backup_jazzquiz_activity_task.class.php b/backup/moodle2/backup_jazzquiz_activity_task.class.php index f3846df..11107dd 100644 --- a/backup/moodle2/backup_jazzquiz_activity_task.class.php +++ b/backup/moodle2/backup_jazzquiz_activity_task.class.php @@ -45,7 +45,7 @@ protected function define_my_steps() { * @param string $content * @return string of content with the URLs encoded */ - static public function encode_content_links($content) { + public static function encode_content_links($content) { global $CFG; $base = preg_quote($CFG->wwwroot, '/'); // Link to the list of JazzQuizes. diff --git a/backup/moodle2/restore_jazzquiz_activity_task.class.php b/backup/moodle2/restore_jazzquiz_activity_task.class.php index 9d57a39..1d82d86 100644 --- a/backup/moodle2/restore_jazzquiz_activity_task.class.php +++ b/backup/moodle2/restore_jazzquiz_activity_task.class.php @@ -41,7 +41,7 @@ protected function define_my_steps() { /** * @return restore_decode_content[] */ - static public function define_decode_contents() { + public static function define_decode_contents() { return [ new restore_decode_content('jazzquiz', ['intro']) ]; @@ -50,7 +50,7 @@ static public function define_decode_contents() { /** * @return restore_decode_rule[] */ - static public function define_decode_rules() { + public static function define_decode_rules() { return [ new restore_decode_rule('JAZZQUIZVIEWBYID', '/mod/jazzquiz/view.php?id=$1', 'course_module'), new restore_decode_rule('JAZZQUIZINDEX', '/mod/jazzquiz/index.php?id=$1', 'course') @@ -60,14 +60,14 @@ static public function define_decode_rules() { /** * @return restore_log_rule[] */ - static public function define_restore_log_rules() { + public static function define_restore_log_rules() { return []; } /** * @return restore_log_rule[] */ - static public function define_restore_log_rules_for_course() { + public static function define_restore_log_rules_for_course() { return []; } From ccad87d647e5f4cdcc7eeb25172654fed2396fa9 Mon Sep 17 00:00:00 2001 From: Hans Georg Schaathun Date: Tue, 6 Sep 2022 16:47:34 +0200 Subject: [PATCH 22/23] New logo (icon) --- pix/icon.svg | 305 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 282 insertions(+), 23 deletions(-) mode change 100755 => 100644 pix/icon.svg diff --git a/pix/icon.svg b/pix/icon.svg old mode 100755 new mode 100644 index dcec1d9..314d5ec --- a/pix/icon.svg +++ b/pix/icon.svg @@ -1,23 +1,282 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f0f23d1c6144177d199c1e06857114668873f33c Mon Sep 17 00:00:00 2001 From: Hans Georg Schaathun Date: Fri, 30 Sep 2022 17:51:20 +0200 Subject: [PATCH 23/23] Checkoboxes fixed. It is inconvenient that the page seems to be fully reloaded. URL parameters are still duplicated. --- edit.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/edit.php b/edit.php index a046c49..888c3c2 100755 --- a/edit.php +++ b/edit.php @@ -64,9 +64,9 @@ function get_qbank_view(\core_question\local\bank\question_edit_contexts $contex 'qpage' => $qpage, 'qperpage' => $qperpage, 'cat' => $pagevars['cat'], - 'recurse' => true, - 'showhidden' => true, - 'qbshowtext' => true + 'recurse' => $pagevars['recurse'], + 'showhidden' => $pagevars['showhidden'], + 'qbshowtext' => $pagevars['qbshowtext'] ]; // Capture question bank display in buffer to have the renderer render output. ob_start();