As far as I understand there are two distinct drag-n-drop mechanisms:
- Global drag-n-drop when objects are dragged from one window/application on desktop to another. In most cases this is very close to clipboard cut-n-paste but with some additional visualization.
- Window local drag-n-drop when objects are dragged inside single window/form. For example some shopping cart implementation.
I have added support of latter one to the h-smile core – local drag-n-drop of DOM elements. Details are here.
Consider following task:
For these two select elements:
<select id="source" size="5"> <option>First<</option> <option>Second<</option> <option>Third<</option> </select> <select id="destination" size="5"></select>
we would like to provide ability to drag <option> elements from #source element to the #destination. In case of htmlayout or the Sciter (both are based on h-smile core) it is enough to write following:
select#source > option { dragging: only-move; /* we can only move options out here*/ } select#destination { accept-drag: selector( select#source > option ); /* we accept only options from select#source*/ drop: append; /* order of items is not relevant, always append dropped option */ }
and this is it – our users now are able to drag items from first <select> to second.
But what about one of main principles of good UI design – “discoverability”? User should have a visual clue while dragging: where and when he/she can drop dragged item. Following additional pseudo-classes will help us in this tasks:
option:moving /* moving (dragging ) option */ { background:blue; color:white; opacity:0.5; } select:drop-target /* active drop target element(s) */ { background: yellow; /* after D&D operation was started all active drop-targets will be highlighted by yellow color */ } select:drag-over /* drop target element under the dragged item.*/ { outline: 1px solid green; /* green outline to show that at current mouse position dragged element can be dropped in this particular drop-target */ }
And that is all we need to enable drag-n-drop in our application.
Oh, forgot to add: what if we need to drag options in both directions – from #destination back to the #source? The same simple idea:
select#destination > option { dragging: only-move; } select#source { accept-drag: selector( select#destination > option ); drop: append; }
And one small piece left: drop:recycle
will declare element it is applied to (drop-target) as a “black hole” – all items dropped here will be deleted.
It would be great if we could specify different “dragging” options for different destinations. I.e. if I drag to trash I would like to specify “only-move” value, but if I drag to different destination I want to have “only-copy” value. Is it possible?