Custom preview images using FileReader js - javascript

I need to create custom preview the selected images. I have seen several answers about doing this and they do it by creating an img element and using appendTo to place them in a specific div. I have done this successfully as shown below in a jquery "change event"
$(document).on("change", "#file", function() {
var countFiles = $(this)[0].files.length;
var imgPreview = $("#img-preview");
for (var i = 0; i < countFiles; i++) {
var reader = new FileReader();
reader.onload = function (e) {
$("<img />", {
"src": e.target.result,
"class": "img-thumbnail"
}).appendTo(imgPreview);
}
reader.readAsDataURL($(this)[0].files[i]);
}
});
The problem I have is to preview the images with the following structure:
Here the custom structure with bootstrap
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="wraper-foto-grande d-flex justify-content-center">
<img class="img-fluid d-flex align-items-center" src="img1.jpg">
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-4">
<div class="wrapper-thumb d-flex justify-content-center">
<img class="img-fluid d-flex align-items-center" src="img2.jpg">
</div>
</div>
<div class="col-md-4">
<div class="wrapper-thumb d-flex justify-content-center">
<img class="img-fluid d-flex align-items-center" src="img3.jpg">
</div>
</div>
<div class="col-md-4">
<div class="wrapper-thumb d-flex justify-content-center">
<img class="img-fluid d-flex align-items-center" src="img4.jpg">
</div>
</div>
</div>
</div>
I have tried to create an array with the target.result to later use it in a function and create the structure mentioned above but I have the problem that the created array is empty. I have also seen several answers on this topic but I have not succeeded in creating the preview.
Here code:
$(document).on("change", "#file", function() {
var countFiles = $(this)[0].files.length;
var imgPreview = $("#img-preview");
var imagesArray = [];
for (var i = 0; i < countFiles; i++) {
var reader = new FileReader();
reader.onload = function (e) {
imagesArray.push(e.target.result);
}
reader.readAsDataURL($(this)[0].files[i]);
}
console.log(imagesArray.length); //show 0
console.log(imagesArray); // guess select 4 images, show 4 elements inside but I cannot access
});
My idea was to use imagesArray in a function to create the custom structure with bootstrap but I don't have access to any element.
Thanks for your help.

