I have two buttons ... when clicked they display some text in a input field. I use some simple javascript to select which text to display, the one defined under the button with id="blabla1" or the one under the button with id="blabla2".
Is it possible to display the text defined in an external .txt file?
It is working fine with the text defined as value under the input button:
<input type="hidden" id="SupSite1Title" value="Subsite1 Title!"><br>
but i want text from a txt file instead.
<body>
<div id="leftnav">
<ul>
<li><input type="text" id="TextField1"><br><br></li>
</ul>
</div>
<div id="rightnav">
<ul>
<li><button id="blabla1" onclick="myFunction1()">Side1</button></li>
<li><button id="blabla2" onclick="myFunction2()">Side2</button></li>
</ul>
</div>
<input type="hidden" id="SupSite1Title" value="Subsite1 Title!"><br>
<input type="hidden" id="SupSite2Title" value="Subsite2 Title!"><br>
<script>
function myFunction1() {document.getElementById("TextField1").value =document.getElementById("SupSite1Title").value;
}
</script>
<script>
function myFunction2() {document.getElementById("TextField1").value =document.getElementById("SupSite2Title").value;
}
</script>
If you want to display the text content of the .txt file ... you can use an API called FileReader API (you need to check if your browser supports that)
here is how you can do it :
UPDATED :
var file1 = document.getElementById('file1');
var file2 = document.getElementById('file2');
document.getElementById('bOne').addEventListener("click", function(){getFile(file1)})
document.getElementById('bTwo').addEventListener("click", function(){getFile(file2)})
function getFile(target) {
const input = target;
if ('files' in input && input.files.length > 0) {
placeFileContent(
document.getElementById('display'),
input.files[0])
}
}
function placeFileContent(target, file) {
readFileContent(file).then(content => {
target.value = content
}).catch(error => console.log(error))
}
function readFileContent(file) {
const reader = new FileReader()
return new Promise((resolve, reject) => {
reader.onload = event => resolve(event.target.result)
reader.onerror = error => reject(error)
reader.readAsText(file)
})
}
label {
display : block;
margin-top : 40px;
margin-bottom : 20px;
}
<label for="file1">Upload file 1 : </label>
<input type="file" accept=".txt" id="file1" name="file1">
<label for="file2">Upload file 2 : </label>
<input type="file" accept=".txt" id="file2" name="file2">
<button id="bOne">Display file1</button>
<button id="bTwo">Display file2</button>
<label for="file2">Selected file : </label>
<input type="text" id="display" for="display">
METHOD N°2 (data fetching from a server) :
function fetchData(buttonNumber) {
var btn1 = document.getElementById('b1')
var btn2 = document.getElementById('b2')
var display = document.getElementById('display')
//fetching data
if (buttonNumber == 1) {
//replace 'file1.txt' with your file URL
fetch('file1.txt').then(x => {
x.text().then(function(text) {
display.value = text
});
})
} else {
//replace 'file2.txt' with your file URL
fetch('file2.txt').then(x => {
x.text().then(function(text) {
display.value = text
});
})
}
}
#b1,
#b2 {
display: block;
margin: 40px;
}
<button id="b1" onclick="fetchData(1)">Get file 1 and show it</button>
<button id="b2" onclick="fetchData(2)">Get file 2 and show it</button>
<label for="file2">Selected file : </label>
<input type="text" id="display" for="display">
If you want to read the contents of a text file you cannot load it from local file system. You should put it on server and load it from there.
Give the input field the attributes type="file" and accept=".txt", and that should work
<input type="file" accept=".txt" />
And you can read this .txt file using node.js(Also you can read it with vanilla js), But i prefer node.js like this
const fs = require('fs');
const fileData = fs.readFileSync('fileName.txt', 'utf-8');
console.log(fileData) // Whatever inside .txt file
Update according to comment:
Suppose in your project folder, you have one index.html file and one index.js file. Create two .txt file named as file1.txt and file2.txt And write something on those file. NOTE: For simplicity i am writing solution using jQuery.
index.html
<body>
<p id="text-field"></p>
<button id="btn1">Button 1</button>
<button id="btn2">Button 2</button>
</body>
index.js
const fs = require('fs');
let fileData = '';
$('#btn1').click(()=> {
fileData = fs.readFileSync('file1.txt', 'utf-8');
$('#text-field').append(fileData);
});
$('#btn2').click(()=> {
fileData = fs.readFileSync('file2.txt', 'utf-8');
$('#text-field').append(fileData);
});
That's it. According to button click text will be append into p element.
You can handle two button click with one function also, like this
$('button').click(event => {
event.stopImmediatePropagation();
event.stopPropagation();
if($(event.target).attr('id') === 'btn1') {
fileData = fs.readFileSync('file1.txt', 'utf-8');
$('#text-field').append(fileData);
}else if($(event.target).attr('id') === 'btn2') {
fileData = fs.readFileSync('file2.txt', 'utf-8');
$('#text-field').append(fileData);
}
});
Related
I have two buttons - 'Input the File' which uploads a CSV file from PC and 'Load File' which loads it for other utility in my application.
<input type="file" class="custom-file-input form-control-sm" id="inputFile" onchange="handleFiles(this.files)" accept=".csv">
<label class="custom-file-label col-form-label-sm" for="inputFile" onclick="checkFunc()">Input the File</label>
<button type="button" class="btn btn-outline-dark rounded w1-right set-sql" id="lfb">Load File</button>
I want to add a js function to the Load File button so that when it loads file which is uploaded from the local PC, it checks the number of columns the file has and whether it is X number of columns. And then displays a success message(if X columns) or failure message(if more than or less than X number of columns).
Here is what I have tried. The function is not working. What can I do/change here?
async function checkFunc() {
if (inputFile.files.length) {
try {
var csvFileInText = await inputFile.files[0].text();
console.log(csvFileInText);
var arrObje = [];
var lines = csvFileInText.split('\n');
var lineA = lines[0].split(',');
let linesize = lineA.length;
if (linesize == 3){
alert("File uploaded successfully.");
}
else{
alert("File was not uploaded. Please check the instructions.");
}
} catch (e) {
console.error(e);
}
}
}
You need to split on the below characters that is why it isn't working for you:
let lines = csvFileInText.split(/\r?\n/);
Currently, I'm developing a drag and drop feature. The problem is that I can't figure out how to get multiple files from user separately. Let's say that we have a drop zone container and when user drops there images, it assigns them to <input type="file">. Let's say, a user drops here an image and then decides to drop another image and we have to somehow add this second image to the input. I tried finding solution in the Internet(of course :)) but found nothing that solves this problem.
Here is my HTML:
<form action="" method="POST" enctype="multipart/form-data">
<div class="drop_zone">
<span class="drop_zone__prompt">Drop your files here</span>
<input required name="images" type="file" multiple class="drop_zone__input">
</div>
<input type="submit" value="Отправить">
</form>
JavaScript:
document.querySelectorAll('.drop_zone__input').forEach(InputElement => {
const dropZoneElement = InputElement.closest('.drop_zone');
dropZoneElement.addEventListener('drop', e => {
e.preventDefault();
if (e.dataTransfer.files.length){
InputElement.files = e.dataTransfer.files;
}
});
I tried this:
dropZoneElement.addEventListener('drop', e => {
e.preventDefault();
if (e.dataTransfer.files.length){
myfiles = e.dataTransfer.add(InputElement.files);
InputElement.files = myfiles;
}
});
But it returns error saying that 'e.dataTransfer.add is not a function'
Why I tried this:
I found add() method here
And this article says:
The DataTransferItemList object is a list of DataTransferItem objects representing items being dragged. During a drag operation, each DragEvent has a dataTransfer property and that property is a DataTransferItemList.
Actually, there is a way to do that. It's far from straightforward, but it does work.
The only way to create a FileList object is to create a custom DataTransfer object. You can add files to it using dataTransfer.items.add(), and obtain the corresponding FileList through dataTransfer.files.
So, create a new DataTransfer object every time you want to add files, add the existing and the new files to it, and assign its FileList to the files property of the input element.
Note: You can't use the drop event's DataTransfer object for this, because it's read-only.
document.querySelectorAll('.drop_zone__input').forEach(InputElement => {
const dropZoneElement = InputElement.closest('.drop_zone');
dropZoneElement.addEventListener('dragover', e => {
e.preventDefault()
});
dropZoneElement.addEventListener('drop', e => {
e.preventDefault();
//Create a new DataTransfer object
const dataTransfer = new DataTransfer
//Add new files from the event's DataTransfer
for(let i = 0; i < e.dataTransfer.files.length; i++)
dataTransfer.items.add(e.dataTransfer.files[i])
//Add existing files from the input element
for(let i = 0; i < InputElement.files.length; i++)
dataTransfer.items.add(InputElement.files[i])
//Assign the files to the input element
InputElement.files = dataTransfer.files
});
})
.drop_zone{
height: 200px;
width: 200px;
border: solid black 1px;
}
<form action="" method="POST" enctype="multipart/form-data">
<div class="drop_zone">
<span class="drop_zone__prompt">Drop your files here</span>
<input required name="images" type="file" multiple class="drop_zone__input">
</div>
<input type="submit" value="Отправить">
</form>
You can also reuse the same DataTransfer object, so you don't have to re-add the existing files.
However, in this case, you also have to handle input events on the input element.
document.querySelectorAll('.drop_zone__input').forEach(InputElement => {
const dropZoneElement = InputElement.closest('.drop_zone');
const dataTransfer = new DataTransfer
dropZoneElement.addEventListener('dragover', e => {
e.preventDefault()
});
dropZoneElement.addEventListener('drop', e => {
e.preventDefault();
//Add new files from the event's DataTransfer
for(let i = 0; i < e.dataTransfer.files.length; i++)
dataTransfer.items.add(e.dataTransfer.files[i])
//Assign the files to the input element
InputElement.files = dataTransfer.files
});
InputElement.addEventListener('input', e => {
dataTransfer.items.clear()
for(let i = 0; i < InputElement.files.length; i++)
dataTransfer.items.add(InputElement.files[i])
})
})
.drop_zone{
height: 200px;
width: 200px;
border: solid black 1px;
}
<form action="" method="POST" enctype="multipart/form-data">
<div class="drop_zone">
<span class="drop_zone__prompt">Drop your files here</span>
<input required name="images" type="file" multiple class="drop_zone__input">
</div>
<input type="submit" value="Отправить">
</form>
Or, if you want to add the files when interacting with the file input instead of replacing them, you can do this:
document.querySelectorAll('.drop_zone__input').forEach(InputElement => {
const dropZoneElement = InputElement.closest('.drop_zone');
const dataTransfer = new DataTransfer
dropZoneElement.addEventListener('dragover', e => {
e.preventDefault()
});
dropZoneElement.addEventListener('drop', e => {
e.preventDefault();
//Add new files from the event's DataTransfer
for(let i = 0; i < e.dataTransfer.files.length; i++)
dataTransfer.items.add(e.dataTransfer.files[i])
//Assign the files to the input element
InputElement.files = dataTransfer.files
});
InputElement.addEventListener('input', e => {
e.preventDefault()
for(let i = 0; i < InputElement.files.length; i++)
dataTransfer.items.add(InputElement.files[i])
InputElement.files = dataTransfer.files
})
})
.drop_zone{
height: 200px;
width: 200px;
border: solid black 1px;
}
<form action="" method="POST" enctype="multipart/form-data">
<div class="drop_zone">
<span class="drop_zone__prompt">Drop your files here</span>
<input required name="images" type="file" multiple class="drop_zone__input">
</div>
<input type="submit" value="Отправить">
</form>
You can remove files from the DataTransfer object using dataTransfer.items.remove():
document.querySelectorAll('.drop_zone__input').forEach(InputElement => {
const dropZoneElement = InputElement.closest('.drop_zone');
const removeFirstElement = dropZoneElement.querySelector('.drop_zone__remove_first')
const dataTransfer = new DataTransfer
dropZoneElement.addEventListener('dragover', e => {
e.preventDefault()
});
dropZoneElement.addEventListener('drop', e => {
e.preventDefault();
//Add new files from the event's DataTransfer
for(let i = 0; i < e.dataTransfer.files.length; i++)
dataTransfer.items.add(e.dataTransfer.files[i])
//Assign the files to the input element
InputElement.files = dataTransfer.files
});
InputElement.addEventListener('input', e => {
e.preventDefault()
for(let i = 0; i < InputElement.files.length; i++)
dataTransfer.items.add(InputElement.files[i])
InputElement.files = dataTransfer.files
})
removeFirstElement.addEventListener('click', () => {
dataTransfer.items.remove(0)
InputElement.files = dataTransfer.files
})
})
.drop_zone{
height: 200px;
width: 200px;
border: solid black 1px;
}
<form action="" method="POST" enctype="multipart/form-data">
<div class="drop_zone">
<span class="drop_zone__prompt">Drop your files here</span>
<input required name="images" type="file" multiple class="drop_zone__input">
<input type="button" class="drop_zone__remove_first" value="Remove first file">
</div>
<input type="submit" value="Отправить">
</form>
You can't add to the files to the input's list of files, although apparently you can replace that list as described by FZs, which largely comes to the same thing.
Another way to deal with this is to make the original input hidden via CSS and add a new input where it used to be, so it can receive new files. You can make the UI clean by listing all of the files you're going to upload separately from the input.
How you deal with on submission depends on how you're handling submission.
If you're doing a standard HTTP form submission, ensure that your server side script handles all of the files regardless of which input they came from (it will receive more than one).
If you're submitting via ajax, you can use a FormData object and append each file to it, then submit that.
Here's a quick and dirty example maintaining the files in a FormData object:
let nextFileNum = 1;
const formData = new FormData();
const fileList = document.getElementById("file-list");
document.getElementById("inputs").addEventListener("input", function() {
let input = event.target.closest("input[type=file]");
if (!input) {
return;
}
for (const file of input.files) {
const fileId = `file${nextFileNum++}`;
formData.append(fileId, file, file.name);
debugShowCurrentFiles("added");
let div = document.createElement("div");
// This is a Q&D sketch, needs a11y
div.innerHTML = "<span tabindex class=delete>[X]</span><span class=filename></span>";
div.querySelector(".filename").textContent = file.name;
div.querySelector(".delete").addEventListener("click", function() {
formData.delete(fileId);
debugShowCurrentFiles("deleted");
div.remove();
div = null;
});
fileList.appendChild(div);
}
this.removeChild(input);
this.insertAdjacentHTML("beforeend", input.outerHTML);
input = null;
});
function debugShowCurrentFiles(action) {
const contents = [...formData.entries()];
console.log(`--- ${action}, updated formData contents (${contents.length}):`);
for (const [key, value] of contents) {
console.log(`${key}: ${value.name}`);
}
}
#file-list .delete {
margin-right: 2em;
cursor: pointer;
}
<div id="inputs">
<input type="file" multiple>
</div>
<div id="file-list"></div>
You can do this with FileList, heres an article about it.
Also added code snippet which outputs file name and type after you submit the form just for visualization.
let form = document.getElementById('file_drop_form');
function getFiles(event) {
event.preventDefault();
let files = document.getElementById('file').files;
for(let i = 0; i < files.length; i++) {
document.write(`Title: ${files[i].name}; Type: ${files[i].type} <br>`);
}
}
form.addEventListener('submit', getFiles);
<form id="file_drop_form" method="post" enctype="multipart/form-data">
<div>
<label for="file">Drop your files here</label>
<input type="file" id="file" name="file" required multiple>
</div>
<input type="submit" value="Submit">
</form>
I have a problem while uploading files using a drop area. It seems that files get converted to strings when they arrive at the backend. I'm adding the file objects to a new array because I want the users to be able to remove unwanted files before they submit the form.
The form looks like this:
<form action="" class="dropzone" id="image_upload" enctype="multipart/form-data">
<div class="upload-input">
<label for="delivery_address" id="delivery_address_label">Delivery address</label>
<input type="text" name="delivery_address" id="delivery_address" class="form-control" />
</div>
<div class="" id="drop-area">
<p>Upload multiple files with the file dialog or by dragging and dropping images onto the dashed
region
</p>
</div>
<div class="upload-input">
<input class="btn btn-info w-100" type="submit" id="btnUpload" value="Send" />
</div>
</form>
Javascript:
let dropArea = document.getElementById("drop-area");
let fileList = [];
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false)
})
function preventDefaults(e) {
e.preventDefault()
e.stopPropagation()
}
dropArea.addEventListener('drop', handleDrop, false)
function handleDrop(e) {
let dt = e.dataTransfer;
let files = dt.files;
handleFiles(files);
}
function handleFiles(files) {
files = [...files];
files.forEach(addFiles);
}
function addFiles(file) {
fileList.push(file);
}
btnUpload.addEventListener("click", function(evt) {
evt.preventDefault();
const xhr = new XMLHttpRequest();
const form = document.getElementById("image_upload");
const formData = new FormData(form);
console.log(fileList);
formData.append("fileList", fileList);
xhr.open("POST", "add.php");
xhr.onreadystatechange = function() {
document.getElementById("phpResponse").innerHTML = this.responseText;
};
xhr.send(formData);
});
And in the PHP file I'm just var dumping $_FILES for now to see what's going through:
var_dump($_FILES);
Which returns
array(0) { }
var_dump($_POST) returns:
array(3) { ["delivery_type"]=> string(14) "Latvijas pasts" ["delivery_address"]=> string(6) "qweeqe" ["fileList"]=> string(27) "[object File],[object File]" }
I can't find where the problem is. The form is set to enctype="multipart/form-data". Before sending the form I console.log the fileList variable and it looks like the files are still files:
As suggested, I have to loop through every instance of File in the fileList array and append each File to FormData individually.
This part:
formData.append("fileList", fileList);;
Becomes:
for (let i = 0; i < fileList.length; i++) {
formData.append("fileList[]", fileList[i]);
}
And on the backend I can loop through every file:
foreach($_FILES['fileList']['tmp_name'] as $key => $tmp_name){
echo $_FILES['fileList']['name'][$key] . "<br />";
}
How to remove specific file from files selected with input type with multiple attribute?
<input type="file" (change)="onFileChange($event)" #fileInput multiple>
I want to delete one of the selected file.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
https://jsfiddle.net/Sagokharche/eL3eg6k4/
Do you need it to be impossible to choose? Then use HTML Input file accept property. accept="image/png" for instance.
Or you want it to filter from the input after the user selected it?
Then you should use a custom directive or check for the file types in the ts code upon upload.
EDIT
in that case, in your code:
onFileChange(event) {
const fileList = event.target.files;
console.log("User selected fileList:", fileList)
Array.from(fileList).filter(
item => {
console.log("file mime type:", item['type'])
})
const filesToUpload = Array.from(fileList).filter(
item => { return item['type'] != "application/zip" })
console.log("reduced list:", filesToUpload)
}
Working stackblitz example here.
You can access the inputs FileList-object in .ts side like this:
onFileChange(event) {
console.log(event.srcElement.files);
}
Edit:
If you are looking for a solution how to make dynamic form (add and delete inputs), then have a look at this answer and demo:
Angular 4 Form FormArray Add a Button to add or delete a form input row
In your hmtl code
<div class="row">
<div class="col-md-2 productAddfromImages" *ngFor='let url of imageurls; let i = index'>
<img class="img-fluid" [src]="url.base64String">
<a (click)="removeImage(i)" class="btn btn-xs btn-danger">Remove</a>
</div>
</div>
Remove function
removeImage(i) {
this.imageurls.splice(i, 1);
}
Add Function
onSelectFile(event) {
if (event.target.files && event.target.files[0]) {
var filesAmount = event.target.files.length;
for (let i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = (event: any) => {
this.imageurls.push({ base64String: event.target.result, });
}
reader.readAsDataURL(event.target.files[i]);
}
}
}
}
For more details:https://findandsolve.com/articles/how-to-upload-and-remove-multiple-image-using-anular-code-example
I have done this in jQuery, to get filename from input file tag, With jQuery it works perfectly.
//jQuery('input[type=file]').on('change', prepareUpload);
document.getElementsByTagName('input[type=file]').addEventListener('change',prepareUpload1,true);
/*
//this works in jQuery
function prepareUpload(event)
{
var files = event.target.files;
var fileName = files [0].name
alert(fileName);
}
*/
/****Check it here ****/
// it does not work in javascript
function prepareUpload1(event)
{
var files = event.target.files;
var fileName = files [0].name
alert("fileName 2 : "+fileName);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" />
But I found Event.target does not work in IE, I tried to change it to java script addeventlistener, it did not work.
It throws error
Uncaught ReferenceError: input is not defined
It is working in jQuery but it is not working in JS, Due to IE issue I need to change it to JS.
Can some one help
I found the problem to be in getElementsByTagName method, you use this when you have a group of elements with the same tag name.
Try this code below, it works
//HTML
<input id="inp" type="file" />
// JavaScript
document.getElementById('inp').addEventListener('change',prepareUpload,false);
function prepareUpload(event)
{
var files = event.target.files;
var fileName = files[0].name;
alert(fileName);
}
Below is the code if you want to do it for more than one element
<body>
<input type="file" class="input"/>
<input type="file" class="input"/>
<input type="file" class="input"/>
<input type="file" class="input"/>
<script>
var inputArray = document.getElementsByClassName('input');
for(var i = 0; i < inputArray.length; i++){
inputArray[i].addEventListener('change',prepareUpload,false);
};
function prepareUpload(event)
{
var files = event.target.files;
var fileName = files[0].name;
alert(fileName);
}
</script>
</body>
This will work
var fileName = $("input[type='file']").val().split('/').pop().split('\\').pop();
The code above is correct for all but IE simply because IE doesn't like event.target - you need event.srcElement: https://developer.mozilla.org/en-US/docs/Web/API/Event/srcElement
So something like this should sort that out:
var files;
if (window.navigator.userAgent.indexOf("MSIE ") > 0) ?
files = event.srcElement.files :
files = event.target.files;
I couldn't make that work in the "Run Snippet" thing SO has, though, so here's how you can just get it using another button:
document.getElementById('myBtn').addEventListener('click', function() {
doUpload();
});
function doUpload()
{
var myFile = myInput.files[0];
// can also use var myFile = document.querySelector('input').files[0];
var fileName = myFile.name;
alert(fileName);
}
<input id="myInput" type="file" />
<button id="myBtn">Try Me</button>