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
Also related to openhab/openhab-core#4084 and openhab/openhab-core#3430

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 ccfd1ef
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 27 deletions.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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: 38 additions & 26 deletions bundles/org.openhab.ui.basic/web-src/smarthome.js
Original file line number Diff line number Diff line change
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,6 +2359,8 @@
_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;
Expand All @@ -2385,22 +2382,34 @@
}
})();

function emitEvent() {
var command = _t.input.value;
var
unlockTimeout = null,
lastSentCmd = null;

function emitEvent(value) {
if (value === lastSentCmd) {
window.console.log("emitEvent -> unchanged command");
return;
}

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
}));
lastSentCmd = value;
}

_t.debounceProxy = new DebounceProxy(function() {
emitEvent();
}, 200);
emitEvent(_t.input.value);
}, _t.sendFrequency);

_t.setValuePrivate = function(value, itemState) {
window.console.log("setValuePrivate " + value);
if (_t.hasValue) {
_t.valueNode.innerHTML = value;
}
Expand All @@ -2425,32 +2434,34 @@
_t.valueNode.style.color = smarthome.UI.adjustColorToTheme(_t.valueColor);
};

var
unlockTimeout = null;

function onChange() {
window.console.log("onChange " + _t.input.value);
_t.debounceProxy.finish();
emitEvent(_t.input.value);
}

function onInput() {
if (_t.releaseOnly) {
return;
}
window.console.log("onInput " + _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();
lastSentCmd = 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,6 +2470,7 @@
[ _t.input, "mousedown", onChangeStart ],
[ _t.input, "touchend", onChangeEnd ],
[ _t.input, "mouseup", onChangeEnd ],
[ _t.input, "input", onInput ],
[ _t.input, "change", onChange ]
];

Expand Down

0 comments on commit ccfd1ef

Please sign in to comment.