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