-2

Please check this 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.

I am trying to follow this example (https://codepen.io/brissmyr/pen/egidw) to create an X using css (not fonts) but I am unable to create it. What am I doing wrong? All I see are two vertical bars at the top corner of the image box but they are not transforming by 45degrees. I suspect that it could be a css transform issue but I could be wrong

The code is

/*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.textContent = "x";*/
  /*dont want font*/
  closeButtonLink.setAttribute('href', "#");
  closeButtonLink.classList.add("close");
  document.querySelector('#imageContainer').appendChild(newImage);

  document.querySelector('#imageContainer').appendChild(closeButtonLink);

}
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 {
  position: relative;
  margin: 0px;
  padding: 0px
  /*right: 80px;
      top:80px;
      width: 32px;
      height: 32px;
      */
  opacity: 0.3;
}

.close:hover {
  opacity: 1;
}

.close:before,
.close:after {
  /*position: relative;*/
  /*left: 15px;*/
  border: 1px solid black;
  top: 0px;
  right: 80px;
  content: ' ';
  /*height: 33px;*/
  width: 2px;
  background-color: #333;
}

.close:before {
  transform: rotate(45deg);
}

.close:after {
  transform: rotate(-45deg);
}
<!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>
  <!--a href="#" class="close"></a-->

  <div id="form-div" class="body__div--background">
    <form id="new-question-form" class="practice-question-form" [formGroup]="practiceQuestionForm" (ngSubmit)="addPracticeQuestion()" novalidate>

      <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" multiple onchange="handleFileSelect(this.files)">

          <label style="width:50%" class="custom-file-label" for="question-file-upload"></label>


        </div>

      </div>
      <div id="imageContainer"></div>
      <button type="submit" id="submit-practice-question-button" class="content-div__button--blue"> Submit! </button>
    </form>
  </div>
</body>
Manu Chadha
  • 15,555
  • 19
  • 91
  • 184
  • That duplicate could easily be found by typing your question title into Google verbatim, btw. – CBroe Aug 02 '18 at 09:34
  • I suspect that the issue is css transform but it isn't it seems. Basically I am trying to replicate a code to create an X in pure css but am unable to do so. I thought it could be some issue with transform but probably it isn't. Its something else but I don't know what – Manu Chadha Aug 02 '18 at 09:41
  • Your pseudo elements don’t have a height, so what you are rotating here are basically two tiny little squares to begin with, so you don’t see much of the effect. – CBroe Aug 02 '18 at 09:57
  • Thanks. Your comment on height was relevant but there was one more issue. I could transform the `pseudo-elements` only if I give them `position:absolute` i.e. `.close:before, .close:after { position:absolute}`. Without this, I only see vertical bars. The solution is that I give `imageContainer` a relative position, then I give the pseudo-elements absolute position and set `left` to 95 (because image is 80 and height is 31, so 80+15=95, almost center). But I don't understand why `position:absolute` is important. Would you know? I have updated the code - https://codepen.io/manuchadha/pen/PBKYBJ – Manu Chadha Aug 02 '18 at 10:34
  • _“But I don't understand why position:absolute is important. Would you know?”_ - because of what was explained in the answer given here, and also in the duplicate … Absolute positioning is not _required_ for this to work, it jut fixes the issue implicitly. – CBroe Aug 02 '18 at 10:59
  • sorry, I am struggling to understand the explanation. The answer here and in duplicate talks of `display`, not `position`. Absolute position seem to be required as otherwise I don't see the `X` – Manu Chadha Aug 02 '18 at 11:22
  • Exactly … so why are you using position then? – CBroe Aug 02 '18 at 11:22
  • Not sure if we are talking the same thing. Maybe I didn't ask the right question. Why `position:absolute` works but `position:relative` doesn't? – Manu Chadha Aug 02 '18 at 11:27
  • Looked at things again. So I either need to do `display:inline-block` or I need to set `position` for things to work. Got it. Also, for `position:relative` to work, I need to provide `display:inline-block` but I don't understand the relation between these two – Manu Chadha Aug 02 '18 at 11:30
  • Check out https://www.w3.org/TR/css-position-3/#dis-pos-flo – CBroe Aug 02 '18 at 11:38
  • Thanks bud! Happy to accept your suggestions as answer. It was your comment on height plus display. – Manu Chadha Aug 02 '18 at 11:43

1 Answers1

0

Pseudo elements are inline by default, so you must apply display: block or display: inline-block to transform them, check below snippet

/*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.textContent = "x";*/
  /*dont want font*/
  closeButtonLink.setAttribute('href', "#");
  closeButtonLink.classList.add("close");
  document.querySelector('#imageContainer').appendChild(newImage);

  document.querySelector('#imageContainer').appendChild(closeButtonLink);

}
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 {
  position: relative;
  margin: 0px;
  padding: 0px
  /*right: 80px;
      top:80px;
      width: 32px;
      height: 32px;
      */
  opacity: 0.3;
}

.close:hover {
  opacity: 1;
}

.close:before,
.close:after {
  /*position: relative;*/
  /*left: 15px;*/
  border: 1px solid black;
  top: 0px;
  right: 80px;
  content: 'X';
  /*height: 33px;*/
  width: 2px;
  display: inline-block;
  background-color: #333;
}

.close:before {
  transform: rotate(45deg);
}

.close:after {
  transform: rotate(-45deg);
}
<!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>
  <!--a href="#" class="close"></a-->

  <div id="form-div" class="body__div--background">
    <form id="new-question-form" class="practice-question-form" [formGroup]="practiceQuestionForm" (ngSubmit)="addPracticeQuestion()" novalidate>

      <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" multiple onchange="handleFileSelect(this.files)">

          <label style="width:50%" class="custom-file-label" for="question-file-upload"></label>


        </div>

      </div>
      <div id="imageContainer"></div>
      <button type="submit" id="submit-practice-question-button" class="content-div__button--blue"> Submit! </button>
    </form>
  </div>
</body>
  • thanks but it doesn't work. I don't want to use X in content. If you check the example I am trying to replicate, that example uses pure css and doesn't use content. – Manu Chadha Aug 02 '18 at 09:39
  • you wanted to check the transform property working or not right ? Here its working and if you don't want X in content then remove it. – Manpreet Matharu Aug 02 '18 at 09:41
  • I suspected that my code isn't working due to transform not working but it isn't the case it seems. I have now edited the description – Manu Chadha Aug 02 '18 at 09:42