Final Project Code Breakdown
My image drag and drop feature which fetches image data from the backend to add to gallery
%%html
<head>
<title>Image Upload</title>
<!-- CSS Styling of the Page-->
<style>
body {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100vh;
}
.drop-zone {
width: 400px;
height: 400px;
border: 2px dashed #ccc;
text-align: center;
padding: 20px;
font-size: 16px;
margin-top: 40px;
margin-left: auto;
margin-right: auto;
}
.drop-zone.dragged-over {
background-color: #f7f7f7;
}
#imagePreview {
width: 200px;
height: auto;
margin-top: 20px;
}
</style>
</head>
<body>
<!-- Creating an HTML form where user inputs image, image name, and id -->
<form id="uploadForm">
<!-- To make it easy for users to drag and drop their images, there is a dropzone on screen -->
<div class="drop-zone" id="dropZone">
<p>Drag and drop images here</p>
</div>
<div>
<label for="imageName">Image Name:</label>
<input type="text" id="imageName" name="name">
</div>
<div>
<label for="uid">UID:</label>
<input type="text" id="uid" name="uid">
</div>
<input type="submit" value="Upload">
</form>
<!-- Creates an image preview for user to see -->
<img id="imagePreview" src="#" alt="Preview" style="display: none;">
<!-- Javascript Code Below -->
<script>
// Defines elements based on their HTML ids to attribute the image
const dropZone = document.getElementById('dropZone');
const imagePreview = document.getElementById('imagePreview');
const uploadForm = document.getElementById('uploadForm');
let base64Image = ''; // Variable to store the base64 value of the image
let formattedImage = '';
// Dropzone behavior
// event.preventDefault => prevents the default function of dropping an image, which would be to not allow the image to be dropped
// dropZone.classList.add() => changes css to match the css in parentheses
dropZone.addEventListener('dragenter', (event) => {
event.preventDefault();
dropZone.classList.add('dragged-over');
});
dropZone.addEventListener('dragleave', (event) => {
event.preventDefault();
dropZone.classList.remove('dragged-over');
});
dropZone.addEventListener('dragover', (event) => {
event.preventDefault();
dropZone.classList.add('dragged-over');
});
dropZone.addEventListener('drop', (event) => {
event.preventDefault();
dropZone.classList.remove('dragged-over');
// creates a constant for the file which is dragged over
const file = event.dataTransfer.files[0];
const reader = new FileReader();
// reads the file which was uploaded
reader.onload = (e) => {
// e.target.result --> reads the file using the FileReader JS object
// .split(',')[1] --> makes sure that the actual base64 data is sent, as the string which is saved is split after the first comma, to ensure that the base 64 code is given
base64Image = e.target.result.split(',')[1]; // Extract base64 value
// adds headers to the base64 image
// these headers may appear in base64Image, we wanted to make sure to have proper headers as we wanted
formattedImage = `data:image/jpeg;base64,${base64Image}`;
// can compare formatted to nonformatted data
console.log(base64Im)
console.log(formattedImage)
imagePreview.src = formattedImage;
imagePreview.style.display = 'block';
};
reader.readAsDataURL(file);
});
// code to post data to the API based on clicking the submit button
uploadForm.addEventListener('submit', (event) => {
event.preventDefault();
// takes data from the user input, gets the keys to be appended to api
const formData = {
image: formattedImage,
likes: '0',
name: uploadForm.elements.imageName.value,
uid: uploadForm.elements.uid.value
};
// request options for api
const requestOptions = {
method: 'POST', // Needs to be post to add data
body: JSON.stringify(formData), // Makes sure to post JSON file
mode: 'cors', // headers for cors policy
cache: 'default', // cache header
credentials: 'omit', // header for credentials
headers: {
'Content-Type': 'application/json', // necessary headers
'Authorization': 'Bearer my-token',
},
};
fetch('https://alaat.duckdns.org/api/images/', requestOptions) // change to your own API url
.then(response => {
console.log('Image uploaded successfully');
// Resets form and image preview
uploadForm.reset();
imagePreview.src = '#';
imagePreview.style.display = 'none';
base64Image = ''; // Clear base64Image for the next upload
})
// error code
.catch(error => {
console.error('Error uploading image:', error);
});
});
</script>
</body>
%%html
<style>
body {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100vh;
}
.drop-zone {
width: 400px;
height: 400px;
border: 2px dashed #ccc;
text-align: center;
padding: 20px;
font-size: 16px;
margin-top: 40px;
margin-left: auto;
margin-right: auto;
}
.drop-zone.dragged-over {
background-color: #f7f7f7;
}
#imagePreview {
width: 200px;
height: auto;
margin-top: 20px;
}
</style>
%%html
<body>
<!-- Creating an HTML form where user inputs image, image name, and id -->
<!-- Most items have unique ids so they can be accessed in Javascript to get their values -->
<form id="uploadForm">
<!-- To make it easy for users to drag and drop their images, there is a dropzone on screen -->
<div class="drop-zone" id="dropZone">
<p>Drag and drop images here</p>
</div>
<div>
<!-- Label for place to input the name of the image -->
<label for="imageName">Image Name:</label>
<input type="text" id="imageName" name="name">
</div>
<div>
<!-- Label for place to input the id of the image -->
<label for="uid">UID:</label>
<input type="text" id="uid" name="uid">
</div>
<!-- button to submit the form upon completion -->
<input type="submit" value="Upload">
</form>
<!-- Creates an image preview for user to see -->
<img id="imagePreview" src="#" alt="Preview" style="display: none;">
%%js
// Defines elements based on their HTML ids to attribute the image
const dropZone = document.getElementById('dropZone');
const imagePreview = document.getElementById('imagePreview');
const uploadForm = document.getElementById('uploadForm');
let base64Image = ''; // Variable to store the base64 value of the image
let formattedImage = '';
// Dropzone behavior
// event.preventDefault => prevents the default function of dropping an image, which would be to not allow the image to be dropped(you cannot generally drag and drop things, so this disables that)
// dropZone.classList.add() => changes css, changes based on whatever is specified in the style portion of code
dropZone.addEventListener('dragenter', (event) => {
event.preventDefault();
dropZone.classList.add('dragged-over');
});
dropZone.addEventListener('dragleave', (event) => {
event.preventDefault();
dropZone.classList.remove('dragged-over');
});
dropZone.addEventListener('dragover', (event) => {
event.preventDefault();
dropZone.classList.add('dragged-over');
});
dropZone.addEventListener('drop', (event) => {
event.preventDefault();
dropZone.classList.remove('dragged-over');
// creates a constant for the file which is dragged over
const file = event.dataTransfer.files[0];
// uses Javascript FileReader object to go through whatever data is in the file
const reader = new FileReader();
// reads the file which was uploaded
reader.onload = (e) => {
// e.target.result --> reads the file using the FileReader JS object
// .split(',')[1] --> makes sure that the actual base64 data is sent, as the string which is saved is split after the first comma, to ensure that the base 64 code is given
base64Image = e.target.result.split(',')[1]; // Extract base64 value
// adds headers to the base64 image
// these headers may appear in base64Image, we wanted to make sure to have proper headers as we wanted
formattedImage = `data:image/jpeg;base64,${base64Image}`;
// can compare formatted to nonformatted data
console.log(base64Image)
console.log(formattedImage)
// sets image preview to the formatted image
imagePreview.src = formattedImage;
imagePreview.style.display = 'block';
};
// read data in the file, also gets a url representation of the file, which is necessary for the base64 encryption
reader.readAsDataURL(file);
});
// code to post data to the API based on clicking the submit button
uploadForm.addEventListener('submit', (event) => {
event.preventDefault();
// takes data from the user input, gets the keys to be appended to api
const formData = {
// gets all of these values from the HTML elements or defined variables
image: formattedImage,
likes: '0',
name: uploadForm.elements.imageName.value,
uid: uploadForm.elements.uid.value
};
// request options for api
const requestOptions = {
method: 'POST', // Needs to be post to add data
body: JSON.stringify(formData), // Makes sure to post JSON file
mode: 'cors', // headers for cors policy
cache: 'default', // cache header
credentials: 'omit', // header for credentials
headers: {
'Content-Type': 'application/json', // necessary headers
'Authorization': 'Bearer my-token',
},
};
fetch('https://alaat.duckdns.org/api/images/', requestOptions) // change to your own API url
.then(response => {
console.log('Image uploaded successfully');
// Resets form and image preview after posting image
uploadForm.reset();
imagePreview.src = '#';
imagePreview.style.display = 'none';
base64Image = ''; // Clear base64Image for the next upload
})
// error code
.catch(error => {
console.error('Error uploading image:', error);
});
});
All together, this code creates a functional drag and drop feature which classifies the image based on user input and stores an image as a base64 value for easy uploading to an API and allows the image to be accessed in multiple places.