1st: Check if more than 1 images selected then conditionally set [col-12] class for first preview and rest of set [col-4] class & before image append in result div(#imageResults) should be empty like $('#imageResults').html('');.
2nd:
Check inline condition like i==0?'12':'4'.
Note: I added border class in image parent div for testing purpose only.
$(document).on("change", "#file", function() {
var countFiles = $(this)[0].files.length;
//Result div empty before appending new selected image
$('#imageResults').html('');
for (var i = 0; i < countFiles; i++) {
//`const columnSet` for full col-12 or col-4 class
const columnSet = (i==0?'12':'4');
var reader = new FileReader();
reader.onload = function (e) {
// Append image preview divs
$('#imageResults').append(`<div class="mb-3 col-`+columnSet+`">
<div class="border d-flex justify-content-center">
<img class="img-fluid d-flex align-items-center" src="`+e.target.result+`">
</div>
</div>`);
}
reader.readAsDataURL($(this)[0].files[i]);
}
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container my-3">
<div class="row">
<div class="col-md-12">
<div class="input-group mb-3">
<label class="custom-file">
<input type="file" class="custom-file-input" id="file" accept="image/*" multiple="multiple">
<span class="custom-file-label">Choose multiple image</span>
</label>
</div>
</div>
</div>
<!-- Image Preview Area -->
<div class="row" id="imageResults">
</div>
</div>

Related

how to add same nodes two times with append()?

I want to add node named as card into container two times but the way1 didn't worked.
So i solved way2. But it looks like not good code. so i want to anohter way
Please teach me.
html
<div class="container">
<div class="row">
<div class="col-sm-4">
<img src="https://via.placeholder.com/600" class="w-100">
<h5 class="title">Card title</h5>
<p class="price">price : 70000</p>
</div>
</div>
</div>
js //way1 didn't added two times
let card = document.querySelector('.row').cloneNode(true) //want to add in container two times
let container = document.querySelector('.container');
container.append(card)
container.append(card)
js //way2 to solve but doesn't look good
let card = document.querySelector('.row').cloneNode(true);
let card2 = document.querySelector('.row').cloneNode(true);
let container = document.querySelector('.container');
container.append(card, card2)
You have to 're-clone' the row to be able to append it again. You can't append the same elements again. Try using a clone function, something like
const container = document.querySelector(`.container`);
const cloneRow = _ =>
document.querySelector(`.container .row:first-child`).cloneNode(true);
container.append(cloneRow());
container.append(cloneRow());
<div class="container">
<div class="row">
<div class="col-sm-4">
<img src="https://via.placeholder.com/50" class="w-100">
<h5 class="title">Card title</h5>
<p class="price">price : 70000</p>
</div>
</div>
</div>
Alternative is to use the html of the row to copy/append:
const container = document.querySelector(`.container`);
const nwRow = document.querySelector(`.row`).innerHTML;
// add 5 rows
for (let i = 0; i < 5; i += 1) {
container.append(
Object.assign(
document.createElement(`div`),
{className: `row`, innerHTML: nwRow} ) );
}
<div class="container">
<div class="row">
<div class="col-sm-4">
<img src="https://via.placeholder.com/50" class="w-100">
<h5 class="title">Card title</h5>
<p class="price">price : 70000</p>
</div>
</div>
</div>

Cant bind .change() event with dynamically generated elements

I have a button, when clicking on it the table rows and profile pic instances are generated.
Profile Pic instance which is generated:
<div class="row justify-content-center" id="owner-pic-row">
----> <div class="col-sm-2 prof-pic-col" id="col-owner-pic-1">
<div class="avatar-upload">
<div class="avatar-edit">
<input type='file' id="imageUploadOwner" accept=".png, .jpg, .jpeg" />
<label for="imageUploadOwner"></label>
</div>
<div class="avatar-preview">
<div id="imagePreviewOwner" style="background-image: url('/media/profile_images/default-profile-pic-owner.jpg');">
</div>
<p class="owner-pic-des">Owner</p>
</div>
</div>
</div> <----
</div>
The code inside ----> code <---- is generated while pressing the button
when clicking the button only one time, overall HTML code:
<div class="row justify-content-center" id="owner-pic-row">
<div class="col-sm-2 prof-pic-col" id="col-owner-pic-1">
<div class="avatar-upload">
<div class="avatar-edit">
<input type='file' id="imageUploadOwner" accept=".png, .jpg, .jpeg" />
<label for="imageUploadOwner"></label>
</div>
<div class="avatar-preview">
<div id="imagePreviewOwner" style="background-image: url('/media/profile_images/default-profile-pic-owner.jpg');">
</div>
<p class="owner-pic-des">Owner</p>
</div>
</div>
</div>
<div class="col-sm-2 prof-pic-col" id="col-owner-pic-2">
<div class="avatar-upload">
<div class="avatar-edit">
<input type='file' id="imageUploadOwner" accept=".png, .jpg, .jpeg" />
<label for="imageUploadOwner"></label>
</div>
<div class="avatar-preview">
<div id="imagePreviewOwner" style="background-image: url('/media/profile_images/default-profile-pic-owner.jpg');">
</div>
<p class="owner-pic-des">Owner</p>
</div>
</div>
</div>
</div>
Below is the JS Script for handling change event :
function readURL(input, type) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
if (type == "Owner") {
$($(input).parent().parent()).find('#imagePreviewOwner').css('background-image', "url('" + e.target.result + "')");
$($(input).parent().parent()).find('#imagePreviewOwner').hide();
$($(input).parent().parent()).find('#imagePreviewOwner').fadeIn(650);
}
}
reader.readAsDataURL(input.files[0]);
}
}
$("#owner-pic-row").on("click", "#imageUploadOwner", function() {
===> console.log($($(this).parent().parent().parent()).attr("id")) <===
$(this).change(function () {
let type = "Owner"
readURL(this, type);
});
})
Now the problem here is when ever I click on the input[id="imageUploadOwner"] in the second profile instance i.e. div[id="col-owner-pic-2"], the code inside ===> <=== prints id="col-owner-pic-1" instead of col-owner-pic-2. This means that when I change the profile pic the image is shown in the first instance everytime, regardless of which instance I want to change. The javascript code which I showed works perfectly for similar kind of logic but not here. What should I do?

