apankrat / nullboard

Nullboard is a minimalist kanban board, focused on compactness and readability.
https://nullboard.io/preview
Other
2.52k stars 197 forks source link

Touch support #58

Open 4jag opened 2 years ago

4jag commented 2 years ago

It seems that touch is not supported, both on mobile screens and on desktop (laptops).

Looking through the scripts, I'm not clear whether you included the code of an existing drag-and-drop framework, or rolled your own. Is it Dragster? (Maybe an older version? I see the word "dragsters" in there, but the latest Dragster supports touch screens).

I was hoping to update the drag/drop code to support touch, but I just thought I ask first so I might find a better starting point.

Thank you!

4jag commented 2 years ago

Without getting too fancy, doubling up on the mouse events with equivalent touch events, a-la below, almost gets there, but when dragging with touch the note snaps to a place outside any droppable containers and then touch looses hold of the note position.

    $('.wrap').on('mousedown touchstart', '.board .note .text', function(ev){
        NB.noteDrag.prime(this.parentNode, ev);
    });

    $('.config').on('mousedown touchstart', 'a.load-board', function(ev){
        if ($('.config a.load-board').length > 1)
            NB.loadDrag.prime(this, ev);
    });

    $('.config').on('mousedown touchstart', '.ui-fs .val', function(ev){
        var org = getFontSize();
        NB.varAdjust.start(ev, function(delta){ setFontSize( org + delta/50. ); }, saveUiPrefs);
    });

    $('.config').on('mousedown touchstart', '.ui-lh .val', function(ev){
        var org = getLineHeight();
        NB.varAdjust.start(ev, function(delta){ setLineHeight( org + delta/50. ); }, saveUiPrefs);
    });

    $('.config').on('mousedown touchstart', '.ui-lw .val', function(ev){
        var org = getListWidth();
        NB.varAdjust.start(ev, function(delta){ setListWidth( org + delta/5. ); }, saveUiPrefs);
    });

    $(document).on('mouseup touchend', function(ev){
        NB.noteDrag.end();
        NB.loadDrag.end();
        NB.varAdjust.end();
    });

    $(document).on('mousemove', function(ev){
        setRevealState(ev);
        NB.noteDrag.onMouseMove(ev);
        NB.loadDrag.onMouseMove(ev);
        NB.varAdjust.onMouseMove(ev);
    });

        // Different function because need touches[] function
    $(document).on('touchmove', function(ev) {
        setRevealState(ev);
        NB.noteDrag.onTouchMove(ev);
        NB.loadDrag.onTouchMove(ev);
        NB.varAdjust.onTouchMove(ev);
    });

    this.onTouchMove = function(ev)
    {
        this.mouseEv = ev;

        if (! this.item)
            return;

        if (this.priming)
        {
            var touch = ev.touches[0];
            var x = touch.clientX;
            var y = touch.clientY;
                if (x*x + y*y > 5*5)
                    this.onPrimed();
        }
        else
        {
            this.adjustDrag();
        }
    }

EDIT

I don't have a fix yet, but I read that the x/y coords are different for touchmove, so onTouchMove becomes:

    var touch = ev.touches[0];
    var x = touch.clientX;
    var y = touch.clientY;

But more importantly touchmove events stop after the DOM is modified. So once the drag element is removed from the DOM the touchmove event ends and no touchend fires.

From: Why touchmove event is not fired after DOM changes?: "The target of this event must be the same Element on which the touch point started when it was first placed on the surface, even if the touch point has since moved outside the interactive area of the target element."

Ref: https://www.w3.org/TR/touch-events/#the-touchmove-event

And...

I think this is what's needed for onTouchMove (I cloned onMouseMove, and changed it to support x/y for touch) is what's described in ZitRo's SO post: https://stackoverflow.com/a/45760014