Skip to content

Commit

Permalink
[BasicUI] Fix slider behaviour and implement two different modes
Browse files Browse the repository at this point in the history
Fix openhab#2525
Related to openhab/openhab-core#4084

Two behaviour modes are now supported.
- If releaseOnly attribute is set, the new value is sent to the item only when the slider is released.
- If releaseOnly attribute is unset, new values are sent to the item while moving the slider. Events are sent at a certain frequency, this frequency is defined by the sendFrequency attribute if set or every 200 ms by default.

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
  • Loading branch information
lolodomo committed Apr 19, 2024
1 parent 1232bf5 commit 6d154f1
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 25 deletions.
Expand Up @@ -83,6 +83,7 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th

snippet = preprocessSnippet(snippet, w);
snippet = snippet.replace("%frequency%", frequency);
snippet = snippet.replace("%release_only%", s.isReleaseOnly() ? "true" : "flase");
snippet = snippet.replace("%switch%", s.isSwitchEnabled() ? "1" : "0");
snippet = snippet.replace("%unit%", unit == null ? "" : unit);
snippet = snippet.replace("%minValue%", minValueOf(s));
Expand Down
Expand Up @@ -21,7 +21,8 @@
data-icon-color="%icon_color%"
>
<input
data-freq="%frequency%"
data-send-frequency="%frequency%"
data-release-only="%release_only%"
data-state="%state%"
class="mdl-slider mdl-js-slider"
type="range"
Expand Down
64 changes: 40 additions & 24 deletions bundles/org.openhab.ui.basic/web-src/smarthome.js
Expand Up @@ -296,10 +296,10 @@
callback.apply(null, args);
_t.lock = true;
setTimeout(function() {
_t.lock = false;
if (!finished) {
callback.apply(null, args);
_t.call(callback, callInterval);
}
_t.lock = false;
}, callInterval);
}
};
Expand Down Expand Up @@ -1856,26 +1856,21 @@
setColor(c);
};

// Some browsers fire onchange while the slider handle is being moved.
// This is incorrect, according to the specs, but it's impossible to detect,
// so DebounceProxy is used
function onSliderChange() {
_t.debounceProxy.finish();
_t.hsvValue.v = _t.slider.value / 100;
_t.debounceProxy.call();
callback(_t.hsvValue);
}

function onSliderFinish() {
function onSliderInput() {
_t.hsvValue.v = _t.slider.value / 100;

_t.debounceProxy.call();
_t.debounceProxy.finish();
}

var
eventMap = [
[ _t.slider, "input", onSliderInput ],
[ _t.slider, "change", onSliderChange ],
[ _t.slider, "touchend", onSliderFinish ],
[ _t.slider, "mouseup", onSliderFinish ],
[ _t.image, "mousedown", onMove ],
[ _t.image, "mousemove", onMove ],
[ _t.image, "touchmove", onMove ],
Expand Down Expand Up @@ -2364,9 +2359,13 @@
_t = this;

_t.input = _t.parentNode.querySelector("input[type=range]");
_t.sendFrequency = parseInt(_t.input.getAttribute("data-send-frequency"), 10);
_t.releaseOnly = _t.input.getAttribute("data-release-only") === "true";
_t.hasValue = _t.parentNode.getAttribute("data-has-value") === "true";
_t.valueNode = _t.parentNode.parentNode.querySelector(o.formValue);
_t.locked = false;
_t.lastInputValue = null;
_t.lastEmittedValue = null;

_t.unit = _t.parentNode.getAttribute("data-unit");

Expand All @@ -2385,22 +2384,27 @@
}
})();

function emitEvent() {
var command = _t.input.value;
function emitEvent(value) {
var command = value;
if (_t.unit) {
command = command + " " + _t.unit;
}
window.console.log("emitEvent " + command);
_t.parentNode.dispatchEvent(createEvent("control-change", {
item: _t.item,
value: command
}));
_t.lastEmittedValue = value;
}

_t.debounceProxy = new DebounceProxy(function() {
emitEvent();
}, 200);
if (_t.lastInputValue !== null) {
emitEvent(_t.lastInputValue);
}
}, _t.sendFrequency);

_t.setValuePrivate = function(value, itemState) {
window.console.log("setValuePrivate " + value);
if (_t.hasValue) {
_t.valueNode.innerHTML = value;
}
Expand Down Expand Up @@ -2429,28 +2433,39 @@
unlockTimeout = null;

function onChange() {
window.console.log("onChange " + _t.input.value);
_t.debounceProxy.finish();
if (_t.input.value !== _t.lastEmittedValue) {
emitEvent(_t.input.value);
} else {
window.console.log("onChange -> do nothing");
}
}

function onInput() {
if (_t.releaseOnly) {
return;
}
window.console.log("onInput " + _t.input.value);
_t.lastInputValue = _t.input.value;
_t.debounceProxy.call();
}

function onChangeStart() {
window.console.log("onChangeStart releaseOnly " + _t.releaseOnly + " sendFrequency " + _t.sendFrequency);
if (unlockTimeout !== null) {
clearTimeout(unlockTimeout);
}
_t.locked = true;
smarthome.changeListener.pause();
_t.lastInputValue = null;
_t.lastEmittedValue = null;
}

function onChangeEnd() {
// mouseUp is fired earlier than the value is changed
// quite a dirty hack, but I don't see any other way
_t.debounceProxy.call();
setTimeout(function() {
smarthome.changeListener.resume();
}, 5);
window.console.log("onChangeEnd");
unlockTimeout = setTimeout(function() {
_t.locked = false;
}, 300);
_t.debounceProxy.finish();
}

var
Expand All @@ -2459,7 +2474,8 @@
[ _t.input, "mousedown", onChangeStart ],
[ _t.input, "touchend", onChangeEnd ],
[ _t.input, "mouseup", onChangeEnd ],
[ _t.input, "change", onChange ]
[ _t.input, "change", onChange ],
[ _t.input, "input", onInput ]
];

_t.destroy = function() {
Expand Down

0 comments on commit 6d154f1

Please sign in to comment.