JavaScript Drag and Drop
JavaScript Drag and Drop
dragstart
drag
dragend
When you hold a mouse button and begin to move the mouse,
the dragstart event fires on the draggable element that you’re dragging.
The cursor changes to a no-drop symbol (a circle with a line through
it) to indicate that you cannot drop the element on itself.
The target of all events (e.target) is the element that is being dragged.
When you drag an element over a valid drop target, these events fire
in the following sequence:
dragenter
dragover
dragleave or drop
When you drag the element outside of the boundary of the drop
target, the dragover event stops firing and the dragleave event fires.
In case you drop the element on the target, the drop event fires instead
of the dragleave event.
To turn an element into a valid drop target, you can override the
default behavior of both dragenter and dragover events by calling
the event.preventDefault() method in their corresponding event handlers.
(See the example section for more information)
dataTransfer.setData(format, data)
Code language: CSS (css)
dataTransfer(format)
Third, place the link to the style.css and script tag that links to the app.js in
the index.html file like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0">
<title>JavaScript - Drag and Drop Demo</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script src="js/app.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0">
<title>JavaScript - Drag and Drop Demo</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<h1>JavaScript - Drag and Drop</h1>
<div class="drop-targets">
<div class="box">
<div class="item" id="item">
</div>
</div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
<script src="js/app.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
If you open the index.html and try to drag the yellow box, you’ll see the
cursor indicating that you cannot drag:
To make the element draggable, you add the draggable property with the
value of true to its HTML tag as follows:
Now, if you save the index.html, open it in the browser again, you’ll see
that you can drag the item element like this:
.hide {
display: none;
}
Code language: CSS (css)
function dragStart(e) {
console.log('drag starts...');
}
Code language: JavaScript (javascript)
How it works:
If you open the index.html file and start dragging the draggable
element, you’ll see the drag starts... message in the console.
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
e.target.classList.add('hide');
}
Code language: JavaScript (javascript)
If you drag the element, you’ll see that it disappears once you start
dragging.
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
setTimeout(() => {
e.target.classList.add('hide');
}, 0);
}
Code language: JavaScript (javascript)
Now, you can drag the draggable element out of its original position:
The style.css file also has a CSS class called .drag-over that turns the
border style of the drop target into dashed and red:
.drag-over {
border: dashed 3px red;
}
Code language: CSS (css)
In the app.js, you need to select the drop target elements and handle
the dragenter, dragover, dragleave, and drop events of these elements:
boxes.forEach(box => {
box.addEventListener('dragenter', dragEnter)
box.addEventListener('dragover', dragOver);
box.addEventListener('dragleave', dragLeave);
box.addEventListener('drop', drop);
});
function dragEnter(e) {
}
function dragOver(e) {
}
function dragLeave(e) {
}
function drop(e) {
}
Code language: JavaScript (javascript)
function dragEnter(e) {
e.target.classList.add('drag-over');
}
function dragOver(e) {
e.target.classList.add('drag-over');
}
function dragLeave(e) {
e.target.classList.remove('drag-over');
}
function drop(e) {
e.target.classList.remove('drag-over');
}
Code language: JavaScript (javascript)
Now, if you drag the draggable element to another drop target, you’ll
see that the border of the drop target changes as shown in the
following picture:
To make the drop target valid, you need to call event.preventDefault() in
the dragenter and dragover event handlers like this:
function dragEnter(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
Code language: JavaScript (javascript)
If you drag the draggable element to a drop target, you’ll see that the
cursor changes indicating that you can drop the element:
Now, if you drop the item element, you’ll see that it disappears
immediately.
function drop(e) {
e.target.classList.remove('drag-over');
/* draggable element */
const item = document.querySelector('.item');
item.addEventListener('dragstart', dragStart);
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
setTimeout(() => {
e.target.classList.add('hide');
}, 0);
}
/* drop targets */
const boxes = document.querySelectorAll('.box');
boxes.forEach(box => {
box.addEventListener('dragenter', dragEnter)
box.addEventListener('dragover', dragOver);
box.addEventListener('dragleave', dragLeave);
box.addEventListener('drop', drop);
});
function dragEnter(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragLeave(e) {
e.target.classList.remove('drag-over');
}
function drop(e) {
e.target.classList.remove('drag-over');
Summary
JavaScript FileReader
Introduction to the JavaScript FileReader API
Second, call one of the read methods to read the content of a file. For
example:
reader.readAsDataURL(file);
Code language: JavaScript (javascript)
For example, you can use the readAsDataURL() to read an image and show
its base64 encoded string on a webpage.
Since all of these methods read the file’s data asynchronously, you
cannot just return the result like this:
When you drag & drop images to the drop zone, the application will
use the FileReader to read the images and show them on the page
together with the filename and filesize:
Also, the application will use the Fetch API to upload the files to the
server.
For the server-side, we’ll implement a simple PHP script that uploads
the images to the 'uploads' folder on the server.
├── css
| └── style.css
├── images
| └── upload.svg
├── js
| └── app.js
├── index.html
├── upload.php
└── uploads
Code language: JavaScript (javascript)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,
initial-scale=1.0" />
<link rel="stylesheet" href="css/style.css" />
<title>FileReader API Demo - Image Upload
Application</title>
</head>
<body>
<main>
<div class="dropzone">
<img src="images/upload.svg" alt="upload"
width="60" />
<input type="file" class="files"
id="images"
accept="image/png, image/jpeg"
multiple />
<label for="images">Choose multiple
images</label>
The file input element accepts multiple files and only allows jpeg and
png images:
First, select dropzone, file input (files), and image list elements using
the querySelector() method:
[...images].forEach((image) =>
formData.append('images[]', image, image.name)
);
[...images].forEach((image) =>
formData.append('images[]', image, image.name)
);
Code language: JavaScript (javascript)
[...images]
Code language: JavaScript (javascript)
All key/value pairs in the form data have the same key as images[]; in
PHP, you can access it as an array ($_FILES['images'])
Eighth, add the change event handler to the file input element if users
select files using this input element:
In the change event handler, you can access the FileList object
as e.target.files. The logic for showing and uploading images is the same
as drag & drop.
Note that if you drag & drop images outside the dropzone, the web
browser will display the images by default.
To prevent this, you call the preventDefault() method of
the dragover and drop event objects of the document like this:
[...images].forEach((image) =>
formData.append('images[]', image, image.name)
);
<?php
const MESSAGES = [
UPLOAD_ERR_OK => 'File uploaded successfully',
UPLOAD_ERR_INI_SIZE => 'File is too big to upload',
UPLOAD_ERR_FORM_SIZE => 'File is too big to
upload',
UPLOAD_ERR_PARTIAL => 'File was only partially
uploaded',
UPLOAD_ERR_NO_FILE => 'No file was uploaded',
UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary
folder on the server',
UPLOAD_ERR_CANT_WRITE => 'File is failed to save to
disk.',
UPLOAD_ERR_EXTENSION => 'File is not allowed to
upload to this server',
];
const ALLOWED_FILES = [
'image/png' => 'png',
'image/jpeg' => 'jpg'
];
const HTTP_STATUSES = [
200 => 'OK',
400 => 'Bad Request',
404 => 'Not Found',
405 => 'Method Not Allowed'
];
$is_post_request =
strtolower($_SERVER['REQUEST_METHOD']) === 'post';
$has_files = isset($_FILES['images']);
if (!$is_post_request || !$has_files) {
response(405, [
'success' => false,
'message' => ' Method not allowed or files do
not exist'
]);
}
$files = $_FILES['images'];
$file_count = count($files['name']);
// validation
$errors = [];
for ($i = 0; $i < $file_count; $i++) {
// get the uploaded file info
$status = $files['error'][$i];
$filename = $files['name'][$i];
$tmp = $files['tmp_name'][$i];
// an error occurs
if ($status !== UPLOAD_ERR_OK) {
$errors[$filename] = MESSAGES[$status];
continue;
}
// validate the file size
$filesize = filesize($tmp);
if ($errors) {
response(400, [
'success' => false,
'message' => $errors
]);
}
response(200, [
'success' => true,
'message' => 'The files uploaded successfully'
]);
/**
* Return a mime type of file or false if an error
occurred
*
* @param string $filename
* @return string | bool
*/
function get_mime_type(string $filename)
{
$info = finfo_open(FILEINFO_MIME_TYPE);
if (!$info) {
return false;
}
return $mime_type;
}
/**
* Return a human-readable file size
*
* @param int $bytes
* @param int $decimals
* @return string
*/
function format_filesize(int $bytes, int $decimals =
2): string
{
$units = 'BKMGTP';
$factor = floor((strlen($bytes) - 1) / 3);
/**
* Response JSON to the client
* @param int $status_code
* @param array|null $data
*/
function response(int $status_code, array $data = null)
{
header("HTTP/1.1 " . $status_code . " " .
HTTP_STATUSES[$status_code]);
header("Content-Type: application/json");
echo json_encode($data);
exit;
}
Code language: JavaScript (javascript)
Summary
Use the JavaScript FileReader API to read the files selected by users via drag
& drop or file input element.
The Geolocation API allows the web application to access your location
if you agree to share it.
Why Geolocation API
The Geolocation API is useful for web applications that need to work
based on the user’s locations such as Search Engines, eCommerce
websites, maps, and weather apps.
Similarly, the search engine like Google.com can return local search
results based on your search term and location.
For example, if you’re in San Fransisco and search for Pizza, Google
will show you a list of Pizza restaurants that are near to your current
location.
if (!navigator.geolocation) {
console.error(`Your browser doesn't support
Geolocation`);
}
Code language: JavaScript (javascript)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0">
<title>JavaScript Geolocation Demo</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<button id="show" class="btn">Show my
location</button>
<div id="message"></div>
</div>
<script src="js/app.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
And the following shows the app.js file:
(() => {
const message = document.querySelector('#message');
message.classList.add('success');
message.textContent = `Your location: ($
{latitude},${longitude})`;
}
How it works.
Then, select the button and attach a click event handler. The click
event handler calls the getCurrentPosition() method of
the navigator.geolocation object to get the current position of the user.
Note that all the code in the app.js are wrapped in an IIFE.
The following illustrates how to run the web application using Google
Chrome. If you’re using a different browser like Firefox, Edge, or
Safari, you should be able to follow the steps.
The Geolocation API allows web applications to access the user’s current
position.
Use the navigator.geolocation.getCurrentPosition() method to get the current
user’s location.