NIFI-1426: - Introducing a universal capture for key events to ensure a consistent behavior throughout the application. - Allowing backspace to remove components from the canvas. - Introducing a more consistent behavior around the escape button.

Signed-off-by: Aldrin Piri <aldrin@apache.org>
This commit is contained in:
Matt Gilman 2016-01-28 10:30:16 -05:00 committed by Aldrin Piri
parent 8a9a44c102
commit b3990ecdcf
32 changed files with 339 additions and 211 deletions

View File

@ -28,6 +28,8 @@
<link rel="stylesheet" href="../nifi/css/reset.css" type="text/css" />
<script type="text/javascript" src="../nifi/js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="../nifi/js/jquery/combo/jquery.combo.js"></script>
<script type="text/javascript" src="../nifi/js/nf/nf-namespace.js"></script>
<script type="text/javascript" src="../nifi/js/nf/nf-universal-capture.js"></script>
<script type="text/javascript">
var $$ = $.noConflict(true);
$$(document).ready(function () {

View File

@ -273,6 +273,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/canvas/nf-canvas-utils.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-shell.js</include>
@ -329,6 +330,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/history/nf-history.js</include>
@ -342,6 +344,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/provenance/nf-provenance.js</include>
@ -354,6 +357,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/nf-processor-details.js</include>
@ -369,6 +373,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/counters/nf-counters.js</include>
@ -381,6 +386,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/templates/nf-templates.js</include>
@ -393,6 +399,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/cluster/nf-cluster.js</include>
@ -405,6 +412,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/users/nf-users.js</include>
@ -417,6 +425,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/bulletin-board/nf-bulletin-board.js</include>
@ -428,6 +437,7 @@
<includes>
<include>${staging.dir}/js/nf/nf-client.js</include>
<include>${staging.dir}/js/nf/nf-common.js</include>
<include>${staging.dir}/js/nf/nf-universal-capture.js</include>
<include>${staging.dir}/js/nf/nf-dialog.js</include>
<include>${staging.dir}/js/nf/nf-storage.js</include>
<include>${staging.dir}/js/nf/login/nf-login.js</include>

View File

@ -15,6 +15,7 @@
nf.bulletin.board.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/bulletin-board/nf-bulletin-board.js?${project.version}"></script>

View File

@ -16,6 +16,7 @@
nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-client.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/canvas/nf-canvas-utils.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-shell.js?${project.version}"></script>\n\

View File

@ -15,6 +15,7 @@
nf.cluster.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/cluster/nf-cluster.js?${project.version}"></script>\n\

View File

@ -15,6 +15,7 @@
nf.counters.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/counters/nf-counters.js?${project.version}"></script>\n\

View File

@ -15,6 +15,7 @@
nf.history.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/history/nf-history.js?${project.version}"></script>\n\

View File

@ -14,6 +14,7 @@
# limitations under the License.
nf.login.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/login/nf-login.js?${project.version}"></script>

View File

@ -15,6 +15,7 @@
nf.provenance.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/provenance/nf-provenance.js?${project.version}"></script>\n\

View File

@ -15,6 +15,7 @@
nf.summary.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-processor-details.js?${project.version}"></script>\n\

View File

@ -15,6 +15,7 @@
nf.templates.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/templates/nf-templates.js?${project.version}"></script>\n\

View File

@ -15,6 +15,7 @@
nf.users.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/users/nf-users.js?${project.version}"></script>\n\

View File

@ -15,8 +15,8 @@
limitations under the License.
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="label-configuration" class="dialog">
<div>
<div id="label-configuration">
<div id="label-configuration-contents">
<div class="setting" style="margin-top: 5px;">
<div class="setting-name">Label Value</div>
<div class="setting-field">
@ -30,9 +30,4 @@
</div>
</div>
</div>
<div id="label-configuration-button-container">
<div id="label-configuration-apply" class="button button-normal">Apply</div>
<div id="label-configuration-cancel" class="button button-normal">Cancel</div>
<div class="clear"></div>
</div>
</div>

View File

@ -15,7 +15,7 @@
limitations under the License.
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="status-history-dialog" class="dialog">
<div id="status-history-dialog">
<div id="status-history-details"></div>
<div id="status-history-container">
<div id="status-history-refresh-container">
@ -30,8 +30,4 @@
<div id="status-history-chart-control-container"></div>
</div>
<div class="clear"></div>
<div class="dialog-buttons">
<div id="status-history-close" class="button button-normal">Close</div>
<div class="clear"></div>
</div>
</div>

View File

@ -23,11 +23,13 @@
z-index: 1301;
display: none;
padding: 10px;
border: 3px solid #365C6A;
box-shadow: 4px 4px 6px rgba(0, 0, 0, 0.9);
cursor: move;
}
#label-configuration-contents {
margin-top: -50px;
}
#label-value {
width: 375px;
height: 210px;
@ -43,12 +45,4 @@
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
#label-configuration-button-container {
position: absolute;
left: 0;
bottom: 0;
right: 0;
padding: 0 8px 10px;
}

