-
In this video I wannna look at a feature
of web browsers and something you can
-
do in JavaScript in general but also
this thing is built in to p5.js library
-
and in a rather nice way that I enjoy
and this feature is dragging a file
-
into the browser and making use of that
file and that file could be an image
-
it could be a text file, it could be
some sort of data file; data is a thing
-
that am gonna get into to in some future
videos, which there's different kinds of
-
data formats so there's lot of potential
to what you could do if you ask the
-
user to say hey, give me an image and I'll
do something that's really exciting
-
and interesting in the browser with that
image or give a hundred images
-
and even that. So let's look at how that's
that works, so first of all what I mean
-
by that and I guess I probably don't need
this diagram (laughs) but am gonna
-
draw it anyway; is on the webpage am
gonna make an area on the page
-
right? Because am gonna have a
canvas and I want an area on the
-
page where if I have some sort of file
if I drag that file and release it there
-
and if this is an image I wanna see that
image then suddenly appear and be
-
drawn into the canvas so how do you
do that?
-
Let's go and look.. so I've sort of set
this up in advance. I have this particular
-
example and you can see it's got exactly
what am talking about.
-
This canvas is made with the
createCanvas() function and you
-
can see background() is called so you
you can see that it has a black
-
blackground, then there's above the
canvas is this like dashed area
-
on the screen that says drag you file up
here. Now where did that come from?
-
That is written into the HTML file
so am gonna go over here and look
-
at the ahh.. --gonna hit cancel--
and look at the HTML file and you
-
can see there it is. There is just a
paragraph element, 'Drag you file here'
-
I gave it an id called dropzone; because
am gonna need to refer to it
-
hey! that's the paragraph element that
I wanna be able to drop something on to
-
and also I've just written some style
some styles referring to that dropzone
-
and maybe just so it's a little bit more
visible I might say font-size is 36pt
-
and maybe I'll do something like width is
50%. So by the way this is also something
-
that you might have not have seen
before, there's all of this units that
-
are happening in CSS: px for pixels; so
actually like the number of pixels on
-
that padding, pt (point) for something
that has to do with typography (laughs)
-
am sure somebody understands much
better than I do, but you know
-
the larger the point, the larger the
font-size but also percentage %, being
-
relative; so if this DOM element is
always just gonna be 50% the size
-
of the page which.. you'll see now if I
hit run again, you can see as I resize
-
the page that DOM element doesn't
have a fixed size it's always just 50%
-
of the page. That's a nice little tip-bit
that am adding into this video.
-
So how do I make it so that I can
drag a file there?
-
Incedentally what happens if I drag a file
right now?
-
I drag this file over here, I drop it and
am lost I'm gone from the page
-
look and you can see what it is, is that
file has just literally opened up in the
-
page. It's just a file of bacteria
I don't know, I was trying to do
-
something other than rainbows and
unicorns with maybe bacteria and I went
-
in the wrong direction (laughs)
but it's interesting. Ok so umm
-
so I need to; I need to get this working
so first of all I need to add some
-
javascript event to this element.
I wanna handle the event, so the
-
browser handled that event for me
right? When you dragged the file into the
-
browser it assumes like 'ooh I'm a
browser, you're dragging me a file, I'll
-
open it.' I wanna say to the browser,
"No no no no no noo; I'm in charge here.
-
Don't do what you're gonna do, I got
something else for you, I got
-
something else planned." So if I come
over here and I first I need to do is, get
-
ahh, am gonna make a variable and am
gonna call select() so select, and let's
-
make this a global variable because I
might wanna access it in other places
-
I'm gonna say select the dropzone,
now something that am doing here
-
which might, you might find it a little
bit confusing but I find
-
I find this to be just so convenient
I like to just name my variable the same
-
name as the id, it's absolutely not
requiered. The id can be totally
-
diff, and nobody knows whether,
or cares whether they're the same
-
just you the programmer, for me it's
a little bit convenient but I don't
-
want you to be confused that there's
some like matching happening there
-
that's just I happen to name the variable
the same name as the id
-
ok so what's next (sighs) you know that
you can attach an event to an area
-
by referencing that event aah as a
function called on that object
-
so the mousePressed() event, the
changed() event the input() event
-
the mouseOver(), the mouseOut()
this are events that I've looked at
-
in previous videos. I've got a new event
for you (laughs) I don't remember
-
what it's called but I do know there's
one that is drag.. dragOver() so
-
the dragOver event let's handle that with
a function called highlight ok?
-
So I'm gonna say function highlight()
dropzone dot style, background
-
color and let's give it a little gray
am gonna zoom back out here
-
so now this should atleast I've handled
one event dragOver, ok so now if I take
-
this file and drag it over here you see
it becomes gray. Now it's never not
-
becoming gray but atleast I've got that
event, so this by the way is nothing
-
to do so far this has nothing to do with
the file am just handling an event
-
if you drag over it; if I move the mouse
over it it doesn't do anything
-
if I drag the mouse over it without a file
it doesn't do anything.
-
This is an event only for when I drag a
file over it, you can see it becomes gray
-
so that's one thing I can do now what if
I want if l'm like dragging a file and
-
then am like "no no no no no, bad
idea bad idea take the file out"
-
maybe I wanna unhighlight it right?
So I could then say aahh I can't remeber
-
what it's called but I think it's dragOut()
unhighlight and I'll just reset the
-
background color oops I'm gonna write
another function and I''m gonna reset the
-
background color to white, now you might
be asking yourself a question, and I need
-
to get to this in another video
but you might be asking a question
-
like why do I need this two functions for?
I could really have just one function that
-
accepts an argument: white or black..
I mean white or grey,
-
and then I could say dragOver call that
function with gr.. white.. gray huuh
-
dragOut call that function with white.
This is actually quite possible in
-
javascript I'm doing it this way for
convenience because again the other
-
way requires a sort of some trickiness
for how do I get an argument kind of
-
into those functions. I'd love to get to
that, remind me! remind me! remind me.
-
I'll remeber, am gonna think of a good
scenario and try to make a nice video that
-
cause it sort of like a fundamental
aspect of javascript
-
it uses a this thing called a closure
ok so but we're not doing that right now
-
am not doing that right now am gonna
leave these as two separate functions
-
but you're right to ask that question
(laughs) cause you being the
-
metaphorical person who I think I'm
talking to I mean you're.. umm yeah
-
ok so umm oop undefined is not a
function line 8.
-
drag.. probably dragOut is wrong.
-
(laughs) So how do we figure this out,
I should stop being so like am just
-
gonna imagine what the p5 DOM API
has in it and I should probably go
-
and look this stuff up, so if you were
doing this and you got this error
-
and you wanted to figure out how to
find it; you could open up a browser
-
you go to p5js.org
am gonna click on this uuhh umm
-
you should be able to find this under
reference and am sure that will change
-
at some point soon but an easier way
to find is am gonna go under libraries
-
and am gonna go to p5 DOM and
now I'm gonna see oh look at all of these
-
look at all these methods and look at
that I called the dragOut but we can see
-
here the mess.. the the event is actually
called dragLeave() that's the name of
-
the function dragLeave.. and by the way
there's addClass() and removeClass()
-
huh interestingly class().. am thinking
of something that happened in the
-
previous video and I wonder if that
should actually be changed but anyway
-
ahh it's a side topic I'll have to think
about that in my own time, so
-
dragLeave() is the name of the function
that I wanted
-
so am gonna minimize that, and come
back and I could've clicked on it to see
-
some more information but
I don't need to do that right now
-
I feel confident that I can just type
dragLeave here and now I can run this
-
again and here we go
file leave, file leave look at that
-
what a nice little am so good at
user interface interaction design (laughs)
-
am being sarcastic, because am not
good at that
-
umm but you can see this is a bit more
intuitive atleast to be able to handle
-
this type of events of when you have the
thing over and when you have
-
the thing out so, but we're missing kind
of the exciting.. this is just like
-
nothing is gonna happen like if I;
look that's the same thing happened
-
that event the drop event when I let go
of the mouse, when I perform this
-
release action; this is me miming the
release action umm I need to handle
-
that event and that event is handled
with the drop() function. Now what goes
-
in here? Let's think about this for a
second so let me comment this out
-
and run this there.. there are two things
that have to happen and this is
-
tricky; one thing that has to happen is
I need to read that file the other
-
thing that needs to happen is I might
wanna uuh this is ok what actually
-
there really aren't two things I was like
there aren't, intuitively there aren't two
-
things; there's one moment right?
I drop. So the moment I drop I might
-
wanna handle that event by like
applying some style to it like
-
unhighlighitng it and then I also wanna
read the file that's being dropped
-
but those are actually divided into two
separate callback, and there's a really
-
good reason for that and the good
reason for that is that I might wanna
-
take all of these images. What if I drag
all of these images into the browser
-
I need a callback to handle each file
one at a time but there's only one
-
moment of dropping so umm so in
that sense and I forget which is which
-
let's go back to the reference, so oops
ahh let me go back to the reference here
-
and I'm gonna click on this drop event
and you can see we could read this
-
(callback, callback) so look at this
callb.. the first callback is triggered
-
when files are dropped so that's the
event the actual event of dropping the
-
files then the second callback is to when
the file is loaded and actually this also
-
happens at separate time cause what if
you drag and drop like 500MB image
-
file right? That drop moment happens
instantly but it might take the browser
-
quite a while to read that very large file
so that's why those are two separate
-
events so I can go back to my code
and I can say you know what when I
-
drop it I also wanna unhighlight the box
right? That's ah I wanna unhighlight it
-
and then I wanna handle the file
so am now acc.. am doing two things
-
as soon as I drop it, unhighlight the box
and also trigger a new function gotFile()
-
function gotFile(file) now interestingly
enough
-
so let's just run this and atleast see now
when I drag the unicorn over here
-
ahh let's just only the unicorn please
it highlights it unhighlights
-
it highlights it unhighlights
let's drop it, it unhighlights and
-
I've over ridden the default browser
behaviour the default browser behaviour
-
would have been to open that file
but I've now over ridden by whatever
-
goes here. So now I can do whatever
I want and not only can I do whatever
-
I want; I can do whatever I want with
the data in that file.
-
For example, I could say createImg(file)
now I dont think this is actually gonna
-
work (laughs) I know it's not gonna work
cause that's.. so but let's try it with
-
this rainbow right? It, something
appeared there but it's like a broken
-
image so this thing here the argument
that comes in to the function
-
this might actually be something rather
new to you am realising because most
-
of our callbacks like highlight() or
unhighlight() like don't have data
-
that arrives with it; so this is a new
scenario this callback p5 is not only
-
triggering the callback when the file is
ready to be loaded but it's also handing
-
a variable and inside that variable is
just.. p5 is like such a nice wonderful
-
friend that p5 is like look am gonna
hand you am gonna call this function
-
am gonna hand you this variable and
am gonna fill that variable for you
-
with all the data associated with that
file, so this file variable is actually
-
an instance of a p5 file object and
there's all of this information like
-
I know how big the file is what's it's
name is, there's lots of metadata
-
associated with that file and something
that's in that file is a property called
-
data and that data might just be
the text that's in the file , it might be
-
the the other some other data format
that's in the file or it might be image data
-
so if I createImg(file.data)
now watch this!
-
uhh oh oh , ok let's look at the reference
did I, sure I saved that I ran that am
-
pretty sure that was right but you know
we have a bit of a problem here, it's not
-
working so let me go back to the
reference and am gonna go to the
-
reference and I wanna look for file
mmmh file this is where this is
-
this is the um where's the p5 file object?
somebody find it for me, quickly! (laughs)
-
p5 image p5.file am not seeing it umm
so you know for some reason it's not in
-
the reference which it probably should
be am gonna, am taking drastic
-
measures here and I'm gonna go to the
p5.js GitHub repository
-
I should just actually just look for..
you know what I should look for an
-
example that does thi. There's actually
an example that does this
-
I could go.. I was gonna go into the
GItHub repository for this..
-
am just gonna like you know, fast
forward through the video like
-
30 seconds or a minute you can skip
this part but am gonna go look for
-
under ahh learning maybe or under
DOM let's look at ahh
-
lets ahh under p5 element am gonna
look for the drop this is probably not
-
the right place.. yeah yeaah no I wanna
under examples ahh DOM ran-dom
-
ran-dom dom, ahh drop there we go ahh
ahh ahhh file.data
-
well by golly I was right wasn't I?
createImg(file.data) so that's
-
what I meant to do, why didn't that work?
(laughs) Let's just ..
-
ok well let's just be a little methodical
about this maybe something else
-
is going wrong that I don't know about
so for example umm let's look
-
let's see if there's some of the metadatas
there, Imma say createP(file.name)
-
ahh createP(file.type), createP(file.size)
and so there.. there're.. all
-
A file has all this metadata associated
with it; it's name, it's type
-
it's size so there are strings that's just
data and data should actually be the
-
image stuff so let's run this and let me
drag in this rainbow file
-
and you can see undefined drop undefined
-
ooh you know what, I wonder if I
guess what I think I might have done
-
I know what I did, I probably
reversed the order of those
-
I reversed the order of those uhh
callbacks. So this is a very common
-
thing that happens, aren't you
enjoying the fact that I just mess this
-
stuff up all the time? I really hope
you are
-
so this is, this is something so you know
we've looked at this and realised
-
like the callback is triggering
I mean ofcourse it's triggering
-
because there are two callbacks
both of them are triggering
-
but I'm triggering them probably in the
wrong order
-
so let's go back to the p5 reference
ahh ahh libraries; DOM;
-
and let's look at this drop function
right here and let's read this again
-
the first callback triggers when the files
are dropped
-
the second callback triggers to receive
the loaded file
-
isn't that the way I did it?
aah first callback but..
-
but I have a feeling the reference
so it wasn't entirely my mistake
-
I have a feeling the reference misled me
let's switch the order of these
-
it's probably the first argument is the
calback to handle the file
-
and the second argument is the callback
to handle the event that's just
-
the dropping event so let's try this again
and here we go yaaaay!!
-
so I've got my.. and let's let's do
something where i say var image equals
-
crreateImg() I say image.size(100,100)
and I'm gonna do createP
-
am gonna just join one string ahh
so am gonna take this out just to make
-
this look a little shorter, now let's look
at this again
-
am gonna make a bigger window we can
have this nice moment where I drag
-
the unicorn here , there's our unicorn
I drag the rainbow here, there's the
-
rainbow. I drag another rainbow here
there's that.
-
So you can see here, the files are
coming in I'm adding them to the page
-
and also I get information; how big was
the file, what was the name of the file
-
I could use that information I'm just
sort of like spitting it right back
-
so (takes a deep breath) this is
interesting hopefully
-
I mean, so am not really doing anything
that and also I should mention
-
let's just prove that this works, am
-
gonna ref.. refresh this page to start
over
-
let's drag all of the images all at once
and there you go all of them appear
-
so we've handled.. that callback was
triggered many many times for each
-
image um so am gonna do one more
thing which I think it just kinda of like
-
makes this seem a bit more magical
so you can have a DOM element
-
that has like a dotted line that says drag
your files here but anything
-
can be a DOM element that you drag
stuff on to you know like a button could
-
or a slider could even though that
barely makes any sense
-
but let's actually do something to this
example am gonna do save as
-
ahh drag and drop 2
am gonna say you know what forget
-
about this dropzone thing take that out
of there, take that out of there;
-
why not store the canvas in a variable
and say canvas.dragOver
-
canvas.dragLeave, canvas.Drop
-
so look at this if I run this now
I can just take this image and drag
-
it over the canvas; dropzone is not
defined ah oh alright I don't need any
-
of this styling stuff aymore to be
honest with you I dont
-
am deciding like not to care about that
I can do something much simpler
-
I can just use the single callback of
dropping it you know am not..
-
just skipping the visual feedback part
right? So anything can be a drag and
-
drop element and now let's think about
this even more in a different way what if
-
when I drag the element on to the
canvas I wanna see the image in the
-
canvas, so what can I do?
I can just call the image function
-
image(img, 0, 0, width, height)
so this is the difference again
-
between making a DOM element image
and then drawing and.. versus drawing an
-
image into the canvas. The image()
function draws that image whether it's
-
through draw image or create image into
the canvas, createImg makes the
-
DOM elements; so now we should be
too see this ahhh that. Now am only
-
seeing the top left corner of the image
cause they're kind of small
-
am surprised about that because am
drawing it supposedly ahh with the width
-
and height of the umm of.. so am kind
of surprised; I feel like that's a little
-
bit of like a p5 bug there. I don't know
whay that's not working am gonna have to
-
look into.. examine that. But also the
thing I wanted to show you is that
-
I don't even though I might have it do it
this way to create the image via umm
-
this ahh umm to create the image ahh
as a way of like getting the data from the
-
file I can use, I can use the p5 function
image.hide(). So I can make that DOM
-
element purely to open that file and
then I can hide it instantly and then draw
-
it into the canvas. And I'm actually sort
of surprised that this is working
-
cause I realised that.. I was sort of
thinking that there might be another
-
problem associated with this.
Ohh but now it's working I don't lnow
-
what I missed with the width and height
before umm maybe that.. oh that size
-
thing probably messed things up.
But you can see look at this that
-
was a transparent image o you can see
now the.. as I drag and drop the images
-
on to the canvas I see the image there.
So that concludes this particular video
-
umm where what I was hoping to
demonstrate I think I did; which is
-
the idea that you can create on any
element on the page and you can
-
handle when you're dragging the file
over it, when you decide you're not
-
gonna drag the file over it
and when you actually drop
-
that file and if it's an image file
you can use that image to display the
-
image data and umm in.. talking
about other videos in the future
-
I'll probably show you how to
do it with a text file and do something
-
like word counting in the text file
but that's.. that you might investigate
-
the loadStrings() function and sort of see
how you might do that umm..
-
I don't have a good exercise I can't think
of one.. I'll write something in the
-
description. Ok thanks and I think I have
one more sort of DOM video to make
-
after this one.