mirror of
https://github.com/morris/vanilla-todo.git
synced 2025-08-11 08:33:58 +02:00
mobile improvements
This commit is contained in:
@@ -738,3 +738,7 @@ Projects I've inspected for drag & drop architecture:
|
|||||||
- [React DnD](https://react-dnd.github.io)
|
- [React DnD](https://react-dnd.github.io)
|
||||||
- [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd)
|
- [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd)
|
||||||
- [dragula](https://github.com/bevacqua/dragula)
|
- [dragula](https://github.com/bevacqua/dragula)
|
||||||
|
|
||||||
|
Other interesting articles:
|
||||||
|
|
||||||
|
- [The case for vanilla front-end development (pushdata.io)](https://pushdata.io/blog/1)
|
||||||
|
@@ -8,6 +8,7 @@ VT.AppDraggable = function (el, options) {
|
|||||||
|
|
||||||
var originX, originY;
|
var originX, originY;
|
||||||
var clientX, clientY;
|
var clientX, clientY;
|
||||||
|
var startTime;
|
||||||
var dragging = false;
|
var dragging = false;
|
||||||
var clicked = false;
|
var clicked = false;
|
||||||
var data;
|
var data;
|
||||||
@@ -40,13 +41,75 @@ VT.AppDraggable = function (el, options) {
|
|||||||
function start(e) {
|
function start(e) {
|
||||||
if (el.classList.contains('_nodrag')) return;
|
if (el.classList.contains('_nodrag')) return;
|
||||||
if (e.type === 'mousedown' && e.button !== 0) return;
|
if (e.type === 'mousedown' && e.button !== 0) return;
|
||||||
|
if (e.touches && e.touches.length > 1) return;
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var p = getPositionHost(e);
|
var p = getPositionHost(e);
|
||||||
clientX = originX = p.clientX || p.pageX;
|
clientX = originX = p.clientX || p.pageX;
|
||||||
clientY = originY = p.clientY || p.pageY;
|
clientY = originY = p.clientY || p.pageY;
|
||||||
|
startTime = Date.now();
|
||||||
|
|
||||||
|
startListening();
|
||||||
|
}
|
||||||
|
|
||||||
|
function move(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var p = getPositionHost(e);
|
||||||
|
clientX = p.clientX || p.pageX;
|
||||||
|
clientY = p.clientY || p.pageY;
|
||||||
|
|
||||||
|
if (dragging) {
|
||||||
|
dispatchDrag();
|
||||||
|
dispatchTarget();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var deltaX = clientX - originX;
|
||||||
|
var deltaY = clientY - originY;
|
||||||
|
|
||||||
|
if (Math.abs(deltaX) < dragThreshold && Math.abs(deltaY) < dragThreshold) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent unintentional dragging on touch devices
|
||||||
|
if (e.touches && Date.now() - startTime < 50) {
|
||||||
|
stopListening();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dragging = true;
|
||||||
|
data = {};
|
||||||
|
|
||||||
|
dispatchStart();
|
||||||
|
dispatchDrag();
|
||||||
|
dispatchTarget();
|
||||||
|
dispatchOverContinuously();
|
||||||
|
}
|
||||||
|
|
||||||
|
function end(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
|
||||||
|
if (!dragging) {
|
||||||
|
e.target.click();
|
||||||
|
clicked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopListening();
|
||||||
|
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
clicked = false;
|
||||||
|
|
||||||
|
if (dragging) {
|
||||||
|
dispatchTarget();
|
||||||
|
dispatchEnd();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startListening() {
|
||||||
if (window.navigator.pointerEnabled) {
|
if (window.navigator.pointerEnabled) {
|
||||||
el.addEventListener('pointermove', move);
|
el.addEventListener('pointermove', move);
|
||||||
el.addEventListener('pointerup', end);
|
el.addEventListener('pointerup', end);
|
||||||
@@ -61,40 +124,7 @@ VT.AppDraggable = function (el, options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function move(e) {
|
function stopListening() {
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var p = getPositionHost(e);
|
|
||||||
clientX = p.clientX || p.pageX;
|
|
||||||
clientY = p.clientY || p.pageY;
|
|
||||||
|
|
||||||
if (dragging) return;
|
|
||||||
|
|
||||||
var deltaX = clientX - originX;
|
|
||||||
var deltaY = clientY - originY;
|
|
||||||
|
|
||||||
if (Math.abs(deltaX) < dragThreshold && Math.abs(deltaY) < dragThreshold) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchStart();
|
|
||||||
dispatchLoop();
|
|
||||||
dispatchOver();
|
|
||||||
}
|
|
||||||
|
|
||||||
function end(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
|
|
||||||
if (!dragging) {
|
|
||||||
e.target.click();
|
|
||||||
clicked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
dragging = false;
|
|
||||||
clicked = false;
|
|
||||||
|
|
||||||
if (window.navigator.pointerEnabled) {
|
if (window.navigator.pointerEnabled) {
|
||||||
el.removeEventListener('pointermove', move);
|
el.removeEventListener('pointermove', move);
|
||||||
el.removeEventListener('pointerup', end);
|
el.removeEventListener('pointerup', end);
|
||||||
@@ -107,15 +137,11 @@ VT.AppDraggable = function (el, options) {
|
|||||||
el.removeEventListener('touchmove', move);
|
el.removeEventListener('touchmove', move);
|
||||||
el.removeEventListener('touchend', end);
|
el.removeEventListener('touchend', end);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
function dispatchStart() {
|
function dispatchStart() {
|
||||||
dragging = true;
|
|
||||||
data = {};
|
|
||||||
|
|
||||||
setImage(el);
|
setImage(el);
|
||||||
|
|
||||||
el.dispatchEvent(
|
el.dispatchEvent(
|
||||||
@@ -126,17 +152,6 @@ VT.AppDraggable = function (el, options) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatchLoop() {
|
|
||||||
dispatchDrag();
|
|
||||||
dispatchTarget();
|
|
||||||
|
|
||||||
if (dragging) {
|
|
||||||
requestAnimationFrame(dispatchLoop);
|
|
||||||
} else {
|
|
||||||
dispatchEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function dispatchDrag() {
|
function dispatchDrag() {
|
||||||
image.dispatchEvent(
|
image.dispatchEvent(
|
||||||
new CustomEvent('draggableDrag', {
|
new CustomEvent('draggableDrag', {
|
||||||
@@ -147,6 +162,8 @@ VT.AppDraggable = function (el, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function dispatchTarget() {
|
function dispatchTarget() {
|
||||||
|
if (!dragging) return;
|
||||||
|
|
||||||
var nextTarget = getTarget();
|
var nextTarget = getTarget();
|
||||||
|
|
||||||
if (nextTarget === currentTarget) return;
|
if (nextTarget === currentTarget) return;
|
||||||
@@ -174,6 +191,26 @@ VT.AppDraggable = function (el, options) {
|
|||||||
currentTarget = nextTarget;
|
currentTarget = nextTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dispatchOverContinuously() {
|
||||||
|
if (!dragging) return;
|
||||||
|
|
||||||
|
dispatchOver();
|
||||||
|
setTimeout(dispatchOver, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dispatchOver() {
|
||||||
|
if (currentTarget) {
|
||||||
|
currentTarget.dispatchEvent(
|
||||||
|
new CustomEvent('draggableOver', {
|
||||||
|
detail: buildDetail(),
|
||||||
|
bubbles: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(dispatchOver, 50);
|
||||||
|
}
|
||||||
|
|
||||||
function dispatchEnd() {
|
function dispatchEnd() {
|
||||||
if (currentTarget) {
|
if (currentTarget) {
|
||||||
currentTarget.addEventListener('draggableDrop', cleanUpOnce);
|
currentTarget.addEventListener('draggableDrop', cleanUpOnce);
|
||||||
@@ -193,21 +230,6 @@ VT.AppDraggable = function (el, options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatchOver() {
|
|
||||||
if (!dragging) return;
|
|
||||||
|
|
||||||
if (currentTarget) {
|
|
||||||
currentTarget.dispatchEvent(
|
|
||||||
new CustomEvent('draggableOver', {
|
|
||||||
detail: buildDetail(),
|
|
||||||
bubbles: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(dispatchOver, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
function buildDetail() {
|
function buildDetail() {
|
||||||
|
@@ -10,12 +10,10 @@ VT.TodoItemInput = function (el) {
|
|||||||
var inputEl = el.querySelector('.input');
|
var inputEl = el.querySelector('.input');
|
||||||
var saveEl = el.querySelector('.save');
|
var saveEl = el.querySelector('.save');
|
||||||
|
|
||||||
|
VT.AppLateBlur(inputEl);
|
||||||
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
||||||
|
|
||||||
saveEl.addEventListener('click', save);
|
inputEl.addEventListener('keypress', function (e) {
|
||||||
inputEl.addEventListener('keypress', handleKeypress);
|
|
||||||
|
|
||||||
function handleKeypress(e) {
|
|
||||||
switch (e.keyCode) {
|
switch (e.keyCode) {
|
||||||
case 13: // enter
|
case 13: // enter
|
||||||
save();
|
save();
|
||||||
@@ -24,7 +22,14 @@ VT.TodoItemInput = function (el) {
|
|||||||
clear();
|
clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
inputEl.addEventListener('lateBlur', save);
|
||||||
|
|
||||||
|
saveEl.addEventListener('click', function () {
|
||||||
|
save();
|
||||||
|
inputEl.focus();
|
||||||
|
});
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
var label = inputEl.value.trim();
|
var label = inputEl.value.trim();
|
||||||
@@ -39,7 +44,6 @@ VT.TodoItemInput = function (el) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
inputEl.value = '';
|
inputEl.value = '';
|
||||||
inputEl.focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
.todo-frame {
|
.todo-frame {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,6 +7,12 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
transition: transform 0.2s ease-out, opacity 0.2s ease-out;
|
transition: transform 0.2s ease-out, opacity 0.2s ease-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-item > .checkbox {
|
.todo-item > .checkbox {
|
||||||
|
Reference in New Issue
Block a user