Replace class name on window resize

Here is my Markup. I want to update/replace class name col-sm-3
to col-md-6 on widow resize (ex: width < 800)
<div class="llotherlogos-userthumb">
<div class="col-sm-3">
<div class="logo-thumb">
<img class="img-fluid" src="images/logos/logo-seven.jpg" alt="">
<div class="logo-caption">
<div class="ll-category">Business</div>
<div class="ll-price"><span>1000BDT</span>5000 BDT</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="logo-thumb">
<img class="img-fluid" src="images/logos/logo-eight.jpg" alt="">
<div class="logo-caption">
<div class="ll-category">Business</div>
<div class="ll-price"><span>1000BDT</span>5000 BDT</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="logo-thumb">
<img class="img-fluid" src="images/logos/logo-nine.jpg" alt="">
<div class="logo-caption">
<div class="ll-category">Business</div>
<div class="ll-price"><span>1000BDT</span>5000 BDT</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="logo-thumb">
<img class="img-fluid" src="images/logos/logo-ten.jpg" alt="">
<div class="logo-caption">
<div class="ll-category">Business</div>
<div class="ll-price"><span>1000BDT</span>5000 BDT</div>
</div>
</div>
</div>
</div>
JavaScript
var otherlogos = function(){
var ww = document.body.clientWidth;
var myLogos = document.querySelectorAll(".llotherlogos-userthumb .col-sm-3");
if(ww < 800){
myLogos.className.replace(col-sm-3, col-md-6);
}
}
window.onresize = otherLogos;
You need this:
myLogos.className.replace(col-sm-3, col-md-6);
To be:
myLogos[0].classList.replace('col-sm-3', 'col-md-6');
(querySelectorAll returns an array of elements, even if only one element matches, hence the need for myLogos[0].)
To do this for multiple elements, you'd need something like this (explicit for loop, because I think foreach doesn't work here):
for (let i = 0; i < myLogos.length; ++i)
myLogos[i].classList.replace('col-sm-3', 'col-md-6');
with jQuery you could do something like this
<script>
$(window).resize(function () {
if($(window).width()<800){
$('.llotherlogos-userthumb').children().removeClass('col-sm-3').addClass('col-md-6');
}else{
$('.llotherlogos-userthumb').children().removeClass('col-md-6').addClass('col-sm-3');
}
});
</script>
You just require to use toggle for achieving the goal. The example is given below:
myLogos.classList.toggle('col-sm-3');
myLogos.classList.toggle('col-md-6');
or
var myLogos = document.querySelectorAll(".llotherlogos-userthumb .col-sm-3");
var classes = myLogos.classList;
var result = classes.replace("col-sm-3", "col-md-6");
console.log(result);
For more info on above access this link
try this jquery code:
enter$( window ).resize(function() {
var ww = document.body.clientWidth;
<==========now select id or element==============>
$("#a1").addClass( "my-hidden").removeClass("my-disply");
// code here
});

Change Image on div onclick()

