Setting file input as background for an HTML element - javascript

I am creating a UI where the user wants to upload her profile picture using <input type="file"> by clicking on its corresponding <label>. I want to show the preview of the image as the background of the same <label>. I tried to use inputNode.files[0] in JavaScript but it does not work.
I am also working on a button X which clears the selected file field values and essentially the background image too but that's the next step of the goal. Some guidance regarding this is also welcome, since I have not thought about this either.
document.getElementById("avatar").onchange = function(e) {
console.log("file changed", e.target.files[0]);
// document.getElementById("preview-img");
document.getElementById("avatar-label").style.backgroundImage = e.target.files[0];
// document.getElementById("avatar-label").style.backgroundImage = 'url("https://picsum.photos/70/70")';
};
#avatar {
display: inline-block;
height: 0;
width: 0;
}
#avatar-label {
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 70px;
width: 70px;
border: solid 1px #333;
/*background: url('https://picsum.photos/70/70');*/
}
#avatar-label:hover {
cursor: pointer;
}
/* styling for unselecting the image */
#avatar-label #unselect-image {
display: none;
position: absolute;
top: 0;
right: 0;
border: none;
outline: none;
background: #fff;
}
<form action="" method="get">
<input accept="image/*" type="file" name="avatar" id="avatar">
<label for="avatar" id="avatar-label">
+
<button type="button" id="unselect-image">X</button>
</label>
<img src="" alt="" id="preview-img">
</form>

Showing in background
Use file reader instead of directly assigning the image object.
You may change your script to show background image as below
document.getElementById('avatar').onchange = function (e){
var file = e.target.files[0];
var reader = new FileReader();
reader.onloadend = function(){
document.getElementById('avatar-label').style.backgroundImage = "url(" + reader.result + ")";
document.getElementById('unselect-image').style.display = "inline";
}
if(file){
reader.readAsDataURL(file);
}
}
Clearing the background
For clearing the background image the following script may help
document.getElementById('unselect-image').onclick = function (){
document.getElementById('avatar-label').style.background = "none";
document.getElementById('unselect-image').style.display = "none";
};

The value of the background-image property in CSS is a string consisting of url(, followed by a URL, followed by ).
It is not a file object.
So you need to take that file object and convert it into a URL. This answer to another question explains how to do that.
Then you need to wrap the result in url( and ) and assign it:
.then( data => {
document.getElementById("avatar-label").style.backgroundImage = `url(${data})`;
})

Here are making thumbnail on uploading image
And to clear selected field is simple.
You assign '' into "src" property of html "img" element and value property of html "input" element.
Replace "label" with "img" if possible.

Related

Creating ID card with HTML

