JavaScript Loop(Make sure my loop isn't rewriting) - javascript

So I need some help saving some files that people will submit via a file upload.
Right now my code replaces it each time, but I want it to not replace each time. Like for example my user chooses a certain amount of files like 3 files, uploads them, and then chooses 1 file and uploads that as well. That would be a total of 4 files. What my code is doing now is if my user uploads 3 files, it saves the 3 files and then if they upload 1 file it gets rid of the 3 and only has one file.
I want it to not get rewritten, and have 4 files. Please help. This seem very trivial but I can't seem to get it.
function handleFileSelect(e) {
if (!e.target.files) return;
selDiv.innerHTML = "";
var files = e.target.files;
for (var i = 0; i < files.length; i++) {
var f = files[i];
selDiv.innerHTML += f.name + "<br/>";
}
}

I believe your issue is you are resetting the innerHTML in the function call. I assume this function is called every time files are uploaded?
function handleFileSelect(e) {
if (!e.target.files) return;
selDiv.innerHTML = ""; // <--- this will empty the div
var files = e.target.files;
for (var i = 0; i < files.length; i++) {
var f = files[i];
selDiv.innerHTML += f.name + "<br/>";
}
}
If you have uploaded files, then called this function and displayed them and then upload more files and call this function it will constantly reset the innerHTML. I believe if you remove that line it will continue to append the uploaded files without overwriting the previous ones.

Related

How to access the contents of a directory passed in the URL parameters passed to a browser

First off, for Chromecast reasons, I want to, currently, limit the solution to the Chrome browser.
What I'd like to do is package up a directory of images, with a launcher batch file (cmd or sh) and an html file. The html file is to be completely self contained, with no imports.
The bat file would contain something like:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files "file://%CD%\SlideShow1.2.html?slideDir=%CD%\Slides"
Currently I can use
<input type="file" id="slideInput" multiple="multiple" webkitdirectory="webkitdirectory" onchange="appendToSlideList();" accept=".png,.gif,.jpg,.jpeg" />
to manually select files, and
var slideList = [];
var numSlides = 0;
function appendToSlideList()
{
var slideInput = document.getElementById("slideInput");
var slides = slideInput.files;
for(j = 0; j < slides.length; j++)
{
slideList[numSlides++] = slides[j];
}
}
to append pictures from selected directories to the master slide list. Then the following, via a Timer() object displays the slides:
function showNext()
{
if(picture == null)
{
picture = document.getElementById("slideShow");
intervalElem = document.getElementById("interval");
}
if(currentPicture == numSlides)
{
currentPicture = 0;
}
// this comes from https://www.w3.org/TR/file-upload/#file
picture.src = window.URL.createObjectURL(slideList[currentPicture++]);
var interval = parseInt(intervalElem.value) * 1000;
timer = new Timer(showNext, interval);
}
If you've read this far, kudos :). So, all this (plus other auxiliary code that is not germane to the desired solution) works to show a slideshow based on user input from the object.
My desire is to package things up so that all the user has to do is double click on the bat file, and the browser proceeds to show the slide show.
So, after all this, my question is, how do I take the directory passed in, and get all the graphic files in that directory, for use in the already working code.
I've spent the last six hours researching this question, much on StackOverflow, and it appears, to me, currently, that this is an impossible quest.
Here's a fiddle with 'complete' minimalist code: https://jsfiddle.net/hrvrdfjs/
Thanks!
Tom.
There is currently no way for JavaScript in the browser to list files from a directory without the user explicitly choosing the directory in the browser.
However, you can easily create a JavaScript file that contains a list of the image files in the directory from a batch file like this:
#echo off
echo var toC = ` > "C:\slides\data.js"
dir C:\slides\*.png,*.gif,*.jpg,*.jpeg /B >> "C:\slides\data.js"
echo `; >> C:\slides\data.js
This will create file data.js which looks like this:
var toC = `
funny.png
serious.png
holidays.jpeg
`;
Explanations:
echo var toC = ` > "C:\slides\data.js"
Creates or overwrites the file C:\slides\data.js with the javascript code that is the first part of creating a template literal.
dir C:\slides\*.png,*.gif,*.jpg,*.jpeg /B >> "C:\slides\data.js"
Tells dir to list the files with the given extensions in the given directory and appends the file names to the file data.js. The parameter /B makes dir only output the files names, no other information and also skip outputting a header and footer for the listing.
echo `; >> C:\slides\data.js
This appends the end of the javascript template literal.
In JavaScript ES6 and newer, template literals can be used to create string literals that span multiple lines and can contain arbitrary characters.
Load the file data.js dynamically from your html document (by inserting a script tag that refers to the file) and you can access the variable toC which contains the list of files as a multi-line string.
This is a demo where the data.js file is statically included:
<html>
<head>
<script src="C:\slides\data.js"></script>
</head>
<body>
<script>
window.alert(toC);
</script>
</body>
</html>
I wasn't able to use the "dir" command as given above, perhaps because I'm using windows 7. Here is what I came up with, instead:
mkdir C:\Temp\slideShow
rem Replace each instance of a back slash with two, as javascript will remove a single backslash
rem (Unless it is followed by a 'valid' backslash char (r,n,etc.), which is not what we want.).
echo var topLocation = '%CD:\=\\%'; > C:\Temp\slideShow\topLocation.js
echo var slideDirContents = ' > "C:\Temp\slideShow\slideDirContents.js"
dir %CD%\Slides\*.jpeg %CD%\Slides\*.jpg %CD%\Slides\*.png %CD%\Slides\*.gif /B /ON >> "C:\Temp\slideShow\slideDirContents.js"
echo '; >> C:\Temp\slideShow\slideDirContents.js
Then, to split out each file from the input .js file, and create a file path that would later be used to build an URL that the img.src could present the file (NOTE: the add function had to be done after the page was loaded, so the textarea element would be present for the javascript to modify):
function doOnloadFunctions()
{
addStaticsToSlideList();
}
function addStaticsToSlideList()
{
// Empty dir on Windows == size 2 (CR-LF)
// Empty dir on others == size 1 (CR or LF)
if((slideDirContents.length != 2) && (slideDirContents.length != 1))
{
var slidelistElem = document.getElementById("slidelist");
// Linux/Unix/BSD based line separator = \n
// Windows based line separator = \r\n
// Mac based line separator = \r
var re = /\n|\r\n|\r/;
var slides = slideDirContents.split(re);
for(j = 0; j < slides.length; j++)
{
var aFile = {};
var theName = slides[j].trim();
if(theName.length > 0)
{
var fileName = slides[j];
aFile.fileName = topLocation + '\\Slides\\' + fileName;
// Set the original index to the current insertion point.
aFile.oi = numSlides;
// Set the shuffle index simply to instantiate it. We'll
// set the si for real when we want to shuffle the array.
aFile.si = 0;
var listElem = document.createElement("li");
listElem.appendChild(document.createTextNode(fileName));
slidelistElem.appendChild(listElem);
slideList[numSlides++] = aFile;
}
}
}
}
There's a <file> input element that can be used to append local files to the slide list, the <file> input doesn't fill in fileName it just fills in name thus this is the differentiating code that instantiates each <img> with the proper url:
if(!(typeof slideList[currentPicture].fileName === 'undefined' || slideList[currentPicture].fileName === null))
{
// variable is defined and not null
picture.src = "file://" + slideList[currentPicture++].fileName;
}
else
{
// this comes from https://www.w3.org/TR/file-upload/#file
picture.src = window.URL.createObjectURL(slideList[currentPicture++]);
}
Thanks to NineBerry for the code and suggestions!

JavaScript FileReader and Dynamic Tables

I am trying to upload a file and read its contents and then output the contents to a table. The information needs to be place on a new row whenever there is a > char in the string.
I am having a bit of an issue wrapping my head around how I can create a new 'tr' and then add data to the a cell 'td' in that row.
I am stuck on the <tr> and <td> and adding them dynamically with the contents from the file. I am sure I can use regex to look for the > char but that isn't really what I need help with. I am struggling with how I take the information after the > char and add it to a new row in the table.
UPDATE: Ok, so I am still not fully functional on what I am trying to do. I am uploading the file, reading it, and storing the information as an object. However, I can only do this for one instance. When I upload a text file there will be multiple DNA sequences in the file. Each sequence will have a sequence_id like this:
9013e1
ACAAGATGCCATTGTCCCCCGGCCTCCTGCTGCTGCTGCTCTCCGGGGCCACGGCCACCGCTGCCCTGCC
CCTGGAGGGTGGCCCCACCGGCCGAGACAGCGAGCATATGCAGGAAGCGGCAGGAATAAGGAAAAGCAGC
CTCCTGACTTTCCTCGCTTGGTGGTTTGAGTGGACCTCCCAGGCCAGTGCCGGGCCCCTCATAGGAGAGG
AAGCTCGGGAGGTGGCCAGGCGGCAGGAAGGCGCACCCCCCCAGCAATCCGCGCGCCGGGACAGAATGCC
CTGCAGGAACTTCTTCTGGAAGACCTTCTCCTCCTGCAAATAAAACCTCACCCATGAATGCTCACGCAAG
TTTAATTACAGACCTGAA
So, I am trying to read the file, find all sequence ID's and then sequences and I want an editable leading and trailing trim like so:
var objArray = [
{
'id': '>9013e1',
'sequence': 'ACAAGATGCCATTGTCCCCCGGCCT...',
'lead_trim': //get the value from a input from the user,
'trail_trim': //same as above
},
{
//another obj like above
}
]
The sequence also needs to have a line break inserted after every 60 characters. Once I have processed the data in the text file correctly I then need to output the data to a table like I stated in my original post. The problem I am having is I am getting stuck on only being able to store information for one obj in my objArray.
Here is a look at my code...
function scanForSequences(event) {
//Get the file from HTML input tag
var file = event.target.files[0];
var output = document.getElementById('table');
if(file) {
var sequenceArray = [];
var objArray = [];
var obj = {};
var str = '';
var subStr = '';
//Create a new file reader
var reader = new FileReader();
//When the file reader loads
reader.onload = function(evt) {
//Add the contents of file to variable contents
var contentsByLine = evt.target.result.split('\n');
//Alert user the file upload has succeeded
alert('File ' + file.name + ' has been uploaded!');
for(var i = 0; i < contentsByLine.length; i++){
if(contentsByLine[i].charAt(i) == '>'){
obj['id'] = contentsByLine[i];
}else{
sequenceArray.push(contentsByLine[i]);
str = sequenceArray.toString();
subStr += str.substring(0, 60) + '\n';
str = str.substring(60);
obj['sequence'] = subStr;
obj['lead_trim'] = 0;
obj['trail_trim'] = 0;
}
objArray.push(obj);
console.log(objArray);
}
}
reader.readAsText(file);
} else {
alert('Failed to upload file!');
}
console.log(obj);
}
document.getElementById('fileItem').addEventListener('change', scanForSequences, false);
Please find my proposed solution in the fiddle below:
https://jsfiddle.net/w6jbuqfy/
Here's an explanation of what's going on:
First we have a input of type file:
<input id="input" type="file">
We then attach an event listener to it to execute a function once a user has selected a file
var inputElement = document.getElementById("input");
inputElement.addEventListener("change", handleFile, false);
Inside the handleFile function, we use a FileReader to read the file.
var fileList = this.files;
var file = fileList[0];
var fr = new FileReader();
fr.readAsText(file);
Now fileReaders are asynchronous in nature, here i've got a simple interval that checks on the status of the filereader every 100ms.
var checkReadyId = setInterval(function(){
if(fr.readyState === 2){ //done
window.clearInterval(checkReadyId);
addFileDataToResults(fr.result);
} else{
console.log('not done yet');
}
}, 100);
FileReaders are done reading when their readyState is 2. So we check for that and once we are done, we can access the result from FileReader.result. As we read this as a text earlier above, we'll get a string back. We then pass this to our addFileDataToResults function.
function addFileDataToResults(fileAsString){
var resultsDiv = document.getElementById('results');
var tr = document.createElement('tr');
var td = document.createElement('td');
var linesInFile = fileAsString.split('\n');
console.log(linesInFile);
td.textContent = linesInFile[0];
tr.appendChild(td);
resultsDiv.appendChild(tr);
}
What is happening here is that we grab the resultsDiv which is a real node in our HTML. We then use createElement which creates virtual nodes and put data into them. IN this case, we are simply putting the text of the first line into our file. Once we are done creating this virtual nodes, we use appendChild to our real node which turns the virtual node into a real node and you can see it in the html.
Hope this helps
:)