View File

@ -20,8 +20,6 @@
display: none;
z-index: 1301;
padding: 10px;
border: 3px solid #365C6A;
box-shadow: 4px 4px 6px rgba(0, 0, 0, 0.9);
cursor: move;
}
@ -86,6 +84,7 @@
float: left;
margin-left: 2px;
margin-bottom: 35px;
margin-top: -50px;
}
#status-history-chart-container {
@ -111,6 +110,7 @@
padding-top: 8px;
padding: 3px;
overflow: auto;
margin-top: -50px;
}
div.status-history-detail {

View File

@ -298,6 +298,16 @@
return this.each(function () {
selectOption($(this), option.text, option.value);
});
},
/**
* Destroy's the combo.
*/
destroy: function () {
$(this).empty().unbind().removeData();
// remove the options if open
$('div.combo-glass-pane').click();
}
};

View File

@ -203,11 +203,8 @@
$('#faded-background').show();
}
// show the centered dialog - performing these operation in the
// opposite order one might expect. for some reason, the call to
// center is causeing the graph to flicker in firefox (3.6). displaying
// the dialog container before centering seems to address the issue.
dialog.show().center();
// center and show the dialog
dialog.center().show();
}
});
},

View File

@ -109,16 +109,12 @@
'Esc': function (cm) {
if (isFunction(options.escape)) {
options.escape();
return;
}
return CodeMirror.Pass;
},
'Enter': function (cm) {
if (isFunction(options.enter)) {
options.enter();
return;
}
return CodeMirror.Pass;
}
}
});
@ -161,6 +157,15 @@
codeMirror.addClass('modified');
});
// handle keyHandled to stop event propagation/default as necessary
editor.on('keyHandled', function (cm, name, evt) {
if (name === 'Esc') {
// stop propagation of the escape event
evt.stopImmediatePropagation();
evt.preventDefault();
}
});
// handle sensitive values differently
if (sensitive) {
code.addClass('sensitive');

View File

@ -122,6 +122,10 @@
scope.save();
} else if (e.which === $.ui.keyCode.ESCAPE) {
scope.cancel();
// prevent further propagation or escape press and prevent default behavior
e.stopImmediatePropagation();
e.preventDefault();
}
};
@ -459,7 +463,7 @@
var configurationOptions = propertyContainer.data('options');
// create the wrapper
wrapper = $('<div></div>').css({
wrapper = $('<div class="combo-editor"></div>').css({
'z-index': 1999,
'position': 'absolute',
'background': 'white',
@ -572,6 +576,7 @@
};
this.destroy = function () {
combo.combo('destroy');
wrapper.remove();
};
@ -630,7 +635,7 @@
*/
var showPropertyValue = function (propertyGrid, descriptors, row, cell) {
// remove any currently open detail dialogs
nf.Common.removeAllPropertyDetailDialogs();
nf.UniversalCapture.removeAllPropertyDetailDialogs();
// get the property in question
var propertyData = propertyGrid.getData();
@ -734,7 +739,10 @@
minWidth: 175,
minHeight: 100,
readOnly: true,
resizable: true
resizable: true,
escape: function () {
cleanUp();
}
});
} else {
// prevent dragging over standard components
@ -752,11 +760,17 @@
'overflow-y': 'auto',
'resize': 'both',
'margin-bottom': '28px'
}).text(property.value).appendTo(wrapper);
}).text(property.value).on('keydown', function (evt) {
if (evt.which === $.ui.keyCode.ESCAPE) {
cleanUp();
evt.stopImmediatePropagation();
evt.preventDefault();
}
}).appendTo(wrapper);
}
// add an ok button that will remove the entire pop up
var ok = $('<div class="button button-normal">Ok</div>').on('click', function () {
var cleanUp = function () {
// clean up the editor
if (editor !== null) {
editor.nfeditor('destroy');
@ -764,7 +778,13 @@
// clean up the rest
wrapper.hide().remove();
};
// add an ok button that will remove the entire pop up
var ok = $('<div class="button button-normal">Ok</div>').on('click', function () {
cleanUp();
});
$('<div></div>').css({
'position': 'absolute',
'bottom': '0',
@ -1306,7 +1326,7 @@
var clear = function (propertyTableContainer) {
var options = propertyTableContainer.data('options');
if (options.readOnly === true) {
nf.Common.removeAllPropertyDetailDialogs();
nf.UniversalCapture.removeAllPropertyDetailDialogs();
} else {
// clear any existing new property dialogs
if (nf.Common.isDefinedAndNotNull(options.dialogContainer)) {

View File

@ -537,92 +537,8 @@ nf.Canvas = (function () {
nf.Settings.resetTableSize();
}
}).on('keydown', function (evt) {
var isCtrl = evt.ctrlKey || evt.metaKey;
// consider escape, before checking dialogs
if (!isCtrl && evt.keyCode === 27) {
// esc
// prevent escape when a property value is being edited and it is unable to close itself
// (due to focus loss on field) - allowing this to continue would could cause other
// unsaved changes to be lost as it would end up cancel the entire configuration dialog
// not just the field itself
if ($('div.value-combo').is(':visible') || $('div.slickgrid-nfel-editor').is(':visible') || $('div.slickgrid-editor').is(':visible')) {
return;
}
// first consider read only property detail dialog
if ($('div.property-detail').is(':visible')) {
nf.Common.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;
}
// if a dialog is open, disable canvas shortcuts
if ($('.dialog').is(':visible')) {
if ($('.dialog').is(':visible') || $('#search-field').is(':focus')) {
return;
}
@ -630,41 +546,45 @@ nf.Canvas = (function () {
var selection = nf.CanvasUtils.getSelection();
// handle shortcuts
var isCtrl = evt.ctrlKey || evt.metaKey;
if (isCtrl) {
if (evt.keyCode === 82) {
// ctrl-r
nf.Actions.reloadStatus();
evt.preventDefault();
// default prevented in nf-universal-capture.js
} else if (evt.keyCode === 65) {
// ctrl-a
nf.Actions.selectAll();
nf.CanvasToolbar.refresh();
// only want to prevent default if the action was performed, otherwise default select all would be overridden
evt.preventDefault();
} else if (evt.keyCode === 67) {
// ctrl-c
if (nf.Common.isDFM() && nf.CanvasUtils.isCopyable(selection)) {
// ctrl-c
nf.Actions.copy(selection);
// only want to prevent default if the action was performed, otherwise default copy would be overridden
evt.preventDefault();
}
} else if (evt.keyCode === 86) {
// ctrl-v
if (nf.Common.isDFM() && nf.CanvasUtils.isPastable()) {
// ctrl-p
nf.Actions.paste(selection);
// only want to prevent default if the action was performed, otherwise default paste would be overridden
evt.preventDefault();
}
}
} else {
if (evt.keyCode === 46) {
if (evt.keyCode == 8 || evt.keyCode === 46) {
// backspace or delete
if (nf.Common.isDFM() && nf.CanvasUtils.isDeletable(selection)) {
// delete
nf.Actions['delete'](selection);
evt.preventDefault();
}
// default prevented in nf-universal-capture.js
}
}
});

View File

@ -1379,7 +1379,7 @@ nf.ControllerService = (function () {
}],
select: function () {
// remove all property detail dialogs
nf.Common.removeAllPropertyDetailDialogs();
nf.UniversalCapture.removeAllPropertyDetailDialogs();
// update the property table size in case this is the first time its rendered
if ($(this).text() === 'Properties') {

View File

@ -26,48 +26,59 @@ nf.LabelConfiguration = (function () {
* Initializes the label details dialog.
*/
init: function () {
var apply = function () {
var revision = nf.Client.getRevision();
// get the new values
var labelValue = $('#label-value').val();
var fontSize = $('#label-font-size').combo('getSelectedOption');
// save the new label value
$.ajax({
type: 'PUT',
url: labelUri,
data: {
'version': revision.version,
'clientId': revision.clientId,
'label': labelValue,
'style[font-size]': fontSize.value
},
dataType: 'json'
}).done(function (response) {
// update the revision
nf.Client.setRevision(response.revision);
// get the label out of the response
nf.Label.set(response.label);
}).fail(nf.Common.handleAjaxError);
// reset and hide the dialog
labelUri = '';
$('#label-configuration').hide();
};
var cancel = function () {
labelUri = '';
$('#label-configuration').hide();
};
// make the new property dialog draggable
$('#label-configuration').draggable({
$('#label-configuration').modal({
overlayBackground: true,
buttons: [{
buttonText: 'Apply',
handler: {
click: function () {
var revision = nf.Client.getRevision();
// get the new values
var labelValue = $('#label-value').val();
var fontSize = $('#label-font-size').combo('getSelectedOption');
// save the new label value
$.ajax({
type: 'PUT',
url: labelUri,
data: {
'version': revision.version,
'clientId': revision.clientId,
'label': labelValue,
'style[font-size]': fontSize.value
},
dataType: 'json'
}).done(function (response) {
// update the revision
nf.Client.setRevision(response.revision);
// get the label out of the response
nf.Label.set(response.label);
}).fail(nf.Common.handleAjaxError);
// reset and hide the dialog
this.modal('hide');
}
}
}, {
buttonText: 'Cancel',
handler: {
click: function () {
this.modal('hide');
}
}
}],
handler: {
close: function () {
labelUri = '';
}
}
}).draggable({
containment: 'parent',
cancel: 'textarea, .button, .combo'
}).on('click', '#label-configuration-apply', apply).on('click', '#label-configuration-cancel', cancel);
});
// create the available sizes
var sizes = [];
@ -128,7 +139,7 @@ nf.LabelConfiguration = (function () {
});
// show the detail dialog
$('#label-configuration').center().show();
$('#label-configuration').modal('show');
}
}
};

View File

@ -471,7 +471,7 @@ nf.ProcessorConfiguration = (function () {
}],
select: function () {
// remove all property detail dialogs
nf.Common.removeAllPropertyDetailDialogs();
nf.UniversalCapture.removeAllPropertyDetailDialogs();
// update the processor property table size in case this is the first time its rendered
if ($(this).text() === 'Properties') {

View File

@ -311,7 +311,7 @@ nf.ReportingTask = (function () {
}],
select: function () {
// remove all property detail dialogs
nf.Common.removeAllPropertyDetailDialogs();
nf.UniversalCapture.removeAllPropertyDetailDialogs();
// update the property table size in case this is the first time its rendered
if ($(this).text() === 'Properties') {

View File

@ -516,15 +516,6 @@ nf.Common = (function () {
});
},
/**
* 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();
},
/**
* Formats the tooltip for the specified property.
*

View File

@ -70,7 +70,7 @@ nf.ProcessorDetails = (function () {
}],
select: function () {
// remove all property detail dialogs
nf.Common.removeAllPropertyDetailDialogs();
nf.UniversalCapture.removeAllPropertyDetailDialogs();
// resize the property grid in case this is the first time its rendered
if ($(this).text() === 'Properties') {

View File

@ -393,8 +393,7 @@ nf.StatusHistory = (function () {
// show/center the dialog if necessary
if (!statusHistoryDialog.is(':visible')) {
$('#glass-pane').show();
statusHistoryDialog.center().show();
statusHistoryDialog.modal('show');
}
// the container for the main chart
@ -1163,24 +1162,36 @@ nf.StatusHistory = (function () {
}
});
// make the new property dialog draggable
$('#status-history-dialog').draggable({
// configure the dialog and make it draggable
$('#status-history-dialog').modal({
overlayBackground: false,
buttons: [{
buttonText: 'Close',
handler: {
click: function () {
this.modal('hide');
}
}
}],
handler: {
close: function () {
// remove the current status history
$('#status-history-dialog').removeData('status-history').hide();
// reset the dom
$('#status-history-chart-container').empty();
$('#status-history-chart-control-container').empty();
$('#status-history-details').empty();
// clear the extent and selected descriptor
brushExtent = null;
descriptor = null;
instances = null;
}
}
}).draggable({
cancel: '#status-history-chart-container, #status-history-chart-control-container, div.status-history-detail, div.button, div.combo, div.summary-refresh',
containment: 'parent'
}).on('click', '#status-history-close', function () {
// remove the current status history
$('#status-history-dialog').removeData('status-history').hide();
$('#glass-pane').hide();
// reset the dom
$('#status-history-chart-container').empty();
$('#status-history-chart-control-container').empty();
$('#status-history-details').empty();
// clear the extent and selected descriptor
brushExtent = null;
descriptor = null;
instances = null;
});
},

View File

@ -0,0 +1,131 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Captures keydown on the window to ensure certain keystrokes are handled in a consistent manner, particularly those
* that can lead to browser navigation/reload.
*/
$(document).ready(function () {
// setup a listener to ensure keystrokes are being overridden in a consistent manner
$(window).on('keydown', function (evt) {
// consider escape, before checking dialogs
var isCtrl = evt.ctrlKey || evt.metaKey;
if (!isCtrl && evt.keyCode === 27) {
// esc
// prevent escape when editing a property with allowable values - that component does not handle key
// events so it can bubble up to here. once here we are unable to cancel the current edit so we simply
// return. this is not an issue for viewing in read only mode as the table is not in an edit mode. this
// is not an issue for other fields as they can handle key events locally and cancel the edit appropriately
var visibleCombo = $('div.value-combo');
if (visibleCombo.is(':visible') && visibleCombo.parent().hasClass('combo-editor')) {
return;
}
// consider property detail dialogs
if ($('div.property-detail').is(':visible')) {
nf.UniversalCapture.removeAllPropertyDetailDialogs();
// prevent further bubbling as we're already handled it
evt.stopImmediatePropagation();
evt.preventDefault();
} else {
var target = $(evt.target);
if (target.length) {
// special handling for body as the target
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') && (zIndex !== null && typeof zIndex !== 'undefined')) {
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.stopImmediatePropagation();
evt.preventDefault();
return;
}
}
// now see if we're in a frame
if (top !== window) {
// and our parent has shell defined
if (typeof parent.nf !== 'undefined' && typeof parent.nf.Shell !== 'undefined') {
parent.$('#shell-close-button').click();
// prevent further bubbling as we're already handled it
evt.stopImmediatePropagation();
evt.preventDefault();
return;
}
}
}
}
} else {
if (isCtrl) {
if (evt.keyCode === 82) {
// ctrl-r
evt.preventDefault();
}
} else {
if (!$('input').is(':focus') && (evt.keyCode == 8 || evt.keyCode === 46)) {
// backspace or delete
evt.preventDefault();
}
}
}
});
});
nf.UniversalCapture = (function() {
return {
/**
* Removes all read only property detail dialogs.
*/
removeAllPropertyDetailDialogs: function () {
var propertyDetails = $('body').find('div.property-detail');
propertyDetails.find('div.nfel-editor').nfeditor('destroy'); // look for any nfel editors
propertyDetails.find('div.value-combo').combo('destroy'); // look for any combos
propertyDetails.hide().remove();
}
};
}());

View File

@ -53,6 +53,7 @@
<script type="text/javascript" src="../nifi/js/jquery/slickgrid/slick.grid.js"></script>
<script type="text/javascript" src="../nifi/js/codemirror/lib/codemirror-compressed.js"></script>
<script type="text/javascript" src="../nifi/js/nf/nf-namespace.js"></script>
<script type="text/javascript" src="../nifi/js/nf/nf-universal-capture.js"></script>
<script type="text/javascript" src="../nifi/js/jquery/nfeditor/languages/nfel.js"></script>
<script type="text/javascript" src="../nifi/js/jquery/nfeditor/jquery.nfeditor.js"></script>
<script type="text/javascript" src="js/application.js"></script>

View File

@ -393,7 +393,7 @@ div.slickgrid-nfel-editor .nfel-editor {
margin-bottom: 30px;
}
div.update-attribute-detail .nfel-editor {
div.property-detail .nfel-editor {
margin-bottom: 30px;
}

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
/* global Slick */
/* global Slick, nf */
$(document).ready(function () {
ua.editable = $('#attribute-updater-editable').text() === 'true';
@ -1545,7 +1545,7 @@ var ua = {
var offset = cellNode.offset();
// create the wrapper
var wrapper = $('<div class="update-attribute-detail"></div>').css({
var wrapper = $('<div class="property-detail"></div>').css({
'z-index': 100000,
'position': 'absolute',
'background': 'white',
@ -1558,6 +1558,8 @@ var ua = {
'left': offset.left - 5
}).appendTo(container);
var editor = null;
// the attribute column does not get the nfel editor
if (columnDefinition.id === 'attribute') {
// make it draggable
@ -1575,7 +1577,14 @@ var ua = {
'overflow-y': 'auto',
'resize': 'both',
'margin-bottom': '28px'
}).text(value).appendTo(wrapper);
}).text(value).on('keydown', function (evt) {
if (evt.which === $.ui.keyCode.ESCAPE) {
cleanUp();
evt.stopImmediatePropagation();
evt.preventDefault();
}
}).appendTo(wrapper);
} else {
var languageId = 'nfel';
var editorClass = languageId + '-editor';
@ -1587,21 +1596,35 @@ var ua = {
});
// create the editor
$('<div></div>').addClass(editorClass).appendTo(wrapper).nfeditor({
editor = $('<div></div>').addClass(editorClass).appendTo(wrapper).nfeditor({
languageId: languageId,
width: (cellNode.width() - 5) + 'px',
content: value,
minWidth: 175,
minHeight: 100,
readOnly: true,
resizable: true
resizable: true,
escape: function () {
cleanUp();
}
});
}
var cleanUp = function () {
// clean up the editor
if (editor !== null) {
editor.nfeditor('destroy');
}
// clean up the rest
wrapper.hide().remove();
};
// add an ok button that will remove the entire pop up
var ok = $('<div class="button button-normal">Ok</div>').on('click', function () {
wrapper.hide().remove();
cleaUp();
});
$('<div></div>').css({
'position': 'absolute',
'bottom': '0',
@ -1615,7 +1638,7 @@ var ua = {
* Removes all currently open process property detail dialogs.
*/
removeAllDetailDialogs: function () {
$('body').children('div.update-attribute-detail').hide().remove();
nf.UniversalCapture.removeAllPropertyDetailDialogs();
},
/**
@ -1677,6 +1700,7 @@ var ua = {
if (e.which === $.ui.keyCode.ENTER && e.ctrlKey) {
scope.save();
} else if (e.which === $.ui.keyCode.ESCAPE) {
e.stopImmediatePropagation();
e.preventDefault();
scope.cancel();
} else if (e.which === $.ui.keyCode.TAB && e.shiftKey) {