Repository navigation
Expand file tree
/
Copy pathsignalk-multi-switch.html
More file actions
149 lines (134 loc) · 6 KB
/
Copy pathsignalk-multi-switch.html
File metadata and controls
149 lines (134 loc) · 6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<script type="text/javascript">
RED.nodes.registerType('signalk-multi-switch',{
category: 'Signal K',
color: '#ffcc01',
defaults: {
name: {value:""},
path: {value:"", required: true},
displayName: {value:""},
optionType: { value: 'string', required: true },
options: { value: [], required: true }
},
inputs:1,
outputs:1,
outputLabels: [ 'state' ],
inputLabels: [ 'state' ],
icon: "bridge.png",
label: function() {
return this.name||"signalk-multi-switch";
},
paletteLabel: 'multi switch',
oneditprepare: function() {
// Initialize the Editable List widget
$('#node-input-options-container').editableList({
addItem: function (container, i, data) {
// This runs when the "Add" button is clicked
var row = $('<div/>', {
style: 'display: flex; gap: 8px;'
}).appendTo(container);
var titleField = $('<input/>', {
class: "node-input-option-title",
type: "text",
placeholder: "Title",
style: "width: 50%;"
}).appendTo(row);
var valueField = $('<input/>', {
class: "node-input-option-value",
type: "text",
placeholder: "Value",
style: "width: 50%;"
}).appendTo(row);
var optionValue;
if (data.option && typeof data.option === 'object') {
optionValue = data.option.value;
} else {
optionValue = data.option;
}
if (optionValue !== undefined && optionValue !== null) {
valueField.val(String(optionValue));
}
if (data.option && typeof data.option === 'object') {
titleField.val(data.option.title || '');
} else if (data.option) {
titleField.val(data.option);
}
},
sortable: true, // Optional: allows drag-and-drop reordering
removable: true // Adds a delete icon next to each row
});
// Load existing items into the UI when opening the dialog
if (this.options) {
this.options.forEach(function (option) {
$('#node-input-options-container').editableList('addItem', { option: option });
});
}
},
oneditsave: function () {
var node = this;
var optionsList = $('#node-input-options-container').editableList('items');
var validationErrors = [];
var optionType = $('#node-input-optionType').val();
node.options = [];
// Loop through UI rows and save values back to the array
optionsList.each(function (index) {
var optionTitle = $(this).find(".node-input-option-title").val();
var optionRawValue = $(this).find(".node-input-option-value").val().trim();
if (optionRawValue) {
var parsedValue = optionRawValue;
if (optionType === 'number') {
var numValidation = RED.utils.validateTypedProperty(optionRawValue, 'num');
if (numValidation !== true) {
validationErrors.push(index + 1);
return;
}
parsedValue = Number(optionRawValue);
}
node.options.push({
title: optionTitle || optionRawValue,
value: parsedValue
});
}
});
if (validationErrors.length > 0) {
RED.notify(
'Invalid numeric value in option row(s): ' + validationErrors.join(', '),
'error'
);
throw new Error('Invalid option value');
}
}
});
</script>
<script type="text/x-red" data-template-name="signalk-multi-switch">
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-path"><i class="icon-tag"></i> Path</label>
<input type="text" id="node-input-path" placeholder="Path">
</div>
<div class="form-row">
<label for="node-input-displayName"><i class="icon-tag"></i> Display Name</label>
<input type="text" id="node-input-displayName" placeholder="Display Name">
</div>
<div class="form-row">
<label for="node-input-optionType"><i class="icon-tag"></i> Option Type</label>
<select id="node-input-optionType">
<option value="string">string</option>
<option value="number">number</option>
</select>
</div>
<div class="form-row" style="margin-bottom:0px;">
<label><i class="fa fa-cogs"></i> Options</label>
</div>
<div class="form-row node-input-options-container-row">
<ol id="node-input-options-container"></ol>
</div>
</script>
<script type="text/x-red" data-help-name="signalk-multi-switch">
<p>Multi switch for the given path in the Signal K server. ".state" will be appended automatically if not present.</p>
<p>The state of the switch is stored in the global context in a store called skpersist which defaults to localstorage.</p>
<p>The options are defined in the node configuration, and the payload of incoming messages must match one of the options.</p>
<p>All option values must use the selected Option Type.</p>
</script>