Javascript: How to loop through files

I am making an Illustrator CS6 Javascript that does the following:
Open a folder of Illustrator files
Open each file in the folder (these files are called the source files)
Select all the contents of the source file
Copy the contents of the source file
Create a new target file Paste these contents into the target file as a new layer
Ensure the new layer has the same name as the old source file
My script works except, it doesn't loop through the files in the source folder correctly. Instead, it runs fine on the first source file. But then it endlessly just pastes the second source file in the destination document (I.e. it doesn't move onto any of the other source file). It just endlessly pastes and so I have to force quit!
How can I get it to loop through the folders properly and then move onto the next file.
Here is my code:
// JavaScript Document
//Set up vairaibles
var destDoc, sourceDoc, sourceFolder, newLayer;
// Select the source folder.
sourceFolder = Folder.selectDialog('Select the folder with Illustrator files that you want to mere into one', '~');
destDoc = app.documents.add();
// If a valid folder is selected
if (sourceFolder != null) {
files = new Array();
// Get all files matching the pattern
files = sourceFolder.getFiles();
if (files.length > 0) {
// Get the destination to save the files
for (i = 0; i < files.length; i++) {
sourceDoc = app.open(files[i]); // returns the document object
var myLayers = sourceDoc.layers; // Select All layers in Active Document
//Go through all layers of source document and copy artwork
for (i = 0; i < myLayers.length; i++) {
myLayers[i].hasSelectedArtwork = true;
};
with(sourceDoc) {
var count = pageItems.length;
for (var i = 0; i < count; i++) {
pageItems[i].selected = true;
}
redraw();
copy();
for (var i = 0; i < count; i++) {
pageItems[i].selected = false;
}
}
//Create a new title variable that has the title of the source document
var title = sourceDoc.name;
var title = title.substring(0, title.length - 4); //(remove extension from name)
//Close the Source Document
sourceDoc.close(SaveOptions.DONOTSAVECHANGES);
//Open the Destination Document and create a new layer in it that is named after the title variation
newLayer = destDoc.layers.add();
newLayer.name = title;
//Paste into this new layer
newLayer = app.paste();
}
}
else {
alert('No matching files found');
}
}
Ps. I wasn't sure if I should post this in Code Review or Graphic Design, but I think Stack overflow is the best place to post this as it is a general question about javascript looping, so I hope this is the right place.
It appears that you are using "i" for the variable in each of your loops, giving it a range of unexpected values in other loops that also use that same variable. I would try using a separate variable for each loop. E.g. for j=0, for k=0, for l=0, etc.

