You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2016/12/22 21:52:15 UTC
nifi git commit: [NIFI-96] add align horizontal and align vertical
capability to components on the canvas. This closes #1354
Repository: nifi
Updated Branches:
refs/heads/master e65aad8fe -> 5ea17d30c
[NIFI-96] add align horizontal and align vertical capability to components on the canvas. This closes #1354
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/5ea17d30
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/5ea17d30
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/5ea17d30
Branch: refs/heads/master
Commit: 5ea17d30c5858fd9e56498e01a6cbd9fa3423c73
Parents: e65aad8
Author: Scott Aslan <sc...@gmail.com>
Authored: Thu Dec 22 16:06:38 2016 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Thu Dec 22 16:47:34 2016 -0500
----------------------------------------------------------------------
.../src/main/webapp/css/common-ui.css | 5 +
.../src/main/webapp/js/nf/canvas/nf-actions.js | 148 ++++++++-
.../main/webapp/js/nf/canvas/nf-canvas-utils.js | 28 ++
.../main/webapp/js/nf/canvas/nf-context-menu.js | 15 +-
.../main/webapp/js/nf/canvas/nf-draggable.js | 297 ++++++++++---------
5 files changed, 353 insertions(+), 140 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/5ea17d30/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
index a0f6af7..e871537 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
@@ -97,6 +97,11 @@ i[class^="icon-"]:before, i[class*=" icon-"]:before {
margin: -2px;
}
+/*shift rotated font awesome icons*/
+.fa-rotate-90 {
+ left: -2px !important;
+}
+
body {
display: block;
font-family: Roboto, sans-serif;
http://git-wip-us.apache.org/repos/asf/nifi/blob/5ea17d30/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
index a9c05b8..b27e291 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
@@ -75,6 +75,13 @@ nf.Actions = (function () {
});
};
+ // determine if the source of this connection is part of the selection
+ var isSourceSelected = function (connection, selection) {
+ return selection.filter(function (d) {
+ return nf.CanvasUtils.getConnectionSourceComponentId(connection) === d.id;
+ }).size() > 0;
+ };
+
return {
/**
* Initializes the actions.
@@ -867,7 +874,7 @@ nf.Actions = (function () {
// refresh the birdseye
nf.Birdseye.refresh();
-
+
// inform Angular app values have changed
nf.ng.Bridge.digest();
}).fail(nf.Common.handleAjaxError);
@@ -1095,6 +1102,145 @@ nf.Actions = (function () {
},
/**
+ * Aligns the components in the specified selection vertically along the center of the components.
+ *
+ * @param {array} selection The selection
+ */
+ alignVertical: function (selection) {
+ var updates = d3.map();
+ // ensure every component is writable
+ if (nf.CanvasUtils.canModify(selection) === false) {
+ nf.Dialog.showOkDialog({
+ headerText: 'Component Position',
+ dialogContent: 'Must be authorized to modify every component selected.'
+ });
+ return;
+ }
+ // determine the extent
+ var minX = null, maxX = null;
+ selection.each(function (d) {
+ if (d.type !== "Connection") {
+ if (minX === null || d.position.x < minX) {
+ minX = d.position.x;
+ }
+ var componentMaxX = d.position.x + d.dimensions.width;
+ if (maxX === null || componentMaxX > maxX) {
+ maxX = componentMaxX;
+ }
+ }
+ });
+ var center = (minX + maxX) / 2;
+
+ // align all components left
+ selection.each(function(d) {
+ if (d.type !== "Connection") {
+ var delta = {
+ x: center - (d.position.x + d.dimensions.width / 2),
+ y: 0
+ };
+ // if this component is already centered, no need to updated it
+ if (delta.x !== 0) {
+ // consider any connections
+ var connections = nf.Connection.getComponentConnections(d.id);
+ $.each(connections, function(_, connection) {
+ var connectionSelection = d3.select('#id-' + connection.id);
+
+ if (!updates.has(connection.id) && nf.CanvasUtils.getConnectionSourceComponentId(connection) === nf.CanvasUtils.getConnectionDestinationComponentId(connection)) {
+ // this connection is self looping and hasn't been updated by the delta yet
+ var connectionUpdate = nf.Draggable.updateConnectionPosition(nf.Connection.get(connection.id), delta);
+ if (connectionUpdate !== null) {
+ updates.set(connection.id, connectionUpdate);
+ }
+ } else if (!updates.has(connection.id) && connectionSelection.classed('selected') && nf.CanvasUtils.canModify(connectionSelection)) {
+ // this is a selected connection that hasn't been updated by the delta yet
+ if (nf.CanvasUtils.getConnectionSourceComponentId(connection) === d.id || !isSourceSelected(connection, selection)) {
+ // the connection is either outgoing or incoming when the source of the connection is not part of the selection
+ var connectionUpdate = nf.Draggable.updateConnectionPosition(nf.Connection.get(connection.id), delta);
+ if (connectionUpdate !== null) {
+ updates.set(connection.id, connectionUpdate);
+ }
+ }
+ }
+ });
+ updates.set(d.id, nf.Draggable.updateComponentPosition(d, delta));
+ }
+ }
+ });
+ nf.Draggable.refreshConnections(updates);
+ },
+
+ /**
+ * Aligns the components in the specified selection horizontally along the center of the components.
+ *
+ * @param {array} selection The selection
+ */
+ alignHorizontal: function (selection) {
+ var updates = d3.map();
+ // ensure every component is writable
+ if (nf.CanvasUtils.canModify(selection) === false) {
+ nf.Dialog.showOkDialog({
+ headerText: 'Component Position',
+ dialogContent: 'Must be authorized to modify every component selected.'
+ });
+ return;
+ }
+
+ // determine the extent
+ var minY = null, maxY = null;
+ selection.each(function (d) {
+ if (d.type !== "Connection") {
+ if (minY === null || d.position.y < minY) {
+ minY = d.position.y;
+ }
+ var componentMaxY = d.position.y + d.dimensions.height;
+ if (maxY === null || componentMaxY > maxY) {
+ maxY = componentMaxY;
+ }
+ }
+ });
+ var center = (minY + maxY) / 2;
+
+ // align all components with top most component
+ selection.each(function(d) {
+ if (d.type !== "Connection") {
+ var delta = {
+ x: 0,
+ y: center - (d.position.y + d.dimensions.height / 2)
+ };
+
+ // if this component is already centered, no need to updated it
+ if (delta.y !== 0) {
+ // consider any connections
+ var connections = nf.Connection.getComponentConnections(d.id);
+ $.each(connections, function(_, connection) {
+ var connectionSelection = d3.select('#id-' + connection.id);
+
+ if (!updates.has(connection.id) && nf.CanvasUtils.getConnectionSourceComponentId(connection) === nf.CanvasUtils.getConnectionDestinationComponentId(connection)) {
+ // this connection is self looping and hasn't been updated by the delta yet
+ var connectionUpdate = nf.Draggable.updateConnectionPosition(nf.Connection.get(connection.id), delta);
+ if (connectionUpdate !== null) {
+ updates.set(connection.id, connectionUpdate);
+ }
+ } else if (!updates.has(connection.id) && connectionSelection.classed('selected') && nf.CanvasUtils.canModify(connectionSelection)) {
+ // this is a selected connection that hasn't been updated by the delta yet
+ if (nf.CanvasUtils.getConnectionSourceComponentId(connection) === d.id || !isSourceSelected(connection, selection)) {
+ // the connection is either outgoing or incoming when the source of the connection is not part of the selection
+ var connectionUpdate = nf.Draggable.updateConnectionPosition(nf.Connection.get(connection.id), delta);
+ if (connectionUpdate !== null) {
+ updates.set(connection.id, connectionUpdate);
+ }
+ }
+ }
+ });
+ updates.set(d.id, nf.Draggable.updateComponentPosition(d, delta));
+ }
+ }
+ });
+
+ nf.Draggable.refreshConnections(updates);
+ },
+
+ /**
* Opens the fill color dialog for the component in the specified selection.
*
* @param {type} selection The selection
http://git-wip-us.apache.org/repos/asf/nifi/blob/5ea17d30/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
index 1fb262e..e743d3d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
@@ -545,6 +545,34 @@ nf.CanvasUtils = (function () {
tip.style('display', 'none');
});
},
+
+ /**
+ * Determines if the specified selection is alignable (in a single action).
+ *
+ * @param {selection} selection The selection
+ * @returns {boolean}
+ */
+ canAlign: function(selection) {
+ var canAlign = true;
+
+ // determine if the current selection is entirely connections
+ var selectedConnections = selection.filter(function(d) {
+ var connection = d3.select(this);
+ return nf.CanvasUtils.isConnection(connection);
+ });
+
+ // require multiple selections besides connections
+ if (selection.size() - selectedConnections.size() < 2) {
+ canAlign = false;
+ }
+
+ // require write permissions
+ if (nf.CanvasUtils.canModify(selection) === false) {
+ canAlign = false;
+ }
+
+ return canAlign;
+ },
/**
* Determines if the specified selection is colorable (in a single action).
http://git-wip-us.apache.org/repos/asf/nifi/blob/5ea17d30/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
index 8100678..b51ddb0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
@@ -158,8 +158,17 @@ nf.ContextMenu = (function () {
};
/**
+ * Determines whether the components in the specified selection are alignable.
+ *
+ * @param {selection} selection The selection
+ */
+ var canAlign = function (selection) {
+ return nf.CanvasUtils.canAlign(selection);
+ };
+
+ /**
* Determines whether the components in the specified selection are colorable.
- *
+ *
* @param {selection} selection The selection
*/
var isColorable = function (selection) {
@@ -435,7 +444,9 @@ nf.ContextMenu = (function () {
{condition: canMoveToParent, menuItem: {clazz: 'fa fa-arrows', text: 'Move to parent group', action: 'moveIntoParent'}},
{condition: canListQueue, menuItem: {clazz: 'fa fa-list', text: 'List queue', action: 'listQueue'}},
{condition: canEmptyQueue, menuItem: {clazz: 'fa fa-minus-circle', text: 'Empty queue', action: 'emptyQueue'}},
- {condition: isDeletable, menuItem: {clazz: 'fa fa-trash', text: 'Delete', action: 'delete'}}
+ {condition: isDeletable, menuItem: {clazz: 'fa fa-trash', text: 'Delete', action: 'delete'}},
+ {condition: canAlign, menuItem: {clazz: 'fa fa-align-center', text: 'Align vertical', action: 'alignVertical'}},
+ {condition: canAlign, menuItem: {clazz: 'fa fa-align-center fa-rotate-90', text: 'Align horizontal', action: 'alignHorizontal'}}
];
return {
http://git-wip-us.apache.org/repos/asf/nifi/blob/5ea17d30/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js
index f6ae344..08b4590 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js
@@ -23,7 +23,7 @@ nf.Draggable = (function () {
/**
* Updates the positioning of all selected components.
- *
+ *
* @param {selection} dragSelection The current drag selection
*/
var updateComponentsPosition = function (dragSelection) {
@@ -40,107 +40,6 @@ nf.Draggable = (function () {
if (delta.x === 0 && delta.y === 0) {
return;
}
-
- var updateComponentPosition = function(d) {
- var newPosition = {
- 'x': d.position.x + delta.x,
- 'y': d.position.y + delta.y
- };
-
- // build the entity
- var entity = {
- 'revision': nf.Client.getRevision(d),
- 'component': {
- 'id': d.id,
- 'position': newPosition
- }
- };
-
- // update the component positioning
- return $.Deferred(function (deferred) {
- $.ajax({
- type: 'PUT',
- url: d.uri,
- data: JSON.stringify(entity),
- dataType: 'json',
- contentType: 'application/json'
- }).done(function (response) {
- // update the component
- nf[d.type].set(response);
-
- // resolve with an object so we can refresh when finished
- deferred.resolve({
- type: d.type,
- id: d.id
- });
- }).fail(function (xhr, status, error) {
- if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
- nf.Dialog.showOkDialog({
- headerText: 'Component Position',
- dialogContent: nf.Common.escapeHtml(xhr.responseText)
- });
- } else {
- nf.Common.handleAjaxError(xhr, status, error);
- }
-
- deferred.reject();
- });
- }).promise();
- };
-
- var updateConnectionPosition = function(d) {
- // only update if necessary
- if (d.bends.length === 0) {
- return null;
- }
-
- // calculate the new bend points
- var newBends = $.map(d.bends, function (bend) {
- return {
- x: bend.x + delta.x,
- y: bend.y + delta.y
- };
- });
-
- var entity = {
- 'revision': nf.Client.getRevision(d),
- 'component': {
- id: d.id,
- bends: newBends
- }
- };
-
- // update the component positioning
- return $.Deferred(function (deferred) {
- $.ajax({
- type: 'PUT',
- url: d.uri,
- data: JSON.stringify(entity),
- dataType: 'json',
- contentType: 'application/json'
- }).done(function (response) {
- // update the component
- nf.Connection.set(response);
-
- // resolve with an object so we can refresh when finished
- deferred.resolve({
- type: d.type,
- id: d.id
- });
- }).fail(function (xhr, status, error) {
- if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
- nf.Dialog.showOkDialog({
- headerText: 'Component Position',
- dialogContent: nf.Common.escapeHtml(xhr.responseText)
- });
- } else {
- nf.Common.handleAjaxError(xhr, status, error);
- }
-
- deferred.reject();
- });
- }).promise();
- };
var selectedConnections = d3.selectAll('g.connection.selected');
var selectedComponents = d3.selectAll('g.component.selected');
@@ -156,55 +55,30 @@ nf.Draggable = (function () {
// go through each selected connection
selectedConnections.each(function (d) {
- var connectionUpdate = updateConnectionPosition(d);
+ var connectionUpdate = nf.Draggable.updateConnectionPosition(d, delta);
if (connectionUpdate !== null) {
updates.set(d.id, connectionUpdate);
}
});
-
+
// go through each selected component
selectedComponents.each(function (d) {
// consider any self looping connections
var connections = nf.Connection.getComponentConnections(d.id);
$.each(connections, function(_, connection) {
if (!updates.has(connection.id) && nf.CanvasUtils.getConnectionSourceComponentId(connection) === nf.CanvasUtils.getConnectionDestinationComponentId(connection)) {
- var connectionUpdate = updateConnectionPosition(nf.Connection.get(connection.id));
+ var connectionUpdate = nf.Draggable.updateConnectionPosition(nf.Connection.get(connection.id), delta);
if (connectionUpdate !== null) {
updates.set(connection.id, connectionUpdate);
}
}
});
-
+
// consider the component itself
- updates.set(d.id, updateComponentPosition(d));
+ updates.set(d.id, nf.Draggable.updateComponentPosition(d, delta));
});
- // wait for all updates to complete
- $.when.apply(window, updates.values()).done(function () {
- var dragged = $.makeArray(arguments);
- var connections = d3.set();
-
- // refresh this component
- $.each(dragged, function (_, component) {
- // check if the component in question is a connection
- if (component.type === 'Connection') {
- connections.add(component.id);
- } else {
- // get connections that need to be refreshed because its attached to this component
- var componentConnections = nf.Connection.getComponentConnections(component.id);
- $.each(componentConnections, function (_, connection) {
- connections.add(connection.id);
- });
- }
- });
-
- // refresh the connections
- connections.forEach(function (connectionId) {
- nf.Connection.refresh(connectionId);
- });
- }).always(function(){
- nf.Birdseye.refresh();
- });
+ nf.Draggable.refreshConnections(updates);
};
/**
@@ -246,7 +120,7 @@ nf.Draggable = (function () {
// lazily create the drag selection box
if (dragSelection.empty()) {
- // get the current selection
+ // get the current selection
var selection = d3.selectAll('g.component.selected');
// determine the appropriate bounding box
@@ -327,10 +201,159 @@ nf.Draggable = (function () {
dragSelection.remove();
});
},
-
+
+ /**
+ * Update the component's position
+ *
+ * @param d The component
+ * @param delta The change in position
+ * @returns {*}
+ */
+ updateComponentPosition: function(d, delta) {
+ var newPosition = {
+ 'x': d.position.x + delta.x,
+ 'y': d.position.y + delta.y
+ };
+
+ // build the entity
+ var entity = {
+ 'revision': nf.Client.getRevision(d),
+ 'component': {
+ 'id': d.id,
+ 'position': newPosition
+ }
+ };
+
+ // update the component positioning
+ return $.Deferred(function (deferred) {
+ $.ajax({
+ type: 'PUT',
+ url: d.uri,
+ data: JSON.stringify(entity),
+ dataType: 'json',
+ contentType: 'application/json'
+ }).done(function (response) {
+ // update the component
+ nf[d.type].set(response);
+
+ // resolve with an object so we can refresh when finished
+ deferred.resolve({
+ type: d.type,
+ id: d.id
+ });
+ }).fail(function (xhr, status, error) {
+ if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
+ nf.Dialog.showOkDialog({
+ headerText: 'Component Position',
+ dialogContent: nf.Common.escapeHtml(xhr.responseText)
+ });
+ } else {
+ nf.Common.handleAjaxError(xhr, status, error);
+ }
+
+ deferred.reject();
+ });
+ }).promise();
+ },
+
+ /**
+ * Update the connection's position
+ *
+ * @param d The connection
+ * @param delta The change in position
+ * @returns {*}
+ */
+ updateConnectionPosition: function(d, delta) {
+ // only update if necessary
+ if (d.bends.length === 0) {
+ return null;
+ }
+
+ // calculate the new bend points
+ var newBends = $.map(d.bends, function (bend) {
+ return {
+ x: bend.x + delta.x,
+ y: bend.y + delta.y
+ };
+ });
+
+ var entity = {
+ 'revision': nf.Client.getRevision(d),
+ 'component': {
+ id: d.id,
+ bends: newBends
+ }
+ };
+
+ // update the component positioning
+ return $.Deferred(function (deferred) {
+ $.ajax({
+ type: 'PUT',
+ url: d.uri,
+ data: JSON.stringify(entity),
+ dataType: 'json',
+ contentType: 'application/json'
+ }).done(function (response) {
+ // update the component
+ nf.Connection.set(response);
+
+ // resolve with an object so we can refresh when finished
+ deferred.resolve({
+ type: d.type,
+ id: d.id
+ });
+ }).fail(function (xhr, status, error) {
+ if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
+ nf.Dialog.showOkDialog({
+ headerText: 'Component Position',
+ dialogContent: nf.Common.escapeHtml(xhr.responseText)
+ });
+ } else {
+ nf.Common.handleAjaxError(xhr, status, error);
+ }
+
+ deferred.reject();
+ });
+ }).promise();
+ },
+
+ /**
+ * Refresh the connections after dragging a component
+ *
+ * @param updates
+ */
+ refreshConnections: function(updates) {
+ // wait for all updates to complete
+ $.when.apply(window, updates.values()).done(function () {
+ var dragged = $.makeArray(arguments);
+ var connections = d3.set();
+
+ // refresh this component
+ $.each(dragged, function (_, component) {
+ // check if the component in question is a connection
+ if (component.type === 'Connection') {
+ connections.add(component.id);
+ } else {
+ // get connections that need to be refreshed because its attached to this component
+ var componentConnections = nf.Connection.getComponentConnections(component.id);
+ $.each(componentConnections, function (_, connection) {
+ connections.add(connection.id);
+ });
+ }
+ });
+
+ // refresh the connections
+ connections.forEach(function (connectionId) {
+ nf.Connection.refresh(connectionId);
+ });
+ }).always(function(){
+ nf.Birdseye.refresh();
+ });
+ },
+
/**
* Activates the drag behavior for the components in the specified selection.
- *
+ *
* @param {selection} components
*/
activate: function (components) {
@@ -339,7 +362,7 @@ nf.Draggable = (function () {
/**
* Deactivates the drag behavior for the components in the specified selection.
- *
+ *
* @param {selection} components
*/
deactivate: function (components) {