I'm trying to create a simple ID card template with HTML but I got stocked for days looking for how to make passport photograph appear in the photograph box. I also noticed that the print preview of the ID card is not the same as what I see on screen, how can I fix this too please? Below is the code...
function printDiv(divName) {
var printContents = document.getElementById(divName).innerHTML;
w = window.open();
w.document.write(printContents);
w.print();
w.close();
}
body {
background-image: url("id-template.jpg");
background-attachment: fixed;
background-repeat: no-repeat;
background-position: center;
}
#media print {
#print {
display: none;
}
}
#print {
position: fixed;
bottom: -4px;
}
div {
padding-top: 204px;
}
<div id="identity"> <span style="padding-left: 436px;">
<form style="display: inline;"><input type="file" accept="image/jpeg"
placeholder="PASSPORT PHOTO" style="border-color: grey; border-radius: 90px; height: 155px; width: 155px; text-align: center; font-family: monospace; font-size: 10px; margin-bottom: 7px" /></form></span>
<br>
<span style="padding-left: 370px">
<form style="display: inline;"><input placeholder="YOUR NAME" style="border-color: grey; border-radius: 5px; height: 25px; width: 280px; text-align: center; font-family: monospace; font-size: 20px;" /></form></span>
</div><br>
<center><input type="button" id="print" onclick="print()" value="Print" /></center>
The two helps I need
I want the photograph to appear when selected from the user's device.
I want the print preview to show exactly what on the page.
This is the id-template.jpg I'm working with.
Thanks.
The html in your question has lots of noise and was relying on odd strategies for positioning.
For the sake of showing the core of the issue you are meant to solve, I stripped it down to the bare minimum. It won't perfectly match with your expectations but the css is well commmented so it will be easy for you to restyle it according to your needs.
Displaying the picture loaded by user in an <input type=file>
Anyway the main problem there was how to show the picture in the file just loaded inside an input type="file" element.
The key is having a change event handler on your input file element so that when the user loads a new file, it will attempt to read it using a FileReader and will change the src attribute of an <img> element existing in the dom.
.noprint class to style elements when #media print
I also added a class noprint to add to all the elements that will be hidden by the media query #media print. Such class is given to the <input type="file"> and to the <button> for printing.
References
https://developer.mozilla.org/en-US/docs/Web/API/FileReader
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
Demo
I did a very small demo to show the point:
function printDiv(divName) {
var printContents = document.getElementById(divName).innerHTML;
w = window.open();
w.document.write(printContents);
w.print();
w.close();
}
/*shows inside #preview the picture loaded in the #photo element*/
function previewImage() {
var preview = document.getElementById('preview');
var file = document.getElementById('photo').files[0];
//creates a FileReader with the onLoadEnd event handler
var reader = new FileReader();
reader.onloadend = function () {
//..that will change the src attribute of the preview element to show the picture loaded
preview.src = reader.result;
}
//if there's a file loaded
if (file) {
//unhide the #preview element
preview.style.display = "block";
//lets the FileReader reads the file loaded
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
body {
font-family: monospace; /* <----- here I set the font/size for all children in body */
font-size: 18px;
}
/*hides the .noprint elements when printing*/
#media print {
.noprint {
display: none !important;
}
}
/*flex container*/
#identity{
display: flex;
flex-direction: column;
gap: 1em; /* <----- here I set space between elements in the container */
}
/*flex items*/
#identity > *{
margin: 0 auto; /*horizontally centered*/
}
/*all input elements*/
input{
border-color: grey;
text-align: center;
}
/*name input*/
#name{
width: 30ch; /* <----- here I chose the name input to have 30ch*/
}
/*preview*/
#preview{
width: 30%; /* <----- here I chose the preview to have 30% container width*/
}
#print{
display: block;
margin: 1em auto 0 auto;
cursor: pointer;
}
<body>
<form id="identity">
<input
id="photo"
class="noprint"
name="photo"
type="file"
accept="image/jpeg"
placeholder="PASSPORT PHOTO"
onchange="previewImage()">
<img id="preview" src="#" alt="Image preview" style="display:none;">
<input
id="name"
name="name"
placeholder="YOUR NAME">
</form>
<button type="button" id="print" class="noprint" onclick="print()">Print</button>
</body>

Insert an HTML icon within a Javascript new div

In this Django project, there is a Javascript function creating a new div in which we display some data.
for (var i = 0; i < files.length; i++) {
var newDiv = document.createElement('div');
newDiv.setAttribute("class","files_div");
//Call the helper function to check if it's a PDF
newDiv.setAttribute("onclick","check_files(this)")
console.log(files[i]) //Print the files
newDiv.innerHTML = files[i];
divParent.appendChild(newDiv);
}
I need to add icons next to this data. For example, a pdf icon if it's a pdf file.
How do you add icons in Javascript once a new div is created?
Have you considered a css-based solution on this? You can add an icon to any element using pseudo elements. This adds another element next to .pdf which you can style to fit your purpose. Using background-image allows you to add an icon.
.pdf {
padding-left: 35px;
position: relative;
}
.pdf:before {
content: "";
height: 20px;
width: 20px;
display: block;
background: url("https://via.placeholder.com/20");
position: absolute;
left: 0;
}
<div class="pdf">PDF</div>

Get Original Image Width And Height From A New Image() Object - JavaScript

