@@ -16,44 +16,54 @@ export default class extends Controller {
1616 await nextFrame ( )
1717 this . dragItem = this . #itemContaining( event . target )
1818 this . sourceContainer = this . #containerContaining( this . dragItem )
19+ this . originalDraggedItemCssVariable = this . #containerCssVariableFor( this . sourceContainer )
1920 this . dragItem . classList . add ( this . draggedItemClass )
2021 }
2122
2223 dragOver ( event ) {
2324 event . preventDefault ( )
25+ if ( ! this . dragItem ) { return }
26+
2427 const container = this . #containerContaining( event . target )
2528 this . #clearContainerHoverClasses( )
2629
2730 if ( ! container ) { return }
2831
2932 if ( container !== this . sourceContainer ) {
3033 container . classList . add ( this . hoverContainerClass )
34+ this . #applyContainerCssVariable( container )
35+ } else {
36+ this . #restoreOriginalDraggedItemCssVariable( )
3137 }
3238 }
3339
3440 async drop ( event ) {
35- const container = this . #containerContaining( event . target )
41+ const targetContainer = this . #containerContaining( event . target )
3642
37- if ( ! container || container === this . sourceContainer ) { return }
43+ if ( ! targetContainer || targetContainer === this . sourceContainer ) { return }
3844
3945 this . wasDropped = true
46+ this . #increaseCounter( targetContainer )
4047 this . #decreaseCounter( this . sourceContainer )
48+
4149 const sourceContainer = this . sourceContainer
42- await this . #submitDropRequest( this . dragItem , container )
43- this . #reloadSourceFrame( sourceContainer ) ;
50+ this . #insertDraggedItem( targetContainer , this . dragItem )
51+ await this . #submitDropRequest( this . dragItem , targetContainer )
52+ this . #reloadSourceFrame( sourceContainer )
4453 }
4554
4655 dragEnd ( ) {
4756 this . dragItem . classList . remove ( this . draggedItemClass )
4857 this . #clearContainerHoverClasses( )
4958
50- if ( this . wasDropped ) {
51- this . dragItem . remove ( )
59+ if ( ! this . wasDropped ) {
60+ this . #restoreOriginalDraggedItemCssVariable ( )
5261 }
5362
5463 this . sourceContainer = null
5564 this . dragItem = null
5665 this . wasDropped = false
66+ this . originalDraggedItemCssVariable = null
5767 }
5868
5969 #itemContaining( element ) {
@@ -68,30 +78,73 @@ export default class extends Controller {
6878 this . containerTargets . forEach ( container => container . classList . remove ( this . hoverContainerClass ) )
6979 }
7080
71- async #submitDropRequest( item , container ) {
72- const body = new FormData ( )
73- const id = item . dataset . id
74- const url = container . dataset . dragAndDropUrl . replaceAll ( "__id__" , id )
81+ #applyContainerCssVariable( container ) {
82+ const cssVariable = this . #containerCssVariableFor( container )
83+ if ( cssVariable ) {
84+ this . dragItem . style . setProperty ( cssVariable . name , cssVariable . value )
85+ }
86+ }
7587
76- return post ( url , { body, headers : { Accept : "text/vnd.turbo-stream.html" } } )
88+ #restoreOriginalDraggedItemCssVariable( ) {
89+ if ( this . originalDraggedItemCssVariable ) {
90+ const { name, value } = this . originalDraggedItemCssVariable
91+ this . dragItem . style . setProperty ( name , value )
92+ }
7793 }
7894
79- #reloadSourceFrame( sourceContainer ) {
80- const frame = sourceContainer . querySelector ( "[data-drag-and-drop-refresh]" )
81- if ( frame ) frame . reload ( )
95+ #containerCssVariableFor( container ) {
96+ const { dragAndDropCssVariableName, dragAndDropCssVariableValue } = container . dataset
97+ if ( dragAndDropCssVariableName && dragAndDropCssVariableValue ) {
98+ return { name : dragAndDropCssVariableName , value : dragAndDropCssVariableValue }
99+ }
100+ return null
101+ }
102+
103+ #increaseCounter( container ) {
104+ this . #modifyCounter( container , count => count + 1 )
105+ }
106+
107+ #decreaseCounter( container ) {
108+ this . #modifyCounter( container , count => Math . max ( 0 , count - 1 ) )
82109 }
83110
84- #decreaseCounter ( sourceContainer ) {
85- const counterElement = sourceContainer . querySelector ( "[data-drag-and-drop-counter]" )
111+ #modifyCounter ( container , fn ) {
112+ const counterElement = container . querySelector ( "[data-drag-and-drop-counter]" )
86113 if ( counterElement ) {
87114 const currentValue = counterElement . textContent . trim ( )
88115
89116 if ( ! / ^ \d + $ / . test ( currentValue ) ) return
90117
91- const count = parseInt ( currentValue )
92- if ( count > 0 ) {
93- counterElement . textContent = count - 1
94- }
118+ counterElement . textContent = fn ( parseInt ( currentValue ) )
95119 }
96120 }
121+
122+ #insertDraggedItem( container , item ) {
123+ const itemContainer = container . querySelector ( "[data-drag-drop-item-container]" )
124+ const topItems = itemContainer . querySelectorAll ( "[data-drag-and-drop-top]" )
125+ const firstTopItem = topItems [ 0 ]
126+ const lastTopItem = topItems [ topItems . length - 1 ]
127+
128+ const isTopItem = item . hasAttribute ( "data-drag-and-drop-top" )
129+ const referenceItem = isTopItem ? firstTopItem : lastTopItem
130+
131+ if ( referenceItem ) {
132+ referenceItem [ isTopItem ? "before" : "after" ] ( item )
133+ } else {
134+ itemContainer . prepend ( item )
135+ }
136+ }
137+
138+ async #submitDropRequest( item , container ) {
139+ const body = new FormData ( )
140+ const id = item . dataset . id
141+ const url = container . dataset . dragAndDropUrl . replaceAll ( "__id__" , id )
142+
143+ return post ( url , { body, headers : { Accept : "text/vnd.turbo-stream.html" } } )
144+ }
145+
146+ #reloadSourceFrame( sourceContainer ) {
147+ const frame = sourceContainer . querySelector ( "[data-drag-and-drop-refresh]" )
148+ if ( frame ) frame . reload ( )
149+ }
97150}
0 commit comments