I'm trying to define the image that appears when I drag an element inside my page.
I saw how to do it with DataTransfer.setDragImage() in that link but with me it is not working.
There are two differences between my code and the example:
I'm trying to make this change through the DragEnter event while the link is done in DragStart;
The image to be dragged will be in the user's file explorer, not in the HTML document.
I already did a test and the image is being generated correctly.
This is the code responsible for this functionality:
function handleDragEnter(event)
{
const img = new Image;
const reader = new FileReader;
reader.readAsDataURL((new Blob(icon(faPhotoFilmMusic).html, { type: 'image/svg+xml' })));
reader.addEventListener('load', () => {
img.src = reader.result;
event.dataTransfer.setDragImage(img, 10, 10);
});
}
I think the problem is in missing parentheses:
function handleDragEnter(event)
{
const img = new Image(); // <=== change this
const reader = new FileReader(); // <=== change this
reader.readAsDataURL((new Blob(icon(faPhotoFilmMusic).html, { type: 'image/svg+xml' })));
reader.addEventListener('load', () => {
img.src = reader.result;
event.dataTransfer.setDragImage(img, 10, 10);
});
}
Related
I am changing the src attribute of an image element. If there's an error I want to know the error status code.
You could adapt this source example on mdn web docs. If you change the src attribute programmatically and need to check first if it gives an error code, it could do the job. Here a draft, I hope this is going to help you.
let changesrc = (newsrc) => {
const myImage = document.getElementById('testimg');
const myRequest = new Request(newsrc);
fetch(myRequest).then((response) => {
console.log(response.status);
if(response.status == "200") {
response.blob().then((myBlob) => {
const objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
}
});
};
<button onclick="changesrc('https://picsum.photos/200');">test ok</button>
<button onclick="changesrc('https://picsum.photos/noway');">test not ok</button>
<img id='testimg' src="https://picsum.photos/200">
You can use Image API in Javascript, for know when image load fail:
function mountImage(src) {
const img = new Image();
img.src = src;
img.onload = () => {
// image loaded
}
img.onerror = () => {
// image fail load
}
}
I'm making a typical drag and drop for upload images from desktop to browser, i can drop content inside the box and with a console.log view the content in the browser console:
File { name: "deam230mthumb.jpg", lastModified: 1194641808000, lastModifiedDate: Date 2007-11-09T20:56:48.000Z, size: 60313, type: "image/jpeg" }
I want to view the image inside a box and then upload on submit.
Here my code is use Jade template engine:
Jade (HTML)
form(action="" enctype="multipart/form-data")
div(class="all-100 miniatures")
div(class="all-100 drop ink-droppable align-center fallback" id="dropZone" ondrop="drop(event)" ondragover="allowDrop(event)")
Javascript
script.
var dropZone = document.getElementById('dropZone');
function allowDrop(e){
e.preventDefault();
}
function drop(e){
var file = e.dataTransfer.files[0];
e.preventDefault();
console.log(file);
//e.target.appendChild(file);
}
I added an array for content each file from the event, on the following code we need to add a controller for handle each file from the array with a register of each one on the database.
script.
var dropZone = document.getElementById('dropZone');
function allowDrop(e){
e.preventDefault();
}
var files = [];
function drop(e){
var file = e.dataTransfer.files[0];
files.push(file);
console.log(file)
e.preventDefault();
var reader = new FileReader();
reader.onload = function(event){
var miniatures = document.getElementById("miniatures");
var img = new Image();
img.src = event.target.result;
var miniature = document.createElement("div");
miniature.className = "all-20";
miniature.appendChild(img);
miniatures.appendChild(miniature);
}
var readerContent = reader.readAsDataURL(file);
var input = document.getElementById("upload");
input.files = readerContent;
console.log(files);
}
Ok, my Javascript looks this now:
At this point we can drag images from our desktop to browser and view
them, now, we need to upload that files.
script.
var dropZone = document.getElementById('dropZone');
function allowDrop(e){
e.preventDefault();
}
function drop(e){
var file = e.dataTransfer.files[0];
e.preventDefault();
console.log(file);
var reader = new FileReader();
reader.onload = function(event){
var miniatures = document.getElementById('miniatures');
var miniature = new Image();
miniature.src = event.target.result;
miniature.width = 100;
miniatures.appendChild(miniature);
}
reader.readAsDataURL(file);
}
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
};