Preload images from more then one file input - javascript

I find an methode to preload an image before uploading, but i have more then one file input. And i want for each input file to preload the image. In generell not a big problem but the amount how many file inputs are used on the website is not stable. An user can addan upload image block so he can add 2 or 3 and i want for each he ads the possibility to preload the image.
But my experience dont reach this level what it needs.
So my question is it possible to realilze it?
My code for preload the image for one specific file input is this:
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#blah')
.attr('src', e.target.result)
.height(50);
};
reader.readAsDataURL(input.files[0]);
}
}
If an user adds one image block this is how it looks like:
<div id="divImage-1" class="form-group form-file-upload">
<label id="labelImage-1" for="labelImage2-1">New Picture</label>
<div></div>
<label id="labelImage2-1" for="inputImage-1" class="form-file-upload1">Upload Image</label>
<input id="inputImage-1" type="file" onchange="readURL(this);">
<img id="blah" height="50" alt="Image preview">
</div>
If the user create an second one all IDs ae count to 2 (divImage-2).

Lets assume you this in your HTML
<button class="btn btn-primary" id="addBtn">Add Image Block</button>
<div class="container"></div>
Then, as first step you need to create two global variables:
let imageBlockCout = 0 for counting number of image blocks.
let addedPicSet = nnew Set() a set of pic names which are being used by other blocks.
Then for every click on add button we will add a new block of image with code lets say:
$(
$.parseHTML(
`<div class="row">
<input type="file" multiple id="photos-${imageBlockCount}">
<div id="gallery-${imageBlockCount}" class="row"></div>
</div>`
)
).appendTo(".container");
Now, for every file input added you need to attach an on-change listener:
let currentBlockCount = imageBlockCount;
$("#photos-" + imageBlockCount).on("change", function () {
let input = this;
if (!input.files) {
return;
}
//for every image that has been read by FileReader we show it
//in its own card inside its button gallery
let onFileLoaded = function (event) {
$(
$.parseHTML(
`<div class="col-sm-3">
<div class="card">
<img
class="card-img-top"
src="${event.target.result}">
</div>
</div`
)
).appendTo("#gallery-" + currentBlockCount);
};
//input.files is an array like object, so we convert it to array
Array.from(input.files)
.filter(
//first we filter images which are already in use
(file) => !addedPicSet.has(file.name)
)
.forEach((file) => {
let reader = new FileReader();
//we attach an onLoad listener for each reader
reader.onload = onFileLoaded;
//then we tell the reader object which file to read
reader.readAsDataURL(file);
//add the image name in the set of used image names
addedPicSet.add(file.name);
});
});
I have also made a pen for your help: https://codepen.io/abdullah-shabaz/pen/qBdvZMQ

Related

Angular - Use a default image if image does not exist on server

I have a component that will display a cover image. The user can upload a cover image and the component will display the user uploaded image. If the user doesn't upload an image, then I want to display a default image.
If there is no user uploaded image I want to return an error and call the changeSource(event), which should in theory bind a new image url to the img src. However I'm getting undefined for the event.target.src and I'm seeing a blank space where the default image should be. It works fine when displaying the custom image.
component.html
<div *ngFor="let coverPhoto of coverPhotos">
<img src="{{coverPhoto}}"
(error) ="changeSource($event)" />
</div>
component.ts
this.myService.getPhotos(ImageType.Cover, this.id).subscribe(result => {
this.coverPhotos = result;
}, error => {
this.errors = error;
this.changeSource(event);
}, () => {
}
);
changeSource(event) {
event.target.src = "https://imageurl";
}
directly use (where defaultImage is a variable in ts file which holds the default image path) -
(error)="$event.target.src = defaultImage"
your HTML -
<div *ngFor="let coverPhoto of coverPhotos">
<img src="{{ coverPhoto }}" (error)="$event.target.src = defaultImage" />
</div>
Working example here.
You are passing event from this code in ts, which is obviously undefined, and you don't need to call this function from here -
this.myService.getPhotos(ImageType.Cover, this.id).subscribe(result => {
this.coverPhotos = result;
}, error => {
this.errors = error;
this.changeSource(event);
}, () => {
}
);
The *ngFor was throwing it off. Removing this seemed to solve the problem. Not quite sure why so will post an edit when I discover why.
<div>
<img src="{{coverPhotos}}"
(error)="$event.target.src = defaultImage" />
</div>

React.js Previewing an Image with input type file

Currently I am trying to preview an image up on an upload of an image file. I can recieve the image, and console log however I can not display it in the img tag.
Here is the way that I am trying to render them:
<input type='file' id="uploadImage" onChange={this.handleImageChange} className="upload-input" />
<label htmlFor="uploadImage" className="upload-image-button">Choose An Image</label>
{this.state.imagePreview[0] ?
<img src={this.state.imagePreview[0]} alt="" className="image-preview" />
:
<img alt="" className="image-preview" />
}
Here are my state and my handle on change method for the input:
state = {
imagePreview: {}
}
handleImageChange = async (e) => {
console.log(e.target.files)
await this.setState({ imagePreview: e.target.files })
console.log(this.state.imagePreview)
}
Here are my console logs for the files:
You'll need to use a FileReader object, in order to get the base64 data and apply it to the source of the image tag.
Also, I don't see any need for this to be an async function (unless, for the sake of brevity, you left out a promise you're working with).
From the code you've presented, something like this should work:
handleImageChange(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function(event) {
// The file's text will be printed here, if you want to see the base64
console.log(event.target.result)
// Set state with base64 data
this.setState({ imagePreview: e.target.result })
};
reader.readAsText(file);
}
Html (or jsx) would look something like so:
<img src={this.state.imagePreview} alt="" className="image-preview" />

