[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/lti/amd/src/ -> tool_card_controller.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   * Controls all of the behaviour and interaction with a tool type card. These are
  18   * listed on the LTI tool type management page.
  19   *
  20   * See template: mod_lti/tool_card
  21   *
  22   * @module     mod_lti/tool_card_controller
  23   * @class      tool_card_controller
  24   * @package    mod_lti
  25   * @copyright  2015 Ryan Wyllie <ryan@moodle.com>
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   * @since      3.1
  28   */
  29  define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/tool_type', 'mod_lti/events', 'mod_lti/keys',
  30          'core/str'],
  31          function($, ajax, notification, templates, toolType, ltiEvents, KEYS, str) {
  32  
  33      var SELECTORS = {
  34          DELETE_BUTTON: '.delete',
  35          NAME_ELEMENT: '.name',
  36          DESCRIPTION_ELEMENT: '.description',
  37          CAPABILITIES_CONTAINER: '.capabilities-container',
  38          ACTIVATE_BUTTON: '.tool-card-footer a.activate',
  39      };
  40  
  41      // Timeout in seconds.
  42      var ANNOUNCEMENT_TIMEOUT = 2000;
  43  
  44      /**
  45       * Return the delete button element.
  46       *
  47       * @method getDeleteButton
  48       * @private
  49       * @param {JQuery} element jQuery object representing the tool card.
  50       * @return {JQuery} jQuery object
  51       */
  52      var getDeleteButton = function(element) {
  53          return element.find(SELECTORS.DELETE_BUTTON);
  54      };
  55  
  56      /**
  57       * Return the element representing the tool type name.
  58       *
  59       * @method getNameElement
  60       * @private
  61       * @param {JQuery} element jQuery object representing the tool card.
  62       * @return {JQuery} jQuery object
  63       */
  64      var getNameElement = function(element) {
  65          return element.find(SELECTORS.NAME_ELEMENT);
  66      };
  67  
  68      /**
  69       * Return the element representing the tool type description.
  70       *
  71       * @method getDescriptionElement
  72       * @private
  73       * @param {JQuery} element jQuery object representing the tool card.
  74       * @return {JQuery} jQuery object
  75       */
  76      var getDescriptionElement = function(element) {
  77          return element.find(SELECTORS.DESCRIPTION_ELEMENT);
  78      };
  79  
  80      /**
  81       * Return the activate button for the type.
  82       *
  83       * @method getActivateButton
  84       * @private
  85       * @param {Object} element jQuery object representing the tool card.
  86       * @return {Object} jQuery object
  87       */
  88      var getActivateButton = function(element) {
  89          return element.find(SELECTORS.ACTIVATE_BUTTON);
  90      };
  91  
  92      /**
  93       * Checks if the type card has an activate button.
  94       *
  95       * @method hasActivateButton
  96       * @private
  97       * @param {JQuery} element jQuery object representing the tool card.
  98       * @return {Boolean} true if has active buton
  99       */
 100      var hasActivateButton = function(element) {
 101          return getActivateButton(element).length ? true : false;
 102      };
 103  
 104      /**
 105       * Return the element that contains the capabilities approval for
 106       * the user.
 107       *
 108       * @method getCapabilitiesContainer
 109       * @private
 110       * @param {Object} element jQuery object representing the tool card.
 111       * @return {Object} The element
 112       */
 113      var getCapabilitiesContainer = function(element) {
 114          return element.find(SELECTORS.CAPABILITIES_CONTAINER);
 115      };
 116  
 117      /**
 118       * Checks if the tool type has capabilities that need approval. If it
 119       * does then the container will be present.
 120       *
 121       * @method hasCapabilitiesContainer
 122       * @private
 123       * @param {JQuery} element jQuery object representing the tool card.
 124       * @return {Boolean} true if has capbilities.
 125       */
 126      var hasCapabilitiesContainer = function(element) {
 127          return getCapabilitiesContainer(element).length ? true : false;
 128      };
 129  
 130      /**
 131       * Get the type id.
 132       *
 133       * @method getTypeId
 134       * @private
 135       * @param {Object} element jQuery object representing the tool card.
 136       * @return {String} Type ID
 137       */
 138      var getTypeId = function(element) {
 139          return element.attr('data-type-id');
 140      };
 141  
 142      /**
 143       * Stop any announcement currently visible on the card.
 144       *
 145       * @method clearAllAnnouncements
 146       * @private
 147       * @param {JQuery} element jQuery object representing the tool card.
 148       */
 149      var clearAllAnnouncements = function(element) {
 150          element.removeClass('announcement loading success fail capabilities');
 151      };
 152  
 153      /**
 154       * Show the loading announcement.
 155       *
 156       * @method startLoading
 157       * @private
 158       * @param {JQuery} element jQuery object representing the tool card.
 159       */
 160      var startLoading = function(element) {
 161          clearAllAnnouncements(element);
 162          element.addClass('announcement loading');
 163      };
 164  
 165      /**
 166       * Hide the loading announcement.
 167       *
 168       * @method stopLoading
 169       * @private
 170       * @param {JQuery} element jQuery object representing the tool card.
 171       */
 172      var stopLoading = function(element) {
 173          element.removeClass('announcement loading');
 174      };
 175  
 176      /**
 177       * Show the success announcement. The announcement is only
 178       * visible for 2 seconds.
 179       *
 180       * @method announceSuccess
 181       * @private
 182       * @param {JQuery} element jQuery object representing the tool card.
 183       * @return {Promise} jQuery Deferred object
 184       */
 185      var announceSuccess = function(element) {
 186          var promise = $.Deferred();
 187  
 188          clearAllAnnouncements(element);
 189          element.addClass('announcement success');
 190          setTimeout(function() {
 191              element.removeClass('announcement success');
 192              promise.resolve();
 193          }, ANNOUNCEMENT_TIMEOUT);
 194  
 195          return promise;
 196      };
 197  
 198      /**
 199       * Show the failure announcement. The announcement is only
 200       * visible for 2 seconds.
 201       *
 202       * @method announceFailure
 203       * @private
 204       * @param {JQuery} element jQuery object representing the tool card.
 205       * @return {Promise} jQuery Deferred object
 206       */
 207      var announceFailure = function(element) {
 208          var promise = $.Deferred();
 209  
 210          clearAllAnnouncements(element);
 211          element.addClass('announcement fail');
 212          setTimeout(function() {
 213              element.removeClass('announcement fail');
 214              promise.resolve();
 215          }, ANNOUNCEMENT_TIMEOUT);
 216  
 217          return promise;
 218      };
 219  
 220      /**
 221       * Delete the tool type from the Moodle server. Triggers a success
 222       * or failure announcement depending on the result.
 223       *
 224       * @method deleteType
 225       * @private
 226       * @param {JQuery} element jQuery object representing the tool card.
 227       * @return {Promise} jQuery Deferred object
 228       */
 229      var deleteType = function(element) {
 230          var promise = $.Deferred();
 231          var typeId = getTypeId(element);
 232          startLoading(element);
 233  
 234          if (typeId === "") {
 235              return $.Deferred().resolve();
 236          }
 237  
 238          str.get_strings([
 239                  {
 240                      key: 'delete',
 241                      component: 'mod_lti'
 242                  },
 243                  {
 244                      key: 'delete_confirmation',
 245                      component: 'mod_lti'
 246                  },
 247                  {
 248                      key: 'delete',
 249                      component: 'mod_lti'
 250                  },
 251                  {
 252                      key: 'cancel',
 253                      component: 'core'
 254                  },
 255              ])
 256              .done(function(strs) {
 257                      notification.confirm(strs[0], strs[1], strs[2], strs[3], function() {
 258                              toolType.delete(typeId)
 259                                  .done(function() {
 260                                          stopLoading(element);
 261                                          announceSuccess(element)
 262                                              .done(function() {
 263                                                      element.remove();
 264                                                  })
 265                                              .fail(notification.exception)
 266                                              .always(function() {
 267                                                      // Always resolve because even if the announcement fails the type was deleted.
 268                                                      promise.resolve();
 269                                                  });
 270                                      })
 271                                  .fail(function(error) {
 272                                          announceFailure(element);
 273                                          promise.reject(error);
 274                                      });
 275                          }, function() {
 276                                  stopLoading(element);
 277                                  promise.resolve();
 278                              });
 279                  })
 280              .fail(function(error) {
 281                      stopLoading(element);
 282                      notification.exception(error);
 283                      promise.reject(error);
 284                  });
 285  
 286          return promise;
 287      };
 288  
 289      /**
 290       * Save a given value in a data attribute on the element.
 291       *
 292       * @method setValueSnapshot
 293       * @private
 294       * @param {JQuery} element jQuery object representing the element.
 295       * @param {String} value to be saved.
 296       */
 297      var setValueSnapshot = function(element, value) {
 298          element.attr('data-val-snapshot', value);
 299      };
 300  
 301      /**
 302       * Return the saved value from the element.
 303       *
 304       * @method getValueSnapshot
 305       * @private
 306       * @param {JQuery} element jQuery object representing the element.
 307       * @return {String} the saved value.
 308       */
 309      var getValueSnapshot = function(element) {
 310          return element.attr('data-val-snapshot');
 311      };
 312  
 313      /**
 314       * Save the current value of the tool description.
 315       *
 316       * @method snapshotDescription
 317       * @private
 318       * @param {JQuery} element jQuery object representing the tool card.
 319       */
 320      var snapshotDescription = function(element) {
 321          var descriptionElement = getDescriptionElement(element);
 322  
 323          if (descriptionElement.hasClass('loading')) {
 324              return;
 325          }
 326  
 327          var description = descriptionElement.text().trim();
 328          setValueSnapshot(descriptionElement, description);
 329      };
 330  
 331      /**
 332       * Send a request to update the description value for this tool
 333       * in the Moodle server.
 334       *
 335       * @method updateDescription
 336       * @private
 337       * @param {JQuery} element jQuery object representing the tool card.
 338       * @return {Promise} jQuery Deferred object
 339       */
 340      var updateDescription = function(element) {
 341          var typeId = getTypeId(element);
 342  
 343          // Return early if we don't have an id because it's
 344          // required to save the changes.
 345          if (typeId === "") {
 346              return $.Deferred().resolve();
 347          }
 348  
 349          var descriptionElement = getDescriptionElement(element);
 350  
 351          // Return early if we're already saving a value.
 352          if (descriptionElement.hasClass('loading')) {
 353              return $.Deferred().resolve();
 354          }
 355  
 356          var description = descriptionElement.text().trim();
 357          var snapshotVal = getValueSnapshot(descriptionElement);
 358  
 359          // If the value hasn't change then don't bother sending the
 360          // update request.
 361          if (snapshotVal == description) {
 362              return $.Deferred().resolve();
 363          }
 364  
 365          descriptionElement.addClass('loading');
 366  
 367          var promise = toolType.update({id: typeId, description: description});
 368  
 369          promise.done(function(type) {
 370              descriptionElement.removeClass('loading');
 371              // Make sure the text is updated with the description from the
 372              // server, just in case the update didn't work.
 373              descriptionElement.text(type.description);
 374          }).fail(notification.exception);
 375  
 376          // Probably need to handle failures better so that we can revert
 377          // the value in the input for the user.
 378          promise.fail(function() {
 379            descriptionElement.removeClass('loading');
 380          });
 381  
 382          return promise;
 383      };
 384  
 385      /**
 386       * Save the current value of the tool name.
 387       *
 388       * @method snapshotName
 389       * @private
 390       * @param {JQuery} element jQuery object representing the tool card.
 391       */
 392      var snapshotName = function(element) {
 393          var nameElement = getNameElement(element);
 394  
 395          if (nameElement.hasClass('loading')) {
 396              return;
 397          }
 398  
 399          var name = nameElement.text().trim();
 400          setValueSnapshot(nameElement, name);
 401      };
 402  
 403      /**
 404       * Send a request to update the name value for this tool
 405       * in the Moodle server.
 406       *
 407       * @method updateName
 408       * @private
 409       * @param {JQuery} element jQuery object representing the tool card.
 410       * @return {Promise} jQuery Deferred object
 411       */
 412      var updateName = function(element) {
 413          var typeId = getTypeId(element);
 414  
 415          // Return if we don't have an id.
 416          if (typeId === "") {
 417              return $.Deferred().resolve();
 418          }
 419  
 420          var nameElement = getNameElement(element);
 421  
 422          // Return if we're already saving.
 423          if (nameElement.hasClass('loading')) {
 424              return $.Deferred().resolve();
 425          }
 426  
 427          var name = nameElement.text().trim();
 428          var snapshotVal = getValueSnapshot(nameElement);
 429  
 430          // If the value hasn't change then don't bother sending the
 431          // update request.
 432          if (snapshotVal == name) {
 433              return $.Deferred().resolve();
 434          }
 435  
 436          nameElement.addClass('loading');
 437          var promise = toolType.update({id: typeId, name: name});
 438  
 439          promise.done(function(type) {
 440              nameElement.removeClass('loading');
 441              // Make sure the text is updated with the name from the
 442              // server, just in case the update didn't work.
 443              nameElement.text(type.name);
 444          });
 445  
 446          // Probably need to handle failures better so that we can revert
 447          // the value in the input for the user.
 448          promise.fail(function() {
 449            nameElement.removeClass('loading');
 450          });
 451  
 452          return promise;
 453      };
 454  
 455      /**
 456       * Send a request to update the state for this tool to be configured (active)
 457       * in the Moodle server. A success or failure announcement is triggered depending
 458       * on the result.
 459       *
 460       * @method setStatusActive
 461       * @private
 462       * @param {JQuery} element jQuery object representing the tool card.
 463       * @return {Promise} jQuery Deferred object
 464       */
 465      var setStatusActive = function(element) {
 466          var id = getTypeId(element);
 467  
 468          // Return if we don't have an id.
 469          if (id === "") {
 470              return $.Deferred().resolve();
 471          }
 472  
 473          startLoading(element);
 474  
 475          var promise = toolType.update({
 476              id: id,
 477              state: toolType.constants.state.configured
 478          });
 479  
 480          promise.done(function(toolTypeData) {
 481              stopLoading(element);
 482  
 483              var announcePromise = announceSuccess(element);
 484              var renderPromise = templates.render('mod_lti/tool_card', toolTypeData);
 485  
 486              $.when(renderPromise, announcePromise).then(function(renderResult) {
 487                  var html = renderResult[0];
 488                  var js = renderResult[1];
 489  
 490                  templates.replaceNode(element, html, js);
 491              });
 492          });
 493  
 494          promise.fail(function() {
 495              stopLoading(element);
 496              announceFailure(element);
 497          });
 498  
 499          return promise;
 500      };
 501  
 502      /**
 503       * Show the capabilities approval screen to show which groups of data this
 504       * type requires access to in Moodle (if any).
 505       *
 506       * @method displayCapabilitiesApproval
 507       * @private
 508       * @param {JQuery} element jQuery object representing the tool card.
 509       */
 510      var displayCapabilitiesApproval = function(element) {
 511          element.addClass('announcement capabilities');
 512      };
 513  
 514      /**
 515       * Hide the capabilities approval screen.
 516       *
 517       * @method hideCapabilitiesApproval
 518       * @private
 519       * @param {JQuery} element jQuery object representing the tool card.
 520       */
 521      var hideCapabilitiesApproval = function(element) {
 522          element.removeClass('announcement capabilities');
 523      };
 524  
 525      /**
 526       * The user wishes to activate this tool so show them the capabilities that
 527       * they need to agree to or if there are none then set the tool type's state
 528       * to active.
 529       *
 530       * @method activateToolType
 531       * @private
 532       * @param {JQuery} element jQuery object representing the tool card.
 533       */
 534      var activateToolType = function(element) {
 535          if (hasCapabilitiesContainer(element)) {
 536              displayCapabilitiesApproval(element);
 537          } else {
 538              setStatusActive(element);
 539          }
 540      };
 541  
 542      /**
 543       * Sets up the listeners for user interaction on this tool type card.
 544       *
 545       * @method registerEventListeners
 546       * @private
 547       * @param {JQuery} element jQuery object representing the tool card.
 548       */
 549      var registerEventListeners = function(element) {
 550          var deleteButton = getDeleteButton(element);
 551          deleteButton.click(function(e) {
 552              e.preventDefault();
 553              deleteType(element);
 554          });
 555          deleteButton.keypress(function(e) {
 556              if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
 557                  if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
 558                      e.preventDefault();
 559                      deleteButton.click();
 560                  }
 561              }
 562          });
 563  
 564          var descriptionElement = getDescriptionElement(element);
 565          descriptionElement.focus(function(e) {
 566              e.preventDefault();
 567              // Save a copy of the current value for the description so that
 568              // we can check if the user has changed it before sending a request to
 569              // the server.
 570              snapshotDescription(element);
 571          });
 572          descriptionElement.blur(function(e) {
 573              e.preventDefault();
 574              updateDescription(element);
 575          });
 576          descriptionElement.keypress(function(e) {
 577              if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
 578                  if (e.keyCode == KEYS.ENTER) {
 579                      e.preventDefault();
 580                      descriptionElement.blur();
 581                  }
 582              }
 583          });
 584  
 585          var nameElement = getNameElement(element);
 586          nameElement.focus(function(e) {
 587              e.preventDefault();
 588              // Save a copy of the current value for the name so that
 589              // we can check if the user has changed it before sending a request to
 590              // the server.
 591              snapshotName(element);
 592          });
 593          nameElement.blur(function(e) {
 594              e.preventDefault();
 595              updateName(element);
 596          });
 597          nameElement.keypress(function(e) {
 598              if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
 599                  if (e.keyCode == KEYS.ENTER) {
 600                      e.preventDefault();
 601                      nameElement.blur();
 602                  }
 603              }
 604          });
 605  
 606          // Only pending tool type cards have an activate button.
 607          if (hasActivateButton(element)) {
 608              var activateButton = getActivateButton(element);
 609              activateButton.click(function(e) {
 610                  e.preventDefault();
 611                  activateToolType(element);
 612              });
 613              activateButton.keypress(function(e) {
 614                  if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
 615                      if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
 616                          e.preventDefault();
 617                          activateButton.click();
 618                      }
 619                  }
 620              });
 621          }
 622  
 623          if (hasCapabilitiesContainer(element)) {
 624              var capabilitiesContainer = getCapabilitiesContainer(element);
 625  
 626              capabilitiesContainer.on(ltiEvents.CAPABILITIES_AGREE, function() {
 627                  setStatusActive(element);
 628              });
 629  
 630              capabilitiesContainer.on(ltiEvents.CAPABILITIES_DECLINE, function() {
 631                  hideCapabilitiesApproval(element);
 632              });
 633          }
 634      };
 635  
 636      return /** @alias module:mod_lti/tool_card_controller */ {
 637  
 638          /**
 639           * Initialise this module.
 640           *
 641           * @param {JQuery} element jQuery object representing the tool card.
 642           */
 643          init: function(element) {
 644              registerEventListeners(element);
 645          }
 646      };
 647  });


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