[ Index ]

PHP Cross Reference of Unnamed Project

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


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