Some other things I use in HTML
Upload to the browser
There are 2 steps:
- capture the file using input tag + change event or a div with drop event
- then use the fileReader() object to read the file via the load event
Using the input tag to capture the file
html:
<input id='myinput' type='file' accept='.png, .jpg, .jpeg, .csv, .txt, .html' />
javascript:
var myinput = document.getElementById('myinput');
myinput.addEventListener('change', function(e) {
// this step will capture the file, but thats all
var file = e.target.files[0];
console.log(file);
});
Using the input tag to capture the file THEN read it to the console
There are 2 different events here.
- The first event is triggered when the input file records a change. That event captures the file that triggered it.
- The second event is triggered when the 'load' event is recorded which happens when we pass the file we captured in step 1 thru the fileReader
html:
<input id='myinput' type='file' accept='.png, .jpg, .jpeg, .csv, .txt, .html' />
javascript:
var myinput = document.getElementById('myinput');
myinput.addEventListener('change', function(e) {
// 1. capture the file
var file = e.target.files[0];
// 2. make a fileReader object
var reader = new FileReader();
// 3. define how the filereader object behaves once its done reading the file
reader.addEventListener('load', function(e) {
console.log(e);
var fileContentAsText = e.target.result;
console.log(fileContentAsText);
}, false);
// 4. use the fileReader object to read the file, and return a string
reader.readAsText(file);
});
readAsArrayBuffer(file) and Uint8Array(contents)
2018-11-10: Here is something interesting I have learned. If I want to read the file as text, I will use readAsText() and that will apply encoding. But if I want to read the bytes of the file, I should use readAsBinaryString().
OK! now I get it. I want to use readAsArrayBuffer(). So I might do something like this:
var myinput = document.getElementById('myinput');
myinput.addEventListener('change', function(e) {
/* 1. capture the file */
var file = e.target.files[0];
//console.log(file);
/* 2. make a fileReader object */
var reader = new FileReader();
/* 3. define how the filereader behaves - examine the load event */
reader.addEventListener('load', function(e) {
var contents = e.target.result;
getInfoAboutTheFile(file, contents);
}, false);
/* 4. use the fileReader object to read the file, and return a string */
reader.readAsArrayBuffer(file); // yes!
});
function getInfoAboutTheFile(file, contents) {
console.log(file.name);
console.log(contents); // gibberish!
var data = new Uint8Array(contents);
console.log(data) // every bit of the file displayed as a decimal! SO EXCITING!
}
Drag and drop
drag and drop a file here
Events dragenter, dragover, dragleave and drop
For each of dragenter, dragover and dragleave, we need to write something like the following:
// dragenter event listener
container.addEventListener('dragenter', function(e) {
e.stopPropagation();
e.preventDefault();
this.style.border = '2px dashed rgb(50, 50, 50)';
}, false);
The line e.preventDefault(); has an important function, especially for drop.
When you drop a file into the browser, the browser will open up that file as a file: URL from its location.
Probably, we dont want to be redirected when we drop a file into the container, so we need to prevent that default action.
The line this.style.border = '2px dashed rgb(50, 50, 50)'; is obviously just changing the color of the border. It depends on the event. The border will become darker when a file enters its borders or hovers over it, and becomes lighter when that file leaves or is dropped into it.
The drop event itself
Basically, when you drop a file into the container, the drop event listener is triggered. The event e will contain all the information about that event.
The property that contains all the info about the file is e.dataTransfer.files, which is an array of files. If you drag and drop multiple files into the container, then there will be multiple elements.
Theres a glitch in the console. If I write console.log(e);, e.dataTransfer.files will look empty. But if I write console.log(e.dataTransfer.files[0]), I will see the results.
Anyhow, if I write e.dataTransfer.files[0], then Im just focusing on the first element of that array.
Each element of e.dataTranfer.files will have lots of metadata about the file that triggered the event, like:
- name
- size
- type
- lastModified
The drop event listener callback function
container.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
this.style.border = '2px dashed rgb(170, 170, 170)';
/* there is a glitch in the console
console.log(e) wont show e.dataTransfer.files[0] */
/* after you drop a file, check the console
check out what you can access */
console.log(e.dataTransfer.files[0]);
/* all the metadata about the file comes from here */
console.log(e.dataTransfer.files[0].name);
}, false);
Drag and drop + fileReader to read file contents
drag and drop a file here
The fileReader() object
In the above case, I stopped once I had some metadata about the file using e.dataTransfer.files[0].
But here, Im going to read the contents of the file.
Take a look at the drop event callback function.
There are 2 events! Here is the lay of the land:
- First, we drop a file into the container, triggering the drop event
- This gives us e.dataTransfer.files[0]
- We feed e.dataTransfer.files[0] thru fileReader which returns a result
- When fileReader is done reading the file, that triggers the fileReader.onload event
This is how to use the fileReader object
- Make a fileReader object like this: var reader = new FileReader();
- The role of the fileReader is to read files. A fileReader object has a special event, load, which is triggered when the fileReader is done reading a file. So its a good idea to decide what code will run when this event is triggered. Obviously, we can do this the regular ways, like reader.addEventListner('load', function(){}); or reader.onload = function(){};
- The result of the reading is e.target.result, where e is the second event, the load event which has been triggered. So it is an object with all the information about that file whose completed reading triggered it [the event] into existence.
- In the below case, Im reading the file via reader.readAsText(e.dataTransfer.files[0]);, where readAsText is an object method which accepts a file as its argument. Its function should be obvious. But there are other methods:
- reader.readAsText(file) to read the file as text
- reader.readAsDataURL(file) will return a data URL, which I could, for instance, set as the href attribute to an <a> tag.
- I havent looked much into the other but Im sure theyre pretty nifty
Ideas with this bit of code
as of 2018-10-27 I can drag+drop or upload a csv file with lat-lon data and plot the points on either a static map onto a canvas with p5js or a slippy map with mapbox gl js
im trying to see if i can take apart an excel file but it is hard. csv files are simple enough, but it is an extra step of saving the file as csv which is a hassle
I think it would be pretty cool if I had a simple text file, dropped it into the container, read the contents as text and stored the results as a string in the first step.
Then perform a basic Caesar shift on the string and convert it to a dataURL, where I could set it as an <a href=''>, so that the downloaded result would be a very simply encrypted version of the original file.
The drop event listener callback function
container.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
this.style.border = '2px dashed rgb(170, 170, 170)';
/* this is where we put on our jet pants */
/* right now, we have access to e.dataTransfer.files[0] */
/* remember, we dont have to save it as a variable. that the drop event was recorded is enough for that data to be captured */
/* 1. make a fileReader object */
var reader = new FileReader();
/* 2. we define what happens when the fileReader is done reading something */
reader.addEventListener('load', function(e) {
var fileContentAsText = e.target.result;
console.log(fileContentAsText);
}, false);
/* 3. use the fileReader object to read the file, and return a string */
reader.readAsText(e.dataTransfer.files[0]);
}, false);
drag and drop - the whole thing, for laziness
<div id="dropContainer" style="border: 2px dashed rgb(170, 170, 170); float: left; padding: 4px; width: 300px; height: 200px; margin: 10px;">
<p id='containerMessage' style='line-height: 150px; text-align: center; font-family: calibri; font-size: 20px;'> Drag and drop an image file here. </p>
</div>
<script>
var container = document.getElementById('dropContainer');
// dragenter event listener
container.addEventListener('dragenter', function(e) {
e.stopPropagation();
e.preventDefault();
this.style.border = '2px dashed rgb(50, 50, 50)';
}, false);
// dragover event listener
container.addEventListener('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
this.style.border = '2px dashed rgb(50, 50, 50)';
}, false);
// dragleave event listener
container.addEventListener('dragleave', function(e) {
e.stopPropagation();
e.preventDefault();
this.style.border = '2px dashed rgb(170, 170, 170)';
}, false);
container.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
this.style.border = '2px dashed rgb(170, 170, 170)';
/* 1. make a fileReader object */
var reader = new FileReader();
/* 2. we define what happens when the fileReader is done reading something */
reader.addEventListener('load', function(e) {
var fileContentAsText = e.target.result;
console.log(fileContentAsText);
}, false);
/* 3. use the fileReader object to read the file, and return a string */
reader.readAsText(e.dataTransfer.files[0]);
}, false);
</script>