[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/quiz/ -> module.js (source)

   1  // This file is part of Moodle - http://moodle.org/
   2  //
   3  // Moodle is free software: you can redistribute it and/or modify
   4  // it under the terms of the GNU General Public License as published by
   5  // the Free Software Foundation, either version 3 of the License, or
   6  // (at your option) any later version.
   7  //
   8  // Moodle is distributed in the hope that it will be useful,
   9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11  // GNU General Public License for more details.
  12  //
  13  // You should have received a copy of the GNU General Public License
  14  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  15  
  16  /**
  17   * JavaScript library for the quiz module.
  18   *
  19   * @package    mod
  20   * @subpackage quiz
  21   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  M.mod_quiz = M.mod_quiz || {};
  26  
  27  M.mod_quiz.init_attempt_form = function(Y) {
  28      M.core_question_engine.init_form(Y, '#responseform');
  29      Y.on('submit', M.mod_quiz.timer.stop, '#responseform');
  30      M.core_formchangechecker.init({formid: 'responseform'});
  31  };
  32  
  33  M.mod_quiz.init_review_form = function(Y) {
  34      M.core_question_engine.init_form(Y, '.questionflagsaveform');
  35      Y.on('submit', function(e) { e.halt(); }, '.questionflagsaveform');
  36  };
  37  
  38  M.mod_quiz.init_comment_popup = function(Y) {
  39      // Add a close button to the window.
  40      var closebutton = Y.Node.create('<input type="button" />');
  41      closebutton.set('value', M.util.get_string('cancel', 'moodle'));
  42      Y.one('#id_submitbutton').ancestor().append(closebutton);
  43      Y.on('click', function() { window.close() }, closebutton);
  44  }
  45  
  46  // Code for updating the countdown timer that is used on timed quizzes.
  47  M.mod_quiz.timer = {
  48      // YUI object.
  49      Y: null,
  50  
  51      // Timestamp at which time runs out, according to the student's computer's clock.
  52      endtime: 0,
  53  
  54      // Is this a quiz preview?
  55      preview: 0,
  56  
  57      // This records the id of the timeout that updates the clock periodically,
  58      // so we can cancel.
  59      timeoutid: null,
  60  
  61      /**
  62       * @param Y the YUI object
  63       * @param start, the timer starting time, in seconds.
  64       * @param preview, is this a quiz preview?
  65       */
  66      init: function(Y, start, preview) {
  67          M.mod_quiz.timer.Y = Y;
  68          M.mod_quiz.timer.endtime = M.pageloadstarttime.getTime() + start*1000;
  69          M.mod_quiz.timer.preview = preview;
  70          M.mod_quiz.timer.update();
  71          Y.one('#quiz-timer').setStyle('display', 'block');
  72      },
  73  
  74      /**
  75       * Stop the timer, if it is running.
  76       */
  77      stop: function(e) {
  78          if (M.mod_quiz.timer.timeoutid) {
  79              clearTimeout(M.mod_quiz.timer.timeoutid);
  80          }
  81      },
  82  
  83      /**
  84       * Function to convert a number between 0 and 99 to a two-digit string.
  85       */
  86      two_digit: function(num) {
  87          if (num < 10) {
  88              return '0' + num;
  89          } else {
  90              return num;
  91          }
  92      },
  93  
  94      // Function to update the clock with the current time left, and submit the quiz if necessary.
  95      update: function() {
  96          var Y = M.mod_quiz.timer.Y;
  97          var secondsleft = Math.floor((M.mod_quiz.timer.endtime - new Date().getTime())/1000);
  98  
  99          // If time has expired, set the hidden form field that says time has expired and submit
 100          if (secondsleft < 0) {
 101              M.mod_quiz.timer.stop(null);
 102              Y.one('#quiz-time-left').setContent(M.util.get_string('timesup', 'quiz'));
 103              var input = Y.one('input[name=timeup]');
 104              input.set('value', 1);
 105              var form = input.ancestor('form');
 106              if (form.one('input[name=finishattempt]')) {
 107                  form.one('input[name=finishattempt]').set('value', 0);
 108              }
 109              M.core_formchangechecker.set_form_submitted();
 110              form.submit();
 111              return;
 112          }
 113  
 114          // If time has nearly expired, change the colour.
 115          if (secondsleft < 100) {
 116              Y.one('#quiz-timer').removeClass('timeleft' + (secondsleft + 2))
 117                      .removeClass('timeleft' + (secondsleft + 1))
 118                      .addClass('timeleft' + secondsleft);
 119          }
 120  
 121          // Update the time display.
 122          var hours = Math.floor(secondsleft/3600);
 123          secondsleft -= hours*3600;
 124          var minutes = Math.floor(secondsleft/60);
 125          secondsleft -= minutes*60;
 126          var seconds = secondsleft;
 127          Y.one('#quiz-time-left').setContent(hours + ':' +
 128                  M.mod_quiz.timer.two_digit(minutes) + ':' +
 129                  M.mod_quiz.timer.two_digit(seconds));
 130  
 131          // Arrange for this method to be called again soon.
 132          M.mod_quiz.timer.timeoutid = setTimeout(M.mod_quiz.timer.update, 100);
 133      }
 134  };
 135  
 136  M.mod_quiz.nav = M.mod_quiz.nav || {};
 137  
 138  M.mod_quiz.nav.update_flag_state = function(attemptid, questionid, newstate) {
 139      var Y = M.mod_quiz.nav.Y;
 140      var navlink = Y.one('#quiznavbutton' + questionid);
 141      navlink.removeClass('flagged');
 142      if (newstate == 1) {
 143          navlink.addClass('flagged');
 144          navlink.one('.accesshide .flagstate').setContent(M.util.get_string('flagged', 'question'));
 145      } else {
 146          navlink.one('.accesshide .flagstate').setContent('');
 147      }
 148  };
 149  
 150  M.mod_quiz.nav.init = function(Y) {
 151      M.mod_quiz.nav.Y = Y;
 152  
 153      Y.all('#quiznojswarning').remove();
 154  
 155      var form = Y.one('#responseform');
 156      if (form) {
 157          function find_enabled_submit() {
 158              // This is rather inelegant, but the CSS3 selector
 159              //     return form.one('input[type=submit]:enabled');
 160              // does not work in IE7, 8 or 9 for me.
 161              var enabledsubmit = null;
 162              form.all('input[type=submit]').each(function(submit) {
 163                  if (!enabledsubmit && !submit.get('disabled')) {
 164                      enabledsubmit = submit;
 165                  }
 166              });
 167              return enabledsubmit;
 168          }
 169  
 170          function nav_to_page(pageno) {
 171              Y.one('#followingpage').set('value', pageno);
 172  
 173              // Automatically submit the form. We do it this strange way because just
 174              // calling form.submit() does not run the form's submit event handlers.
 175              var submit = find_enabled_submit();
 176              submit.set('name', '');
 177              submit.getDOMNode().click();
 178          };
 179  
 180          Y.delegate('click', function(e) {
 181              if (this.hasClass('thispage')) {
 182                  return;
 183              }
 184  
 185              e.preventDefault();
 186  
 187              var pageidmatch = this.get('href').match(/page=(\d+)/);
 188              var pageno;
 189              if (pageidmatch) {
 190                  pageno = pageidmatch[1];
 191              } else {
 192                  pageno = 0;
 193              }
 194  
 195              var questionidmatch = this.get('href').match(/#q(\d+)/);
 196              if (questionidmatch) {
 197                  form.set('action', form.get('action') + '#q' + questionidmatch[1]);
 198              }
 199  
 200              nav_to_page(pageno);
 201          }, document.body, '.qnbutton');
 202      }
 203  
 204      if (Y.one('a.endtestlink')) {
 205          Y.on('click', function(e) {
 206              e.preventDefault();
 207              nav_to_page(-1);
 208          }, 'a.endtestlink');
 209      }
 210  
 211      if (M.core_question_flags) {
 212          M.core_question_flags.add_listener(M.mod_quiz.nav.update_flag_state);
 213      }
 214  };
 215  
 216  M.mod_quiz.secure_window = {
 217      init: function(Y) {
 218          if (window.location.href.substring(0, 4) == 'file') {
 219              window.location = 'about:blank';
 220          }
 221          Y.delegate('contextmenu', M.mod_quiz.secure_window.prevent, document, '*');
 222          Y.delegate('mousedown',   M.mod_quiz.secure_window.prevent_mouse, 'body', '*');
 223          Y.delegate('mouseup',     M.mod_quiz.secure_window.prevent_mouse, 'body', '*');
 224          Y.delegate('dragstart',   M.mod_quiz.secure_window.prevent, document, '*');
 225          Y.delegate('selectstart', M.mod_quiz.secure_window.prevent_selection, document, '*');
 226          Y.delegate('cut',         M.mod_quiz.secure_window.prevent, document, '*');
 227          Y.delegate('copy',        M.mod_quiz.secure_window.prevent, document, '*');
 228          Y.delegate('paste',       M.mod_quiz.secure_window.prevent, document, '*');
 229          Y.on('beforeprint', function() {
 230              Y.one(document.body).setStyle('display', 'none');
 231          }, window);
 232          Y.on('afterprint', function() {
 233              Y.one(document.body).setStyle('display', 'block');
 234          }, window);
 235          Y.on('key', M.mod_quiz.secure_window.prevent, '*', 'press:67,86,88+ctrl');
 236          Y.on('key', M.mod_quiz.secure_window.prevent, '*', 'up:67,86,88+ctrl');
 237          Y.on('key', M.mod_quiz.secure_window.prevent, '*', 'down:67,86,88+ctrl');
 238          Y.on('key', M.mod_quiz.secure_window.prevent, '*', 'press:67,86,88+meta');
 239          Y.on('key', M.mod_quiz.secure_window.prevent, '*', 'up:67,86,88+meta');
 240          Y.on('key', M.mod_quiz.secure_window.prevent, '*', 'down:67,86,88+meta');
 241      },
 242  
 243      is_content_editable: function(n) {
 244          if (n.test('[contenteditable=true]')) {
 245              return true;
 246          }
 247          n = n.get('parentNode');
 248          if (n === null) {
 249              return false;
 250          }
 251          return M.mod_quiz.secure_window.is_content_editable(n);
 252      },
 253  
 254      prevent_selection: function(e) {
 255          return false;
 256      },
 257  
 258      prevent: function(e) {
 259          alert(M.util.get_string('functiondisabledbysecuremode', 'quiz'));
 260          e.halt();
 261      },
 262  
 263      prevent_mouse: function(e) {
 264          if (e.button == 1 && /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL|A)$/i.test(e.target.get('tagName'))) {
 265              // Left click on a button or similar. No worries.
 266              return;
 267          }
 268          if (e.button == 1 && M.mod_quiz.secure_window.is_content_editable(e.target)) {
 269              // Left click in Atto or similar.
 270              return;
 271          }
 272          e.halt();
 273      },
 274  
 275      init_close_button: function(Y, url) {
 276          Y.on('click', function(e) {
 277              M.mod_quiz.secure_window.close(url, 0)
 278          }, '#secureclosebutton');
 279      },
 280  
 281      close: function(Y, url, delay) {
 282          setTimeout(function() {
 283              if (window.opener) {
 284                  window.opener.document.location.reload();
 285                  window.close();
 286              } else {
 287                  window.location.href = url;
 288              }
 289          }, delay*1000);
 290      }
 291  };


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1