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