Javascript get all files minus certain file extentions

I have a script that returns all the files contained within a folder. However, there are some file types in there that I do not want my script to do anything with. I just want it to literally skip over it as if it wasn't there and only deal with the other file types.
How can I achieve this?
So far this is how I'm getting all the files contained within a folder:
var samplesFolder = Folder(Path)
//Get the files
var fileList = samplesFolder.getFiles()
//Creat Array to hold names
var renderTypes = new Array();
//Parse Initial name to get similar render elements
var beautyRender = fileList[0].name
beautyRender = beautyRender.substr(0, beautyRender.length-4)
//Get the render elements with a similar name
for (var i = 0; i < fileList.length; i++)
{
if(fileList[i].name.substring(0,beautyRender.length) === beautyRender)
{
renderTypes[i] = fileList[i].name
}
}
This is not used for web purposes I should hasten to add.
edit
Above is the complete code I have to get all the image files in a folder and bring them into photoshop once the user has selected the folder they want to use. At the moment it is bringing in every single image in the folder when there is a single type I want it to ignore.
You can iterate over the list and only collect those with extensions you care about. i see photoshop so I'll assume image files only:
var distilledFileList = [];
for (var i = 0; i < fileList.length; i++){
if (/\.(?:jpe?g|png|gif|psd)$/i.test(fileList[i].name)){
distilledFileList.push(fileList[i]);
}
}
Now distilledFileList contains only *.jpg, *.jpeg, *.png, *.gif, and *.psd files.
if you want an easier (more readable) way to check extensions (maybe you're not as fluent as regular expressions):
// fileList = ....
// setup an array of bad extensions here:
var bad = ['txt', 'log', 'db'],
// holds new list of files that are acceptable
distilledFileList = [];
// iterate over entire list
for (var i = 0; i < fileList.length; i++){
// grab the file extenion (if one exists)
var m = fileList[i].name.match(/\.([^\.]+)$/);
// if there is an extenions, make sure it's now in the
// 'bad' list:
if (m && bad.indexOf(m[1].toLowerCase()) != -1){
// it's safe, so add it to the distilled list
distilledFileList.push(fileList[is]);
}
}
Assuming fileList is just an array of strings you could do something along the lines of:
for (var i = 0, len = fileList.length; i < len; i++) {
var filename = fileList[i].name;
if (filename.match(/\.(txt|html|gif)$/i) !== null) { continue; }
// Your logic here
}
Where txt, html and gif are file extensions you want to skip over, you can add more by separating them with |

javascript internet explorer byte order mark

I am working on a way to save an HTML table to a csv file. Ideally, this should be cross-browser, and I have gotten this to work on everything but Internet Explorer. However, I have gotten the obvious parts working. What remains is that I am unable to get a working csv file from my JavaScript because a byte order mark is prepended to the data I wish to download.
I have confirmed that this is the case by downloading the csv file in IE and everything else and used a hex editor to view the raw file, I can confirm the file that Internet Explorer downloaded prepends the unicode character "FFFE".
Please see the code below this does this. saveTable takes an "<a>" node that is located inside a table.
If anyone can help me disgnose the issue and offer some solution I'd be grateful. Please forgive any faux pas on my part, I don't think I've ever used a site of this nature before. So if you need me to provide any further information please do just let me know and I shall do my best to get it on here.
function findTable(node) { // Finds a nodes parent table.
return (node.nodeName !== "TABLE") ? findTable(node.parentNode) : node;
}
function saveTable(node) {
var csv = [];
var table = findTable(node);
var rows = table.getElementsByTagName("tr");
var header = [];
var csv = [];
for (var i = 0; i < rows.length; i++) {
if (i == 0) {
// Do csv stuff.
var dates = rows[i].getElementsByTagName("th");
for (var j = 0; j < dates.length; j++)
(j == 0) ? header.push("") : header.push(dates[j].innerHTML);
csv.push(header.join(","));
}
else {
var rowArray = [];
var jobName = rows[i].getElementsByTagName("th")[0].innerHTML;
var times = rows[i].getElementsByTagName("td");
rowArray.push(jobName);
for (var k = 0; k < times.length; k++)
rowArray.push(times[k].innerHTML);
csv.push(rowArray.join(","));
}
}
node.setAttribute("href", "data:text/csv;charset=utf-8," + csv.join("%0A"));
var fileName = "spreadsheet_data-" + (new Date).getTime() + ".csv";
if (node.download == "")
node.setAttribute("download", fileName);
else {
alert("Handle IE here!");
var bom = "\uFFFE";
var doc = document.open("application/octet-stream", "_blank");
var data = csv.join("\r\n");
doc.charset = "UTF-8";
doc.write(data.replace(bom, ""));
doc.focus();
doc.execCommand('SaveAs', false, fileName);
doc.close();
}
}
Table example, it's not the way I would have chosen to do it myself, but it's how the table is generated by another piece of software.
<table id='results' border='1'>
<tr><th><a href='#' onClick='saveTable(this);' id='download_link'>Download data</a></th><th>2013/05/09</th><th>2013/05/10</th><th>2013/05/10</th><th>2013/05/10</th><th>2013/05/10</th></tr>
<tr>
<th>\PDF\EXOVIGN.PDF</th><td>8.853</td><td>9.050</td><td>8.807</td><td>8.827</td><td>8.835</td></tr>
</table>
If you have no absolute requirement to do this client-side, it might save you a lot of hassle to send the file from the server instead.

Categories

Resources