Managing single, double and long press on a button with javascript

I wanted to share a function to manage single Press, Double press and Long Press in javascript.

1/ Place this code in file named PressHandler.js (after replacing xxx with your user name) in your js directory :

/// <reference path="C:/Users/xxx/AppData/Roaming/Elgato/StreamDeck/Plugins/se.trevligaspel.midi.sdPlugin/ScriptJint/streamdeck-midi.d.ts" />

const tSuffix = "_pt";
const LONG_PRESS_MS = 400;

// Internal state for the single button
let clickCount = 0;
let isPressed = false;
let longFired = false;

// Callback references
let singlePressFn = null;
let doublePressFn = null;
let longPressFn = null;

// Store the last registered button name
let buttonNameGlobal = "";

/**
 * Register the single button
 * Returns the _pt timer name
 */
function registerButton(buttonName, singlePress, doublePress, longPress) {
    buttonNameGlobal = buttonName;
    singlePressFn = singlePress;
    doublePressFn = doublePress;
    longPressFn = longPress;

    // ✅ return the press timer name
    return buttonName + tSuffix;
}

/**
 * Handle press/release events
 */
function ButtonHandler(event) {
    if (!buttonNameGlobal) return;

    const tname = buttonNameGlobal + tSuffix;

    if (event === "press") {
        isPressed = true;

        if (clickCount === 0) {
            longFired = false;
            timer.reset(tname);
            timer.restart(tname, LONG_PRESS_MS);
        }
    } 
    else if (event === "release") {
        isPressed = false;

        if (!longFired) clickCount++;
    }
}

/**
 * Timer callback
 */
function handleTimerElapsed(tname, isGlobal, time) {
    if (!buttonNameGlobal) return;
    if (tname !== buttonNameGlobal + tSuffix) return;

    const count = clickCount;
    clickCount = 0; // reset first

    if (isPressed && longPressFn) {
        longPressFn();
        longFired = true;
    } 
    else if (count === 1 && singlePressFn) {
        singlePressFn();
    } 
    else if (count >= 2 && doublePressFn) {
        doublePressFn();
    }

    timer.reset(tname);
}

module.exports = {registerButton, ButtonHandler, handleTimerElapsed};

Then create a scripted button and use this template (after replacing xxx with your user name).
Customize singlePress(), doublePress() and longPress() functions to your liking:

/// <reference path="C:/Users/xxx/AppData/Roaming/Elgato/StreamDeck/Pluginsse.trevligaspel.midi.sdPlugin/ScriptJint/streamdeck-midi.d.ts" />
const{registerButton, ButtonHandler, handleTimerElapsed} = require("./PressHandler.js");
const bName = "PressTest";
const bName_dt = bName + "_dt";
const DISP_MS = 1500;
let longActive = false;
ui.text("Start");


function OnInit() {ui.text("Init")}

// Register button
const bName_pt = registerButton(bName, singlePress, doublePress, longPress);



// Callbacks for single Press, Double Press or Long Press
function singlePress() { ui.text("Single Press"); timer.restart(bName_dt, DISP_MS);}
function doublePress() { ui.text("Double Press"); timer.restart(bName_dt, DISP_MS);}
function longPress()   { 
    ui.text("Long Press"); 
    longActive = true;   // mark long press active
}



// Stream Deck events
function OnKeyPressed() {ButtonHandler("press");}
function OnKeyReleased() {
    ButtonHandler("release");
    if (longActive) {
            longActive = false;
            //timer.reset(bName_dt);
            timer.restart(bName_dt, DISP_MS);
    }
}
function OnTimerElapsed(tname, isGlobal, time) {
    switch(tname) {
        case bName_pt: handleTimerElapsed(tname, isGlobal, time); break;
        case bName_dt: {
            ui.text("Idle");
            timer.reset(bName_dt);
            break;
        }
        default: return;
    }
}

et voilà !
I have tested it but use at your own risk.

1 Like