Dragndrop is actually a simple variant of dragnswap. So, I shall start by describing which stuff I need to build the dragndrop-ability present in jsTool:
- Function that will check if the pointer (mouse cursor) intersects an html element.
- A function which gets two parameters, a point (2d coordinate) and an html element (containing the top-left coordinate and width and height), returns a boolean
- A function which gets two parameters, a point and a list of html elements, returns the intersecting element with the point
- A function that will hook a handler, to the following events: "mouseup, mouseover, moseout, mouseenter". This handler will pass a message to the the listening item, if there has been an intersection with an item's container.
- Function which hooks the message passing mechanism to the containers.
- The message passing mechanism itself. (Most probably a shared closure)
- Something to unhook the message passing mechanism from the containers.
- Something to verify the message, so if the message is a false positive, we can still brute-force the correct intersecting container.
- Something to calculate the item's position (in html the position of an element in 2d is not defined, css defines this, so we have to make a translation from 2d to 1d) using the information of the container and the relative position of the pointer coordinates. I call this, the virtual index. So a means to calculate the virtual index, so we can sort items within a container. The current implementation assumes that all the items in the container have uniform dimensions. So expect it to break where this assumption does not hold.
If I recall correctly, mozilla firefox 3.0 has built-in drag and drop events, and also a function to return the element on which a pointer intersects. Which makes the aformentioned functionalities 1 to 4, redundant.
Dragndrop goes through three stages, the start of the drag, the dragging itself and the end of the drag, respectively, the dragstart event, the drag event and the dragend event.
- Dragstart: Dragndrop starts by hooking "motion detectors" (message passing mechanism) to the containers of the currently dragged item.
- Drag: Dragndrop uses the message passing mechanism to determine which container the pointer is intersecting (current container), and when the dragndrop ends (the user releases the mouse button), it will see if there's a message about the current container and then it verifies the message. The verification procedure is simple, because it requires only an intersection test of the pointer coordinate, and the container. If the message is a false positive, we loop through all the container for the item, and do intersection tests on each and every one. (brute-force) If there is no message, we do the same, as in the case of the false positive message.
Then the virtual index for the current dragndrop item is calculated, and a proxy item (a visual indicator for the virtual index) is docked, but the dragndrop-item itself is not docked (yet) - Dragend: The "motion detectors" are disabled, by unhooking the message passers. And the dragndrop item is docked to the current container, by replacing the proxy item with the dragndrop item, given there is a proxy. (Which implies there is an active container)
Note: In the current jsTool dragnswap implementation, swapping-behaviour occurs when a container has no more "space" left. That "space" is expressed as an integer, and it has no relation to the actual element real-estate space (2d surface size), which is defined by the css for that element.
TODO
- Make an indicator when swapping-behaviour is available.
In conclusion, these functionalities provide the means to drag and drop to multiple containers and drag and swap to multiple containers.