0 Design: Editable port labels
Uma Sudhan P edited this page 2018-07-10 14:45:05 +10:00

There are two types of port labels:

  1. labels that the node definition provides
  2. labels that the user provides

Node defined labels

In a node definition, the new property outputLabels can be specified. (Note: inputLabels also exists and behaves in exactly the same way - for simplicity, we'll only talk about outputLabels from here-on).

outputLabels can be one of three things:

  1. a static string - this will be used as the label for all outputs

  2. an array of strings - each element in the array provides a label to the corresponding output

  3. a function that takes a single argument to identify the index of the output a label should be returned for. The value of this within the function will be the node instance it is being called for. For example:

     outputLabels: function(i) { return this.id+" output #"+i;}
    

User defined labels

A user should be able to set custom labels on any port - whether there are node-defined labels or not. User-defined labels would take precedence over node-defined labels.

Just as a node can define an outputs property that overrides the same property in its definition, a node should be able to provide its own outputLabels property. One key difference will be that, unlike outputs which a node must declare in its defaults list, the outputLabels property will be valid on any node.

The property will take an array of strings. If a value is blank, the node-defined label will be used (if one is provided).

Editing the labels

The edit tray will have a new expandable section for editing port labels. A table will be presented listing each output and allow its label to be set.

There is a complication here. The Switch node (for example) varies its number of outputs based on the number of rules provided. Within the edit dialog there is no overt mention of outputs - it is the dialog's oneditsave function that knows how to map the number of rules over to the outputs property of the node. After adding some rules, when the user switches from the node-properties view to the port-labels view, they would reasonably expect the table of labels to have the appropriate number of entries. Also, and harder still, if a user reorders the rules they would expect the labels to be reordered to match.

It would not be suitable to call oneditsave when switching between the views as that may have unintended side-effects. It would also make undoing the entire edit harder to do.

One option is to allow the user to provide as many or as few labels as they want - to not tie it to the actual number of outputs. That would solve one part of this, but not the reordering question. Overall, it isn't a desirable solution.

That means a mechanism is needed to keep the labels table in sync with any custom action taken in the node edit dialog. There are two cases to consider:

  1. a node lets the user set the number of outputs explicitly - such as the Function node
  2. the number of outputs are derived from some other editable property - such as the Switch node

In the former case, the edit form will have an input called node-input-outputs to hold the current value. That can be used when switching to the node label table to determine how many outputs the node has.

In the latter case, it hasn't been required to maintain a node-input-outputs input, but there is no reason a node couldn't maintain just such an input (as a hidden input).

That would solve both cases by a single mechanism.

What remains is the reordering case.

In 0.16 we introduced the ability for a node to notify the editor that its outputs had been reordered - so that its wires could be reordered to match.

That is done by the oneditsave function setting a property on the node object called _outputs. This is an object that maps existing outputs to their new index. If an existing output has been deleted, it maps to the value -1. For consistency, that principle should be reused here.

If node-input-outputs contains a simple integer, that is taken as the total number of outputs. If it contains a JSON object, it is the equivalent to the _outputs object as described above. In doing so, the editor code will need to be updated handle that. It will super-cede and ultimately replace the _outputs object - an undocumented feature that can be replaced before it is adopted.

As an example, assume that the initial set of outputs are a,b,c,d. Assume that after configuring, the new outputs are z,a,c. The node-input-outputs should now be {"0":"1", "1":"-1", "2":"2", "3":"-1", "someRandomNo":"0"} where someRandomNo is generated from a function like Math.floor((0x99999 - 0x10000) * Math.random()).toString(16) (adapted from node-red sources)