Browse Source

webui: update colorpicker

ref. https://github.com/xoseperez/espurna/issues/1132#issuecomment-431868924
it is slightly bigger, but better looking and no jquery dependency

rework colorpicker style as well, hide to prevent sending garbage when
lights are off. update lights module to send `lightState()` and separate
state from status payloads

yes, input[type="color"] is an option, but it does not look good
mcspr-patch-1
Maxim Prokhorov 3 years ago
parent
commit
808981ca39
26 changed files with 24389 additions and 24317 deletions
  1. BIN
      code/espurna/data/index.all.html.gz
  2. BIN
      code/espurna/data/index.curtain.html.gz
  3. BIN
      code/espurna/data/index.garland.html.gz
  4. BIN
      code/espurna/data/index.light.html.gz
  5. BIN
      code/espurna/data/index.lightfox.html.gz
  6. BIN
      code/espurna/data/index.rfbridge.html.gz
  7. BIN
      code/espurna/data/index.rfm69.html.gz
  8. BIN
      code/espurna/data/index.sensor.html.gz
  9. BIN
      code/espurna/data/index.small.html.gz
  10. BIN
      code/espurna/data/index.thermostat.html.gz
  11. +2
    -2
      code/espurna/light.cpp
  12. +3252
    -3131
      code/espurna/static/index.all.html.gz.h
  13. +2112
    -2111
      code/espurna/static/index.curtain.html.gz.h
  14. +2074
    -2074
      code/espurna/static/index.garland.html.gz.h
  15. +3001
    -2883
      code/espurna/static/index.light.html.gz.h
  16. +2089
    -2089
      code/espurna/static/index.lightfox.html.gz.h
  17. +2113
    -2113
      code/espurna/static/index.rfbridge.html.gz.h
  18. +3496
    -3496
      code/espurna/static/index.rfm69.html.gz.h
  19. +2159
    -2159
      code/espurna/static/index.sensor.html.gz.h
  20. +2061
    -2061
      code/espurna/static/index.small.html.gz.h
  21. +1956
    -1956
      code/espurna/static/index.thermostat.html.gz.h
  22. +9
    -0
      code/html/custom.css
  23. +56
    -58
      code/html/custom.js
  24. +9
    -17
      code/html/index.html
  25. +0
    -161
      code/html/vendor/jquery.wheelcolorpicker-3.0.8.css
  26. +0
    -6
      code/html/vendor/jquery.wheelcolorpicker-3.0.8.min.js

BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.curtain.html.gz View File


BIN
code/espurna/data/index.garland.html.gz View File


BIN
code/espurna/data/index.light.html.gz View File


BIN
code/espurna/data/index.lightfox.html.gz View File


BIN
code/espurna/data/index.rfbridge.html.gz View File


BIN
code/espurna/data/index.rfm69.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


BIN
code/espurna/data/index.small.html.gz View File


BIN
code/espurna/data/index.thermostat.html.gz View File


+ 2
- 2
code/espurna/light.cpp View File

