Skip to content

Commit dd1f8e3

Browse files
modal.js: Prevent unintentional closing of a modal
Don't close modal if it contains changes and: - `ESCAPE` is pressed - User click on the overlay
1 parent 74369b7 commit dd1f8e3

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

public/js/icinga/behavior/modal.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
this.icinga = icinga;
1818
this.$layout = $('#layout');
1919
this.$ghost = $('#modal-ghost');
20+
this.hasChanges = false;
2021

2122
this.on('submit', '#modal form', this.onFormSubmit, this);
2223
this.on('change', '#modal form select.autosubmit', this.onFormAutoSubmit, this);
@@ -25,6 +26,7 @@
2526
this.on('mousedown', '#layout > #modal', this.onModalLeave, this);
2627
this.on('click', '.modal-header > button', this.onModalClose, this);
2728
this.on('keydown', '#layout > #modal.active', this.onKeyDown, this);
29+
this.on('change', '#modal form', this.OnChange, this);
2830
};
2931

3032
Modal.prototype = new Icinga.EventListener();
@@ -179,7 +181,7 @@
179181
var _this = event.data.self;
180182
var $target = $(event.target);
181183

182-
if ($target.is('#modal')) {
184+
if (! _this.hasChanges && $target.is('#modal')) {
183185
_this.hide($target);
184186
}
185187
};
@@ -201,16 +203,39 @@
201203
* @param event {Event} The `keydown` event triggered by pushing a key
202204
*/
203205
Modal.prototype.onKeyDown = function(event) {
206+
if (event.key !== 'Escape') {
207+
return;
208+
}
209+
204210
var _this = event.data.self;
205211

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()) {
207221
let $modal = _this.$layout.children('#modal');
208222
if ($modal.length) {
209223
_this.hide($modal);
210224
}
211225
}
212226
};
213227

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+
214239
/**
215240
* Make final preparations and add the modal to the DOM
216241
*
@@ -248,6 +273,7 @@
248273
// Remove pointerEvent none style to make the button clickable again
249274
this.modalOpener.style.pointerEvents = '';
250275
this.modalOpener = null;
276+
this.hasChanges = false;
251277

252278
$modal.removeClass('active');
253279
// Using `setTimeout` here to let the transition finish

0 commit comments

Comments
 (0)