I have an image uploader where I have some PHP checks that happen on the server side. What I want to do is also provide frontend validations for the user, but I am having an issue getting the values to do the maths for the image resolution in megapixels. On the server side I can just use the file's width and height properties and then multiply them.
The problem I have is on the frontend when using a new Image() object, when I get the width and height properties it gives me the values of the image file in the container, not the width and height values of the source file / original image.
I thought I could just use the .src property and get the size of that instead, but this doesn't work either.
In the code below as you can see the Image() object is assigned to a thumbnailElement variable.
If you click the Select Files button and add an image it will show the thumbnails and log the original file size to the console, but not the original width ?
Note: the updateThumbnail() function is invoked in the HTML
Codepen Link: https://codepen.io/thechewy/pen/yLjvqWe
var zone = document.getElementById("zone"),
selectedImagesContainer = document.getElementById("show-selected-images"),
fileUploader = document.getElementById("standard-upload-files");
zone.addEventListener("click", (e) => {
// assigns the zone element to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
fileUploader.addEventListener("change", (e) => {
// this function is further down but declared here and shows a thumbnail of the image
[...fileUploader.files].forEach(updateThumbnail);
});
function updateThumbnail(file) {
let uploadImageWrapper = document.createElement("figure"), // image wrapper <figure> element
thumbnailElement = new Image(); // image
// image thumbnail
thumbnailElement.classList.add("thumbnail");
thumbnailElement.src = URL.createObjectURL(file);
// appending elements
selectedImagesContainer.append(uploadImageWrapper); // append <figure> element
uploadImageWrapper.append(thumbnailElement); // append image thumbnail
console.log("file size is: ", file.size);
console.log("file width is: ", thumbnailElement.width);
} // end of 'updateThumbnail' function
body {
margin: 0;
display: flex;
justify-content: center;
font-family: arial;
}
form {
width: 50%;
max-width: 600px;
}
.select-files {
padding: 1rem;
background: red;
cursor: pointer;
color: #fff;
font-weight: bold;
}
#show-selected-images {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-top: 2rem;
}
figure {
width: 100%;
margin: 0;
}
img {
display: block;
width: 100%;
height: auto;
}
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="zone">
<p class="select-files">SELECT FILES</p>
</div>
<div class="inner-wrapper">
<div class="upload-label-wrapper">
<input id="standard-upload-files" style="display:none;" type="file" name="standard-upload-files[]" multiple>
</div>
<button id="submit-images" oninput="updateThumbnail(this.files)">SUBMIT IMAGES</button>
</div>
<div id="show-selected-images"></div>
</form>
You need the naturalWidth property to get actual image width in pixels, also to get that value reliably you should use the HTMLImageElement.decode() method that returns a promise which is resolved once the full-resolution image is fully decoded, like this:
var zone = document.getElementById("zone"),
selectedImagesContainer = document.getElementById("show-selected-images"),
fileUploader = document.getElementById("standard-upload-files");
zone.addEventListener("click", (e) => {
// assigns the zone element to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
fileUploader.addEventListener("change", (e) => {
// this function is further down but declared here and shows a thumbnail of the image
[...fileUploader.files].forEach(updateThumbnail);
});
function updateThumbnail(file) {
let uploadImageWrapper = document.createElement("figure"), // image wrapper <figure> element
thumbnailElement = new Image(); // image
// image thumbnail
thumbnailElement.classList.add("thumbnail");
thumbnailElement.src = URL.createObjectURL(file);
// appending elements
selectedImagesContainer.append(uploadImageWrapper); // append <figure> element
uploadImageWrapper.append(thumbnailElement); // append image thumbnail
console.log("file size is: ", file.size);
thumbnailElement.decode().then(() => {
console.log("file width is: ", thumbnailElement.naturalWidth);
}).catch((encodingError) => {
// Do something with the error.
});
} // end of 'updateThumbnail' function
body {
margin: 0;
display: flex;
justify-content: center;
font-family: arial;
}
form {
width: 50%;
max-width: 600px;
}
.select-files {
padding: 1rem;
background: red;
cursor: pointer;
color: #fff;
font-weight: bold;
}
#show-selected-images {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-top: 2rem;
}
figure {
width: 100%;
margin: 0;
}
img {
display: block;
width: 100%;
height: auto;
}
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="zone">
<p class="select-files">SELECT FILES</p>
</div>
<div class="inner-wrapper">
<div class="upload-label-wrapper">
<input id="standard-upload-files" style="display:none;" type="file" name="standard-upload-files[]" multiple>
</div>
<button id="submit-images" oninput="updateThumbnail(this.files)">SUBMIT IMAGES</button>
</div>
<div id="show-selected-images"></div>
</form>
Yes, .width and .height will return the computed width and height of the element when it's visible in the doc.
Since your <img> element doesn't have an srcset attribute, you can use both its naturalWidth and naturalHeight to get the actual intrinsic size of the loaded image. If you had this srcset attribute though, these values could be divided by the size multiplier of the loaded source.
If you weren't displaying the image in a thumbnail, an efficient way to get the dimensions of the image would have been to call createImageBitmap() either on the File object you have directly, and to check the .width and .height properties of the resolved ImageBitmap object.
But since you do show the image, in your case that'd be overkill. Using .naturalWidth and .naturalHeight (after the image has loaded) is just enough.

How do I prevent my image from disappearing when I use a click event on Javascript?

I'm creating an image gallery and whenever I click on the image, it displays it fully across the screen. However, whenever I try to click off of it and return to the normal website screen, the image is completely gone.
Here is a codepen showing the problem https://codepen.io/designextras/pen/WNrQMdM
In the html I am targeting the image tag by using firstElementChild in my Javascript for ".services-cell"
<div class="services-cell">
<img class="services-cell_img" src="gallery/img-1.jpg" alt="">
<div class="services-cell_text">Digital Marketing</div>
</div>
Here is the Javascript, it is also in the codepen above
let galleryImages = document.querySelectorAll('.services-cell');
let getLatestOpenedImg;
let windowWidth = window.innerWidth;
if(galleryImages) {
galleryImages.forEach(function(image, index){
image.onclick = function() {
console.log(image.firstElementChild);
getLatestOpenedImg = index + 1;
let container = document.body;
let newImgWindow = document.createElement('div');
container.appendChild(newImgWindow);
newImgWindow.setAttribute('class', 'img-window');
newImgWindow.setAttribute('onclick', 'closeImg()');
let newImg = image.firstElementChild;
newImgWindow.appendChild(newImg);
newImg.classList.remove('services-cell_img');
newImg.classList.add('popup-img');
}
})
}
function closeImg() {
document.querySelector('.img-window').remove();
}
and here is the CSS classes that I'm trying to add whenever I click on the image
.img-window {
width: 100vw;
height:100vh;
background: rgba(0,0,0,0.8);
position: fixed;
top: 0;
left: 0;
z-index: 100;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.popup-img {
max-height: 80vh;
max-width: 80vw;
z-index: 200;
}
So the bottom function closeImg() seems to be the problem, but I don't know else I'd write my code in order to close out the image pop up and return to the screen without it completely removing my image from the html
When you append the image to newImgWIndow, you're removing it from its original DIV. You should clone the image instead of moving it.
let newImg = image.firstElementChild.cloneNode();
newImgWindow.appendChild(newImg);
newImg.classList.remove('services-cell_img');
newImg.classList.add('popup-img');

jQuery File Upload Doesn't work on Safari

I have a button that, when clicked in Chrome or Firefox or Edge, shows the file browser window where I can then select a file and complete the file upload. However, when I click the button in Safari, nothing happens - the file browser window does not appear. I am running on Windows 10 and have a Windows version of Safari installed.
Button:
Upload File
Handler:
$(document).ready(function() {
$("#uploadFile").click(function() {
$("#uploadFileHandle").click();
$('html,body').css('cursor','progress');
var formdata = false;
if (window.FormData) {
formdata = new FormData();
}
$("#uploadFileHandle").on("change", function() {
$('html,body').css('cursor','progress');
var i = 0, len = this.files.length, file;
file = this.files[0];
formdata.append("fileUpload", file)
if (formdata) {
csrftoken();
$.ajax({
url: "/profile/uploadFile",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function (response) {
if (response.success) {
var res = response.file;
$('html,body').css('cursor','default');
}
}
})
}
});
});
});
Any ideas on how to get the file browser window to appear when the Upload File button is clicked in Safari?
I believe that, for security reasons, some browsers will baulk at programmatic activation of file upload dialogs.
Instead of an a tag, try using the label tag with a for attribute equal to the ID of your file upload input, like this:
<label for="uploadFileHandle">Upload File</label>
When a label has a for attribute, clicking it will automatically also click the element that has a matching ID. This behavior is not blocked by any browsers I know of and will lighten your javascript, too.
body {
padding: 25px;
}
#uploadFile {
transition: all .2s ease-in-out;
text-transform: uppercase;
text-align: center;
padding: 10px 20px;
background-color: #2ecc71;
border: 2px solid #2ecc71;
color: #ffffff;
font-family: sans-serif;
cursor: pointer;
}
#uploadFile:hover {
background-color: #ffffff;
color: #2ecc71;
}
#uploadFileHandle {
visibility: hidden;
}
<label for="uploadFileHandle" id="uploadFile">Upload File</label>
<input type="file" id="uploadFileHandle">
Figured it out thanks to a comment on this post:
How to open a file / browse dialog using javascript?
I apologize for leaving out an important line in my original question:
<input type="file" class="displayNone" id="uploadFileHandle">
Apparently, Safari doesn't like the class="displayNone" on the input element. I got it working by removing the displayNone class and then styling it differently to hide the element. Thanks for the replies everyone!

Categories