0% found this document useful (0 votes)
240 views38 pages

JavaScript Drag and Drop

The document provides an introduction to JavaScript drag and drop functionality. It describes how to make elements draggable by adding the draggable attribute, and how drag events like dragstart, drag, and dragend fire on draggable elements. It also explains how drop targets work, with dragenter, dragover, dragleave, and drop events firing. The dataTransfer object is used to transfer data between elements. Finally, it provides a code example to demonstrate drag and drop functionality by making an element draggable and allowing it to be dropped onto other elements.

Uploaded by

RAVI Kumar
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
240 views38 pages

JavaScript Drag and Drop

The document provides an introduction to JavaScript drag and drop functionality. It describes how to make elements draggable by adding the draggable attribute, and how drag events like dragstart, drag, and dragend fire on draggable elements. It also explains how drop targets work, with dragenter, dragover, dragleave, and drop events firing. The dataTransfer object is used to transfer data between elements. Finally, it provides a code example to demonstrate drag and drop functionality by making an element draggable and allowing it to be dropped onto other elements.

Uploaded by

RAVI Kumar
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 38

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.

You might also like