@mrvanosh/mcp23x17
Version:
MCP23x17 library that works in newest Node.js versions
80 lines (73 loc) • 2.37 kB
JavaScript
module.exports = class Button {
_doubleClicks = [];
_clicks = [];
_longClicks = [];
constructor(input, options) {
const opt = {
doubleClickThreshold: 300,
longClickThreshold: 1000,
...options,
}
const isPulledUp = input.isPulledUp();
let lastChange; let timer; let isDouble; let longClickTimer;
input.onChange((value) => {
// Invert value if input is pulled up
value = isPulledUp ? !value : value;
let diff = 0;
if (lastChange) {
diff = (new Date()).getTime() - lastChange;
}
// filter debouncing
if (diff && diff < 20) {
return;
}
if (value) {
// validate double click, if pause between click is less then doubleClickThreshold
if (diff && diff < opt.doubleClickThreshold && this._doubleClicks.length) {
isDouble = true;
timer && clearTimeout(timer);
timer = undefined;
} else {
// set up timeout to control holding button
longClickTimer = setTimeout(() => {
this._invoke(this._longClicks);
longClickTimer && clearTimeout(longClickTimer);
longClickTimer = undefined;
}, opt.longClickThreshold);
}
} else {
// release timer if button was released before time longClickThreshold is reached
if (longClickTimer) {
longClickTimer && clearTimeout(longClickTimer);
longClickTimer = undefined;
}
if (isDouble) {
this._invoke(this._doubleClicks);
isDouble = false;
} else if (diff < opt.longClickThreshold) { // Don't execute click if long click has been occurred
// if double click is expected, let's wait second click, otherwise execute immediately
if (this._doubleClicks.length) {
timer = setTimeout(() => {
this._invoke(this._clicks);
}, opt.doubleClickThreshold + 1)
} else {
this._invoke(this._clicks);
}
}
}
lastChange = new Date().getTime();
})
}
_invoke(callbacks) {
callbacks.map((callback) => callback())
}
onDoubleClick(callback) {
this._doubleClicks.push(callback);
}
onLongClick(callback) {
this._longClicks.push(callback);
}
onClick(callback) {
this._clicks.push(callback);
}
}