Direct File Upload Javascript - javascript

How is it possible to upload a file directly without clicking file upload button(I want to click Add Widget Button which should give file upload dialog box)
I have a button declared as follows:
<button class="add-button" style="float:top;">Add Widget</button>
On clicking the button the following function is invoked
$(".add-button").on("click", function() {
// get selected color value
var color = $color_picker.val();
// build the widget, including a class for the selected color value
var $widget = $('<li>', {
'class': 'color_' + color
})
.append($('<button>', {
'class': 'delete-button',
'text':'-'
}))
.append($('<img src="abc.png" height="60px" width="60px">'));
// add widget to the grid
gridster.add_widget($widget, 1, 1);
});
But I first want a upload box to appear where in user can upload the image as soon as the button is clicked then the above code should get executed
I did something like this
$(".add-button").on("click", function() {
var x = document.createElement("INPUT");
x.setAttribute("type", "file");
x.setAttribute("onclick","previewFile()");
// get selected color value
var color = $color_picker.val();
// build the widget, including a class for the selected color value
var $widget = $('<li>', {
'class': 'color_' + color
})
.append($('<button>', {
'class': 'delete-button',
'text':'-'
}))
.append($('<img src="abc.png" height="60px" width="60px">'));
// add widget to the grid
gridster.add_widget($widget, 1, 1);
});
But this does not brings any dialog box where user can upload the image
This uploaded image I want to then use in the place of
.append($('uploaded image'));
Preview File Function (This also needs to be modified)
function previewFile() {
var preview = document.createElement('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader(); //API for reading file stored on user computer
reader.addEventListener("load", function () { //"load" :This eventlisterner "listens" loading of file. Once it is loaded function is triggered
preview.src = reader.result;
});
if (file) {
reader.readAsDataURL(file); // helps in reading the content of "file"
}
document.body.appendChild(preview);
}
My aim is that preview file function should return an image which I can put in
.append($('image from preview file'));
A version of code is at Fiddle

The way to do this is to have some hidden input with file type somewhere on the dom. You might be able to programatically put it there, but really no point in that. Once the add widget button is clicked, you can simulate a click for the hidden input. This will initiate a prompt to pick a file. Then what you want to do is, wait until the file has been "picked" by the user. This is done via the onchange event. Within that, you can grab the file, read it, and then when it's done you can have a callback via the onload method. I put up a working example here. I imagine you wanted to have the file picked as the image set on the src, so I did that as well.
hidden input
<input id="test" type="file" style="position: absolute; top: -10; left: -10; height: 0; width: 0;" />
button click function (this is what will wait until the file has been chosen), the call back method is used on the onload event of the filereader.
$(".add-button").on("click", function() {
$('#test').click();
$('#test').on('change', function(e) {
var test = document.getElementById('test');
if (!test) {
alert("Um, couldn't find the fileinput element.");
}
else if (!test.files) {
alert("This browser doesn't seem to support the `files` property of file inputs.");
}
else if (!test.files[0]) {
alert("Please select a file before clicking 'Load'");
}
else {
file = test.files[0];
console.log(file);
fr = new FileReader();
fr.readAsDataURL(file);
fr.onload = function() {
var data = fr.result; // data <-- in this var you have the file data in Base64 format
callbackAddButton(data);
test.value = ''; //here we are resetting the file input's files
$('#test').replaceWith($('#test').clone()); //here we are resetting the input, if we clone the input with the files then it wont trigger the onchange event if you upload same image. So we need to make sure we have these 2 calls.
};
}
})
});
And finally, the callback method. Which is simply exactly what you had before but now only gets called once the file has been done (done as in, you read it via filereader and have access to contents if needed). The only difference here is now you have a base64 representation of the image the user uploaded. Which I am setting to the new image widget you created.
function callbackAddButton(file) {
// get selected color value
var color = $color_picker.val();
// build the widget, including a class for the selected color value
var $widget = $('<li>', {
'class': 'color_' + color
})
.append($('<button>', {
'class': 'delete-button',
'text':'-'
}))
.append($(`<img src="${file}" height="60px" width="60px">`));
// add widget to the grid
gridster.add_widget($widget, 1, 1);
}
EDIT
Once you're done with the input file element, it's good practice to now clear it because you dont need the file anymore (from the input at least, since you have a base64 representation). Just append a $('#test').replaceWith($('#test').clone()) after the you make the callback call.

Related

dynamically adding a button in html page with simple Javascript without any framework or library

hey there i'm making a simple webpage which requires to download an output image file at the last step..
but i don't know how can i add download button dynamically at correct time, because at starting of a page there is no need of download button..
so i have main.js file:
which looks something looks like this:
let img_code=document.getElementById('img_code');
let textbox=document.getElementById('textbox');
let gen_button_img=document.getElementById("img_button");
gen_button_qr.addEventListener("click",()=>
{
var trailer=textbox.value;
var url='www.example.com';
var result= url.concat(trailer);
if (navigator.onLine)
{
if(trailer.length<=1725 && trailer.length>0)
{
if((trailer !="0")&& (trailer.replace(/\s/g, '').length))
{
image_code.src=result;
alert("Image Generated successfully");
/**/
}
else
{
alert("You cannot create this file spaces only or only with single 0");
}
}
else
{
alert("Maximum charecter limit is exceeded!! ");
}
}
else
{
alert("No Internet Connection");
}
});
So, i have the question is there any way to dynamically add the button which takes file URL as input and download that file through web browser's downloader?
Note=>
I can easily save the result by right click on the picture and save image option; but i want to add an extra button to download the same file.
Most of the things explained in comments so read it first
// arrow function to create and append download button into any element
// it only takes url of file that will download.
const createBtn = (URL) => {
// create button element
const downloadBtn = document.createElement("button");
// you can set any name of id according to your choice
downloadBtn.setAttribute("id", "downloadBtn");
// create anchor element
const downloadLink = document.createElement("a");
// set any thing in inner text
downloadBtn.innerText = "Download Image";
// set download attribute to true
downloadLink.setAttribute("download", true);
// set url with URL
downloadLink.setAttribute("href", URL);
// append button element into anchor element
downloadLink.appendChild(downloadBtn);
// get that element in which download button will append
const container = document.getElementById("container");
// append download button into any element of your choice
container.appendChild(downloadLink);
};
// url of file
const URL = "https://images.pexels.com/photos/863963/pexels-photo-863963.jpeg?cs=srgb&dl=pexels-blaque-x-863963.jpg&fm=jpg"
// call createBtn function with URL
createBtn(URL);
<!-- The element in which download button will be appended -->
<div class="container" id="container"></div>
I am not 100% sure that this will work!
It also not work in stack snippet because iframe tag.
Try to use it locally.

Make File Uploader/Preview Handle Multiple Files

I've built a file uploader (that runs on php in the backend) that previews an image file prior to upload.
The problem I'm having is I can't get it work with multiple files.
It's based on a tutorial I watched and the crux of the issue is in the updateThumbnail function. When this function is called for multiple file uploads I think I need to change the second parameter from fileUploader.files[0] to fileUploader.files, but I'm struggling with the actual function itself.
I clearly need to run a foreach loop (or similar) in the updateThumbnail function but I can't get it to play ball.
Note: It seems CodePen doesn't allow drag & drop functionality, but there is an input file element that is also assigned to the drop-zone that is hidden in the HTML with display:none. This uses a click event listener and fileUploader.click() so when you click the drop-zone you can bring up the file picker window.
Codepen: https://codepen.io/pauljohnknight/pen/JjNNyzO
// hidden on the form, but has drag & drop files assigned to it
var fileUploader = document.getElementById("standard-upload-files");
var dropZone = document.getElementById("drop-zone");
var showSelectedImages = document.getElementById("show-selected-images");
dropZone.addEventListener("click", (e) => {
//assigns the dropzone to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
fileUploader.addEventListener("change", (e) => {
if (fileUploader.files.length) {
// this function is further down but declared here and shows a thumbnail of the image
updateThumbnail(dropZone, fileUploader.files[0]);
}
});
dropZone.addEventListener('dragover', e => {
e.preventDefault()
})
dropZone.addEventListener('dragend', e => {
e.preventDefault()
})
// When the files are dropped in the 'drop-zone'
dropZone.addEventListener("drop", (e) => {
e.preventDefault();
// assign dropped files to the hidden input element
if (e.dataTransfer.files.length) {
fileUploader.files = e.dataTransfer.files;
}
// function is declared here but written further down
updateThumbnail(dropZone, e.dataTransfer.files[0]);
});
// updateThumbnail function that needs to be able to handle multiple files
function updateThumbnail(dropZone, file) {
var thumbnailElement = document.querySelector(".drop-zone__thumb");
if (!thumbnailElement) {
thumbnailElement = document.createElement("img");
thumbnailElement.classList.add("drop-zone__thumb");
// append to showSelectedImages div
showSelectedImages.appendChild(thumbnailElement);
}
if (file.type.startsWith("image/")) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
thumbnailElement.src = reader.result;
};
} else {
thumbnailElement.src = null;
}
} // end of 'updateThumbnail' function
body {
margin: 0;
display: flex;
justify-content: center;
width: 100%;
}
form {
width: 30%;
}
#drop-zone {
border: 1px dashed;
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
}
.select-files {
text-decoration: underline;
cursor: pointer;
}
/* image that is preview prior to form submit*/
.drop-zone__thumb {
width: 200px;
height: auto;
display: block;
}
#submit-images {
margin-top: 1rem;
}
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="drop-zone" class="drop-zone flex">
<p class="td text-center">DRAG AND DROP IMAGES HERE</p>
<p>Or</p>
<p class="select-files">Select Files</p>
</div>
<div id="show-selected-images"></div>
<div class="inner-input-wrapper">
<div class="upload-label-wrapper">
<input id="standard-upload-files" style="display:none" type="file" name="standard-upload-files[]" multiple>
</div>
<input type="submit" name="submit-images" id="submit-images" value="SUBMIT IMAGES">
</div>
</form>
I did quick Codesandbox example from your Codepen
Yes, you just need to iterate over your files and for each file add a preview. You can use for loop or just use Array.from and then .forEach (because FileList is not really an array, you need to convert it to array first to be able to use array inbuilt methods)
Array.from(fileUploader.files).forEach((file) => {
updateThumbnail(dropZone, file);
});
As for previews and updateThumbnail function - it all depends on how you want to use it. If you want users to be able to add more files after first selection then you can just append new previews. If you want to clear the old ones if the user select new ones then you would need to delete old previews. Or maybe you could add "Delete" button for each preview so the user could delete one of them after adding.
Here is the variant when you just want to append new previews:
function updateThumbnail(dropZone, file) {
if (file.type.startsWith('image/')) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
var thumbnailElement = document.createElement('img');
thumbnailElement.classList.add('drop-zone__thumb');
thumbnailElement.src = reader.result;
showSelectedImages.appendChild(thumbnailElement);
};
}
}
For drop you basically do the same:
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
// .. do whatever you want or need here
Array.from(e.dataTransfer.files).forEach((file) => {
updateThumbnail(dropZone, file);
});
});
As you can see functions for handling drop and select are quite similar, you can even make separate function which accepts fileList and then do something with it, so would not need to duplicate your code for both cases.
Made some minor changes to #Danila's version
Most notable differences is the use of es6 and a way to load image faster using URL.createObjectURL. The File reader is pretty much a legecy thing now when there is object urls + new promise based read methods on the prototype itself. Using bae64 is a waste of time decoding/encoding to/from base64
https://codesandbox.io/s/httpsstackoverflowcomquestions68416563-forked-o5spy?file=/src/index.js
import "./styles.css";
// Query all needed elements in one go
const [dropZone, showSelectedImages, fileUploader] = document.querySelectorAll(
"#standard-upload-files, #drop-zone, #show-selected-images"
);
dropZone.addEventListener("click", (evt) => {
// assigns the dropzone to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
// Prevent browser default when draging over
dropZone.addEventListener("dragover", (evt) => {
evt.preventDefault();
});
fileUploader.addEventListener("change", (evt) => {
// Clear the already selected images
showSelectedImages.innerHTML = "";
// this function is further down but declared here and shows a thumbnail of the image
[...fileUploader.files].forEach(updateThumbnail);
});
dropZone.addEventListener("drop", (evt) => {
evt.preventDefault();
// Clear the already selected images
showSelectedImages.innerHTML = "";
// assign dropped files to the hidden input element
if (evt.dataTransfer.files.length) {
fileUploader.files = evt.dataTransfer.files;
}
// function is declared here but written further down
[...evt.dataTransfer.files].forEach(updateThumbnail);
});
// updateThumbnail function that needs to be able to handle multiple files
function updateThumbnail(file) {
if (file.type.startsWith("image/")) {
const thumbnailElement = new Image();
thumbnailElement.classList.add("drop-zone__thumb");
thumbnailElement.src = URL.createObjectURL(file);
showSelectedImages.append(thumbnailElement);
}
} // end of 'updateThumbnail' function

How to preview a file in different pages with one selection in JS

I am making a PDF Viewer. I am using ADOBE View SDK. I have a File input but the problem is that I want to show the file in different views - Full Screen, Half Screen and In-Line. But when the user selects a file and selects a different view the whole page reloads and then the user has to select the file again. I don't want the user to select the file again.
File Input:
<input type='file' onchange="listenForFileUpload(this);" id="file-picker" accept="application/pdf">
listenForFileUpload function:
var fileToRead = document.getElementById("file-picker");
fileToRead.addEventListener("change", function (event) {
var files = fileToRead.files;
var input = document.getElementById('file-data').value
input = files
console.log(files)
document.getElementById('file-form').submit()
if (files.length > 0 && isValidPDF(files[0])) {
var fileName = files[0].name;
var reader = new FileReader();
reader.onloadend = function (e) {
var filePromise = Promise.resolve(e.target.result);
previewFile(filePromise, fileName);
};
reader.readAsArrayBuffer(files[0]);
}
}, false);
}
Please help me to change the view without reloading.
It's this line here:
document.getElementById('file-form').submit()
You are submitting the form there. I'd just remove it.

Download a text file from textarea on Button Click

I am using Jquery UI Dialog. Within the dialog there is textarea that have some text. And I need to save that text as textfile like data.txt when I click the button in the dialog.
<div id = 'metaDataDialog' title='Meta Data' >
<textarea id = 'metaText'>
Some Text
</textarea>
</div>
and this is the jquery ui dialog
$("#metaDataDialog").dialog({ //Jquery UI Dialog Intialization
autoOpen: false,
modal: true,
width: 400,
height: 300,
buttons: {
Save: function() {},
Cancel: function() { $(this).dialog( "close" ); }
},
});
and I need to save/download the text in the local machine, when the save button is clicked
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script>
$(document).ready(function () {
function saveTextAsFile() {
// grab the content of the form field and place it into a variable
var textToWrite = document.getElementById("content").value;
// create a new Blob (html5 magic) that conatins the data from your form feild
var textFileAsBlob = new Blob([textToWrite], { type: 'text/plain' });
// Specify the name of the file to be saved
var fileNameToSaveAs = "myNewFile.txt";
// Optionally allow the user to choose a file name by providing
// an imput field in the HTML and using the collected data here
// var fileNameToSaveAs = txtFileName.text;
// create a link for our script to 'click'
var downloadLink = document.createElement("a");
// supply the name of the file (from the var above).
// you could create the name here but using a var
// allows more flexability later.
downloadLink.download = fileNameToSaveAs;
// provide text for the link. This will be hidden so you
// can actually use anything you want.
downloadLink.innerHTML = "My Hidden Link";
// allow our code to work in webkit & Gecko based browsers
// without the need for a if / else block.
window.URL = window.URL || window.webkitURL;
// Create the link Object.
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
// when link is clicked call a function to remove it from
// the DOM in case user wants to save a second file.
downloadLink.onclick = destroyClickedElement;
// make sure the link is hidden.
downloadLink.style.display = "none";
// add the link to the DOM
document.body.appendChild(downloadLink);
// click the new link
downloadLink.click();
}
function destroyClickedElement(event) {
// remove the link from the DOM
document.body.removeChild(event.target);
}
$("#download").click(function (e) {
e.preventDefault();
saveTextAsFile();
});
});
</script>
</head>
<body>
<input type="button" id="download" value="Download" />
<textarea id="content">In trying to keep this plugin as simple as possible, all four states are always assumed to be present. You should prepare your button image as a single image the width you want your button, and four times the height of the button. All four states should then live in that one image in the same order as the previous list from top to bottom.</textarea>
</body>
</html>

How to detect dimensions of file using File API and Dropzone.js

Using Dropzone.js, I need to detect the dimesions of the image when added files and apply them to its parent .details div. The following code code works and return an alert with the added image width.
myDropzone.on("addedfile", function(file, xhr) {
var fr;
fr = new FileReader;
fr.onload = function() {
var img;
img = new Image;
img.onload = function() {
return alert(img.width);
};
return img.src = fr.result;
};
return fr.readAsDataURL(file);
});
The thing is that I have no idea how to assign the width to its parent .details element which set the preview width of the preview.
I try replacing the alert for this code but it doesn't do anything.
$(this).parent('.details').css('height',img.height);
I'm a bit lost in how to relate the value inside the onload function to applying it to its parent class.
With the latest version of dropzone you don't have to write this code yourself.
Simply read the file.width and file.height properties that are set on the file object when the thumbnail is generated.
The problem, why your CSS doesn't affect the element, is because you didn't specify the unit, px in this case. So your code can be:
myDropzone.on("thumbnail", function(file) {
$(this.element).parent('.details').css('height', file.height + 'px');
});

Categories