NIFI-480:

- Addressing issues caused by canceling a dialog by pressing escape. Previously pressing escape would cause too many dialogs to close. This could lead to potential configuration loss if there was other unsaved changes.
This commit is contained in:
Matt Gilman 2015-04-01 09:42:33 -04:00
parent 4752e284f6
commit 30fc75e2b8
5 changed files with 88 additions and 36 deletions

View File

@ -90,7 +90,7 @@
if (isDefinedAndNotNull(options)) { if (isDefinedAndNotNull(options)) {
// get the combo // get the combo
var dialog = $(this).addClass('dialog cancellable'); var dialog = $(this).addClass('dialog cancellable modal');
var dialogHeaderText = $('<span class="dialog-header-text"></span>'); var dialogHeaderText = $('<span class="dialog-header-text"></span>');
var dialogHeader = $('<div class="dialog-header"></div>').append(dialogHeaderText); var dialogHeader = $('<div class="dialog-header"></div>').append(dialogHeaderText);

View File

@ -58,7 +58,7 @@
previousValue = args.item[args.column.field]; previousValue = args.item[args.column.field];
// create the wrapper // create the wrapper
wrapper = $('<div></div>').css({ wrapper = $('<div></div>').addClass('slickgrid-editor').css({
'z-index': 100000, 'z-index': 100000,
'position': 'absolute', 'position': 'absolute',
'background': 'white', 'background': 'white',
@ -598,7 +598,7 @@
*/ */
var showPropertyValue = function (propertyGrid, descriptors, row, cell) { var showPropertyValue = function (propertyGrid, descriptors, row, cell) {
// remove any currently open detail dialogs // remove any currently open detail dialogs
removeAllPropertyDetailDialogs(); nf.CanvasUtils.removeAllPropertyDetailDialogs();
// get the property in question // get the property in question
var propertyData = propertyGrid.getData(); var propertyData = propertyGrid.getData();
@ -694,13 +694,6 @@
} }
}; };
/**
* Removes all currently open property detail dialogs.
*/
var removeAllPropertyDetailDialogs = function () {
$('body').children('div.property-detail').hide().remove();
};
var initPropertiesTable = function (table, options) { var initPropertiesTable = function (table, options) {
// function for formatting the property name // function for formatting the property name
var nameFormatter = function (row, cell, value, columnDef, dataContext) { var nameFormatter = function (row, cell, value, columnDef, dataContext) {
@ -1029,7 +1022,7 @@
var clear = function (propertyTableContainer) { var clear = function (propertyTableContainer) {
var options = propertyTableContainer.data('options'); var options = propertyTableContainer.data('options');
if (options.readOnly === true) { if (options.readOnly === true) {
removeAllPropertyDetailDialogs(); nf.CanvasUtils.removeAllPropertyDetailDialogs();
} else { } else {
// clear any existing new property dialogs // clear any existing new property dialogs
if (nf.Common.isDefinedAndNotNull(options.newPropertyDialogContainer)) { if (nf.Common.isDefinedAndNotNull(options.newPropertyDialogContainer)) {
@ -1077,7 +1070,7 @@
if (options.readOnly !== true && nf.Common.isDefinedAndNotNull(options.newPropertyDialogContainer)) { if (options.readOnly !== true && nf.Common.isDefinedAndNotNull(options.newPropertyDialogContainer)) {
// build the new property dialog // build the new property dialog
var newPropertyDialogMarkup = var newPropertyDialogMarkup =
'<div class="new-property-dialog dialog">' + '<div class="new-property-dialog dialog cancellable">' +
'<div>' + '<div>' +
'<div class="setting-name">Property name</div>' + '<div class="setting-name">Property name</div>' +
'<div class="setting-field new-property-name-container">' + '<div class="setting-field new-property-name-container">' +

View File

@ -678,20 +678,6 @@ nf.Actions = (function () {
} }
}, },
/**
* Hides and open cancellable dialogs.
*/
hideDialogs: function () {
// ensure all cancellable dialogs are closed
var cancellable = $('.cancellable');
$.each(cancellable, function () {
// if this dialog is open, close it
if ($(this).is(':visible')) {
$(this).modal('hide');
}
});
},
/** /**
* Reloads the status for the entire canvas (components and flow.) * Reloads the status for the entire canvas (components and flow.)
*/ */

View File

@ -870,6 +870,15 @@ nf.CanvasUtils = (function () {
return nf.Clipboard.isCopied(); return nf.Clipboard.isCopied();
}, },
/**
* Removes all read only property detail dialogs.
*/
removeAllPropertyDetailDialogs: function () {
var propertyDetails = $('body').children('div.property-detail');
propertyDetails.find('div.nfel-editor').nfeditor('destroy');
propertyDetails.hide().remove();
},
/** /**
* Persists the current user view. * Persists the current user view.
*/ */

View File

@ -538,18 +538,82 @@ nf.Canvas = (function () {
// consider escape, before checking dialogs // consider escape, before checking dialogs
if (!isCtrl && evt.keyCode === 27) { if (!isCtrl && evt.keyCode === 27) {
// esc // esc
var target = $(evt.target);
if (target.length) { // prevent escape when a property value is being edited and it is unable to close itself
if (target.get(0) === $('#canvas-body').get(0)) { // (due to focus loss on field) - allowing this to continue would could cause other
nf.Actions.hideDialogs(); // unsaved changes to be lost as it would end up cancel the entire configuration dialog
} else { // not just the field itself
target.closest('.cancellable.dialog:visible').modal('hide'); if ($('div.value-combo').is(':visible') || $('div.slickgrid-nfel-editor').is(':visible') || $('div.slickgrid-editor').is(':visible')) {
} return;
evt.stopPropagation();
evt.preventDefault();
} }
// first consider read only property detail dialog
if ($('div.property-detail').is(':visible')) {
nf.CanvasUtils.removeAllPropertyDetailDialogs();
// prevent further bubbling as we're already handled it
evt.stopPropagation();
evt.preventDefault();
} else {
var target = $(evt.target);
if (target.length) {
var isBody = target.get(0) === $('#canvas-body').get(0);
var inShell = target.closest('#shell-dialog').length;
// special handling for body and shell
if (isBody || inShell) {
var cancellables = $('.cancellable');
if (cancellables.length) {
var zIndexMax = null;
var dialogMax = null;
// identify the top most cancellable
$.each(cancellables, function(_, cancellable) {
var dialog = $(cancellable);
var zIndex = dialog.css('zIndex');
// if the dialog has a zIndex consider it
if (dialog.is(':visible') && nf.Common.isDefinedAndNotNull(zIndex)) {
zIndex = parseInt(zIndex, 10);
if (zIndexMax === null || zIndex > zIndexMax) {
zIndexMax = zIndex;
dialogMax = dialog;
}
}
});
// if we've identified a dialog to close do so and stop propagation
if (dialogMax !== null) {
// hide the cancellable
if (dialogMax.hasClass('modal')) {
dialogMax.modal('hide');
} else {
dialogMax.hide();
}
// prevent further bubbling as we're already handled it
evt.stopPropagation();
evt.preventDefault();
}
}
} else {
// otherwise close the closest visible cancellable
var parentDialog = target.closest('.cancellable:visible').first();
if (parentDialog.length) {
if (parentDialog.hasClass('modal')) {
parentDialog.modal('hide');
} else {
parentDialog.hide();
}
// prevent further bubbling as we're already handled it
evt.stopPropagation();
evt.preventDefault();
}
}
}
}
return; return;
} }