Drag-and-drop

Although creating drag-and-drop functionality manually is not a very challenging ordeal, HTML5 takes drag-and-drop to a whole new level. With the new API, we're given the ability to do so much more than just let the browser handle the dragging and dropping actions. The interface allows for customizing the exact way that things are dragged, how the dragging action looks, what data is carried with the draggable object, and so on. Plus, not having to worry about how the low level events are tracked in different platforms and devices is a nice, welcome touch.

For the curious reader, the way we could implement our own drag-and-drop behavior is really quite simple; first, we listen for a mouse down event on the element we want to drag. When that happens, we set a mouse down flag, which we unset once the mouse up event is fired, whether on the element we wish to drag or not. Next, we listen for a mouse movement event, where we check if the mouse is down. If the mouse is moving while the mouse down flag is set, we have a drag motion. One way to handle it is to update the position of the draggable element every time the mouse moves, then setting the element's position when the mouse up event is called. Of course, there are several small details that we'd need to keep track of, or at least be mindful of, such as how to detect where the draggable element was dropped, and how to move it back to its original position if needed.

The good news is that the drag-and-drop API provided by the browser is very flexible, and extremely efficient. Since this feature was first introduced, a lot of developers continued to use JavaScript implementations of it for various reasons, but mostly because a lot of people felt that the native HTML5 version was a bit hard to use, buggy, or not quite as practical as the version provided by whatever other library they chose to use. However, today the API is widely supported, fairly polished, and highly recommended.

How to use it

Now, the way that the drag-and-drop API works is very straight forward. First we need to mark one or more elements as draggable by setting the draggable attribute to true for those elements, as shown in the following code:

<ul>
  <li draggable="true" class="block"
    ondragstart="doOnDragStart(event)"
    data-name="Block 1">Block #1</li>
</ul>

Just this step alone will make those elements all draggable. Of course, that isn't of any use unless we have a place to drop those elements. Believe it or not, we actually can drop a dragged element anywhere. The problem is that we don't have any code in place to handle the event of something being dropped. We can register such events on any element, including the body tag, for example. This is shown in the following code:

document.body.ondragover = doOnDragOver;
document.body.ondragleave = doOnDragLeave;
document.body.ondrop = doOnDrop;

function doOnDragOver(event) {
  event.preventDefault();
  document.body.classList.add("dropme");
}

function doOnDragLeave(event) {
  event.preventDefault();
  document.body.classList.remove("dropme");
}

function doOnDrop(event) {
  event.preventDefault();
  document.body.classList.remove("dropme");
  var newItem = document.createElement("li");
  newItem.setAttribute("draggable", true);
  newItem.classList.add("block");

  document.querySelector("ul").appendChild(newItem);
}

In this example, we append a new list element to the unordered list every time a list element is dropped anywhere on the page, since every element on the page is a child of the body node. Also, whenever a draggable element hovers over the body element, we add a CSS class called dropme, which is meant to give the user a visual feedback letting them know that the drag event is taking place. When the draggable is dropped, we remove that class from the body element indicating the end of the drag action.

One thing we can do with the drag and drop API is transfer data between objects. This data can be a string, or any data type that can be converted into a string. We do this by setting the desired data to the dataTransfer object available to us during the drag action. The data must be set when the drag start function is fired by the system. The key associated with the dataTransfer data can be any string of our choosing as shown in the following code:

function doOnDragStart(event) {
    // First we set the data when the drag event first starts
    event.dataTransfer.setData("who-built-me", event.target.getAttribute("data-name"));
}

function doOnDrop(event) {
    event.preventDefault();
    document.body.classList.remove("dropme");

    var num = document.querySelectorAll("li").length + 1;

    // Then we retrieve that data when the drop event is fired by the browser
    var builtBy = event.dataTransfer.getData("who-built-me");

    var newItem = document.createElement("li");
    newItem.ondragstart = doOnDragStart;
    newItem.setAttribute("draggable", true);
    newItem.setAttribute("data-name", "Block " + num);
    newItem.innerText = "Block #" + num + ", built by " + builtBy;

    newItem.classList.add("block");

    document.querySelector("ul").appendChild(newItem);
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.17.27