C# and HTML5: drag and Drop elements

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

DragAndDrop_App

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="http://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!

How to strip all HTML tags and entities and get clear text?

I was encouraged to write this Tip/Trick because of so many questions received for this issue.
Suppose you're having a bunch of HTML strings, but you just want to remove all the HTML tags and want a plain text.

You can use Regex to come to the rescue.

The Regex I had developed before was more cumbersome, then Chris made a suggestion, so I will now go further with the regex suggested by Chris that is a "\<[^\>]*\>".

I have tested it for many cases. It detects all types of HTML tags, but there may be loopholes inside so if you find any tags which are not passing through this Regex, then kindly inform me about the same.

Regex Definition

  • Regex :\<[^\>]*\>
    • Literal >
    • Any character that NOT in this class:[\>], any number of repetations
    • Literal >

Visual Basic

''' 
''' Remove HTML from string with Regex
''' 
Function StripTags(ByVal html As String) As String
    ' Remove HTML tags.
    Return Regex.Replace(html, "<.*?>", "")
End Function

C#

/// 
/// Remove HTML from string with Regex
/// 
public static string StripTags(string source)
{
    return Regex.Replace(source, "<.*?>", string.Empty);
}

Happy coding!

Using the UpdateProgress to lock down controls in the browser

If it takes awhile for the server to process the postback (e.g. complex rules or badly written code ), the user may not realize that the server is processing the request. This can lead to all kinds of issues with users that are not savvy or familiar with web applications (multiple clicks, moving off the page, etc.). Consequently, I want to tell the user that the server is processing the request and disable the controls on the page. Let's break this down into two steps: show a message, and disable the user's interaction with the controls.

You can use the UpdateProgress control alone with the UpdatePanel to provide a message to the user during the postback. This is very simple -- put the UpdateProgress control within the UpdatePanel like so:

<asp:UpdateProgress ID="UpdateProgress1" runat="server">
    <ProgressTemplate>
        Update in progress. Please wait ...
    </ProgressTemplate>
</asp:UpdateProgress>
 

This will display the "Update in progress. Please wait ..." message to the the user while the server is processing the request. However, it doesn't prevent the user from continuing to interact with the web application. To provide this type of functionality, we will use the PageRequestManager to invoke some JavaScript while also using CSS and DHTML to lock down the UI.

First, we'll add a little more to our UpdateProgress control:

<ProgressTemplate>
    <div id="blur" />
    <div id="progress">
        Update in progress. Please wait ...
    </div>
</ProgressTemplate>
 

We'll use the "blur" and "progress" controls to _overlay _the controls in the UI while also providing a message to the user. To provide the functionality we require, we need to use the following CSS elements:

#blur
{
    width: 100%;
    background-color: black;
    moz-opacity: 0.5;
    khtml-opacity: .5;
    opacity: .5;
    filter: alpha(opacity=50);
    z-index: 120;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}

#progress
{
    z-index: 200;
    background-color: White;
    position: absolute;
    margin-left: auto;
    margin-right: auto;
    border: solid 1px black;
    padding: 5px 5px 5px 5px;
    text-align: center;
    width: 100%;
    left: 0px;
    height: 75px;
    padding-top: 40px;
    padding-bottom: 60px;
}
 

The purpose of the "blur" control is to provide a tag that lays over everything in the browser. Since the opacity is 0.5 (and 50), it appears gray while allowing the user to continue to see the controls behind it. However, since the "blur" control exists between the user and the other controls, the user cannot interact with any other controls.

image

Auto Fill Email Subject and Body

If you're using a list management system that requires specific text to be placed within the email subject or body of your email, this HTML code is for you.

Many times, if you request your visitors to type in a specific email subject or body text in order to subscribe to your publication, they may not type the required text correctly. This mistake will cause you to lose your subscriber, as your system will reject the subscription request.

To prevent this problem, you can create an email link that will automatically fill in the subject line and body when clicked on.

<a href="mailto:manish@simplygraphix.com?subject=Feedback for
webdevelopersnotes.com&body=The Tips and Tricks section is great
&cc=anotheremailaddress@anotherdomain.com
&bcc=onemore@anotherdomain.com">Send me an email</a>

Advertsing

125X125_06

Planet Xamarin

Planet Xamarin

Calendar

<<  November 2017  >>
MonTueWedThuFriSatSun
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

Month List