[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/yui/src/formchangechecker/js/ -> formchangechecker.js (source)

   1  /**
   2   * A utility to check for form changes before navigating away from a page.
   3   *
   4   * @module moodle-core-formchangechecker
   5   */
   6  
   7  /**
   8   * A utility to check for form changes before navigating away from a page.
   9   *
  10   * @class M.core.formchangechecker
  11   * @constructor
  12   */
  13  
  14  var FORMCHANGECHECKERNAME = 'core-formchangechecker',
  15  
  16      FORMCHANGECHECKER = function() {
  17          FORMCHANGECHECKER.superclass.constructor.apply(this, arguments);
  18      };
  19  
  20  Y.extend(FORMCHANGECHECKER, Y.Base, {
  21  
  22          // The delegated listeners we need to detach after the initial value has been stored once
  23          initialvaluelisteners : [],
  24  
  25          /**
  26           * Initialize the module
  27           *
  28           * @method initializer
  29           */
  30          initializer : function() {
  31              var formid = 'form#' + this.get('formid'),
  32                  currentform = Y.one(formid);
  33  
  34              if (!currentform) {
  35                  // If the form was not found, then we can't check for changes.
  36                  return;
  37              }
  38  
  39              // Add change events to the form elements
  40              currentform.delegate('change', M.core_formchangechecker.set_form_changed, 'input', this);
  41              currentform.delegate('change', M.core_formchangechecker.set_form_changed, 'textarea', this);
  42              currentform.delegate('change', M.core_formchangechecker.set_form_changed, 'select', this);
  43  
  44              // Add a focus event to check for changes which are made without triggering a change event
  45              this.initialvaluelisteners.push(currentform.delegate('focus', this.store_initial_value, 'input', this));
  46              this.initialvaluelisteners.push(currentform.delegate('focus', this.store_initial_value, 'textarea', this));
  47              this.initialvaluelisteners.push(currentform.delegate('focus', this.store_initial_value, 'select', this));
  48  
  49              // We need any submit buttons on the form to set the submitted flag
  50              Y.one(formid).on('submit', M.core_formchangechecker.set_form_submitted, this);
  51  
  52              // YUI doesn't support onbeforeunload properly so we must use the DOM to set the onbeforeunload. As
  53              // a result, the has_changed must stay in the DOM too
  54              window.onbeforeunload = M.core_formchangechecker.report_form_dirty_state;
  55          },
  56  
  57          /**
  58           * Store the initial value of the currently focussed element
  59           *
  60           * If an element has been focussed and changed but not yet blurred, the on change
  61           * event won't be fired. We need to store it's initial value to compare it in the
  62           * get_form_dirty_state function later.
  63           *
  64           * @method store_initial_value
  65           * @param {EventFacade} e
  66           */
  67          store_initial_value : function(e) {
  68              var thisevent;
  69              if (e.target.hasClass('ignoredirty')) {
  70                  // Don't warn on elements with the ignoredirty class
  71                  return;
  72              }
  73              if (M.core_formchangechecker.get_form_dirty_state()) {
  74                  // Detach all listen events to prevent duplicate initial value setting
  75                  while (this.initialvaluelisteners.length) {
  76                      thisevent = this.initialvaluelisteners.shift();
  77                      thisevent.detach();
  78                  }
  79  
  80                  return;
  81              }
  82  
  83              // Make a note of the current element so that it can be interrogated and
  84              // compared in the get_form_dirty_state function
  85              M.core_formchangechecker.stateinformation.focused_element = {
  86                  element : e.target,
  87                  initial_value : e.target.get('value')
  88              };
  89          }
  90      },
  91      {
  92          NAME : FORMCHANGECHECKERNAME,
  93          ATTRS : {
  94              formid : {
  95                  'value' : ''
  96              }
  97          }
  98      }
  99  );
 100  
 101  M.core_formchangechecker = M.core_formchangechecker || {};
 102  
 103  // We might have multiple instances of the form change protector
 104  M.core_formchangechecker.instances = M.core_formchangechecker.instances || [];
 105  M.core_formchangechecker.init = function(config) {
 106      var formchangechecker = new FORMCHANGECHECKER(config);
 107      M.core_formchangechecker.instances.push(formchangechecker);
 108      return formchangechecker;
 109  };
 110  
 111  // Store state information
 112  M.core_formchangechecker.stateinformation = [];
 113  
 114  /*
 115   * Set the form changed state to true
 116   */
 117  M.core_formchangechecker.set_form_changed = function(e) {
 118      if (e && e.target && e.target.hasClass('ignoredirty')) {
 119          // Don't warn on elements with the ignoredirty class
 120          return;
 121      }
 122      M.core_formchangechecker.stateinformation.formchanged = 1;
 123  
 124      // Once the form has been marked as dirty, we no longer need to keep track of form elements
 125      // which haven't yet blurred
 126      delete M.core_formchangechecker.stateinformation.focused_element;
 127  };
 128  
 129  /*
 130   * Set the form submitted state to true
 131   */
 132  M.core_formchangechecker.set_form_submitted = function() {
 133      M.core_formchangechecker.stateinformation.formsubmitted = 1;
 134  };
 135  
 136  /*
 137   * Attempt to determine whether the form has been modified in any way and
 138   * is thus 'dirty'
 139   *
 140   * @return Integer 1 is the form is dirty; 0 if not
 141   */
 142  M.core_formchangechecker.get_form_dirty_state = function() {
 143      var state = M.core_formchangechecker.stateinformation,
 144          editor;
 145  
 146      // If the form was submitted, then return a non-dirty state
 147      if (state.formsubmitted) {
 148          return 0;
 149      }
 150  
 151      // If any fields have been marked dirty, return a dirty state
 152      if (state.formchanged) {
 153          return 1;
 154      }
 155  
 156      // If a field has been focused and changed, but still has focus then the browser won't fire the
 157      // onChange event. We check for this eventuality here
 158      if (state.focused_element) {
 159          if (state.focused_element.element.get('value') !== state.focused_element.initial_value) {
 160              return 1;
 161          }
 162      }
 163  
 164      // Handle TinyMCE editor instances
 165      // We can't add a listener in the initializer as the editors may not have been created by that point
 166      // so we do so here instead
 167      if (typeof tinyMCE !== 'undefined') {
 168          for (editor in tinyMCE.editors) {
 169              if (tinyMCE.editors[editor].isDirty()) {
 170                  return 1;
 171              }
 172          }
 173      }
 174  
 175      // If we reached here, then the form hasn't met any of the dirty conditions
 176      return 0;
 177  };
 178  
 179  /*
 180   * Return a suitable message if changes have been made to a form
 181   */
 182  M.core_formchangechecker.report_form_dirty_state = function(e) {
 183      if (!M.core_formchangechecker.get_form_dirty_state()) {
 184          // the form is not dirty, so don't display any message
 185          return;
 186      }
 187  
 188      // This is the error message that we'll show to browsers which support it
 189      var warningmessage = M.util.get_string('changesmadereallygoaway', 'moodle');
 190  
 191      if (M.cfg.behatsiterunning) {
 192          // If the behat site is running we don't want browser alerts.
 193          return;
 194      }
 195  
 196      // Most browsers are happy with the returnValue being set on the event
 197      // But some browsers do not consistently pass the event
 198      if (e) {
 199          e.returnValue = warningmessage;
 200      }
 201  
 202      // But some require it to be returned instead
 203      return warningmessage;
 204  };


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1