The Full Code

The code for this feature is meant to be able to create an image drag and drop screen, as well as places for users to input a name and uid for the image. Once the image is submitted, the data is added to the images API and then be accessed for other purposes.

%%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>

CSS

Here is the code which was used to create the CSS. This was done to make a relatively user friendly interface. This code is easily adaptable to any needs and other website styles and features.

%%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 Code

The HTML code is responsible for creating the displays and what is actually done on screen. These HTML elements are all styled based on the specifications in the CSS file.

A form is created so it is easy for a user to submit all 3 items all at once with the click of the submit button.

%%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;">

Javascript Code

This code is essential for the features to work and to be able to access and post to the API. The javascript code helps for functionality, while HTML and CSS are what mostly create the visual and stylistic features of the webpage.

%%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.