I created a webserver using Python Flask. My "index.html" loads a table. I am planning to create a new field "view result" to each row of the table. On clicking view result, I should be able to visualize the data. I want the filename (corresponding to each entry of "view result"), to be the input file parameter to a javascript.
The filename should get passed here d3.csv("/static/<filename>.csv", function(data){...} which belongs to a file named view_data.js and data from corresponding file is visualized in another html page.
I have index.html page and view_data.js ready. How do I pass filename from index.html page to data.js for visualization?
For now I have hardcoded the filename in view_data.js.
Are you familiar with element selectors and events in javascript?
A simple implementation would be to set up event triggers that will fire when clicking each link, using the filename as that you store in a data attribute.
<a class="view-trigger" data-filename="filename_1.csv">view result</a>
<a class="view-trigger" data-filename="filename_2.csv">view result</a>
etc
You can set up the event using something like a specific class on each of the links (in the example view-trigger.
var resultLinks = document.getElementsByClassName(".view-trigger")
for(var i = 0; i < resultLinks.length; i++) {
(function(index) {
resultLinks[index].addEventListener("click", function(event) {
var filename = event.target.getAttribute('data-filename');
d3.csv("/static/" + filename + ".csv", function(data){...}
})
})(i);
}
I haven't tested this code so you may need to fix/adjust for your case. If you are not familiar with these concepts it's worth reading a bit more about them.
Also, d3.js also seems to come with utilities to do DOM selection and handling events, so you may want to use those instead.
Related
I am a bit stuck. I have created a script for Photoshop that opens a PSD file containing a few layers plus a linked one, sort of a template.
So far, I got things working for me by creating a droplet that runs the following steps and scripts:
Opening the file/image that is dropped.
Opening the PSD file (opening template, scripted).
Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action).
Applying the template features to this linked layer which has been updated previously (scripted).
Saves a PNG file (scripted),
And finally, closing up opened image and template documents (recorded action).
All is good so far. But this has a limitation. It will only work on one file at a time, with a specific name, at a specific location. So, for example, for the update linked layer to work, the name of the image must be 1.png inside Downloads folder only, in this case.
So my question is: How can I script this to run an iteration of the update on the linked layer using as source(s) the images dropped onto the droplet, regardless of file types (png, jpg, etc.), name, location, and index the output saved PNG file(s)? (1.png, 2.png, 3.png, and so on.)
I started working on my approach, and the steps previously mentioned:
1 - Opening the file/image that is dropped onto the Photoshop droplet.
This would happen automatically with the file—Photoshop will open the file dropped onto the droplet, thus triggering the specific actions sequence set forth. Step one solved. Next!
2 - Opening the PSD file (opening template, scripted)
With this step, I wrote a script that opens the template file. The first step in the action sequence would be this!
var template = new File("/Users/name/Desktop/Folder/Template.psd"); // Of course, you can have your template file anywhere on your computer as long as the path to find it is correct. I have selected my desktop for testing purposes.
app.open(template);
That was another effortless one. Next!
3 - Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action)
I needed to ensure that the template would easily find its previously linked layer location for the update for this third step to work. I know there are ways to update this with a script, but I didn't want to tinker with that. It was too much of a hassle for me at this stage and with my limited knowledge. Therefore I've decided to accommodate the necessary so the template would find a familiar file name it would look for when the "Update all Modified Content" action is triggered.
At this stage, there are two files opened in Photoshop, one the initial image that serves as a new source for the template, and the second file the template.psd, which contains the linked layer that needs to be updated with the content of the first file.
First, I have saved a copy of the image using the name that the template would look for when searching for the linked layer's name. Next, I have saved a copy of the template using the location of the first image file to keep the initial template safe from all these actions. And third, I triggered the "Update all Modified Content" action. And voila, everything worked. The initial template had the linked file next to it. So the new template copy would search and find the file next to it, in the same place, folder/location, as it happened on the previews step that helped save it as such.
// The following script will retrieve the path of the opened image and will save a copy that matches the name of the linked layer in the template in the same location.
var image_doc = app.documents[0]; //If two or more documents are opened, this approach will help switch between them.
var image_name = image_doc.name;
var image_path = app.documents[0].path.fsName;
var temp_image = new File("" + image_path + "/" + image_name + "");
var opts, file;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
var image_temp_name = "link.png";
pngFile = new File("" + image_path + "/" + image_temp_name + "");
image_doc.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);
// Save a copy of the template.psd in the same location as the image and the link.png file needed to update the linked layer.
var temp_template = new File("" + image_path + "/" + image_name + "");
app.open(template);
var opts, file;
opts = new PhotoshopSaveOptions();
opts.format = SaveDocumentType.PHOTOSHOP;
var template_temp_name = "template.psd";
psdFile = new File(image_path + "/" + template_temp_name);
psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
activeDocument.saveAs(psdFile, psdSaveOptions, false, Extension.LOWERCASE);
// After these Update all Modified Content action
Now, four, five, and six are straightforward:
4 - Applying the template features to this linked layer which has just been updated previously (scripted). Done!
5 - Saves the newly formed template as a PNG file (scripted). Done!
6 - And finally, closing up opened image and template documents (recorded action). Done!
Currently, I'm developing a WebService which user selects a file and we're doing some pre-processing on user's browser later we will send the file to the server.
When a user selects a file from file manager(<input type=file id="dropzone"/>) an event will fire and will load the selected file using FileReaderAPI, when the process is done(it's guaranteed that this section will execute after the first process finished) when I want to read the file again later in the service using document.getElementById("dropzone") it returns the null.
here is the code for the input component, in this case, I'm using react-dropzone.js:(since I'm accessing input element by getElementById it makes no difference which library is used)
const{
acceptedFiles
} = useDropzone({
accept: "video/*, .mkv",
onDrop: files => props.handle()
});
return(<div> <input {...getInputProps()} id="dropzone"/> </div>) ;
props.handle(files) refer to the function which will be doing the file processing
following is a part of handle() function which deals with the selected file and will fire when a user selects a file.
var upFile = document.getElementById("dropzone");
var file = upFile.files[0];
//Original function iterate over all slices
var r = new FileReader();
var blob = file.slice(offset, length + offset);
r.onload = processChunk;
r.readAsArrayBuffer(blob);
Later when I want to access the file again using document.getElementById("dropzone") it returns null
Any Idea for solving this?
After many trials and errors, I found out this is caused by one of the browser's 3rd party security extensions.
Make sure to disable these kinds of extensions in the developing stage.
I have an HTML page where there is a button to select a HTML file, and once the file is selected, some treatment is applied to it in JavaScript.
The code looks like this:
document.querySelector("#file").addEventListener("change", function() {
// Get filename from selected file
var filename = this.value.replace(/^.*[\\\/]/, '');
console.log(filename);
readTextFile("output/".concat(filename), function(text) {
// and then the actual solution is contained in this function readTextFile
});
});
I would like to be able to tweak this code to be able to apply the treatment to a batch of HTML files all at once. For instance, to all the HTML files in a given folder.
But I am new to JS and I honestly don't have a clue how I could do it.
Is there a way to have a multiple file selection buttons, so that I can apply the treatment to all the selected files?
I have a local text file which is kept changing by other programs. I want to write a html and javascript based web page to show the content of file dynamically. I have searched in google and found that most solutions require to get this text file via html element. I wonder if there is a way to get the file via a fixed path(lets say it is a string of the file directory) in javascript. I am using Javascript fileReader. Any help will be appreciated.
This is not possible using javascript running inside the browser. You will not be able to do anything outside the browser.
EDIT:
You could run a Node.js server though that runs on localhost and does your file operations you desire. You could build a API so your html page that you load in the browser calls your serverscript to do your file operations.
Do you understand what I mean?
How much information does the text file hold, Depending on your scenario it might be worth looking into javascript localstorage W3SCHOOLS local storage. Would that help your situation ?
What you can do is allow the user to choose the file of interest, using a file-input. Once done, the browser wil have access to the file, even though the JS wont have access to the file's full-path.
Once the user has chosen the file, you can reload it and refresh the view pretty-much as often as you please.
Here's a short demo, using a file input (<input type='file'/>) and an iframe. You can pick pretty much anything the browser will normally display, though there are limits on the size of the file that will work - due to the limit of the length of a URL - the file's data is turned into a data-url and that url is set as the source of the iframe.
As a demo, pick a file and then load it. Now, open the file in another program and change it. Finally, press the load button once again - the new content now fills the iframe. You can trigger the loading of the file by a timer or any other event in the page. As far as I'm aware, you cannot re-load it when it changes, since there's no notification from the OS - you have to use a button, timer, element event or whatever. Basically, you have to poll for changes.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
// uncomment this line for on-demand loading.
byId('loadBtn').addEventListener('click', onLoadBtnClick, false);
}
// fileVar is an object as returned by <input type='file'>
// tgtElem is an <iframe> or <img> element - can be on/off screen (doesn't need to be added to the DOM)
function loadFromFile(fileVar, tgtElem)
{
var fileReader = new FileReader();
fileReader.onload = onFileLoaded;
fileReader.readAsBinaryString(fileVar);
function onFileLoaded(fileLoadedEvent)
{
var result,data;
data = fileLoadedEvent.target.result;
result = "data:";
result += fileVar.type;
result += ";base64,";
result += btoa(data);
tgtElem.src = result;
}
}
function onLoadBtnClick(evt)
{
var fileInput = byId('mFileInput');
if (fileInput.files.length != 0)
{
var tgtElem = byId('tgt');
var curFile = fileInput.files[0];
loadFromFile(curFile, tgtElem);
}
}
</script>
<style>
</style>
</head>
<body>
<button id='loadBtn'>Load</button><input id='mFileInput' type='file'/><br>
<iframe id='tgt'></iframe>
</body>
</html>
you can use nodejs to watch for a filechange using watchfile module, if you just want to watch the filechange and its content. you can run following code using node, but it only consoles the file changed in your terminal.
var fs=require('fs');
fs.watchFile('message.text', function (curr, prev) { //listens to file change
fs.readFile('message.text', function(err,data){ //reads the file
console.log(data.toString()); //consoles the file content
});
});
I'm currently working on a small project in which I want to convert couple (or more) Markdown files into HTML and then append them to the main document. I want all this to take place client-side. I have chose couple of plugins such as Showdown (Markdown to HTML converter), jQuery (overall DOM manipulation), and Underscore (for simple templating if necessary). I'm stuck where I can't seem to convert a file into HTML (into a string which has HTML in it).
Converting Markdown into HTML is simple enough:
var converter = new Showdown.converter();
converter.makeHtml('#hello markdown!');
I'm not sure how to fetch (download) a file into the code (string?).
How do I fetch a file from a URL (that URL is a Markdown file), pass it through Showdown and then get a HTML string? I'm only using JavaScript by the way.
You can get an external file and parse it to a string with ajax. The jQuery way is cleaner, but a vanilla JS version might look something like this:
var mdFile = new XMLHttpRequest();
mdFile.open("GET", "http://mypath/myFile.md", true);
mdFile.onreadystatechange = function(){
// Makes sure the document exists and is ready to parse.
if (mdFile.readyState === 4 && mdFile.status === 200)
{
var mdText = mdFile.responseText;
var converter = new showdown.Converter();
converter.makeHtml(mdText);
//Do whatever you want to do with the HTML text
}
}
jQuery Method:
$.ajax({
url: "info.md",
context: document.body,
success: function(mdText){
//where text will be the text returned by the ajax call
var converter = new showdown.Converter();
var htmlText = converter.makeHtml(mdText);
$(".outputDiv").append(htmlText); //append this to a div with class outputDiv
}
});
Note: This assumes the files you want to parse are on your own server. If the files are on the client (IE user files) you'll need to take a different approach
Update
The above methods will work if the files you want are on the same server as you. If they are NOT then you will have to look into CORS if you control the remote server, and a server side solution if you do not. This question provides some relevant background on cross-domain requests.
Once you have the HTML string, you can append to the whatever DOM element you wish, by simply calling:
var myElement = document.getElementById('myElement');
myElement.innerHTML += markdownHTML;
...where markdownHTML is the html gotten back from makeHTML.