Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reading local files selected by user #370

Closed
shiffman opened this issue Sep 14, 2014 · 15 comments
Closed

reading local files selected by user #370

shiffman opened this issue Sep 14, 2014 · 15 comments
Assignees

Comments

@shiffman
Copy link
Member

Picking up on the discussion of #40 I created two examples based off of this html5rocks tutorial.

  1. file select menu -- this example opens a menu for a user to select a file (or files).
  2. drag and drop file -- this allows a user to drag a file onto a div to be read.

Do we want to consider adding this functionality to p5.dom? Something along the lines of. . .

var fileinput = createFileInput();
fileinput.readFile(process);

function process(file, data) {
  console.log(file.name + ' ' + file.type + ' ' + file.size + ' bytes');
  console.log("content: " + data);
}

The above assumes text data but I imagine there could be some hooks for images or other data formats, etc.

@lmccart
Copy link
Member

lmccart commented Sep 25, 2014

great idea, I like this a lot!

@shiffman
Copy link
Member Author

Awesome, it'll take me a bit but I'll work on a pull request soon!

@shiffman shiffman self-assigned this Dec 5, 2014
@shiffman
Copy link
Member Author

shiffman commented Dec 5, 2014

Ok, I have a first working version of this at https://github.com/shiffman/p5.js/tree/selectfileinput. @lmccart can you take a look? The things to decide on are:

  • What should it be called? createFileInput(), createFileSelect(), createSelect(), createSelectInput()?
  • What's the best way for the user to specify whether they want to allow multiple files to be selected or not?
createSelect(true,callback);
createSelect('multiple',callback);
  • Is it weird that I'm adding stuff to the FileAPI?

The relevant parts to look at are createFileInput() and this test example

I'll wait for some discussion to do a pull request. I also need to work on drag / drop.

@shiffman
Copy link
Member Author

shiffman commented Dec 5, 2014

Btw in Processing it's called selectInput()

@GoToLoop
Copy link
Contributor

GoToLoop commented Dec 5, 2014

If possible or reasonable, sticking to Processing's API names is a good strategy! ^_^
There are both selectInput() & selectFolder():

@shiffman
Copy link
Member Author

shiffman commented Dec 6, 2014

A thought occurred to me as I slept . . . it might make sense to have a callback handle a single file (and happen many times) vs. a single call back that receives an array of files. Will consider this as I make updates / revisions.

@shiffman
Copy link
Member Author

shiffman commented Dec 6, 2014

var fileSelect;

function setup() {
  noCanvas();
  fileSelect = createFileInput('multiple', gotFile);
}

function gotFile(file) {
  var div = createDiv(f.name + ' ' + f.type + ' ' + f.size + ' bytes');
  if (file.isImage()) {
    createImg(f.data);
  } else if (file.isText()) {
    createDiv(f.data);
  }
}

@lmccart
Copy link
Member

lmccart commented Dec 6, 2014

I like 'multiple' over true. For naming, the "create" methods generally refer to an element that is being appended to the dom, and usually the second word is the tag that gets added (createCanvas, createButton, etc). These methods also return a p5.Element. Since nothing is getting added, maybe it would make more sense to drop the create part? selectInput might work. or selectFiles?

shiffman added a commit to shiffman/p5.js that referenced this issue Jan 29, 2015
@shiffman
Copy link
Member Author

Ok, I took another pass over this. Here is the current status.

var fileSelect = createFileInput(gotFile);

An optional second argument specifies if you want to allow the user to select multiple files.

var fileSelect = createFileInput(gotFile, 'multiple');

I kept createX b/c the function is creating a new DOM element. It's an input element with type = 'file';. I would prefer something more succinct but can't think of anything.

The argument it takes is a callback which receives a p5.File object, a thin wrapper of native File. Native HTML loads the file content with a separate callback, but I'm oversimplifying and assuming that every file the user selects should be loaded. Both the file metadata and content are embedded in the p5.File object. If the user selects multiple files the callback will be triggered multiple times (as each files loads).

function gotFile(file) {
  var fileDiv = createDiv(file.name + ' ' + file.type + ' ' + file.subtype + ' ' + file.size + ' bytes');
  // Check what kind of file it is
  if (file.type === 'image') {
    // Make an Image DOM element
    var img = createImg(file.data);
  } else if (file.type === 'text') {
    // Pull out some text, etc.
    createDiv(file.data);
  }
}

An alternative would be to pass in the native JS File object and a variable that holds the data, i.e.

function gotFile(file, data) {
  var fileDiv = createDiv(file.name + ' ' + file.type + ' ' + file.subtype + ' ' + file.size + ' bytes');
  // Check what kind of file it is
  if (file.type.indexOf('image') > -1) {
    // Make an Image DOM element
    var img = createImg(data);
  } else if (file.type.indexOf('text') > -1) {
    // Pull out some text, etc.
    createDiv(data);
  }
}

I haven't submitted a pull request yet. Thoughts / comments? I'm sure this is missing a lot but it's a start.

Branch is here: https://github.com/shiffman/p5.js/tree/selectfileinput

@lmccart
Copy link
Member

lmccart commented Feb 3, 2015

ah, my mistake with the naming. createFileInput makes sense to me, as it's creating an input element and the file part specifies which type.

I think embedding the metadata and content in the file object (option 1) makes sense, I think passing both file and data would be confusing for the user. does this cause any issues with performance or seem wrong for any other reason?

@shiffman
Copy link
Member Author

shiffman commented Feb 4, 2015

I've now implemented functionality in p5.Element for a div you can drag files onto. A full example would look like:

var dropZone = createDiv('Drop files here');
dropZone.dragOver(callback1);
dropZone.dragLeave(callback2);
dropZone.drop(callbackDrop, callbackFileLoaded);

But a lot is optional and even just this will work:

var dropZone = createDiv('Drop files here');
dropZone.drop(callbackFileLoaded);

This probably needs some finesse, comments / thoughts welcome. There's also an example in addons/file_input_div.

@shiffman
Copy link
Member Author

shiffman commented Feb 4, 2015

Some open items I need to look still.

  • check if File API available in drop code
  • documentation / examples on p5js.org?

@lmccart
Copy link
Member

lmccart commented Feb 9, 2015

this is awesome. I made a little tweetable gist/gif.
https://gist.github.com/lmccart/c9109a9027ef5c99efa1

once the documentation is on the website I can add links to the specific functions in the ref and tweet.

shiffman added a commit to shiffman/p5.js that referenced this issue Feb 12, 2015
shiffman added a commit to shiffman/p5.js that referenced this issue Feb 12, 2015
shiffman added a commit to shiffman/p5.js that referenced this issue Feb 12, 2015
@shiffman
Copy link
Member Author

Fixed some things and documentation is now inline. Will submit an example for p5js.org next. Then this should be able to be closed.

@lmccart
Copy link
Member

lmccart commented Feb 12, 2015

woohoo!

@lmccart lmccart closed this as completed Feb 12, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants