JavaScript Drag and Drop
Introduction to JavaScript Drag and Drop API
HTML5 formally introduced the drag-and-drop specification. Most
modern web browsers have implemented native drag-and-drop based
on the HTML5 spec.
By default, only image and text can be draggable. To drag an image,
you simply hold the mouse button down and then move it. To drag the
text, you need to highlight some text and drag it in the same way as
you would drag an image.
HTML5 spec specifies that almost all elements can be draggable. To
make an element draggable, you add the draggable property with the
value of true to its HTML tag. For example:
<div class="item" draggable="true"></div>
Code language: HTML, XML (xml)
Events on draggable elements
When you drag an element, these events fire in the following
sequence:
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.
After the dragstart event fires, the drag event fires repeatedly as long as
you drag the element.
And The dragend event fires when you stop dragging the element.
The target of all events (e.target) is the element that is being dragged.
By default, the browser doesn’t change the appearance of the dragged
element. Therefore, you can customize its appearance based on your
preferences.
Events on drop targets
When you drag an element over a valid drop target, these events fire
in the following sequence:
dragenter
dragover
dragleave or drop
The dragenter event fires as soon as you drag the element over a drop
target.
After the dragenter event fires, the dragover event fires repeatedly as long
as you’re dragging the element within the boundary of the drop
target.
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.
The target (e.target) of the dragenter, dragover, dragleave, and drop events are
the drop target elements.
Valid drop target
Almost all elements support the drop target events
(dragenter, dragover, dragleave, and drop). However, they don’t allow dropping
by default.
If you drop an element over a drop target that doesn’t allow to drop,
the drop event won’t fire.
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)
Transfer data using dataTransfer object
To transfer data in a drag-and-drop action, you use
the dataTransfer object.
The dataTransfer object is a property of the event. It allows you to
transfer data from the dragged element to the drop target.
The dataTransfer object has two methods: setData() and getData().
The setData() allows you to set the drag operation’s data to the specified
format and data:
dataTransfer.setData(format, data)
Code language: CSS (css)
The format can be text/plain or text/uri-list. And the data can be a string
representing the data to add to the drag object.
The getData() method retrieves the drag data stored by
the setData() method.
The getData() accepts one argument:
dataTransfer(format)
The format can be text/plain or text/uri-list. The getData() returns a string
stored by the setData() method or an empty string if the drag operation
doesn’t include data.
JavaScript drag and drop example
We’ll develop the following simple drag-and-drop application to
demonstrate the JavaScript drag and drop API:
Create the project structure
First, create a new folder called drag-n-drop-basics. Inside this folder, create
two subfolders called css and js.
Second, create a new file called app.js in the js folder, style.css in
the css folder, and index.html in the drag-n-drop-basics folder.
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)
Build the index.html file
Place the following code in the index.html file:
<!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)
In this index.html file, we used the .container element to align the
heading and drop-targets element.
Inside the drop-targets element, we placed three div elements with the
same class box. And we place another div element with the class item in
the first box.
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:
<div class="item" id="item" draggable="true">
Code language: JavaScript (javascript)
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:
Handle events on the draggable element
The style.css file has the .hide class that hides an element:
.hide {
display: none;
}
Code language: CSS (css)
In the app.js file, you add the following code:
// select the item element
const item = document.querySelector('.item');
// attach the dragstart event handler
item.addEventListener('dragstart', dragStart);
// handle the dragstart
function dragStart(e) {
console.log('drag starts...');
}
Code language: JavaScript (javascript)
How it works:
First, select the draggable element using the querySelector().
Second, attach a dragstart event handler to the draggable element.
Third, define the dragStart() function to handle the dragstart event.
If you open the index.html file and start dragging the draggable
element, you’ll see the drag starts... message in the console.
In the dragStart event handler, you need to store the id of the draggable
element. And you need to hide it:
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.
To solve this, you use the setTimeout() function:
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:
Handle events on drop targets
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:
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) {
}
function dragOver(e) {
}
function dragLeave(e) {
}
function drop(e) {
}
Code language: JavaScript (javascript)
The border style of the drop target should change when
the dragenter and dragover event occurs. It should restore the style when
the dragleave and drop event occurs.
To do it, you add and remove the drag-over class to the drop target like
this:
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 don’t do this, the drop event will never fire because
the div element is not a valid drop target by default.
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.
To solve this issue, you need to add handle the drop event.
First, get the id of the draggable element using the getData() method of
the dataTransfer object.
Second, append the draggable element as a child element of the drop target
element.
Third, remove the hide class from the draggable element.
The following code shows the complete drop event handler:
function drop(e) {
e.target.classList.remove('drag-over');
// get the draggable element
const id = e.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
// add it to the drop target
e.target.appendChild(draggable);
// display the draggable element
draggable.classList.remove('hide');
}
Code language: JavaScript (javascript)
If you drag and drop the draggable element now, it should work as
expected.
The following shows the complete app.js file:
/* 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');
// get the draggable element
const id = e.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
// add it to the drop target
e.target.appendChild(draggable);
// display the draggable element
draggable.classList.remove('hide');
}
Code language: JavaScript (javascript)
And here is the link to the demo.
Summary
Add the draggable property with the value of true to an element to make it
draggable.
The dragstart, drag, and dragend events fire on the draggable element.
The dragenter, dragover, dragleave or drop events fire on the drop target.
Call the event.preventDefault() on the dragenter and dragover event handlers to
make an element a valid drop target.
Use the event.dataTransfer object with the setData() and getData() methods to
transfer data in the drag-and-drop operation.
JavaScript FileReader
Introduction to the JavaScript FileReader API
When you drag and drop files to the web browser or select files to
upload via the file input element, JavaScript represents each file as
a File object.
The File object allows you to access the selected file in JavaScript. And
JavaScript uses the FileList object to hold the File objects.
To read the content of a file, you use the FileReader object. Note that
the FileReader only can access the files you selected via drag & drop or
file input.
To use the FileReader object, you follow these steps:
First, create a new FileObject:
const reader = new FileReader();
Code language: JavaScript (javascript)
Second, call one of the read methods to read the content of a file. For
example:
reader.readAsDataURL(file);
Code language: JavaScript (javascript)
The readAsDataURL() method reads the content of the file, which you get
from the FileList object.
The readAsDataURL() method returns an object with the result property that
contains the data as a data: URL. The data:URL represents the file’s data as
a base64 encoded string.
For example, you can use the readAsDataURL() to read an image and show
its base64 encoded string on a webpage.
Besides the readAsDataURL() method, the FileReader has other methods for
reading file’s data such as readAsText(), readAsBinaryString(),
and readAsArrayBuffer().
Since all of these methods read the file’s data asynchronously, you
cannot just return the result like this:
const data = reader.readAsDataURL(file);
Code language: JavaScript (javascript)
When the readAsDataURL() method completes reading the file
successfully, the FileReader fires the load event.
Third, add an event handler to handle the load event of
the FileReader object:
reader.addEventListener('load', (e) => {
const data = e.target.result;
}
Code language: JavaScript (javascript)
Using JavaScript FileReader to implement an image upload application
We’ll use the FileReader to implement an image upload application:
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.
Setting up the project structure
First, create the following file and directory structure:
├── css
| └── style.css
├── images
| └── upload.svg
├── js
| └── app.js
├── index.html
├── upload.php
└── uploads
Code language: JavaScript (javascript)
index.html
The following shows the index.html file:
<!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>
<h3>or drag & drop your PNG or JPEG files
here</h3>
</div>
<div class="image-list"></div>
</main>
<script src="js/app.js"></script>
</body>
</html>
Code language: JavaScript (javascript)
In the index.html, we add the css/style.css to the head of the html document
and js/app.js before the enclosing body tag.
The div element with the class dropzone allows you to drag and drop
images into it. Also, the file input element will enable you to select
files to upload.
The file input element accepts multiple files and only allows jpeg and
png images:
<input type="file" class="files" id="images"
accept="image/png, image/jpeg"
multiple />
Code language: JavaScript (javascript)
The style.css provides the styles that transform the file input element
into a button. Also, it has the active class that highlights the dropzone
when you drag the file into it.
The div element with the image-list class will show the uploaded images.
app.js
First, select dropzone, file input (files), and image list elements using
the querySelector() method:
const imageList = document.querySelector('.image-
list');
const fileInput = document.querySelector('.files');
const dropzone = document.querySelector('.dropzone');
Code language: JavaScript (javascript)
Second, define a function that adds the active class to or remove it
from the dropzone:
const setActive = (dropzone, active = true) => {
const hasActiveClass =
dropzone.classList.contains('active');
if (active && !hasActiveClass) {
return dropzone.classList.add('active');
}
if (!active && hasActiveClass) {
return dropzone.classList.remove('active');
}
};
Code language: JavaScript (javascript)
If you call setActive(dropzone), it’ll add the active class to the dropzone. If you
call setActive(dropzone, false), it’ll remove the active class from the dropzone.
Third, highlight the dropzone when the dragenter and dragover events occur
and remove the highlight when the dragleave and drop events occur:
dropzone.addEventListener('dragenter', (e) => {
e.preventDefault();
setActive(dropzone);
});
dropzone.addEventListener('dragover', (e) => {
e.preventDefault();
setActive(dropzone);
});
dropzone.addEventListener('dragleave', (e) => {
e.preventDefault();
setActive(dropzone, false);
});
dropzone.addEventListener('drop', (e) => {
e.preventDefault();
setActive(dropzone, false);
// ..
});
Code language: JavaScript (javascript)
Fourth, get the FileList object in the e.target as e.target.files in the drop event
handler of dropzone:
dropzone.addEventListener('drop', (e) => {
e.preventDefault();
setActive(dropzone, false);
// get the FileList
const { files } = e.dataTransfer;
handleImages(files);
});
Code language: JavaScript (javascript)
In the drop event handler, we use object destructuring to get
the FileList object and call the handleImages() function to handle the
uploaded images:
Fifth, define the handleImages() function:
const handleImages = (files) => {
// get valid images
let validImages = [...files].filter((file) =>
['image/jpeg', 'image/png'].includes(file.type)
);
// show the image
validImages.forEach(showImage);
// upload all images
uploadImages(validImages);
};
Code language: JavaScript (javascript)
The handleImages() function gets the valid images, shows each valid image
on the page using the showImage() function and uploads all the images to
the server using the uploadImages() function.
Sixth, define the showImage() function that shows each image in
the validImages array:
const showImage = (image) => {
const reader = new FileReader();
reader.readAsDataURL(image);
reader.addEventListener('load', (e) => {
const div = document.createElement('div');
div.classList.add('image');
div.innerHTML = `
<img src="${e.target.result}" alt="$
{image.name}">
<p>${image.name}</p>
<p>${formatBytes(image.size)}</p>
`;
imageList.appendChild(div);
});
};
Code language: JavaScript (javascript)
The showImage() uses the FileReader to read the uploaded image as the data
URL. Once the FileReader completes reading the file, it’ll create a
new div element to hold the image information.
Note that the formatBytes() function converts the size in bytes into a
human-readable format:
function formatBytes(size, decimals = 2) {
if (size === 0) return '0 bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB',
'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(size) / Math.log(k));
return parseFloat((size / Math.pow(k,
i)).toFixed(dm)) + ' ' + sizes[i];
}
Code language: JavaScript (javascript)
Seventh, define the uploadImages() function that uploads all images to the
server:
const uploadImages = async (images) => {
const formData = new FormData();
[...images].forEach((image) =>
formData.append('images[]', image, image.name)
);
const response = await fetch('upload.php', {
method: 'POST',
body: formData,
});
return await response.json();
};
Code language: JavaScript (javascript)
The uploadImages() function uses the FormData API to construct data for
submission:
const formData = new FormData();
Code language: JavaScript (javascript)
For each image, we add it to the FormData object:
[...images].forEach((image) =>
formData.append('images[]', image, image.name)
);
Code language: JavaScript (javascript)
Note that the images variable is a FileList object, not an array. To use
the forEach() method, you use the spread operator (...) to convert
the FileList object to an array like this:
[...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'])
The uploadImages() function uses the Fetch API to upload the images (as
the FormData object) to the server:
const response = await fetch('upload.php', {
method: 'POST',
body: formData,
});
return await response.json();
Code language: JavaScript (javascript)
Eighth, add the change event handler to the file input element if users
select files using this input element:
fileInput.addEventListener('change', (e) => {
const { files } = e.target;
handleImages(files);
});
Code language: JavaScript (javascript)
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:
// prevent the drag & drop on the page
document.addEventListener('dragover', (e) =>
e.preventDefault());
document.addEventListener('drop', (e) =>
e.preventDefault());
Code language: JavaScript (javascript)
The following shows the complete app.js file:
const imageList = document.querySelector('.image-
list');
const fileInput = document.querySelector('.files');
const dropzone = document.querySelector('.dropzone');
const setActive = (dropzone, active = true) => {
// active class
const hasActiveClass =
dropzone.classList.contains('active');
if (active && !hasActiveClass) {
return dropzone.classList.add('active');
}
if (!active && hasActiveClass) {
return dropzone.classList.remove('active');
}
};
dropzone.addEventListener('dragenter', (e) => {
e.preventDefault();
setActive(dropzone);
});
dropzone.addEventListener('dragover', (e) => {
e.preventDefault();
setActive(dropzone);
});
dropzone.addEventListener('dragleave', (e) => {
e.preventDefault();
setActive(dropzone, false);
});
dropzone.addEventListener('drop', (e) => {
e.preventDefault();
setActive(dropzone, false);
// get the valid files
const { files } = e.dataTransfer;
// hand images
handleImages(files);
});
const handleImages = (files) => {
// get valid images
let validImages = [...files].filter((file) =>
['image/jpeg', 'image/png'].includes(file.type)
);
// show the image
validImages.forEach(showImage);
// upload files
uploadImages(validImages);
};
const showImage = (image) => {
const reader = new FileReader();
reader.readAsDataURL(image);
reader.addEventListener('load', (e) => {
const div = document.createElement('div');
div.classList.add('image');
div.innerHTML = `
<img src="${e.target.result}" alt="$
{image.name}">
<p>${image.name}</p>
<p>${formatBytes(image.size)}</p>
`;
imageList.appendChild(div);
});
};
const uploadImages = async (images) => {
const formData = new FormData();
[...images].forEach((image) =>
formData.append('images[]', image, image.name)
);
const response = await fetch('upload.php', {
method: 'POST',
body: formData,
});
return await response.json();
};
function formatBytes(size, decimals = 2) {
if (size === 0) return '0 bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB',
'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(size) / Math.log(k));
return parseFloat((size / Math.pow(k,
i)).toFixed(dm)) + ' ' + sizes[i];
}
fileInput.addEventListener('change', (e) => {
const { files } = e.target;
handleImages(files);
});
// prevent the drag & drop on the page
document.addEventListener('dragover', (e) =>
e.preventDefault());
document.addEventListener('drop', (e) =>
e.preventDefault());
Code language: JavaScript (javascript)
Finally, create a simple upload.php script that moves the uploaded images
to the uploads folder:
<?php
const APP_ROOT = 'http://localhost:8080/';
const UPLOAD_DIR = __DIR__ . '/uploads';
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 MAX_SIZE = 5 * 1024 * 1024; // 5MB
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 ($filesize > MAX_SIZE) {
// construct an error message
$message = sprintf(
"The file %s is %s which is greater than
the allowed size %s",
$filename,
format_filesize($filesize),
format_filesize(MAX_SIZE)
);
$errors[$filesize] = $message;
continue;
}
// validate the file type
if (!in_array(get_mime_type($tmp),
array_keys(ALLOWED_FILES))) {
$errors[$filename] = "The file $filename is
allowed to upload";
}
}
if ($errors) {
response(400, [
'success' => false,
'message' => $errors
]);
}
// move the files
for ($i = 0; $i < $file_count; $i++) {
$filename = $files['name'][$i];
$tmp = $files['tmp_name'][$i];
$mime_type = get_mime_type($tmp);
// set the filename as the basename + extension
$uploaded_file = pathinfo($filename,
PATHINFO_FILENAME) . '.' . ALLOWED_FILES[$mime_type];
// new filepath
$filepath = UPLOAD_DIR . '/' . $uploaded_file;
// move the file to the upload dir
$success = move_uploaded_file($tmp, $filepath);
if (!$success) {
$errors[$filename] = "The file $filename was
failed to move.";
}
}
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;
}
$mime_type = finfo_file($info, $filename);
finfo_close($info);
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);
return sprintf("%.{$decimals}f", $bytes / pow(1024,
$factor)) . $units[(int)$factor];
}
/**
* 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)
Read more on how to upload multiple files in PHP for more
information.
Summary
Use the JavaScript FileReader API to read the files selected by users via drag
& drop or file input element.
What is Geolocation API
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.
For example, an eCommerce website can request you to share your
location. Once having the information, it can show you the product
availability as well as prices and discounts based on your location.
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.
The geolocation object
The Geolocation API is available through the navigator.geolocation object.
Check if the Geolocation API is supported
To check if a browser supports it, you can test if the geolocation property
exists on the navigator object like this:
if (!navigator.geolocation) {
console.error(`Your browser doesn't support
Geolocation`);
}
Code language: JavaScript (javascript)
Get the current position
To get the user’s current location, you call the getCurrentPosition() method
of the navigator.geolocation object.
The getCurrentPosition() method sends an asynchronous request to detect
the user’s location and queries the positioning hardware (like GPS) to
get the up-to-date data.
The getCurrentPosition() can succeed or fail. It accepts two optional
callbacks that will execute in each case respectively.
If the getCurrentPosition() succeeds, you’ll get the user’s position as
an GeolocationCoordinates object.
The GeolocationCoordinates object has the latitude and longitude properties that
represent a location.
JavaScript Geolocation example
The following example shows a simple application that has one
button. When you click the button, the browser will request you to
share your location. If you agree, it’ll show your current latitude and
longitude.
<!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');
// check if the Geolocation API is supported
if (!navigator.geolocation) {
message.textContent = `Your browser doesn't
support Geolocation`;
message.classList.add('error');
return;
}
// handle click event
const btn = document.querySelector('#show');
btn.addEventListener('click', function () {
// get the current position
navigator.geolocation.getCurrentPosition(onSuccess,
onError);
});
// handle success case
function onSuccess(position) {
const {
latitude,
longitude
} = position.coords;
message.classList.add('success');
message.textContent = `Your location: ($
{latitude},${longitude})`;
}
// handle error case
function onError() {
message.classList.add('error');
message.textContent = `Failed to get your
location!`;
}
})();
Code language: JavaScript (javascript)
How it works.
First, select the #message element by using the querySelector() method.
Next, show an error message if the browser doesn’t support the
Geolocation API.
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.
The onSuccess and onError callback functions are for handling the success
and error cases.
After that, define the onSuccess() function that gets the latitude and
longitude from the position.coords and shows them on the <div> element
with id message.
Finally, define the onError() function that shows an error message in case
the getCurrentPosition() method fails.
Note that all the code in the app.js are wrapped in an IIFE.
Test the app
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.
When you click the Show my location button, the browser will request
you to share your location like this:
If you click the Allow button, you’ll see your location as shown in the
following picture:
Notice that your location may be different.
To change the browser setting, you click the location icon and
the Manage button:
It’ll show a screen like this:
If you click the Trash icon, the allowed site will be removed.
And if you refresh the app and click the Show my location button, it’ll
request you to share your location again.
This time if you click the Block button:
…the app will show an error message:
Summary
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.