@ -1274,6 +1274,7 @@ void _lightWebSocketStatus(JsonObject& root) {
channels.add(lightChannel(id)); channels.add(lightChannel(id));
} }
root["brightness"] = lightBrightness(); root["brightness"] = lightBrightness();
root["lightstate"] = lightState();
} }
void _lightWebSocketOnVisible(JsonObject& root) { void _lightWebSocketOnVisible(JsonObject& root) {
@ -1294,8 +1295,6 @@ void _lightWebSocketOnConnected(JsonObject& root) {
#if RELAY_SUPPORT #if RELAY_SUPPORT
root["ltRelay"] = getSetting("ltRelay", 1 == LIGHT_RELAY_ENABLED); root["ltRelay"] = getSetting("ltRelay", 1 == LIGHT_RELAY_ENABLED);
#endif #endif
_lightWebSocketStatus(root);
} }
void _lightWebSocketOnAction(uint32_t client_id, const char * action, JsonObject& data) { void _lightWebSocketOnAction(uint32_t client_id, const char * action, JsonObject& data) {
@ -1842,6 +1841,7 @@ void lightSetup() {
wsRegister() wsRegister()
.onVisible(_lightWebSocketOnVisible) .onVisible(_lightWebSocketOnVisible)
.onConnected(_lightWebSocketOnConnected) .onConnected(_lightWebSocketOnConnected)
.onData(_lightWebSocketStatus)
.onAction(_lightWebSocketOnAction) .onAction(_lightWebSocketOnAction)
.onKeyCheck(_lightWebSocketOnKeyCheck); .onKeyCheck(_lightWebSocketOnKeyCheck);
#endif #endif


+ 3252
- 3131
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 2112
- 2111
code/espurna/static/index.curtain.html.gz.h
File diff suppressed because it is too large
View File


+ 2074
- 2074
code/espurna/static/index.garland.html.gz.h
File diff suppressed because it is too large
View File


+ 3001
- 2883
code/espurna/static/index.light.html.gz.h
File diff suppressed because it is too large
View File


+ 2089
- 2089
code/espurna/static/index.lightfox.html.gz.h
File diff suppressed because it is too large
View File


+ 2113
- 2113
code/espurna/static/index.rfbridge.html.gz.h
File diff suppressed because it is too large
View File


+ 3496
- 3496
code/espurna/static/index.rfm69.html.gz.h
File diff suppressed because it is too large
View File


+ 2159
- 2159
code/espurna/static/index.sensor.html.gz.h
File diff suppressed because it is too large
View File


+ 2061
- 2061
code/espurna/static/index.small.html.gz.h
File diff suppressed because it is too large
View File


+ 1956
- 1956
code/espurna/static/index.thermostat.html.gz.h
File diff suppressed because it is too large
View File


+ 9
- 0
code/html/custom.css View File

@ -408,6 +408,15 @@ input[disabled] + .toggle .toggle__handler {
text-decoration: none; text-decoration: none;
} }
/* -----------------------------------------------------------------------------
Home panel
-------------------------------------------------------------------------- */
#color {
padding-bottom: 1em;
padding-top: 1em;
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
RF Bridge panel RF Bridge panel
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */


+ 56
- 58
code/html/custom.js View File

@ -14,8 +14,11 @@ var numReload = 0;
var configurationSaved = false; var configurationSaved = false;
var ws_pingpong; var ws_pingpong;
//removeIf(!light)
var colorPicker;
var useWhite = false; var useWhite = false;
var useCCT = false; var useCCT = false;
//endRemoveIf(!light)
var now = 0; var now = 0;
var ago = 0; var ago = 0;
@ -1149,7 +1152,7 @@ function initRelays(data) {
}); });
$("label.toggle", line) $("label.toggle", line)
.prop("for", "relay" + id)
.prop("for", "relay" + id);
line.appendTo("#relays"); line.appendTo("#relays");
@ -1331,68 +1334,68 @@ function initCurtainConfig(data) {
//removeIf(!light) //removeIf(!light)
// wheelColorPicker accepts:
// hsv(0...360,0...1,0...1)
// hsv(0...100%,0...100%,0...100%)
// While we use:
// hsv(0...360,0...100%,0...100%)
function _hsv_round(value) {
return Math.round(value * 100) / 100;
function colorToHsvString(color) {
var h = String(Math.round(color.hsv.h));
var s = String(Math.round(color.hsv.s));
var v = String(Math.round(color.hsv.v));
return h + "," + s + "," + v;
} }
function getPickerRGB(picker) {
return $(picker).wheelColorPicker("getValue", "css");
function hsvStringToColor(hsv) {
var parts = hsv.split(",");
return {
h: parseInt(parts[0]),
s: parseInt(parts[1]),
v: parseInt(parts[2])
};
} }
function setPickerRGB(picker, value) {
$(picker).wheelColorPicker("setValue", value, true);
function colorSlider(type) {
return {component: iro.ui.Slider, options: {sliderType: type}};
} }
// TODO: use pct values instead of doing conversion?
function getPickerHSV(picker) {
var color = $(picker).wheelColorPicker("getColor");
return String(Math.ceil(_hsv_round(color.h) * 360))
+ "," + String(Math.ceil(_hsv_round(color.s) * 100))
+ "," + String(Math.ceil(_hsv_round(color.v) * 100));
function colorWheel() {
return {component: iro.ui.Wheel, options: {}};
} }
function setPickerHSV(picker, value) {
if (value === getPickerHSV(picker)) return;
var chunks = value.split(",");
$(picker).wheelColorPicker("setColor", {
h: _hsv_round(chunks[0] / 360),
s: _hsv_round(chunks[1] / 100),
v: _hsv_round(chunks[2] / 100)
});
function colorBox() {
return {component: iro.ui.Box, options: {}};
} }
function initColor(cfg) {
var rgb = false;
if (typeof cfg === "object") {
rgb = cfg.rgb;
function updateColor(mode, value) {
if (colorPicker) {
if (mode === "rgb") {
colorPicker.color.hexString = value;
} else if (mode === "hsv") {
colorPicker.color.hsv = hsvStringToColor(value);
}
return;
} }
// check if already initialized
var done = $("#colors > div").length;
if (done > 0) { return; }
// TODO: useRGB -> ltWheel?
// TODO: always show wheel + sliders like before?
var layout = []
if (mode === "rgb") {
layout.push(colorWheel());
layout.push(colorSlider("value"));
} else if (mode === "hsv") {
layout.push(colorBox());
layout.push(colorSlider("hue"));
}
// add template
var template = $("#colorTemplate").children();
var line = $(template).clone();
line.appendTo("#colors");
// init color wheel
$("input[name='color']").wheelColorPicker({
sliders: (rgb ? "wrgbp" : "whsp")
}).on("sliderup", function() {
if (rgb) {
sendAction("color", {rgb: getPickerRGB(this)});
} else {
sendAction("color", {hsv: getPickerHSV(this)});
var options = {
color: (mode === "rgb") ? value : hsvStringToColor(value),
layout: layout
};
colorPicker = new iro.ColorPicker("#color", options);
colorPicker.on("input:change", function(color) {
if (mode === "rgb") {
sendAction("color", {rgb: color.hexString});
} else if (mode === "hsv") {
sendAction("color", {hsv: colorToHsvString(color)});
} }
}); });
} }
function initCCT() { function initCCT() {
@ -1417,12 +1420,9 @@ function initChannels(num) {
var done = $("#channels > div").length > 0; var done = $("#channels > div").length > 0;
if (done) { return; } if (done) { return; }
// does it have color channels?
var colors = $("#colors > div").length > 0;
// calculate channels to create // calculate channels to create
var max = num; var max = num;
if (colors) {
if (colorPicker) {
max = num % 3; max = num % 3;
if ((max > 0) & useWhite) { if ((max > 0) & useWhite) {
max--; max--;
@ -1798,15 +1798,13 @@ function processData(data) {
//removeIf(!light) //removeIf(!light)
if ("rgb" === key) {
initColor({rgb: true});
setPickerRGB($("input[name='color']"), value);
if ("lightstate" === key) {
$("#color").toggle(value);
return; return;
} }
if ("hsv" === key) {
initColor({hsv: true});
setPickerHSV($("input[name='color']"), value);
if (("rgb" === key) || ("hsv" === key)) {
updateColor(key, value);
return; return;
} }


+ 9
- 17
code/html/index.html View File

@ -11,9 +11,6 @@
<link rel="stylesheet" href="vendor/pure-1.0.0.min.css" /> <link rel="stylesheet" href="vendor/pure-1.0.0.min.css" />
<link rel="stylesheet" href="vendor/pure-grids-responsive-1.0.0.min.css" /> <link rel="stylesheet" href="vendor/pure-grids-responsive-1.0.0.min.css" />
<link rel="stylesheet" href="vendor/side-menu.css" /> <link rel="stylesheet" href="vendor/side-menu.css" />
<!-- removeIf(!light) -->
<link rel="stylesheet" href="vendor/jquery.wheelcolorpicker-3.0.8.css" />
<!-- endRemoveIf(!light) -->
<!-- removeIf(!rfm69) --> <!-- removeIf(!rfm69) -->
<link rel="stylesheet" href="vendor/datatables-1.10.16.css" /> <link rel="stylesheet" href="vendor/datatables-1.10.16.css" />
<!-- endRemoveIf(!rfm69) --> <!-- endRemoveIf(!rfm69) -->
@ -240,13 +237,12 @@
<div id="relays"></div> <div id="relays"></div>
<!-- removeIf(!curtain) -->
<div id="curtains"></div>
<!-- endRemoveIf(!curtain) -->
<!-- removeIf(!light) --> <!-- removeIf(!light) -->
<div id="colors"></div>
<div id="color"></div>
<div id="cct"></div> <div id="cct"></div>
<!-- endRemoveIf(!light) -->
<!-- removeIf(!light) -->
<div id="channels"></div> <div id="channels"></div>
<!-- endRemoveIf(!light) --> <!-- endRemoveIf(!light) -->
@ -254,6 +250,10 @@
<div id="magnitudes"></div> <div id="magnitudes"></div>
<!-- endRemoveIf(!sensor) --> <!-- endRemoveIf(!sensor) -->
<!-- removeIf(!curtain) -->
<div id="curtains"></div>
<!-- endRemoveIf(!curtain) -->
<!-- removeIf(!rfm69) --> <!-- removeIf(!rfm69) -->
<div class="pure-g module module-rfm69"> <div class="pure-g module module-rfm69">
<label class="pure-u-1 pure-u-lg-1-4">Packet count</label> <label class="pure-u-1 pure-u-lg-1-4">Packet count</label>
@ -2176,14 +2176,6 @@
<!-- endRemoveIf(!sensor) --> <!-- endRemoveIf(!sensor) -->
<!-- removeIf(!light) --> <!-- removeIf(!light) -->
<div id="colorTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Color</label>
<input class="pure-u-1 pure-u-lg-1-4" data-wcp-layout="block" name="color" readonly />
</div>
</div>
<div id="brightnessTemplate" class="template"> <div id="brightnessTemplate" class="template">
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Brightness</label> <label class="pure-u-1 pure-u-lg-1-4">Brightness</label>
@ -2281,7 +2273,7 @@
<script src="vendor/jquery-3.4.1.slim.min.js"></script> <script src="vendor/jquery-3.4.1.slim.min.js"></script>
<script src="custom.js"></script> <script src="custom.js"></script>
<!-- removeIf(!light) --> <!-- removeIf(!light) -->
<script src="vendor/jquery.wheelcolorpicker-3.0.8.min.js"></script>
<script src="vendor/iro-5.3.1.min.js"></script>
<!-- endRemoveIf(!light) --> <!-- endRemoveIf(!light) -->
<!-- removeIf(!rfm69) --> <!-- removeIf(!rfm69) -->
<script src="vendor/datatables-1.10.16.min.js"></script> <script src="vendor/datatables-1.10.16.min.js"></script>


+ 0
- 161
code/html/vendor/jquery.wheelcolorpicker-3.0.8.css View File

@ -1,161 +0,0 @@
/**
* Wheel Color Picker for jQuery
* Base Stylesheet
*
* https://raffer.one/projects/jquery-wheelcolorpicker
*
* Copyright © 2011-2019 Fajar Chandra. All rights reserved.
* Released under MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
* Note: Width, height, left, and top properties are handled by the
* plugin. These values might change on the fly.
*/
.jQWCP-wWidget {
position: absolute;
width: 250px;
height: 180px;
background: #eee;
box-shadow: 1px 1px 4px rgba(0,0,0,.5);
border-radius: 4px;
border: solid 1px #aaa;
padding: 10px;
z-index: 1001;
touch-action: none;
}
.jQWCP-wWidget.jQWCP-block {
position: relative;
border-color: #aaa;
box-shadow: inset 1px 1px 1px #ccc;
}
.jQWCP-wWheel {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
position: relative;
float: left;
width: 180px;
height: 180px;
-webkit-border-radius: 90px;
-moz-border-radius: 50%;
border-radius: 50%;
border: solid 1px #aaa;
margin: -1px;
margin-right: 10px;
transition: border .15s;
cursor: crosshair;
}
.jQWCP-wWheel:hover {
border-color: #666;
}
.jQWCP-wWheelOverlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
opacity: 0;
-webkit-border-radius: 90px;
-moz-border-radius: 50%;
border-radius: 50%;
}
.jQWCP-wWheelCursor {
width: 8px;
height: 8px;
position: absolute;
top: 50%;
left: 50%;
margin: -6px -6px;
cursor: crosshair;
border: solid 2px #fff;
box-shadow: 1px 1px 2px #000;
border-radius: 50%;
}
.jQWCP-slider-wrapper,
.jQWCP-wPreview {
position: relative;
width: 20px;
height: 180px;
float: left;
margin-right: 10px;
}
.jQWCP-wWheel:last-child,
.jQWCP-slider-wrapper:last-child,
.jQWCP-wPreview:last-child {
margin-right: 0;
}
.jQWCP-slider,
.jQWCP-wPreviewBox {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
box-sizing: border-box;
border: solid 1px #aaa;
margin: -1px;
-moz-border-radius: 4px;
border-radius: 4px;
transition: border .15s;
}
.jQWCP-slider {
cursor: crosshair;
}
.jQWCP-slider-wrapper:hover .jQWCP-slider {
border-color: #666;
}
.jQWCP-scursor {
position: absolute;
left: 0;
top: 0;
right: 0;
height: 6px;
margin: -5px -1px -5px -3px;
cursor: crosshair;
border: solid 2px #fff;
box-shadow: 1px 1px 2px #000;
border-radius: 4px;
}
.jQWCP-wAlphaSlider,
.jQWCP-wPreviewBox {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEVAQEB/f39eaJUuAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QYRBDgK9dKdMgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAARSURBVAjXY/jPwIAVYRf9DwB+vw/x6vMT1wAAAABJRU5ErkJggg==') center center;
}
.jQWCP-overlay {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 1000;
}
/*********************/
/* Mobile layout */
.jQWCP-mobile.jQWCP-wWidget {
position: fixed;
bottom: 0;
left: 0 !important;
top: auto !important;
width: 100%;
height: 75%;
max-height: 240px;
box-sizing: border-box;
border-radius: 0;
}

+ 0
- 6
code/html/vendor/jquery.wheelcolorpicker-3.0.8.min.js
File diff suppressed because it is too large
View File


Loading…
Cancel
Save