How to get file path from File object observer in v-file-input Vuetify?

I am building feature upload image with Vuetify. I need preview image before upload to server
In v-input-file
<v-file-input
accept="image/*"
multiple
label="Add your files"
chips
filled
prepend-icon="mdi-camera"
#change="onAddFiles"
></v-file-input>
In method change
onAddFiles(files) {
console.log(files);
}
You can see there is no information file path in File object observer array
I don't know how to get file path from this File object observer. Please help me and i'm so grateful!
in data, include the following
previews: [],
errorImage: "url of an image to use to indicate an error",
obviously you need to set errorImage to something useful
Then add some code to onAddFiles to generate an array of previews
onAddFiles(files) {
this.previews = [];
files.forEach((file, index) => {
const reader = new FileReader();
reader.addEventListener('load', e => this.previews[index] = e.target.result);
reader.addEventListener('error', e => this.previews[index] = this.errorImage);
reader.readAsDataURL(file);
});
}
In your markup - wherever you want you previews shown, something like
<span v-for="src in previews">
<img v-if="src && src.length" :src="src"/>
</span>

Wordpress custom image upload

I need to use custom image field in wp plugin, everything works fine with upload/set function but have problem, when changing image:
Problem:
When i already have a image and need to replace i pick up new image from media library and submit, old one image stay visible so i have two images in view.
I asume that problem is with select function and append part, obviously i'm using wrong logic here, bellow are jquery+html of my code and screenshot of problem:
Problem(two images):
First one should replaced with new selection image (second image)
Two images screenshot
This is my code:
$('#btn-upload-image').on('click', function(e) {
e.preventDefault();
var button = $(this);
var figure = button.siblings("figure");
var custom_uploader = wp.media({
title: 'Insert image',
library: { type : 'image' },
button: { text: 'Use this image' },
id: 'library-' + (Math.random() * 10),
multiple: false
}).on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
figure.append( $('<img/>', { 'src': attachment.url }) );
inputImage.val(attachment.url);
inputImageId.val(attachment.id);
})
.open();
});
and html:
<div class="form-group">
<label>Image</label>
<figure></figure>
<button type="button" class="btn btn-primary" id="btn-upload-image">Upload Image</button>
<input type="hidden" name="image" id="input-image" />
<input type="hidden" name="image_id" id="input-image-id" />
</div>
Here's the problem:
figure.append( $('<img/>', { 'src': attachment.url }) );
append inserts content at the end of the target element, maintaining existing content in place. What you want in this case is to replace whatever is in there with new content (the new image), so:
figure.html( $('<img/>', { 'src': attachment.url }) );
html replaces any content that was in the targeted element(s) with the new one.
Hope that helps!

Trouble loading upload image previews, Angular 1.5.8 on IOS 11 Safari

OK, weird error. This code works in browsers and in Safari on IOS 10 and previous.
I've got a page where we're building an item to submit to our DB, and this item is made up of multiple line items have images arrays that store images per line item. When the file is uploaded (using ng-file-upload), we analyze the file to make sure it matches some size and type restrictions and then stuff it in an array, at which point there is another control on the page that gives the user an image preview of the item and a button to remove the image if they no longer want to upload it.
HTML:
<div ng-repeat="item in items">
<div class="row">
<div class="col-xs-12 col-md-2">
<div class="form-group">
<div class="btn btn-default" ngf-select ngf-change="UploadFile(item, $file)" ngf-multiple="false">Upload Image</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-xs-12">
<ul class="thumbnail-list">
<li class="image-thumbnail" ng-repeat="image in item.images">
<span ng-click='removeImage(image, item, $index)' class='remove'>X</span>
<img ngf-src="image.file" ngf-no-object-url="true" ngf-accept="'image/*'">
</li>
</ul>
</div>
</div>
</div>
JS Controller code:
$scope.fileReader = new FileReader();
$scope.fileReader.onload = function () {
$scope.CurrentItem.images[$scope.CurrentItem.images.length - 1].base64 = this.result;
$scope.selectedImage.base64 = this.result;
};
$scope.UploadFile = function (item, file) {
if (file != null && file != "") {
$scope.error = '';
$scope.CurrentItem = item;
// Validation Logic here removed
if (valid) {
$scope.selectedImage = {};
$scope.selectedImage = {
'size': file.size,
'type': file.type,
'name': file.name,
'file': file
};
$scope.CurrentItem.images.push($scope.selectedImage);
$scope.fileReader.readAsDataURL(file);
} else {
// Handle Validation Failure
}
}
}
On IOS 11, the image is successfully added to the array, an element for the image added to the page, and the red X for the delete operation is positioned correctly on it. However, the actual image preview does not appear. However, if you change the orientation of the iPad from Portrait to Landscape or vice versa, it seems like some refresh is invoked on orientation change and the image preview fills in.
On IOS 10 and below, as well as on desktop browsers (including Safari 11 on OSX), this just renders the image out at the same time as the element is added to the page as intended.
Anyone have any ideas?

Categories