How can I able to preview a image before it is uploaded. The preview action should be executed in all browsers without using Ajax to upload the image.
Most of the examples are using FileReader, which wont work in IE9.
Is there any plugins or any alternative to make it working in IE9
f (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#blah').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
Here's the updated code. Hope it works for you.
if (input.files && input.files[0]) {
var url = URL.createObjectURL(input.files[0]);
$('#blah').attr('src', url);
}
JavaScript:
$('#fileID').on('change',function(){ }
var imageName = '';
if (this.files && this.files.length > 0) {
imageName = this.files[0].name;
}
else if (this.value) {
imageName = this.value;
}
if (window.FileReader) {
//as same as other samples
}
else{
var image = document.getElementById('imgItem');
image.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale', src='" + imageName + "')";
image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
}
//code end
I find this works well in emulation-IE9.
Another way to draw a image:
var canvas = document.getElementById('imgArea');
var img = new Image();
img.src = imageName;
img.onload = function () {
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, 200, 200);
}
Note: Add 2017/12/27
One solution to preview a local image with IE-9:
IE-9 does`nt support FileReader, so I tried to upload it first then return the imageName(with server path) to View to change the 'src' attribute of the img.
and it works well.
Points:(the example is using MVC)
1.In the 'change' event of input-type-file, do the ajaxSubmit(the action method:void)
2.In the Controller,using [Newtonsoft.Json.JsonConvert.SerializeObject],to return the json-formatted string.
Response.Write(strData);
3.In the callback of the ajaxSubmit, just change the src of the img.
(dont forget convert the result to json)
Related
I have a drag and drop container for uploading images. Something like the option that stackoverflow has in the editor. As you know, it works in two ways:
drag and drop an image
click on the container and then a window will be opened to choose an image
Now I'm exactly doing something like that:
// click
$('.upload_image').on('change', function () {
file = $(this)[0].files;
frm = $(this).closest('form');
addImageToInput();
return false;
});
// drag and drop
$(".container").on('drop dragdrop', function (e) {
file = e.originalEvent.dataTransfer.files;
frm = $(this).closest('form');
addImageToInput();
return false;
});
Also I have one more function for making a preview:
function addImageToInput() {
if ( file !== "" || frm !== "" ) {
let uploadFormData = new FormData(frm[0]);
uploadFormData.append("imageToUpload", file[0]);
readURL(frm.find(".upload_image")[0]);
formData = uploadFormData;
} else {
alert('something went wrong');
}
}
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('.modal-dropzone-img').html("<img src='" + e.target.result + "' class='upload_image_preview_img'/>");
}
reader.readAsDataURL(input.files[0]);
}
}
Anyway, the preview part works well when I attach an image by using "click" (browse) the image, and the preview part doesn't word (even no error throws) when I use drag and drop approach.
After some tests, I figured out, these aren't equal:
file = $(this)[0].files; // click approach
file = e.originalEvent.dataTransfer.files; // drag and drop approach
Any idea how can I make them equal? (in other word, I have to make the second one like the first one, because the first one is the working one)
I have modified the readURL method little bit to accept a file only, it can be drag drop or uploaded . Also addImageToInput() is changed accordingly
function addImageToInput() {
if ( file !== "" || frm !== "" ) {
let uploadFormData = new FormData(frm[0]);
uploadFormData.append("imageToUpload", file[0]);
readURL(file[0]);
formData = uploadFormData;
} else {
alert('something went wrong');
}
}
function readURL(input) {
if (input) {
var reader = new FileReader();
reader.onload = function(e) {
$('.modal-dropzone-img').html("<img src='" + e.target.result + "' class='upload_image_preview_img'/>");
}
reader.readAsDataURL(input);
}
}
here is a working fiddle
https://jsfiddle.net/153dp05q/
I want to do:
after clicking plus sign, insert image instead of plus sign
create new plus sign after added image
My codepen demo:
CodePen
function readImage(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('.cert img').attr('src', e.target.result);
$('.cert label').css('opacity', '0');
}
reader.readAsDataURL(input.files[0]);
}
}
This isn't quite perfect, but it works to load multiple images and does clean up the duplicated ID. You can try it in your CodePen JS box:
function readImage(input, element) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$(element).find("img").attr("src", e.target.result);
};
reader.readAsDataURL(input.files[0]);
}
}
$("#certImg0").change(function() {
var element = $(this)
.parent()
.clone();
$(element).find('input').remove();
$(element).find('label').remove();
element.insertAfter($(this).parent());
readImage(this, element);
});
The intent of this is to take the element that is generated and pass the actual element that was created to the readImage function and the new image that is loaded is directly stored in the img element on the new div structure.
(This could be optimized to generate only the div with the img element, and that would make it so that the new images are not clickable. In fact, I modified the code to do that- deleting the input and label from the cloned element.)
I know that I should follow the DRY principle in coding. However, I am not that into javascript so I want to ask how to make the code below more readable and maintanable.
$('#frontfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = frontvImageIsLoaded;
});
$('#rearfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = rearvImageIsLoaded;
});
$('#rightfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = rightvImageIsLoaded;
});
$('#leftfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = leftvImageIsLoaded;
});
//called after an image file has been chosen
function frontvImageIsLoaded(e) {
$("#frontimagepreview").attr('src', e.target.result);
$("#frontpreview-msg").css('color', 'green');
};
function rearvImageIsLoaded(e) {
$("#rearimagepreview").attr('src', e.target.result);
$("#rearpreview-msg").css('color', 'green');
};
function rightvImageIsLoaded(e) {
$("#rightimagepreview").attr('src', e.target.result);
$("#rightpreview-msg").css('color', 'green');
};
function leftvImageIsLoaded(e) {
$("#leftimagepreview").attr('src', e.target.result);
$("#leftpreview-msg").css('color', 'green');
};
This is the code for Main.Mod.image_change()
var image_change = function handleFileImageChange(obj){
//holds the image preview object
var file = obj.files[0];
var imagefile = file.type;
var match= ["image/jpeg","image/png","image/jpg"];
if(!((imagefile==match[0]) || (imagefile==match[1]) || (imagefile==match[2]))){
alert("Incorrect image file. You still be able to upload this form but the system " +
"will be using the default image.");
$("#preview-msg").css('color', 'red');
return false;
}else{
var reader = new FileReader();
//reader.onload = imageIsLoaded;
reader.readAsDataURL(obj.files[0]);
return reader;
}
};
The code above, will handle file input change event then change img src base on the file input.
I know the code i wrote really sucks since I have to repeat my code several times. How can I implement it in a more efficient way?
Thanks.
use , to combine selectors:
$('#frontfile_v,#rearfile_v').change(function(){
// ...
})
The "change" event will be bound to every object matched by the selector. This way you don't need to duplicate the binding.
Merge the "image loaded" functions into one function by passing parameters:
var idsMap = {
leftfile_v : {preview : '#frontimagepreview', msg : '#frontpreview-msg'},
// etc...
};
$('#leftfile_v,#rearfile_v').change(function(){
var ids = idsMap[$(this).attr('id')];
reader = Main.Mod.image_change(this);
reader.onload = function(e) {
imageIsLoaded(e, ids.preview, ids.msg);
};
});
function imageIsLoaded(e, preview, msg) {
$(preview).attr('src', e.target.result);
$(msg).css('color', 'green');
};
Yet another variant. As say #Malki: use comma in selector
$('#frontfile_v, #rearfile_v,#rightfile_v,#leftfile_v').change(function(){
var id = this.id.replace(/file_v$/,'');
reader = Main.Mod.image_change(this);
if(reader){ //for case when `image_change` return not "false"
// use mode generic function
reader.onload = function(e){
$("#"+id+"imagepreview").attr('src', e.target.result);
$("#"+id+"preview-msg").css('color', 'green');
};
}
});
As for handleFileImageChange you need use Array.indexOf function
var image_change = function handleFileImageChange(obj){
//holds the image preview object
var file = obj.files[0];
var imagefile = file.type;
var match= ["image/jpeg","image/png","image/jpg"];
if(match.indexOf(imagefile) == -1){
alert("Incorrect image file. You still be able to upload this form but the system will be using the default image.");
$("#preview-msg").css('color', 'red');
return false;
}else{
var reader = new FileReader();
//reader.onload = imageIsLoaded;
reader.readAsDataURL(file); //you not need use "obj.files[0]" because you already save it in "var file"
return reader;
}
};
I want drop jpg to Browser from local, and display it on Browser.
I write code, but it don't display jpg.
Please advice.
html
<img id="img1" ondragover="doDragOver(event);"
ondrop="doDrop(event);"
class="droppable">
css
.droppable {
width:500px;
height:500px;
background-color: gray;
}
script
function doDragOver(event){
var type = event.dataTransfer.types.contains("Files");
if (type){
event.preventDefault();
}
}
function doDrop(event){
var img = document.getElementById("img1");
var file = event.dataTransfer.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
img.src = reader.result;
}
}
The problem is that the dragOver function the type list is empty (to it's empty in some browsers), but why check it content? You can check it in the drop function.
Be sure to cancel the default browser behavior using event.preventDefault(); and return false
Code:
function doDragOver(event) {
event.preventDefault();
return false
}
function doDrop(event) {
event.preventDefault();
var img = document.getElementById("img1");
var file = event.dataTransfer.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
img.src = reader.result;
}
}
Demo: http://jsfiddle.net/IrvinDominin/Up2NF/
I'm having an issue with getting the dimensions of a newly updated image element.
I'm using FileReader to display a preview of an image file on screen.
Once the filereader and associated code has finished executing, I retrieve the new dimensions of the image element so I can adjust them accordingly.
On some browsers, the info doesn't get updated straight away and I need to include a delay before I can retrieve the new dimensions. This results in the new image being resized according to the previous image's dimensions, and not its own.
How can I be sure the new image has been fully loaded?
I would have thought FileReader().onloadend would have been sufficient but apparently not. I think this is executed once the fileReader has loaded it, not when the DOM has rendered it. (Am I right?)
Then I found this question, which suggests using a timeout of 1 millisecond. This works sometimes, but not always. It seems to be down to the speed the browser is rendering the image (more-so available resources rather than filesize). Do we have no other way of detecting a change in these parameters?
HTML
<img src="#.png" alt=""/>
<input id="fileInput" type="file" accept='image/*' onChange="loadIt()" />
JS
preview = getElementsByTagName('img')[0];
function loadIt() {
var imgReader = new FileReader();
imgReader.readAsDataURL(document.getElementById('fileInput').files[0]); //read from file input
imgReader.onloadstart = function(e) {
//
}
imgReader.onload = function (imgReaderEvent) {
if (isImage()) {
preview.src = imgReaderEvent.target.result;
//
}
else {
preview.src = 'error.png';
//
}
}
imgReader.onloadend = function(e) {
setImage();
setTimeout(function(){
setImage();
}, 1);
setTimeout(function(){
setImage();
}, 2000);
//
}
};
function setImage() {
preview_w = preview.width;
preview_h = preview.height;
console.log('dimensions: '+avatar_preview_w+' x '+avatar_preview_h);
//
};
You should call preview.onload or preview.onloadend on your image to detect that it has finished loading. You're also calling your events after you readAsDataURL The code should look like this
var preview=document.getElementsByTagName("img")[0];
function loadIt() {
var imgReader=new FileReader();
imgReader.onload=function(){
if (isImage()) {
preview.src = imgReader.result;
preview.onload=setImage;
} else {
preview.src = 'error.png';
//
}
imgReader.readAsDataURL(document.getElementById('fileInput').files[0]); //read from file input
}
function setImage(){
preview_w = preview.width;
preview_h = preview.height;
console.log('dimensions: '+avatar_preview_w+' x '+avatar_preview_h);
}
You're calling imgReader.readAsDataURL before your .onload and .onloadend is set.
I do not know what some of the variables are with-in the body of your setImage();however, start here:
function loadIt() {
var preview = getElementsByTagName('img')[0],
setImage = function () {
preview_w = preview.width;
preview_h = preview.height;
console.log('dimensions: '+avatar_preview_w+' x '+avatar_preview_h);
},
imgReader = new FileReader();
imgReader.onloadstart = function(e) {};
imgReader.onload = function (imgReaderEvent) {
if (isImage()) {
preview.src = imgReaderEvent.target.result;
}
else {
preview.src = 'error.png';
};
};
imgReader.onloadend = function(e) {setImage();};
imgReader.readAsDataURL(document.getElementById('fileInput').files[0]); //read from file input
};