I have a bunch of file uploads on my website and I was looking into making them into drag and drop fields. However I seem to be having an issue with them.
Is there any way to accomplish a drag and drop system without the use of javascript or plugins? I'm trying to make this as light as possible and with the least amount of code.
I have looked at several different methods of doing this such as http://html5demos.com/dnd-upload but they all include javascript.
At the moment I just have regular inputs that look like this
<input type="file" multiple="true" name="" value="" />
Afaik there is not a way to do this without the use of javascript. However, here is a simple example that does use javascript. If you drag an image over the red div it appends the image to the body. I've confirmed it works in IE11, Chrome 38, and Firefox 32. See the Html5Rocks article for a more detailed explanation.
<div id="dropZone" style="width: 100px; height: 100px; background-color: red"></div>
<script>
var dropZone = document.getElementById('dropZone');
// Optional. Show the copy icon when dragging over. Seems to only work for chrome.
dropZone.addEventListener('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
// Get file data on drop
dropZone.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
var files = e.dataTransfer.files; // Array of all files
for (var i=0, file; file=files[i]; i++) {
if (file.type.match(/image.*/)) {
var reader = new FileReader();
reader.onload = function(e2) {
var img = document.createElement('img');
img.src= e2.target.result;
document.body.appendChild(img);
}
reader.readAsDataURL(file);
} } });
</script>
Related
I am trying to create an Angular PWA that is able to take a picture, and after taking it to display it in an img element.
The first step I succeeded in: I now have an FAB button that opens the camera viewfinder (using the html input tag) with this small piece of code:
const element: HTMLElement = document.getElementById('imageCapturer') as HTMLElement;
element.click();
This simulates a click on the following HTML element:
<input type="file" accept="image/*" capture="environment" id="imageCapturer"">
However, after taking a picture I then want to use the image to render it in an img element (and also sending the image to a database with an API call)
I have tried multiple solutions including trying to add the file.name as src to the img element, and trying to create a new img HTML element with an attribute that uses the file. But I am still unable to process the image to be used in the img tag. Can somebody explain to me what the proper way to process the file is to be able to do this?
Cheers!
I solved this problem in the following way:
First, I changed the HTML to this:
<input type="file" accept="image/*" id="imageCapturer" style="display: none;" (change)="useImage($event)">
<img *ngIf="URL" [src]="URL" id="imageViewer">
Then the function useImage looks like this:
useImage(event) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
reader.readAsDataURL(event.target.files[0]); // Read file as data url
reader.onloadend = (e) => { // function call once readAsDataUrl is completed
this.URL = e.target['result']; // Set image in element
this._changeDetection.markForCheck(); // Is called because ChangeDetection is set to onPush
};
}
}
Now whenever a new image is captured or selected it is updated in the view
You can use event change of input file.
This example:
$('#imageCapturer').on('change', function () {
var input = $(this)[0];
if (input.files && input.files[0]) {
var fileName= input.files[0].name;
var reader = new FileReader();
reader.onload = function (e) {
var buffer = e.target.result;
var fileSize = input.files[0].size / 1024 / 1024; // in MB
// SET IMG DISPLAY
$('#image-display').attr('src', buffer).css({
'max-height': '170px',
'max-width': '170px',
};
reader.readAsDataURL(input.files[0]);
}
});
Note: You add more attribute [enctype="multipart/form-data"] in tag form when sumbit form it will send file byte[].
<form id="process_form" method="POST" enctype="multipart/form-data" autocomplete="off" role="form" data-parsley-focus="none">
I have an img src="example.jpg", and I also have an input type="file". I would like to know if there was a way to make the input type="file" change the img to whatever the user chooses off of his/her computer.
Here is a basic example with what you're asking, although it doesn't handle persistence, login sessions, or anything else you'll need for this to work in a production environment.
document.addEventListener('DOMContentLoaded', init);
function init() {
var input = document.querySelector('input');
var reader = new FileReader();
// When the FileReader "load" event fires, update the image.
reader.onload = function (e) {
document.getElementById("image").src = e.target.result;
};
// Listen for when the input changes.
input.addEventListener('change', onInputChange)
function onInputChange(e) {
reader.readAsDataURL(this.files[0]);
}
}
<img src="//placehold.it/200x200" id="image" height="200">
<input type="file">
Sidenote: Welcome to StackOverflow. You're getting downvotes as you're not including anything you've tried. SO is a place to get help with existing code, not to do research or write it for you.
I have the impression that Firefox is "clearing" the data-* attributes on custom elements.
See the script below works in Chrome with native Web Components support, but in Firefox, it seems that once my click event handler is run, the dataset is empty.
document.addEventListener('DOMContentLoaded', function() {
var popups = document.querySelectorAll('iron-image[data-popup]');
for (var i=0; i < popups.length; i++) {
var img = popups[i];
console.log(img.dataset.popup); // <--- this works
img.addEventListener('click', function(ev) {
var app = document.querySelector('sh-app');
app.showPopup(ev.target.dataset.popup); // <-- This fails, dataset is empty
});
}
});
Side Note: I have also tried the WebComponentsReady event, but it doesn't get fired at all for some reason.
Has anyone run into this issue before and understand the cause?
Is this a bug in Polymer (<iron-image> in this case), the Web Components polyfills, or Firefox's implementation thereof?
Event retargeting
Basically, you have to wrap the event using Polymer.dom to normalize it.
document.addEventListener('DOMContentLoaded', function() {
var popups = document.querySelectorAll('iron-image[data-popup]');
for (var i=0; i < popups.length; i++) {
var img = popups[i];
console.log(img.dataset.popup); // <--- this works
img.addEventListener('click', function(ev) {
var app = document.querySelector('sh-app');
var event = Polymer.dom(ev); // you wrap the event using Polymer.dom
app.showPopup(event.localTarget.dataset.popup); // instead of target you should use localTarget
});
}
});
Now I have a form field:
<input id="my_img_field" type="file"/>
After I select the image in the browser, I want to render the selected image file on the target img tag:
<img id="image_preview" />
But I want to do this after the $('#my_img_field').change event, i.e. I may want this done when I click some button later.
I heard that this could be done using HTML5 technique. Can someone teach me how?
the code in vanilla js
var file = document.getElementById('my_img_field').files[0]
var fr = new FileReader()
fr.readAsDataURL(file)
fr.onload = function(e) {
var img = document.getElementById('image_preview')
img.src = this.result
}
The following approach will work:
var file = $('#my_img_field')[0].files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
var img = $('#image_preview');
img.attr('src', this.result);
}
It can be like this
const file = document.getElementById('my_img_field').files[0]
const link = window.URL.createObjectURL(file)
I want dropped text files to be shown by their contents or their complete location so that I can load contents of that location into the "drop_zone".
This is what I have till now. I was just able to access the file name:
<html>
<head>
<title></title>
</head>
<body>
<textarea id="drop_zone">Drop files here</textarea>
<output id="list"></output>
<script>
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files; // FileList object.
document.getElementById('drop_zone').innerHTML = files[0].name;
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}
// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
</script>
</body>
</html>
here is the final code :
<html>
<head>
<title></title>
</head>
<body>
<textarea id="drop_zone">Drop files here</textarea>
<script>
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files; // FileList object.
var reader = new FileReader();
reader.onload = function(event) {
document.getElementById('drop_zone').value = event.target.result;
}
reader.readAsText(files[0],"UTF-8");
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}
// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
</script>
</body>
</html>
http://www.html5rocks.com/en/tutorials/file/dndfiles/ should be a good resource. You need to use a FileReader to read the contents of the file as a String.
Due to security limits, a page isn't able to load contents of files without something like a Java applet set up with appropriate permissions; and, even then, it's not too possible.
However, that isn't to say it's impossible; simply upload the file to a server and echo the contents back out to the browser. That is how many text-editing-type web applications function.
How you implement this is up to you.
Further, as Maz has pointed out, you can also use built-in APIs to aid you in doing what you're trying to do. Do note, however, this solution is not necessarily cross-browser compatible.