mirror of
https://github.com/s00500/ESPUI.git
synced 2024-11-24 07:20:53 +00:00
Support dynamic enabling and disabling of controls
See documentation in README for how this works. This commit handles all the main controls. Pads are not yet supported.
This commit is contained in:
parent
7dcf6a10f4
commit
896dc97c75
31
README.md
31
README.md
@ -37,6 +37,7 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker,
|
|||||||
- [Advanced Features](#advanced-features)
|
- [Advanced Features](#advanced-features)
|
||||||
* [Dynamic Visibility](#dynamic-visibility)
|
* [Dynamic Visibility](#dynamic-visibility)
|
||||||
* [Inline Styles](#inline-styles)
|
* [Inline Styles](#inline-styles)
|
||||||
|
* [Disabling Controls](#disabling-controls)
|
||||||
* [Grouped controls](#grouped-controls)
|
* [Grouped controls](#grouped-controls)
|
||||||
* [Wide controls](#wide-controls)
|
* [Wide controls](#wide-controls)
|
||||||
* [Graph (Experimental)](#graph--experimental-)
|
* [Graph (Experimental)](#graph--experimental-)
|
||||||
@ -470,6 +471,36 @@ The [completeExample](examples/completeExample/completeExample.cpp) example incl
|
|||||||
![More Inline Styles](docs/ui_inlinestyles2.png)
|
![More Inline Styles](docs/ui_inlinestyles2.png)
|
||||||
|
|
||||||
|
|
||||||
|
### Disabling Controls
|
||||||
|
|
||||||
|
It is possible to dynamically enable and disable controls to, for example, provide feedback to the user that a particular feature is
|
||||||
|
temporarily unavailable. To do this use the following function call:
|
||||||
|
|
||||||
|
```
|
||||||
|
ESPUI.setEnabled(controlId, enabled);
|
||||||
|
```
|
||||||
|
|
||||||
|
Setting `enabled` to false will make the control noninteractive and it will visually change to illustrate this to the user. The control
|
||||||
|
will stop firing any events. Note that whilst the widget will change appearance, the panel of the control will remain whatever colour
|
||||||
|
it was set to. If you wish to also change the colour of the panel then you should use inline styles to show the noninteractive state. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
ESPUI.setEnabled(mainButton, false);
|
||||||
|
const String disabledstyle = "background-color: #bbb; border-bottom: #999 3px solid;";
|
||||||
|
ESPUI.setPanelStyle(mainButton, disabledstyle);
|
||||||
|
```
|
||||||
|
|
||||||
|
This CSS style sets the panel background and its border to grey. To put the control back to enabled use the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
ESPUI.setEnabled(mainButton, true);
|
||||||
|
ESPUI.setPanelStyle(mainButton, ";");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that we have to set the inline style to `";"` (i.e. an empty CSS rule) because if we just try to set it to `""` this will be
|
||||||
|
interpreted as "do not change the style".
|
||||||
|
|
||||||
|
Controls can also be set to disabled before the UI is started.
|
||||||
|
|
||||||
### Grouped controls
|
### Grouped controls
|
||||||
|
|
||||||
|
@ -422,7 +422,7 @@ button {
|
|||||||
background-color: #999999;
|
background-color: #999999;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:active {
|
button:enabled:active {
|
||||||
background-color: #666666;
|
background-color: #666666;
|
||||||
transform: translateX(4px) translateY(4px);
|
transform: translateX(4px) translateY(4px);
|
||||||
}
|
}
|
||||||
@ -1148,3 +1148,46 @@ text {
|
|||||||
.vert-slider span {
|
.vert-slider span {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Styles to implement disabled controls */
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
color: #333;
|
||||||
|
background-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
select:disabled {
|
||||||
|
color: #333;
|
||||||
|
background-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:disabled {
|
||||||
|
color: #333;
|
||||||
|
background-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-slider__range:disabled {
|
||||||
|
background-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-slider__range:disabled::-webkit-slider-thumb {
|
||||||
|
background-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-slider__range:disabled::-moz-range-thumb {
|
||||||
|
background-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch.disabled .in::before {
|
||||||
|
background:#bbb;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch.disabled .in::after {
|
||||||
|
background:#bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch.checked.disabled {
|
||||||
|
background: #b1d092;
|
||||||
|
}
|
||||||
|
2
data/css/style.min.css
vendored
2
data/css/style.min.css
vendored
File diff suppressed because one or more lines are too long
55
data/js/controls.js
vendored
55
data/js/controls.js
vendored
@ -568,7 +568,13 @@ function start() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.type >= UI_TITEL && data.type < UPDATE_OFFSET) {
|
||||||
|
//A UI element was just added to the DOM
|
||||||
|
processEnabled(data);
|
||||||
|
}
|
||||||
|
|
||||||
if (data.type >= UPDATE_OFFSET && data.type < UI_INITIAL_GUI) {
|
if (data.type >= UPDATE_OFFSET && data.type < UI_INITIAL_GUI) {
|
||||||
|
//An "update" message was just recieved and processed
|
||||||
var element = $("#id" + data.id);
|
var element = $("#id" + data.id);
|
||||||
|
|
||||||
if(data.hasOwnProperty('panelStyle')) {
|
if(data.hasOwnProperty('panelStyle')) {
|
||||||
@ -593,6 +599,8 @@ function start() {
|
|||||||
);
|
);
|
||||||
element.addClass(colorClass(data.color));
|
element.addClass(colorClass(data.color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processEnabled(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".range-slider__range").each(function(){
|
$(".range-slider__range").each(function(){
|
||||||
@ -816,4 +824,49 @@ var elementHTML = function(data) {
|
|||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var processEnabled = function(data) {
|
||||||
|
//Handle the enabling and disabling of controls
|
||||||
|
//Most controls can be disabled through the use of $("#<item>").prop("disabled", true) and CSS will style it accordingly
|
||||||
|
//The switcher also requires the addition of the "disabled" class
|
||||||
|
switch(data.type) {
|
||||||
|
case UI_SWITCHER:
|
||||||
|
case UPDATE_SWITCHER:
|
||||||
|
if(data.enabled) {
|
||||||
|
$("#sl" + data.id).removeClass('disabled');
|
||||||
|
$("#s" + data.id).prop("disabled", false);
|
||||||
|
} else {
|
||||||
|
$("#sl" + data.id).addClass('disabled');
|
||||||
|
$("#s" + data.id).prop("disabled", true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SLIDER:
|
||||||
|
case UPDATE_SLIDER:
|
||||||
|
$("#sl" + data.id).prop("disabled", !data.enabled);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_NUMBER:
|
||||||
|
case UPDATE_NUMBER:
|
||||||
|
$("#num" + data.id).prop("disabled", !data.enabled);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_TEXT_INPUT:
|
||||||
|
case UPDATE_TEXT_INPUT:
|
||||||
|
$("#text" + data.id).prop("disabled", !data.enabled);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SELECT:
|
||||||
|
case UPDATE_SELECT:
|
||||||
|
$("#select" + data.id).prop("disabled", !data.enabled);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_BUTTON:
|
||||||
|
case UPDATE_BUTTON:
|
||||||
|
$("#btn" + data.id).prop("disabled", !data.enabled);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
8
data/js/controls.min.js
vendored
8
data/js/controls.min.js
vendored
@ -40,11 +40,13 @@ break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);if(data.hasOwnProp
|
|||||||
break;case UPDATE_BUTTON:$("#btn"+data.id).val(data.value);$("#btn"+data.id).text(data.value);if(data.hasOwnProperty('elementStyle')){$("#btn"+data.id).attr("style",data.elementStyle);}
|
break;case UPDATE_BUTTON:$("#btn"+data.id).val(data.value);$("#btn"+data.id).text(data.value);if(data.hasOwnProperty('elementStyle')){$("#btn"+data.id).attr("style",data.elementStyle);}
|
||||||
break;case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#gauge"+data.id).attr("style",data.elementStyle);}
|
break;case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#gauge"+data.id).attr("style",data.elementStyle);}
|
||||||
break;case UPDATE_ACCEL:break;case UPDATE_TIME:var rv=new Date().toISOString();websock.send("time:"+rv+":"+data.id);break;default:console.error("Unknown type or event");break;}
|
break;case UPDATE_ACCEL:break;case UPDATE_TIME:var rv=new Date().toISOString();websock.send("time:"+rv+":"+data.id);break;default:console.error("Unknown type or event");break;}
|
||||||
|
if(data.type>=UI_TITEL&&data.type<UPDATE_OFFSET){processEnabled(data);}
|
||||||
if(data.type>=UPDATE_OFFSET&&data.type<UI_INITIAL_GUI){var element=$("#id"+data.id);if(data.hasOwnProperty('panelStyle')){$("#id"+data.id).attr("style",data.panelStyle);}
|
if(data.type>=UPDATE_OFFSET&&data.type<UI_INITIAL_GUI){var element=$("#id"+data.id);if(data.hasOwnProperty('panelStyle')){$("#id"+data.id).attr("style",data.panelStyle);}
|
||||||
if(data.hasOwnProperty('visible')){if(data['visible'])
|
if(data.hasOwnProperty('visible')){if(data['visible'])
|
||||||
$("#id"+data.id).show();else
|
$("#id"+data.id).show();else
|
||||||
$("#id"+data.id).hide();}
|
$("#id"+data.id).hide();}
|
||||||
if(data.type==UPDATE_SLIDER){element.removeClass("slider-turquoise slider-emerald slider-peterriver slider-wetasphalt slider-sunflower slider-carrot slider-alizarin");element.addClass("slider-"+colorClass(data.color));}else{element.removeClass("turquoise emerald peterriver wetasphalt sunflower carrot alizarin");element.addClass(colorClass(data.color));}}
|
if(data.type==UPDATE_SLIDER){element.removeClass("slider-turquoise slider-emerald slider-peterriver slider-wetasphalt slider-sunflower slider-carrot slider-alizarin");element.addClass("slider-"+colorClass(data.color));}else{element.removeClass("turquoise emerald peterriver wetasphalt sunflower carrot alizarin");element.addClass(colorClass(data.color));}
|
||||||
|
processEnabled(data);}
|
||||||
$(".range-slider__range").each(function(){$(this)[0].value=$(this).attr("value");$(this).next().html($(this).attr("value"));});};websock.onmessage=handleEvent;}
|
$(".range-slider__range").each(function(){$(this)[0].value=$(this).attr("value");$(this).next().html($(this).attr("value"));});};websock.onmessage=handleEvent;}
|
||||||
function sliderchange(number){var val=$("#sl"+number).val();websock.send("slvalue:"+val+":"+number);$(".range-slider__range").each(function(){$(this).attr("value",$(this)[0].value);});}
|
function sliderchange(number){var val=$("#sl"+number).val();websock.send("slvalue:"+val+":"+number);$(".range-slider__range").each(function(){$(this).attr("value",$(this)[0].value);});}
|
||||||
function numberchange(number){var val=$("#num"+number).val();websock.send("nvalue:"+val+":"+number);}
|
function numberchange(number){var val=$("#num"+number).val();websock.send("nvalue:"+val+":"+number);}
|
||||||
@ -94,4 +96,6 @@ data.value+"</span></div>";case UI_NUMBER:return"<input style='color:black;' "+e
|
|||||||
"' value='"+data.value+"' onchange='textchange("+id+")' />";case UI_SELECT:return"<select style='color:black;' "+elementStyle+" id='select"+id+
|
"' value='"+data.value+"' onchange='textchange("+id+")' />";case UI_SELECT:return"<select style='color:black;' "+elementStyle+" id='select"+id+
|
||||||
"' onchange='selectchange("+id+")' />";case UI_GRAPH:return"<figure id='graph"+id+"'><figcaption>"+data.label+"</figcaption></figure>";case UI_GAUGE:return"WILL BE A GAUGE <input style='color:black;' id='gauge"+id+
|
"' onchange='selectchange("+id+")' />";case UI_GRAPH:return"<figure id='graph"+id+"'><figcaption>"+data.label+"</figcaption></figure>";case UI_GAUGE:return"WILL BE A GAUGE <input style='color:black;' id='gauge"+id+
|
||||||
"' type='number' value='"+data.value+"' onchange='numberchange("+id+")' />";case UI_ACCEL:return"ACCEL // Not implemented fully!<div class='accelerometer' id='accel"+id+
|
"' type='number' value='"+data.value+"' onchange='numberchange("+id+")' />";case UI_ACCEL:return"ACCEL // Not implemented fully!<div class='accelerometer' id='accel"+id+
|
||||||
"' ><div class='ball"+id+"'></div><pre class='accelerometeroutput"+id+"'></pre>";default:return"";}}
|
"' ><div class='ball"+id+"'></div><pre class='accelerometeroutput"+id+"'></pre>";default:return"";}}
|
||||||
|
var processEnabled=function(data){switch(data.type){case UI_SWITCHER:case UPDATE_SWITCHER:if(data.enabled){$("#sl"+data.id).removeClass('disabled');$("#s"+data.id).prop("disabled",false);}else{$("#sl"+data.id).addClass('disabled');$("#s"+data.id).prop("disabled",true);}
|
||||||
|
break;case UI_SLIDER:case UPDATE_SLIDER:$("#sl"+data.id).prop("disabled",!data.enabled);break;case UI_NUMBER:case UPDATE_NUMBER:$("#num"+data.id).prop("disabled",!data.enabled);break;case UI_TEXT_INPUT:case UPDATE_TEXT_INPUT:$("#text"+data.id).prop("disabled",!data.enabled);break;case UI_SELECT:case UPDATE_SELECT:$("#select"+data.id).prop("disabled",!data.enabled);break;case UI_BUTTON:case UPDATE_BUTTON:$("#btn"+data.id).prop("disabled",!data.enabled);break;}}
|
@ -783,6 +783,7 @@ void ESPUIClass::updateControl(Control* control, int clientId)
|
|||||||
root["id"] = control->id;
|
root["id"] = control->id;
|
||||||
root["visible"] = control->visible;
|
root["visible"] = control->visible;
|
||||||
root["color"] = (int)control->color;
|
root["color"] = (int)control->color;
|
||||||
|
root["enabled"] = control->enabled;
|
||||||
if (control->panelStyle != 0)
|
if (control->panelStyle != 0)
|
||||||
root["panelStyle"] = control->panelStyle;
|
root["panelStyle"] = control->panelStyle;
|
||||||
if (control->elementStyle != 0)
|
if (control->elementStyle != 0)
|
||||||
@ -855,6 +856,16 @@ void ESPUIClass::setPanelWide(uint16_t id, bool wide) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ESPUIClass::setEnabled(uint16_t id, bool enabled, int clientId) {
|
||||||
|
Control* control = getControl(id);
|
||||||
|
if (control)
|
||||||
|
{
|
||||||
|
control->enabled = enabled;
|
||||||
|
updateControl(control, clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ESPUIClass::setVertical(uint16_t id, bool vert) {
|
void ESPUIClass::setVertical(uint16_t id, bool vert) {
|
||||||
Control* control = getControl(id);
|
Control* control = getControl(id);
|
||||||
if (control)
|
if (control)
|
||||||
@ -1108,6 +1119,7 @@ void ESPUIClass::prepareJSONChunk(AsyncWebSocketClient* client, uint16_t startin
|
|||||||
item["value"] = String(control->value);
|
item["value"] = String(control->value);
|
||||||
item["color"] = (int)control->color;
|
item["color"] = (int)control->color;
|
||||||
item["visible"] = (int)control->visible;
|
item["visible"] = (int)control->visible;
|
||||||
|
item["enabled"] = control->enabled;
|
||||||
if (control->panelStyle != 0)
|
if (control->panelStyle != 0)
|
||||||
item["panelStyle"] = String(control->panelStyle);
|
item["panelStyle"] = String(control->panelStyle);
|
||||||
if (control->elementStyle != 0)
|
if (control->elementStyle != 0)
|
||||||
|
@ -142,6 +142,7 @@ public:
|
|||||||
bool visible;
|
bool visible;
|
||||||
bool wide;
|
bool wide;
|
||||||
bool vertical;
|
bool vertical;
|
||||||
|
bool enabled;
|
||||||
uint16_t parentControl;
|
uint16_t parentControl;
|
||||||
String panelStyle;
|
String panelStyle;
|
||||||
String elementStyle;
|
String elementStyle;
|
||||||
@ -301,6 +302,8 @@ public:
|
|||||||
|
|
||||||
void setPanelWide(uint16_t id, bool wide);
|
void setPanelWide(uint16_t id, bool wide);
|
||||||
void setVertical(uint16_t id, bool vert = true);
|
void setVertical(uint16_t id, bool vert = true);
|
||||||
|
void setEnabled(uint16_t id, bool enabled = true, int clientId = -1);
|
||||||
|
|
||||||
void updateVisibility(uint16_t id, bool visibility, int clientId = -1);
|
void updateVisibility(uint16_t id, bool visibility, int clientId = -1);
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user