[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/assign/amd/src/ -> grading_panel.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 controller for the "Grading" panel at the right of the page.
  18   *
  19   * @module     mod_assign/grading_panel
  20   * @package    mod_assign
  21   * @class      GradingPanel
  22   * @copyright  2016 Damyon Wiese <damyon@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   * @since      3.1
  25   */
  26  define(['jquery', 'core/notification', 'core/templates', 'core/fragment',
  27          'core/ajax', 'core/str', 'mod_assign/grading_form_change_checker',
  28          'mod_assign/grading_events'],
  29         function($, notification, templates, fragment, ajax, str, checker, GradingEvents) {
  30  
  31      /**
  32       * GradingPanel class.
  33       *
  34       * @class GradingPanel
  35       * @param {String} selector The selector for the page region containing the user navigation.
  36       */
  37      var GradingPanel = function(selector) {
  38          this._regionSelector = selector;
  39          this._region = $(selector);
  40          this._userCache = [];
  41  
  42          this.registerEventListeners();
  43      };
  44  
  45      /** @type {String} Selector for the page region containing the user navigation. */
  46      GradingPanel.prototype._regionSelector = null;
  47  
  48      /** @type {Integer} Remember the last user id to prevent unnessecary reloads. */
  49      GradingPanel.prototype._lastUserId = 0;
  50  
  51      /** @type {Integer} Remember the last attempt number to prevent unnessecary reloads. */
  52      GradingPanel.prototype._lastAttemptNumber = -1;
  53  
  54      /** @type {JQuery} JQuery node for the page region containing the user navigation. */
  55      GradingPanel.prototype._region = null;
  56  
  57      /**
  58       * Fade the dom node out, update it, and fade it back.
  59       *
  60       * @private
  61       * @method _niceReplaceNodeContents
  62       * @param {JQuery} node
  63       * @param {String} html
  64       * @param {String} js
  65       * @return {Deferred} promise resolved when the animations are complete.
  66       */
  67      GradingPanel.prototype._niceReplaceNodeContents = function(node, html, js) {
  68          var promise = $.Deferred();
  69  
  70          node.fadeOut("fast", function() {
  71              templates.replaceNodeContents(node, html, js);
  72              node.fadeIn("fast", function() {
  73                  promise.resolve();
  74              });
  75          });
  76  
  77          return promise.promise();
  78      };
  79  
  80      /**
  81       * Make sure all form fields have the latest saved state.
  82       * @private
  83       * @method _saveFormState
  84       */
  85      GradingPanel.prototype._saveFormState = function() {
  86          // Grrrrr! TinyMCE you know what you did.
  87          if (typeof window.tinyMCE !== 'undefined') {
  88              window.tinyMCE.triggerSave();
  89          }
  90  
  91          // Copy data from notify students checkbox which was moved out of the form.
  92          var checked = $('[data-region="grading-actions-form"] [name="sendstudentnotifications"]').val();
  93          $('.gradeform [name="sendstudentnotifications"]').val(checked);
  94      };
  95  
  96      /**
  97       * Make form submit via ajax.
  98       *
  99       * @private
 100       * @param {Object} event
 101       * @param {Integer} nextUserId
 102       * @method _submitForm
 103       */
 104      GradingPanel.prototype._submitForm = function(event, nextUserId) {
 105          // The form was submitted - send it via ajax instead.
 106          var form = $(this._region.find('form.gradeform'));
 107  
 108          $('[data-region="overlay"]').show();
 109  
 110          // We call this, so other modules can update the form with the latest state.
 111          form.trigger('save-form-state');
 112  
 113          // Now we get all the current values from the form.
 114          var data = form.serialize();
 115          var assignmentid = this._region.attr('data-assignmentid');
 116  
 117          // Now we can continue...
 118          ajax.call([{
 119              methodname: 'mod_assign_submit_grading_form',
 120              args: {assignmentid: assignmentid, userid: this._lastUserId, jsonformdata: JSON.stringify(data)},
 121              done: this._handleFormSubmissionResponse.bind(this, data, nextUserId),
 122              fail: notification.exception
 123          }]);
 124      };
 125  
 126      /**
 127       * Handle form submission response.
 128       *
 129       * @private
 130       * @method _handleFormSubmissionResponse
 131       * @param {Array} formdata - submitted values
 132       * @param {Integer} nextUserId - optional. The id of the user to load after the form is saved.
 133       * @param {Array} response List of errors.
 134       */
 135      GradingPanel.prototype._handleFormSubmissionResponse = function(formdata, nextUserId, response) {
 136          if (typeof nextUserId === "undefined") {
 137              nextUserId = this._lastUserId;
 138          }
 139          if (response.length) {
 140              // There was an error saving the grade. Re-render the form using the submitted data so we can show
 141              // validation errors.
 142              $(document).trigger('reset', [this._lastUserId, formdata]);
 143          } else {
 144              str.get_strings([
 145                  {key: 'changessaved', component: 'core'},
 146                  {key: 'gradechangessaveddetail', component: 'mod_assign'},
 147              ]).done(function(strs) {
 148                  notification.alert(strs[0], strs[1]);
 149              }).fail(notification.exception);
 150              if (nextUserId == this._lastUserId) {
 151                  $(document).trigger('reset', nextUserId);
 152              } else {
 153                  $(document).trigger('user-changed', nextUserId);
 154              }
 155          }
 156          $('[data-region="overlay"]').hide();
 157      };
 158  
 159      /**
 160       * Refresh form with default values.
 161       *
 162       * @private
 163       * @method _resetForm
 164       * @param {Event} e
 165       * @param {Integer} userid
 166       * @param {Array} formdata
 167       */
 168      GradingPanel.prototype._resetForm = function(e, userid, formdata) {
 169          // The form was cancelled - refresh with default values.
 170          var event = $.Event("custom");
 171          if (typeof userid == "undefined") {
 172              userid = this._lastUserId;
 173          }
 174          this._lastUserId = 0;
 175          this._refreshGradingPanel(event, userid, formdata);
 176      };
 177  
 178      /**
 179       * Open a picker to choose an older attempt.
 180       *
 181       * @private
 182       * @param {Object} e
 183       * @method _chooseAttempt
 184       */
 185      GradingPanel.prototype._chooseAttempt = function(e) {
 186          // Show a dialog.
 187  
 188          // The form is in the element pointed to by data-submissions.
 189          var link = $(e.target);
 190          var submissionsId = link.data('submissions');
 191          var submissionsform = $(document.getElementById(submissionsId));
 192          var formcopy = submissionsform.clone();
 193          var formhtml = formcopy.wrap($('<form/>')).html();
 194  
 195          str.get_strings([
 196              {key: 'viewadifferentattempt', component: 'mod_assign'},
 197              {key: 'view', component: 'core'},
 198              {key: 'cancel', component: 'core'},
 199          ]).done(function(strs) {
 200              notification.confirm(strs[0], formhtml, strs[1], strs[2], function() {
 201                  var attemptnumber = $("input:radio[name='select-attemptnumber']:checked").val();
 202  
 203                  this._refreshGradingPanel(null, this._lastUserId, '', attemptnumber);
 204              }.bind(this));
 205          }.bind(this)).fail(notification.exception);
 206      };
 207  
 208      /**
 209       * Add popout buttons
 210       *
 211       * @private
 212       * @method _addPopoutButtons
 213       * @param {JQuery} selector The region selector to add popout buttons to.
 214       */
 215      GradingPanel.prototype._addPopoutButtons = function(selector) {
 216          var region = $(selector);
 217  
 218          templates.render('mod_assign/popout_button', {}).done(function(html) {
 219              region.find('.fitem_ffilemanager .fitemtitle').append(html);
 220              region.find('.fitem_feditor .fitemtitle').append(html);
 221              region.find('.fitem_f .fitemtitle').append(html);
 222  
 223              region.on('click', '[data-region="popout-button"]', this._togglePopout.bind(this));
 224          }.bind(this)).fail(notification.exception);
 225      };
 226  
 227      /**
 228       * Make a div "popout" or "popback".
 229       *
 230       * @private
 231       * @method _togglePopout
 232       * @param {Event} event
 233       */
 234      GradingPanel.prototype._togglePopout = function(event) {
 235          event.preventDefault();
 236          var container = $(event.target).closest('.fitem');
 237          if (container.hasClass('popout')) {
 238              $('.popout').removeClass('popout');
 239          } else {
 240              $('.popout').removeClass('popout');
 241              container.addClass('popout');
 242              container.addClass('moodle-has-zindex');
 243          }
 244      };
 245  
 246      /**
 247       * Get the user context - re-render the template in the page.
 248       *
 249       * @private
 250       * @method _refreshGradingPanel
 251       * @param {Event} event
 252       * @param {Number} userid
 253       * @param {String} submissiondata serialised submission data.
 254       * @param {Integer} attemptnumber
 255       */
 256      GradingPanel.prototype._refreshGradingPanel = function(event, userid, submissiondata, attemptnumber) {
 257          var contextid = this._region.attr('data-contextid');
 258          if (typeof submissiondata === 'undefined') {
 259              submissiondata = '';
 260          }
 261          if (typeof attemptnumber === 'undefined') {
 262              attemptnumber = -1;
 263          }
 264          // Skip reloading if it is the same user.
 265          if (this._lastUserId == userid && this._lastAttemptNumber == attemptnumber && submissiondata === '') {
 266              return;
 267          }
 268          this._lastUserId = userid;
 269          this._lastAttemptNumber = attemptnumber;
 270          $(document).trigger('start-loading-user');
 271          // Tell behat to back off too.
 272          window.M.util.js_pending('mod-assign-loading-user');
 273          // First insert the loading template.
 274          templates.render('mod_assign/loading', {}).done(function(html, js) {
 275              // Update the page.
 276              this._niceReplaceNodeContents(this._region, html, js).done(function() {
 277                  if (userid > 0) {
 278                      this._region.show();
 279                      // Reload the grading form "fragment" for this user.
 280                      var params = {userid: userid, attemptnumber: attemptnumber, jsonformdata: JSON.stringify(submissiondata)};
 281                      fragment.loadFragment('mod_assign', 'gradingpanel', contextid, params).done(function(html, js) {
 282                          this._niceReplaceNodeContents(this._region, html, js)
 283                          .done(function() {
 284                              checker.saveFormState('[data-region="grade-panel"] .gradeform');
 285                              $(document).on('editor-content-restored', function() {
 286                                  // If the editor has some content that has been restored
 287                                  // then save the form state again for comparison.
 288                                  checker.saveFormState('[data-region="grade-panel"] .gradeform');
 289                              });
 290                              $('[data-region="attempt-chooser"]').on('click', this._chooseAttempt.bind(this));
 291                              this._addPopoutButtons('[data-region="grade-panel"] .gradeform');
 292                              $(document).trigger('finish-loading-user');
 293                              // Tell behat we are friends again.
 294                              window.M.util.js_complete('mod-assign-loading-user');
 295                          }.bind(this))
 296                          .fail(notification.exception);
 297                      }.bind(this)).fail(notification.exception);
 298                  } else {
 299                      this._region.hide();
 300                      var reviewPanel = $('[data-region="review-panel"]');
 301                      if (reviewPanel.length) {
 302                          this._niceReplaceNodeContents(reviewPanel, '', '');
 303                      }
 304                      $(document).trigger('finish-loading-user');
 305                      // Tell behat we are friends again.
 306                      window.M.util.js_complete('mod-assign-loading-user');
 307                  }
 308              }.bind(this));
 309          }.bind(this)).fail(notification.exception);
 310      };
 311  
 312      /**
 313       * Get the grade panel element.
 314       *
 315       * @method getPanelElement
 316       * @return {jQuery}
 317       */
 318      GradingPanel.prototype.getPanelElement = function() {
 319          return $('[data-region="grade-panel"]');
 320      };
 321  
 322      /**
 323       * Hide the grade panel.
 324       *
 325       * @method collapsePanel
 326       */
 327      GradingPanel.prototype.collapsePanel = function() {
 328          this.getPanelElement().addClass('collapsed');
 329      };
 330  
 331      /**
 332       * Show the grade panel.
 333       *
 334       * @method expandPanel
 335       */
 336      GradingPanel.prototype.expandPanel = function() {
 337          this.getPanelElement().removeClass('collapsed');
 338      };
 339  
 340      /**
 341       * Register event listeners for the grade panel.
 342       *
 343       * @method registerEventListeners
 344       */
 345      GradingPanel.prototype.registerEventListeners = function() {
 346          var docElement = $(document);
 347  
 348          docElement.on('user-changed', this._refreshGradingPanel.bind(this));
 349          docElement.on('save-changes', this._submitForm.bind(this));
 350          docElement.on('reset', this._resetForm.bind(this));
 351  
 352          docElement.on('save-form-state', this._saveFormState.bind(this));
 353  
 354          docElement.on(GradingEvents.COLLAPSE_GRADE_PANEL, function() {
 355              this.collapsePanel();
 356          }.bind(this));
 357  
 358          // We should expand if the review panel is collapsed.
 359          docElement.on(GradingEvents.COLLAPSE_REVIEW_PANEL, function() {
 360              this.expandPanel();
 361          }.bind(this));
 362  
 363          docElement.on(GradingEvents.EXPAND_GRADE_PANEL, function() {
 364              this.expandPanel();
 365          }.bind(this));
 366      };
 367  
 368      return GradingPanel;
 369  });


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