HTML5 API includes Drag and Drop (DnD) native functionality.
The event listener methods for all the drag and drop events accept Event object which has a readonly attribute called dataTransfer. The event.dataTransfer returns DataTransfer object associated with the event
This is the list of events fired during the different stages:
Event | Description |
---|---|
dragstart | Fires when the user starts dragging of the object. |
dragenter | Fired when the mouse is first moved over the target element while a drag is occuring. A listener for this event should indicate whether a drop is allowed over this location. If there are no listeners, or the listeners perform no operations, then a drop is not allowed by default. |
dragover | This event is fired as the mouse is moved over an element when a drag is occuring. Much of the time, the operation that occurs during a listener will be the same as the dragenter event. |
dragleave | This event is fired when the mouse leaves an element while a drag is occuring. Listeners should remove any highlighting or insertion markers used for drop feedback. |
drag | Fires every time the mouse is moved while the object is being dragged. |
drop | The drop event is fired on the element where the drop was occured at the end of the drag operation. A listener would be responsible for retrieving the data being dragged and inserting it at the drop location. |
dragend | Fires when the user releases the mouse button while dragging an object. |
In this post we develop an application to handle the drag and drop events between two elements, and launch a HttpPost method in the server which will ends inserting the dragged value in database.
First of all we create an MVC project in C#. Under Controller folder in the HomeController we add this code:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace HTML5DragAndDrop.Controllers { public class HomeController : Controller { ITestDatabase _testDatabase = new TestDatabase(); public ActionResult Index() { return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } [HttpPost] public JsonResult InsertTestElements(string testElement) { int? insertResult = null; if (!string.IsNullOrEmpty(testElement)) { string[] elementData = testElement.Split(':'); string symbol = elementData[0].Trim(); string name = elementData[1].Trim(); insertResult = _testDatabase.InsertElement(symbol, name); } return Json(insertResult); } } }
Now we create a folder in the root of the project called Code. Under this folder we create two new files:
ITestDatabase.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; public interface ITestDatabase { int InsertElement(string symbol, string name); }
TestDatabase.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; public class TestDatabase : ITestDatabase { /// <summary> /// Save an element in the database and return the new ID /// </summary> /// <param name="symbol"></param> /// <param name="name"></param> /// <returns></returns> public int InsertElement(string symbol, string name) { // save the element in database // now it returns just a number: it will be the Id of the record return 1; } }
The first step is the definition of the UXinterface, in sequence the display is this
We are adding h5utils.js file, with an implementation of AddEvent function to simplify our code:
h5utils.js
var AddEvent = (function () { if (document.addEventListener) { return function (el, type, fn) { if (el && el.nodeName || el === window) { el.addEventListener(type, fn, false); } else if (el && el.length) { for (var i = 0; i < el.length; i++) { AddEvent(el[i], type, fn); } } }; } else { return function (el, type, fn) { if (el && el.nodeName || el === window) { el.attachEvent('on' + type, function () { return fn.call(el, window.event); }); } else if (el && el.length) { for (var i = 0; i < el.length; i++) { AddEvent(el[i], type, fn); } } }; } })(); var pDragElement = document.createElement('p'); var chemicalElements = document.querySelectorAll('div > p'), el = null; for (var i = 0; i < chemicalElements.length; i++) { el = chemicalElements[i]; el.setAttribute('draggable', 'true'); AddEvent(el, 'dragstart', dragStartElement); AddEvent(el, 'dragend', dragEndElement); } function dragStartElement(e) { e.dataTransfer.effectAllowed = 'copy'; e.dataTransfer.setData('Text', this.id); e.dataTransfer.setData('Type', this.innerHTML); this.style.backgroundColor = "#ffa31a"; } function dragEndElement(e) { this.style.backgroundColor = "#fff9f0"; } var divBoxElements = document.querySelector('#divBoxElements'); AddEvent(divBoxElements, 'dragover', function (e) { if (e.preventDefault) e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; return false; }); AddEvent(divBoxElements, 'drop', function (e) { if (e.stopPropagation) e.stopPropagation(); var element = e.dataTransfer.getData('Type'); pDragElement.innerHTML = "Adding " + element + " element"; var pClone = pDragElement.cloneNode(true); var newDiv = document.createElement("div"); newDiv.appendChild(pClone); divBoxElements.appendChild(newDiv); InsertTestElement(element); return false; });
In the Index.cshtml we change as following code:
Index.cshtml
@{ ViewBag.Title = "Home Page"; } <div class="jumbotron"> <h1>Drag and drop example</h1> <p class="lead">HTML5 API includes Drag and Drop (DnD) native functionality. The event listener methods for all the drag and drop events accept Event object which has a readonly attribute called dataTransfer. The event.dataTransfer returns DataTransfer object associated with the event.</p> <p><a href="https://puresourcecode.com" class="btn btn-primary btn-lg">Learn more »</a></p> </div> <div class="row"> <p id="1A">1: A</p> <p id="2B">2: B</p> <p id="3C">3: C</p> <p id="4D">4: D</p> <p id="5E">5: E</p> <div id="divBoxElements style="border: 1px solid #dcdcdc; width: 300px; height: 300px;" ></div> </div> @section scripts { <script src="~/Scripts/html5utils.js"></script> <script> <!-- function InsertTestElement(element) { var url = '@Url.Action("InsertTestElements", "Home")'; $.post(url, { testElement: element }, function (data) { switch (data) { case 1: divBoxElements.innerHTML = element + " inserted OK"; setTimeout(function () { divBoxElements.innerHTML = ""; }, 2000); break; default: alert("Error inserting the element"); } }); } //--> </script> }
Download or fork tthis code on Github.
Happy coding!
One thought on “C# and HTML5: drag and Drop elements”