-
-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add DnD for mobile #699
base: master
Are you sure you want to change the base?
Add DnD for mobile #699
Changes from 8 commits
b5ad480
418675b
d8b9fc5
a1a34a6
32c8c55
dd86325
1892e10
984d543
fafb89b
06706ec
2ef4a4c
cb36af3
40c8c57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,181 @@ | ||
namespace $.$$ { | ||
|
||
/** | ||
* @see https://mol.hyoo.ru/#!section=demos/demo=mol_drag_demo | ||
*/ | ||
export class $mol_drag extends $.$mol_drag { | ||
|
||
@ $mol_mem | ||
status( next = 'ready' as 'ready' | 'drag' ) { return next } | ||
|
||
drag_start( event : DragEvent ) { | ||
|
||
setTimeout( ()=> this.status( 'drag' ) ) | ||
|
||
const transfer = this.transfer() | ||
for( let type in transfer ) { | ||
event.dataTransfer!.setData( type , transfer[ type as keyof typeof transfer] ) | ||
} | ||
|
||
event.dataTransfer!.setDragImage( this.image() , 0 , -32 ) | ||
|
||
const effects = [] as string[] | ||
if( this.allow_copy() ) effects.push( 'Copy' ) | ||
if( this.allow_link() ) effects.push( 'Link' ) | ||
if( this.allow_move() ) effects.push( 'Move' ) | ||
|
||
let effectAllowed = effects[0].toLowerCase() + effects.slice(1).join('') | ||
if( effectAllowed === 'copyLinkMove' ) effectAllowed = 'all' | ||
event.dataTransfer!.effectAllowed = effectAllowed as DataTransfer['effectAllowed'] | ||
|
||
this.start( event ) | ||
|
||
} | ||
|
||
drag_end( event : DragEvent ) { | ||
setTimeout( ()=> this.status( 'ready' ) ) | ||
this.end( event ) | ||
} | ||
|
||
} | ||
} | ||
/** | ||
* @see https://mol.hyoo.ru/#!section=demos/demo=mol_drag_demo | ||
*/ | ||
export class $mol_drag extends $.$mol_drag { | ||
private dragged_task: HTMLElement | null = null; | ||
private initial_task_index: number | null = null; | ||
private draggedOverElem: HTMLElement | null = null; | ||
private dragImageElem: HTMLElement | null = null; | ||
|
||
@$mol_mem | ||
status(next = "ready" as "ready" | "drag") { | ||
return next; | ||
} | ||
|
||
drag_start(event: DragEvent | TouchEvent) { | ||
if (event instanceof TouchEvent) { | ||
this.handle_touch_start(event); | ||
return; | ||
} | ||
|
||
setTimeout(() => this.status("drag")); | ||
|
||
this.dragged_task = event.target as HTMLElement; | ||
this.initial_task_index = Array.from( | ||
this.dragged_task.parentElement!.children | ||
).indexOf(this.dragged_task); | ||
|
||
const transfer = this.transfer(); | ||
for (let type in transfer) { | ||
(event as DragEvent).dataTransfer!.setData( | ||
type, | ||
transfer[type as keyof typeof transfer] | ||
); | ||
} | ||
|
||
(event as DragEvent).dataTransfer!.setDragImage(this.image(), 0, -32); | ||
|
||
const effects = [] as string[]; | ||
if (this.allow_copy()) effects.push("Copy"); | ||
if (this.allow_link()) effects.push("Link"); | ||
if (this.allow_move()) effects.push("Move"); | ||
|
||
let effectAllowed = effects[0].toLowerCase() + effects.slice(1).join(""); | ||
if (effectAllowed === "copyLinkMove") effectAllowed = "all"; | ||
(event as DragEvent).dataTransfer!.effectAllowed = | ||
effectAllowed as DataTransfer["effectAllowed"]; | ||
|
||
this.start(event as DragEvent); | ||
} | ||
|
||
drag_move(event: DragEvent | TouchEvent) { | ||
if (event instanceof TouchEvent) { | ||
this.handle_touch_move(event); | ||
return; | ||
} | ||
|
||
event.preventDefault(); | ||
|
||
const draggedOverElem = document.elementFromPoint( | ||
event.clientX, | ||
event.clientY | ||
); | ||
if ( | ||
draggedOverElem && | ||
draggedOverElem !== this.dragged_task && | ||
draggedOverElem.parentElement === this.dragged_task!.parentElement | ||
) { | ||
const parent = this.dragged_task!.parentElement; | ||
const draggedOverIndex = Array.from(parent!.children).indexOf( | ||
draggedOverElem as HTMLElement | ||
); | ||
|
||
if (draggedOverIndex !== this.initial_task_index) { | ||
parent!.insertBefore(this.dragged_task!, draggedOverElem); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't make any direct changes to the DOM. Instead, we set values for props and the components render the DOM. |
||
this.initial_task_index = draggedOverIndex; | ||
} | ||
} | ||
} | ||
|
||
drag_end(event: DragEvent | TouchEvent) { | ||
if (event instanceof TouchEvent) { | ||
this.handle_touch_end(event); | ||
return; | ||
} | ||
|
||
setTimeout(() => this.status("ready")); | ||
|
||
this.dragged_task = null; | ||
this.initial_task_index = null; | ||
|
||
this.end(event as DragEvent); | ||
} | ||
|
||
handle_touch_start(event: TouchEvent) { | ||
event.preventDefault(); | ||
this.status("drag"); | ||
|
||
this.dragged_task = event.target as HTMLElement; | ||
this.initial_task_index = Array.from( | ||
this.dragged_task!.parentElement!.children | ||
).indexOf(this.dragged_task); | ||
|
||
this.dragImageElem = this.dragged_task.cloneNode(true) as HTMLElement; | ||
|
||
this.dragImageElem.style.position = "absolute"; | ||
this.dragImageElem.style.pointerEvents = "none"; | ||
this.dragImageElem.style.zIndex = "9999"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Also I suggest not to clone the dragged element, it may be large and this may cause glitches since the cloned elements will have the same ids. |
||
this.dragImageElem.style.color = "var(--mol_theme_focus)"; | ||
|
||
document.body.appendChild(this.dragImageElem); | ||
|
||
const touch = event.touches[0]; | ||
this.moveDragImage(touch.clientX, touch.clientY); | ||
|
||
this.start(event); | ||
} | ||
|
||
handle_touch_move(event: TouchEvent) { | ||
event.preventDefault(); | ||
|
||
const touch = event.touches[0]; | ||
const draggedOverElem = document.elementFromPoint( | ||
touch.clientX, | ||
touch.clientY | ||
); | ||
|
||
if (this.dragImageElem) { | ||
this.moveDragImage(touch.clientX, touch.clientY); | ||
} | ||
|
||
this.draggedOverElem = draggedOverElem as HTMLElement; | ||
|
||
if ( | ||
draggedOverElem && | ||
draggedOverElem !== this.dragged_task && | ||
draggedOverElem.parentElement === this.dragged_task!.parentElement | ||
) { | ||
const parent = this.dragged_task!.parentElement; | ||
const draggedOverIndex = Array.from(parent!.children).indexOf( | ||
draggedOverElem as HTMLElement | ||
); | ||
|
||
if (draggedOverIndex !== this.initial_task_index) { | ||
parent!.insertBefore(this.dragged_task!, draggedOverElem); | ||
this.initial_task_index = draggedOverIndex; | ||
} | ||
} | ||
} | ||
|
||
handle_touch_end(event: TouchEvent) { | ||
if (this.draggedOverElem) { | ||
if ( | ||
this.draggedOverElem.id == | ||
"$hyoo_mol.Root(0).Demos().Widget('$mol_drag_demo').Trash()" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will only work for Anyway, this should be handled in |
||
) { | ||
this.dragged_task?.remove(); | ||
} | ||
} | ||
|
||
if (this.dragImageElem) { | ||
this.dragImageElem.remove(); | ||
this.dragImageElem = null; | ||
} | ||
|
||
this.draggedOverElem = null; | ||
this.dragged_task = null; | ||
this.initial_task_index = null; | ||
this.status("ready"); | ||
this.end(event); | ||
} | ||
|
||
moveDragImage(x: number, y: number) { | ||
if (this.dragImageElem) { | ||
this.dragImageElem.style.left = `${x + 50}px`; | ||
this.dragImageElem.style.top = `${y + 50}px`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. -50, -50 would be better, I can't see the object under my finger :) |
||
} | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no info about the dragged element, this is the work for
$mol_drop
. The new position of the passed element must be determined by$mol_drop
.$mol_drag
don't move element before drop.If we want a component that immediately changes the position of elements when the pointer is moved, it will be a different component, not
$mol_drag
.