I want to load different image on different div clicks. How do I know which div is clicked? Do I have to pass the div class as argument?
<script type="javascript">
function ChangeLibaas() {
}
</script>
<div class="Indeximages">
<img src="images/white.png" id="libaasImage" class="img-responsive jubbahImage" alt="" />
</div>
<div class="col-md-12 nopadding customTabs">
<h2>Pick a Colour</h2>
<div class="col-md-3 colourBlue" onclick="ChangeLibaas()"></div>
<div class="col-md-3 colourBlack" onclick="ChangeLibaas()"></div>
<div class="col-md-3 colourGreen" onclick="ChangeLibaas()"></div>
</div>
Simplest inline: pass (this):
<div class="col-md-3 colourBlue" onclick="ChangeLibaas(this)"></div>
and use it :
function ChangeLibaas(theClickedDiv) {
var img = "images/"+
theClickedDiv.className.split("colour")[1].toLowerCase()+".png"; // take the colour
document.getElementById("libaasImage").src=img;
}
To make it all neater, use an attribute and unobtrusive code
window.onload=function() {
var divs = document.querySelectorAll("div.col-md-3");
for (var i=0;i<divs.length;i++) {
divs[i].onclick=function() {
document.getElementById("libaasImage").src="images/"+
this.getAttribute("data-color")+".png";
}
}
}
using
<div class="col-md-3 colourBlue" data-color="blue""></div>
You can pass as an argument, like this:
<div class="col-md-12 nopadding customTabs">
<h2>Pick a Colour</h2>
<div class="col-md-3 colourBlue" onclick="ChangeLibaas(this)"></div>
<div class="col-md-3 colourBlack" onclick="ChangeLibaas(this)"></div>
<div class="col-md-3 colourGreen" onclick="ChangeLibaas(this)"></div>
</div>
And then:
<script type="javascript">
function ChangeLibaas(sender) {
var div = sender;
}
</script>
But it's better if you use event listeners.
I hope it can be useful:
In your html
<div class="Indeximages">
<img src="images/white.png" id="libaasImage" class="img-responsive jubbahImage" alt="" />
</div>
<div class="col-md-12 nopadding customTabs">
<h2>Pick a Colour</h2>
<button class="col-md-3" data-color="colourBlue" onclick="ChangeLibaas(this)">Blue</div>
<button class="col-md-3" data-color="colourBlack" onclick="ChangeLibaas(this)">Black</div>
<button class="col-md-3" data-color="colorGreen" onclick="ChangeLibaas(this)">Green</div>
</div>
In javascript, code looks like:
function ChangeLibaas(origin) {
var color = origin.dataset.color;
var img = document.getElementById('libaasImage');
img.src = color + ".jpg";
}

Javascript in html tags to avoid repetition

I am a newbie to JavaScript and I need to use it with bootstrap for my own web page. My question is now how can I make a loop so that pictures names (stored as an array) can emerge in the right places of the HTML code so I do not have to copy the blocks of code for each picture.
For example :
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="01.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="01.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="02.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="03.jpg">
</div>
</div>
As we can see here the only different text is the src.How can I store the names (paths) in an array and make a loop that changes the src property?
Thank you!
Try this demo: http://jsbin.com/pinoxeqapi/1/edit?html,output
I think that's what you're looking for.
CODE
$(function () {
var images = ["01.jpg", "01.jpg", "02.jpg", "03.jpg"];
$.each(images, function (index, element) {
var imgContainer = "<div class='row'><div class='col-md-3 col-xs-6 portfolio-item><img class='img-responsive' src='" + element + "'></div></div>";
$("body").append(imgContainer);
});
});
First Include JQuery (If not)
<script>
var srcArray = ['01.jpg', '02.jpg', '03.jpg', '04.jpg'];
$(document).ready(function () {
for (var i = 0; i < srcArray.length; i++) {
$('div.row img.img-responsive').eq(i).attr("src", srcArray[i]);
}
});
</script>
I would recommend using one of the templating frameworks described in some of the other answers. If you're interested to see how to implement this in pure JS:
var temp = document.querySelector('#portfolio-item-template');
['01.jpg', '02.jpg', '03.jpg', '04.jpg'].forEach(function(src) {
temp.content.querySelector(".img-responsive").src = src;
var newImg = document.importNode(temp.content, true);
document.querySelector('#insertion-point').appendChild(newImg);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<template id="portfolio-item-template">
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive">
</div>
</div>
</template>
<div id="insertion-point">
</div>
You can use a template stored in the HTML and then generate the actual elements using an array of the image sources. Something like John Resig's micro-templates can achieve this.
<script type="text/template" id="img-tmpl">
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item>
<img class="img-responsive" src="<%= src %>">
</div>
</div>
</script>

Categories

Resources