|
190 | 190 | } |
191 | 191 | } |
192 | 192 | function pMP() { // populateMacroPresets |
193 | | - var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions; |
| 193 | + var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions; |
194 | 194 | var fields = ['A0','A1','MC','MN']; |
195 | 195 | for (var f of fields) { |
196 | 196 | var inp = gN(f); |
|
219 | 219 | rPS(sel, presetOpts, "data-preset"); |
220 | 220 | } |
221 | 221 | } |
| 222 | + function bAO() { // buildAnalogOptions: analog functions + per-segment opacity (segment 0 included; MD=0 => segment 0) |
| 223 | + var o = '<optgroup label="Analog Functions"><option value="250">Global brightness (250)</option><option value="249">Effect speed (249)</option><option value="248">Effect intensity (248)</option><option value="247">Palette (247)</option><option value="200">Primary color hue (200)</option></optgroup><optgroup label="Analog Segment Opacity">'; |
| 224 | + for (var j=0; j<=32; j++) o += `<option value="${j}">Segment ${j} opacity</option>`; |
| 225 | + o += '</optgroup>'; |
| 226 | + return o; |
| 227 | + } |
| 228 | + function isAnalogBtn(t) { return t==7 || t==8; } // BTN_TYPE_ANALOG / BTN_TYPE_ANALOG_INVERTED |
| 229 | + function isSwitchBtn(t) { return t==4 || t==5 || t==9; } // BTN_TYPE_SWITCH / BTN_TYPE_PIR_SENSOR / BTN_TYPE_TOUCH_SWITCH |
| 230 | + function btnTypeName(t) { // mirrors the button type dropdown on the LED settings page |
| 231 | + switch (+t) { |
| 232 | + case 2: return 'Pushbutton'; |
| 233 | + case 3: return 'Push inverted'; |
| 234 | + case 4: return 'Switch'; |
| 235 | + case 5: return 'PIR sensor'; |
| 236 | + case 6: return 'Touch'; |
| 237 | + case 7: return 'Analog'; |
| 238 | + case 8: return 'Analog inverted'; |
| 239 | + case 9: return 'Touch (switch)'; |
| 240 | + default: return 'Disabled'; |
| 241 | + } |
| 242 | + } |
222 | 243 | function rBPO() { // refreshButtonPresetOptions |
223 | | - var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions; |
| 244 | + var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions; |
| 245 | + var analogOpts = bAO(); |
224 | 246 | var container = gId("macros"); |
225 | 247 | if (!container) return; |
| 248 | + // analog buttons only have an MD select (MP/ML are hidden 0 inputs); MD uses analog options, never presets |
226 | 249 | var sels = container.querySelectorAll('select[name^="MP"],select[name^="ML"],select[name^="MD"]'); |
227 | 250 | for (var sel of sels) { |
228 | | - rPS(sel, presetOpts, "data-preset"); |
| 251 | + var bb = sel.closest ? sel.closest(".bb") : null; |
| 252 | + var t = bb ? parseInt(bb.getAttribute("data-btype")||"0",10) : 0; |
| 253 | + rPS(sel, isAnalogBtn(t) ? analogOpts : presetOpts, "data-preset"); |
229 | 254 | } |
230 | 255 | } |
231 | 256 | function Wd() |
|
246 | 271 | if (d.Sf.LTR.value==="S") { d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); } |
247 | 272 | if (d.Sf.LNR.value==="W") { d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); } |
248 | 273 | } |
249 | | - function addRow(i,p,l,d) { |
| 274 | + function addRow(i,p,l,d,t) { |
| 275 | + if (t===undefined) t = 0; |
250 | 276 | var b = String.fromCharCode((i<10?48:55)+i); |
251 | | - var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions; |
| 277 | + var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions; |
| 278 | + var typeName = btnTypeName(t); |
252 | 279 | var buttonBlock = document.createElement('div'); |
253 | 280 | buttonBlock.className = 'bb'; |
254 | | - buttonBlock.innerHTML = ` |
255 | | - <div class="bh">Button (switch) ${i}</div> |
256 | | - <div class="bs"> |
257 | | - <div class="ba"> |
258 | | - <label>Short (on → off)</label> |
259 | | - <select name="MP${b}" class="s" required>${presetOpts}</select> |
| 281 | + buttonBlock.setAttribute('data-btype', t); // read back by rBPO() to rebuild selects correctly |
| 282 | + if (isAnalogBtn(t)) { |
| 283 | + // analog buttons: MD holds the function/segment; short/long press are unused (firmware defaults missing MP/ML to 0) |
| 284 | + buttonBlock.innerHTML = ` |
| 285 | + <div class="bh">Analog ${i} - ${typeName}</div> |
| 286 | + <div class="bs"> |
| 287 | + <div class="ba"> |
| 288 | + <label>Analog function</label> |
| 289 | + <select name="MD${b}" class="s" required>${bAO()}</select> |
| 290 | + </div> |
260 | 291 | </div> |
261 | | - <div class="ba"> |
262 | | - <label>Long (off → on)</label> |
263 | | - <select name="ML${b}" class="s" required>${presetOpts}</select> |
| 292 | + <hr style="width:100%;margin:8px 0 0 0;"> |
| 293 | + `; |
| 294 | + sPSV(buttonBlock.querySelector('select[name="MD'+b+'"]'), String(d), "data-preset"); |
| 295 | + } else if (isSwitchBtn(t)) { |
| 296 | + // switches: MP fires on On->Off, ML on Off->On; double press (MD) is unused (firmware defaults missing MD to 0) |
| 297 | + buttonBlock.innerHTML = ` |
| 298 | + <div class="bh">Switch ${i} - ${typeName}</div> |
| 299 | + <div class="bs"> |
| 300 | + <div class="ba"> |
| 301 | + <label>On → Off</label> |
| 302 | + <select name="MP${b}" class="s" required>${presetOpts}</select> |
| 303 | + </div> |
| 304 | + <div class="ba"> |
| 305 | + <label>Off → On</label> |
| 306 | + <select name="ML${b}" class="s" required>${presetOpts}</select> |
| 307 | + </div> |
264 | 308 | </div> |
265 | | - <div class="ba"> |
266 | | - <label>Double press (n/a)</label> |
267 | | - <select name="MD${b}" class="s" required>${presetOpts}</select> |
| 309 | + <hr style="width:100%;margin:8px 0 0 0;"> |
| 310 | + `; |
| 311 | + var switchSels = buttonBlock.querySelectorAll("select"); |
| 312 | + var switchVals = [String(p), String(l)]; |
| 313 | + for (var si=0; si<switchSels.length; si++) { |
| 314 | + sPSV(switchSels[si], switchVals[si], "data-preset"); |
| 315 | + } |
| 316 | + } else { |
| 317 | + // pushbuttons: short (MP), long (ML) and double (MD) press |
| 318 | + buttonBlock.innerHTML = ` |
| 319 | + <div class="bh">Button ${i} - ${typeName}</div> |
| 320 | + <div class="bs"> |
| 321 | + <div class="ba"> |
| 322 | + <label>Short press</label> |
| 323 | + <select name="MP${b}" class="s" required>${presetOpts}</select> |
| 324 | + </div> |
| 325 | + <div class="ba"> |
| 326 | + <label>Long press</label> |
| 327 | + <select name="ML${b}" class="s" required>${presetOpts}</select> |
| 328 | + </div> |
| 329 | + <div class="ba"> |
| 330 | + <label>Double press</label> |
| 331 | + <select name="MD${b}" class="s" required>${presetOpts}</select> |
| 332 | + </div> |
268 | 333 | </div> |
269 | | - </div> |
270 | | - <hr style="width:100%;margin:8px 0 0 0;"> |
271 | | - `; |
272 | | - var buttonSels = buttonBlock.querySelectorAll("select"); |
273 | | - var buttonVals = [String(p), String(l), String(d)]; |
274 | | - for (var si=0; si<buttonSels.length; si++) { |
275 | | - sPSV(buttonSels[si], buttonVals[si], "data-preset"); |
| 334 | + <hr style="width:100%;margin:8px 0 0 0;"> |
| 335 | + `; |
| 336 | + var buttonSels = buttonBlock.querySelectorAll("select"); |
| 337 | + var buttonVals = [String(p), String(l), String(d)]; |
| 338 | + for (var si=0; si<buttonSels.length; si++) { |
| 339 | + sPSV(buttonSels[si], buttonVals[si], "data-preset"); |
| 340 | + } |
276 | 341 | } |
277 | 342 | gId("macros").appendChild(buttonBlock); |
278 | 343 | } |
@@ -372,7 +437,7 @@ <h3>Timer & Alexa Presets</h3> |
372 | 437 | Alexa On/Off Preset: <input name="A0" class="m" type="number" min="0" max="250" required> <input name="A1" class="m" type="number" min="0" max="250" required><br> |
373 | 438 | </div> |
374 | 439 | <div class="sec"> |
375 | | - <h3>Button (switch) Action Presets</h3> |
| 440 | + <h3>Button Action Presets</h3> |
376 | 441 | <div id="macros"></div> |
377 | 442 | <a href="https://kno.wled.ge/features/macros/#analog-button" target="_blank">Analog Button setup</a> |
378 | 443 | </div> |
|
0 commit comments