Drag and Drop interactions are usually implemented with client-side JavaScript. Developers typically need to listen for pointer events, track the dragged element, prevent default browser behavior, update CSS classes, and finally move or remove the element.
With WebForms Core (WFC), the same interaction can be implemented by defining events and commands on the server. No custom JavaScript event handlers are required.
The following example uses Node.js and Express.
It is recommended to view the drag-and-drop demo before looking at the code.
The Example
The page contains two zones:
-
dragZonecontains draggable elements. -
dropZoneis the destination.
When an item is dragged with a mouse, it can be moved between the two zones. On touch devices, where native HTML Drag and Drop is not normally suitable, a direct tap can be used to move an item between the zones.
const express = require('express');
const { WebForms, HtmlEvent, Fetch } = require('./WebForms');
const app = express();
const PORT = 3000;
app.use(express.static('public'));
app.get('/', (req, res) => {
const form = new WebForms();
form.setCommentEvent("dragZone|<div>*", HtmlEvent.OnDragStart, "drag-start");
form.setCommentEvent("-", HtmlEvent.OnDragEnd, "drag-end");
form.setPreventDefaultEvent("dragZone", HtmlEvent.OnDragOver);
form.setCommentEvent("-", HtmlEvent.OnDragOver, "drag-over-back");
form.setCommentEvent("-", HtmlEvent.OnDragLeave, "drag-leave-back");
form.setCommentEvent("-", HtmlEvent.OnDrop, "drop-back");
form.setPreventDefaultEvent("dropZone", HtmlEvent.OnDragOver);
form.setCommentEvent("-", HtmlEvent.OnDragOver, "drag-over");
form.setCommentEvent("-", HtmlEvent.OnDragLeave, "drag-leave");
form.setCommentEvent("-", HtmlEvent.OnDrop, "drop");
form.setCommentEvent("dragZone|<div>*", HtmlEvent.OnTouchStart, "touch-start");
form.startIndex("drag-start");
form.saveOuterText("$");
form.saveId("$", "id");
form.startIndex("drag-end");
form.deleteClass("$", "hide");
form.assignDelay(100);
form.startIndex("drag-over");
form.insertClass("dropZone", "highlight");
form.startIndex("drag-leave");
form.deleteClass("dropZone", "highlight");
form.startIndex("drop");
form.delete(Fetch.save("id"));
form.addText("dropZone", Fetch.save());
form.startIndex("drag-over-back");
form.insertClass("dragZone", "highlight");
form.startIndex("drag-leave-back");
form.deleteClass("dragZone", "highlight");
form.startIndex("drop-back");
form.delete(Fetch.save("id"));
form.addText("dragZone", Fetch.save());
form.startIndex("touch-start");
form.elementExists("dragZone|{{id}}");
form.assignReplace("{{id}}", Fetch.getId("$"));
form.addText("dropZone", Fetch.getOuterText("$"));
form.else();
form.addText("dragZone", Fetch.getOuterText("$"));
form.delete("$");
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Drag and Drop - WebForms Core</title>
<script type="module" src="/script/web-forms.js"></script>
<style>
#dropZone, #dragZone {
width: 100%;
max-width: 600px;
height: auto;
min-height: 200px;
border: 2px dashed #ccc;
border-radius: 5px;
text-align: center;
padding: 20px;
margin: 20px auto;
}
#dropZone.highlight, #dragZone.highlight {
border-color: #4CAF50;
background-color: #f8f8f8;
}
.dragitem {
width: 100px;
height: 100px;
background-color: #4CAF50;
color: white;
text-align: center;
line-height: 100px;
cursor: move;
margin: 20px auto;
}
.hide {
display: none;
}
</style>
</head>
<body>
<h2>Drag and Drop</h2>
<blockquote>
With a mouse, items are moved via drag and drop;
with touch, they are moved by a direct tap.
</blockquote>
<div id="dragZone">
<div class="dragitem" id="dragitem1" draggable="true">Drag me! 1</div>
<div class="dragitem" id="dragitem2" draggable="true">Drag me! 2</div>
<div class="dragitem" id="dragitem3" draggable="true">Drag me! 3</div>
<div class="dragitem" id="dragitem4" draggable="true">Drag me! 4</div>
</div>
<div id="dropZone">Drop here</div>
${form.exportToHtmlComment()}
</body>
</html>
`);
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:3000`);
});
Defining the Drag Events
The first step is to associate WebForms Core events with the draggable elements.
form.setCommentEvent(
"dragZone|<div>*",
HtmlEvent.OnDragStart,
"drag-start"
);
form.setCommentEvent(
"-",
HtmlEvent.OnDragEnd,
"drag-end"
);
The selector:
dragZone|<div>*
targets the div elements inside dragZone. Each of these elements can therefore participate in the same drag behavior.
The - input place refers to the event target, allowing the same command sequence to operate on the element that triggered the event.
Saving the Dragged Element
When dragging starts, the example stores two pieces of information:
form.startIndex("drag-start");
form.saveOuterText("$");
form.saveId("$", "id");
The outer text is saved so it can later be inserted into another zone, while the element's ID is saved as id.
This is important because the server-generated commands can later use the saved values without requiring custom client-side JavaScript variables.
Highlighting the Drop Zone
While the user is dragging an item over the destination, the destination receives a visual highlight:
form.startIndex("drag-over");
form.insertClass("dropZone", "highlight");
When the pointer leaves the zone, the class is removed:
form.startIndex("drag-leave");
form.deleteClass("dropZone", "highlight");
The same mechanism is used for the original dragZone.
This means the visual state is controlled through WebForms Core commands rather than through a JavaScript event handler.
Moving the Item
The actual drop operation is particularly simple:
form.startIndex("drop");
form.delete(Fetch.save("id"));
form.addText("dropZone", Fetch.save());
The sequence performs two operations:
- Remove the original element using its saved ID.
- Add its saved content to
dropZone.
The important point is that these are DOM manipulation commands generated by the server-side WebForms class. There is no client-side dragstart, dragover, or drop function written by the developer.
Supporting the Reverse Direction
The same mechanism works when moving an element back from dropZone to dragZone.
form.startIndex("drop-back");
form.delete(Fetch.save("id"));
form.addText("dragZone", Fetch.save());
The destination changes, but the basic operation remains the same:
Delete original element → Add its content to destination
Touch Interaction Without JavaScript
Native HTML Drag and Drop is primarily designed around pointer-based dragging and is not a reliable interaction model for touch devices.
Instead of implementing a separate JavaScript touch system, this example defines a WebForms Core OnTouchStart event:
form.setCommentEvent(
"dragZone|<div>*",
HtmlEvent.OnTouchStart,
"touch-start"
);
The touch behavior is then implemented with WebForms Core commands:
form.startIndex("touch-start");
form.elementExists("dragZone|{{id}}");
form.assignReplace("{{id}}", Fetch.getId("$"));
form.addText("dropZone", Fetch.getOuterText("$"));
form.else();
form.addText("dragZone", Fetch.getOuterText("$"));
form.delete("$");
Screenshot of Drag & Drop Example
The logic is:
- If the touched element already exists in
dragZone, move it todropZone. - Otherwise, move it back to
dragZone.
In other words, a touch interaction can provide a simple toggle between the two zones without implementing a custom JavaScript drag-and-drop engine.
One Server-Side Definition, Multiple Client Behaviors
The example demonstrates an important aspect of WebForms Core.
The developer describes the interaction on the server:
Event
↓
WebForms command sequence
↓
WebFormsJS
↓
HTML DOM
WebFormsJS executes the commands in the browser. It does not require the developer to write separate JavaScript functions for each event.
The application therefore does not contain code such as:
element.addEventListener("dragstart", ...);
element.addEventListener("dragover", ...);
element.addEventListener("dragleave", ...);
element.addEventListener("drop", ...);
element.addEventListener("touchstart", ...);
Instead, the interaction is declared through the server-side WebForms class.
Why This Is Different
A conventional implementation usually requires the developer to create a client-side interaction layer:
HTML
↓
JavaScript event handlers
↓
Application state
↓
DOM manipulation
With WebForms Core, the interaction can be expressed as server-defined commands:
Server
↓
WebForms
↓
WebForms Core commands
↓
WebFormsJS
↓
HTML DOM
The browser still performs the actual DOM operations, but the developer does not need to implement those operations as custom JavaScript code.
This is particularly useful for applications where interaction logic is already organized around server-side controls and commands.
No Custom JavaScript Required
The only JavaScript referenced by the page is the WebFormsJS executor:
<script type="module" src="/script/web-forms.js"></script>
There is no custom JavaScript file containing drag-and-drop handlers.
The HTML remains ordinary HTML, and the draggable elements use the standard draggable attribute:
<div class="dragitem" id="dragitem1" draggable="true">
Drag me! 1
</div>
The interaction logic is defined entirely through the server-side WebForms API.
Conclusion
This example shows that Drag and Drop does not necessarily require a custom JavaScript implementation.
With WebForms Core, mouse-based Drag and Drop can be defined through standard HTML events and server-generated commands, while touch interaction can be handled through a separate OnTouchStart event.
The result is a server-orchestrated interaction where:
- the server defines the behavior,
- WebForms Core generates the commands,
- WebFormsJS executes those commands,
- and the browser performs the final DOM operations.
Most importantly, the developer does not have to write a JavaScript Drag and Drop implementation or maintain a separate client-side interaction layer.
If you have any questions, feel free to ask.
If you have any comments, please share them.
We will gladly answer!
Related links
On Elanat:
On GitHub:


Top comments (0)