0

Here is my code:

https://codepen.io/manuchadha/pen/PBKYBJ

I have created a form. I want to be able to upload an image using the file upload input. When an image is selected, I want to show a thumbnail of the image just below the file selector box and also show a close (x) sign on the top-right corner of the image which could be used to delete the image. But I am unable to create it. What am I doing wrong?

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <base href=""> 
  <title>Example</title>
  <!--meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'"-->
  <link rel="stylesheet" media="screen" href="fiddle.css">
  
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.1/css/bootstrap-select.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="fiddle.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.1/js/bootstrap-select.min.js"></script>
 
  
</head>
<body>
    
  <div id="form-div" class="body__div--background"> <!-- takes the complete width/height of content section -->
    <!-- The novalidate attribute in the <form> element prevents the browser from attempting native HTML validations.
    validation will be done using Angular's Validators which come with FormGroups and FormControls-->
    <form id="new-question-form" class="practice-question-form" [formGroup]="practiceQuestionForm" (ngSubmit)="addPracticeQuestion()" novalidate>
      <!-- label and small in same line. select in a new line, thus enclosed select in a div-->
      <div class="form-group">
      
      <div class="form-group">
        <label for="file-upload" class="control-label required">Upload files</label>
      
        <div class="custom-file" id="file-upload" lang="es">
          <input type="file" class="custom-file-input" id="question-file-upload" onchange="handleFileSelect()">
          <label class="custom-file-label" for="question-file-upload">
            Select file...
          </label>        
        </div>
      </div>

  <button type="submit"  id="submit-practice-question-button" class="content-div__button--blue"> Submit! </button>
    </form>
    <div id="imageContainer">
      </div>
      </div>
</div> 
</body>

CSS

body{
  margin:0px;
}

.body__div--background {
  background: linear-gradient(45deg,#33b1f8 37%,#6e90f6 100%); /*syntax linear-gradient(direction, color1 limit, color2 limit)*/
  color:#555555;
  font-family: Helvetica;
  line-height:1.5;
  font-size: 11px;
  letter-spacing: 0.25px;
}




#submit-practice-question-button{
  display:block;
}

#imageContainer{
  display:inline-block;
  border: 1px solid black;
}

.close {
  top:0;
  right:80; /*match the width of the image*/
  position: relative;
  opacity: 0.3;
}
.close:hover {
  opacity: 1;
}
.close:before, .close:after {
  position: relative;
  
  left: 15px;
  content: ' ';
  height: 33px;
  width: 2px;
  background-color: #333;
}
.close:before {
  transform: rotate(45deg);
}
.close:after {
  transform: rotate(-45deg);
}

JS

 /*handler for file upload*/
  function handleFileSelect(){
    console.log("got file upload event:");
    /*
     FileList object is the object returned as a result of a user selecting files using the <input> element,
     from a drag and drop operation's DataTransfer object, or from the mozGetAsFile() API on an HTMLCanvasElement.
     */
    var files = document.getElementById('question-file-upload').files;//event.target.files;
    console.log("files selected:"+files+", total selected: "+files.length);
    for(var i=0;i<files.length;i++)
    {
      console.log("files name:"+files[i].name)
      console.log("files object:"+files[i])
    }

    //working with only 1 file at the moment
    var file = files[0];

    if (files && file) {
      /*
      The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer,
      using File or Blob objects to specify the file or data to read.
       */
      var reader = new FileReader();

      /*bind onload event of FileReader to _handleReaderLoaded
      onload is a handler for the load event. This event is triggered by FileReader each time the reading operation is successfully completed.
       */
      reader.onload =this._handleReaderLoaded.bind(this);

      reader.readAsBinaryString(file);
    }
  }

  function _handleReaderLoaded(readerEvt) {
    var binaryString = readerEvt.target.result;
    var base64textString= btoa(binaryString);
    console.log(btoa(binaryString));
    var src = "data:image/png;base64,";
    src += base64textString;
   
    var newImage = document.createElement('img');
    newImage.src = src;
    newImage.width = newImage.height = "80";
    var closeButtonLink = document.createElement('a');
   closeButtonLink.setAttribute('href',"#"); 
 closeButtonLink.classList.add("close");   
document.querySelector('#imageContainer').appendChild = newImage;
    document.querySelector('#imageContainer').appendChild = closeButtonLink;
    
    
  }
halfer
  • 18,701
  • 13
  • 79
  • 158
Manu Chadha
  • 11,886
  • 11
  • 51
  • 115
  • Maybe you are looking for https://stackoverflow.com/questions/4459379/preview-an-image-before-it-is-uploaded – Ajay Aug 01 '18 at 21:01

1 Answers1

0

appendChild is a method, not a property.

For example instead of node.appendChild = newImage; it should be node.appendChild(newImage);

Also you needed to add the "X" in your anchor tag. I included that in the example below.

One more thing I did a small performance upgrade too where you save the reference to the query in a variable so you don't need to query the DOM twice.

var closeButtonLink = document.createElement('a');
closeButtonLink.textContent = "X";
closeButtonLink.setAttribute('href', "#");
closeButtonLink.classList.add("close");

// use a var here to only query once for imageContainer
var imgc = document.querySelector('#imageContainer');
imgc.appendChild(newImage);
imgc.appendChild(closeButtonLink);
Andrew Lohr
  • 4,830
  • 1
  • 21
  • 36
  • Thanks. I almost got what I have in mind. Instead of `X` as textContent, I want this - https://codepen.io/brissmyr/pen/egidw. Why am I not getting this result? – Manu Chadha Aug 02 '18 at 06:35