From c4783101a0ec08cdcb81f46a0f10da543dd3c14f Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Thu, 17 Aug 2023 17:16:49 +0300 Subject: [PATCH] reworked toolbar dragging (still disabled)... Signed-off-by: Alex A. Naanou --- grid-n-view.js | 202 ++++++++++++++++++++++++++++++------------------- 1 file changed, 123 insertions(+), 79 deletions(-) diff --git a/grid-n-view.js b/grid-n-view.js index d4fd03a..365984f 100644 --- a/grid-n-view.js +++ b/grid-n-view.js @@ -152,6 +152,113 @@ var getTouch = function(evt, id){ return evt.targetTouches[k] } } } } +// XXX need to check if element already set as movable... +var moveable = function(elem, options={}){ + if(elem.dataset.movable){ + throw new Error('element already movable.') } + elem.dataset.movable = true + var { + cls, + handle, + bounds, + start = function(elem, data){ + bounds + ?? (data.bounds = bounds) + return data }, + beforeMove, + move = function(elem, data){ + elem.style.left = data.x + 'px' + elem.style.top = data.y + 'px' + }, + end, + } = options + handle = typeof(handle) == 'string' ? + elem.querySelector(handle) + : handle instanceof Element ? + handle + : elem + var data + + var handleMoveStart = function(evt){ + evt.preventDefault() + evt.stopPropagation() + if(!data){ + cls + && elem.classList.add(cls) + var x = evt.clientX + ?? evt.targetTouches[0].clientX + var y = evt.clientY + ?? evt.targetTouches[0].clientY + data = { + bounds: false, + offset: { + x: x - elem.offsetLeft, + y: y - elem.offsetTop, + }, + touch: evt.targetTouches ? + evt.targetTouches[0].identifier + : undefined, + } + if(typeof(start) == 'function'){ + var res = start(elem, data) + data = res != null ? + res + : data } } } + var handleMove = function(evt){ + if(data){ + var src = data.touch != null ? + getTouch(evt, data.touch) + : evt + if(!src){ + return } + evt.preventDefault() + evt.stopPropagation() + var x = src.clientX + var y = src.clientY + data.x = + data.bounds != null ? + Math.min(data.bounds.right, + Math.max(data.bounds.left, + x - data.offset.x)) + : x - data.offset.x + data.y = + data.bounds != null ? + Math.min(data.bounds.bottom, + Math.max(data.bounds.top, + y - data.offset.y)) + : y - data.offset.y + // NOTE: we only allow a single requestAnimationFrame(..) + // to run per frame... + if(!data.animate){ + data.animate = requestAnimationFrame(function(){ + if(!data){ + return } + move(elem, data) + delete data.animate }) } } } + var handleMoveEnd = function(evt){ + if(data){ + if(evt.targetTouches + && (evt.targetTouches.length == 0 + || getTouch(evt, data.touch))){ + return } + evt.preventDefault() + evt.stopPropagation() + cls + && elem.classList.remove(cls) + end + && end(elem, data) + data = false } } + + // XXX can we reuse these??? + // ...i.e. keep the data in the element??? + handle.addEventListener('mousedown', handleMoveStart) + handle.addEventListener('touchstart', handleMoveStart) + document.addEventListener('mousemove', handleMove) + document.addEventListener('touchmove', handleMove) + document.addEventListener('touchend', handleMoveEnd) + document.addEventListener('mouseup', handleMoveEnd) } + + //--------------------------------------------------------------------- // XXX add shift+arrow to select... @@ -947,87 +1054,24 @@ var Gallery = { toolbar.addEventListener('mouseover', toolbarAutoHideCancel) toolbar.addEventListener('touchstart', toolbarAutoHideCancel) - /* XXX problems: - // - too many interactions: autohide, placement, ... - // - not sure if we need this... + /* XXX needs more tweaking... // toolbar: move... - var handleToolbarMoveStart = function(evt){ - evt.preventDefault() - evt.stopPropagation() - if(!toolbar_moving){ - toolbar.classList.add('moving') - var x = evt.clientX - ?? evt.targetTouches[0].clientX - var y = evt.clientY - ?? evt.targetTouches[0].clientY - toolbar_moving = { - bounds: { - x: that.dom.offsetWidth - toolbar.offsetWidth - 20, - // XXX this gets off on high magnifications... - y: that.dom.offsetHeight - toolbar.offsetHeight - 20, - }, - offset: { - x: x - toolbar.offsetLeft, - y: y - toolbar.offsetTop, - }, - touch: evt.targetTouches ? - evt.targetTouches[0].identifier - : undefined, - } } } - var handleToolbarMoveEnd = function(evt){ - if(toolbar_moving){ - if(evt.targetTouches - && (evt.targetTouches.length == 0 - || getTouch(evt, toolbar_moving.touch))){ - return } - evt.preventDefault() - evt.stopPropagation() - toolbar.classList.remove('moving') - toolbar_moving = false } } - // XXX ignore non-local touches... - // XXX disable button clicking while moving... - var handleToolbarMove = function(evt){ - if(toolbar_moving){ - var src = toolbar_moving.touch != null ? - getTouch(evt, toolbar_moving.touch) - : evt - if(!src){ - return } - evt.preventDefault() - evt.stopPropagation() - var x = src.clientX - var y = src.clientY - toolbar_moving.x = - toolbar_moving.bounds?.x != null ? - Math.min(toolbar_moving.bounds.x, - Math.max(0, - x - toolbar_moving.offset.x)) - : x - toolbar_moving.offset.x - toolbar_moving.y = - toolbar_moving.bounds?.y != null ? - Math.min(toolbar_moving.bounds.y, - Math.max(0, - y - toolbar_moving.offset.y)) - : y - toolbar_moving.offset.y - // NOTE: we only allow a single requestAnimationFrame(..) - // to run per frame... - if(!toolbar_moving.animate){ - toolbar_moving.animate = requestAnimationFrame(function(){ - if(!toolbar_moving){ - return } - toolbar.style.setProperty('--move-x', toolbar_moving.x + 'px') - toolbar.style.setProperty('--move-y', toolbar_moving.y + 'px') - delete toolbar_moving.animate }) } } } - // XXX to drag anywhere on the toolbar we need to prevent + // XXX to drag anywhere on the elem we need to prevent // clicks while dragging... - toolbar.querySelector('.drag-handle') - .addEventListener('mousedown', handleToolbarMoveStart) - toolbar.querySelector('.drag-handle') - .addEventListener('touchstart', handleToolbarMoveStart) - this.dom.addEventListener('mousemove', handleToolbarMove) - this.dom.addEventListener('touchmove', handleToolbarMove) - document.addEventListener('touchend', handleToolbarMoveEnd) - document.addEventListener('mouseup', handleToolbarMoveEnd) + moveable(toolbar, { + cls: 'moving', + handle: '.drag-handle', + // set bounds... + start: function(elem, data){ + data.bounds = { + top: 0, + left: 0, + right: that.dom.offsetWidth - elem.offsetWidth - 20, + bottom: that.dom.offsetHeight - elem.offsetHeight - 20, + } }, + move: function(elem, data){ + elem.style.setProperty('--move-x', data.x + 'px') + elem.style.setProperty('--move-y', data.y + 'px') }, }) //*/ // image clicks...