|
17 | 17 | this.icinga = icinga;
|
18 | 18 | this.$layout = $('#layout');
|
19 | 19 | this.$ghost = $('#modal-ghost');
|
| 20 | + this.hasChanges = false; |
20 | 21 |
|
21 | 22 | this.on('submit', '#modal form', this.onFormSubmit, this);
|
22 | 23 | this.on('change', '#modal form select.autosubmit', this.onFormAutoSubmit, this);
|
|
25 | 26 | this.on('mousedown', '#layout > #modal', this.onModalLeave, this);
|
26 | 27 | this.on('click', '.modal-header > button', this.onModalClose, this);
|
27 | 28 | this.on('keydown', '#layout > #modal.active', this.onKeyDown, this);
|
| 29 | + this.on('change', '#modal form', this.OnChange, this); |
28 | 30 | };
|
29 | 31 |
|
30 | 32 | Modal.prototype = new Icinga.EventListener();
|
|
179 | 181 | var _this = event.data.self;
|
180 | 182 | var $target = $(event.target);
|
181 | 183 |
|
182 |
| - if ($target.is('#modal')) { |
| 184 | + if (! _this.hasChanges && $target.is('#modal')) { |
183 | 185 | _this.hide($target);
|
184 | 186 | }
|
185 | 187 | };
|
|
201 | 203 | * @param event {Event} The `keydown` event triggered by pushing a key
|
202 | 204 | */
|
203 | 205 | Modal.prototype.onKeyDown = function(event) {
|
| 206 | + if (event.key !== 'Escape') { |
| 207 | + return; |
| 208 | + } |
| 209 | + |
204 | 210 | var _this = event.data.self;
|
205 | 211 |
|
206 |
| - if (! event.isDefaultPrevented() && event.key === 'Escape') { |
| 212 | + if (_this.hasChanges || document.activeElement.matches('form :scope')) { |
| 213 | + if (! _this.hasChanges) { |
| 214 | + document.activeElement.blur(); |
| 215 | + } |
| 216 | + |
| 217 | + return; |
| 218 | + } |
| 219 | + |
| 220 | + if (! event.isDefaultPrevented()) { |
207 | 221 | let $modal = _this.$layout.children('#modal');
|
208 | 222 | if ($modal.length) {
|
209 | 223 | _this.hide($modal);
|
210 | 224 | }
|
211 | 225 | }
|
212 | 226 | };
|
213 | 227 |
|
| 228 | + /** |
| 229 | + * Event handler to register whether the modal form has new changes after opening. |
| 230 | + * |
| 231 | + * This prevents the modal from being unintentionally closed |
| 232 | + * |
| 233 | + * @param event {Event} The `OnChange` event |
| 234 | + */ |
| 235 | + Modal.prototype.OnChange = function(event) { |
| 236 | + event.data.self.hasChanges = true; |
| 237 | + } |
| 238 | + |
214 | 239 | /**
|
215 | 240 | * Make final preparations and add the modal to the DOM
|
216 | 241 | *
|
|
248 | 273 | // Remove pointerEvent none style to make the button clickable again
|
249 | 274 | this.modalOpener.style.pointerEvents = '';
|
250 | 275 | this.modalOpener = null;
|
| 276 | + this.hasChanges = false; |
251 | 277 |
|
252 | 278 | $modal.removeClass('active');
|
253 | 279 | // Using `setTimeout` here to let the transition finish
|
|
0 commit comments