355

May 24th, 2021 × #javascript#drag and drop#web api

Hasty Treat - JavaScript's Drag and Drop API

Wes and Scott discuss using the native drag and drop API in JavaScript to enable dragging elements between web apps and customizing the drag experience.

or
Topic 0 00:00

Transcript

Scott Tolinski

CSF. Welcome to syntax on this Monday. Hasty treat. We're gonna be talking about JavaScript's a drag and drop API. Now this is something that Wes has done quite a bit of a deep dive into very recently, and I myself And pretty unfamiliar beyond writing some tools using just, like, Framer Motion, those types of things in JavaScript, and React. So we're gonna be talking all about the drag and drop API built into JavaScript. My name is Scott Talinski. I'm a developer for Denver, Colorado. And with me, As always, this is Wes. Hey, mister Dragon himself.

Scott Tolinski

Mister Dragon? Is that your new nickname? Are you mister Dragon? We should have, like, a comedy duo,

Wes Bos

And I would be dragging, and you'd be drop. Oh, dragging. And we'd be like like slapstick comedy. Yeah. And Scott going around doing tours. Drag and drop. And drop makes sense for me because, I can,

Scott Tolinski

drop to the ground and hit hit some dance moves, but I also drop things pretty regularly because I'm clumsy.

Scott Tolinski

CSF. Well, this is a funny story. One time, I got kicked out of a, I get kicked out of a club for being drunk when I had not had And he think the drink because I dropped my license when the guy asked for it. He's like, you, you're out of here. You're hammered. And I was like, I'm totally sober, man. He's like, Nope. I've been watching you. I'm like, I'm just clumsy. I'm just goofy. Like, you gotta you're gonna penalize me for being goofy? That's rough. Yep. Oh, man. Well, let's talk about dragging and dropping. But before we do so, let's take some time to talk about our sponsors and thank them. One of my sponsors today is Sentry at Sentry dot I o. They have for you today a coupon code of tasty treat, all lowercase, all one word, where you'll get 2 months for free of Sentry. Now this is a service that we've been using for a very long time. And one of the best features that we use in it is the performance tracking metrics so that we can see very clearly how each that we've done has positively impacted our page loading times, and we can see definitively which are the slowest and which are the fastest routes on our site, Which ones have the highest and lowest user misery scores? And since, you're getting this this performance tracking tools, and every time that anybody loads any of your pages, You're getting a whole lot of data to work with. And I'm a data head. I like having a lot of data. So try out Century's new performance tracking tools at century.iocouponcodastytree, all lowercase, all One word. Thank you so much for Sendery for sponsoring

Wes Bos

this tasty treat. We also are sponsored by .techdomainnames, and they have a Really cool sponsorship today, because they're doing a little bit of a collaboration with code dot org when you buy a domain name. So I I think this is really cool because I started learning to code when I was in grade school, And I never had any classes on that type of thing. And, apparently, according to .techandco.org, only 40% of High schools in the US offer, computer science and on and worldwide, only 73% are piloting computer science are doing nothing at all. So there's not a lot of coding going on in great schools, high schools right now, And Code .org is trying to change that with their they've got all kinds of programs and stuff for teachers and stuff for students and and and whatnot, which is really cool because, Like, I'm I'm glad that I learned to code on my own, but I know there's a lot of other people that probably would be really good coders only if they had the chance. So Our sponsor today, .techdomainnames, our favorite sponsor that does what they do in the name of the company.

Wes Bos

And, so .tech domain names along with GoDaddy Pro are donating a 100% of the proceeds to code.org in the period of May 5, 2021 to July 5, 2021. So visit go.tech f. Forward slash syntax.

Wes Bos

And when you buy your domain name, you a 100% of the proceeds is going to go towards code.org. So You need a domain name for your upcoming project, your side project, your new company that you're starting. You want a .tech domain name, and That's pretty cool that the money is going towards code.org as well. So you feel you feel you got a sweet domain name, and you feel good about it as well. Thanks so much to .tech for sponsoring.

Scott Tolinski

Sick.

Scott Tolinski

So let's get into drag and drop. Now this is one of those things that anytime you have to code up a drag and drop, It often feels like a a tremendous pain or you know what? Even with tools like React or other things, Drag and drop has never been super fun. And you know there is Jira drag and drop properties for HTML, but I don't know if you ever use them, but the user experience isn't exactly native feeling. It kinda feels kinda cheap. So I don't typically reach for the HTML Drag and drop, out of the box version.

Topic 1 04:45

Discussing the drag and drop API in JavaScript

Scott Tolinski

So I'm interested to hear what you have to say about the JavaScript's drag and drop API, Largely something I don't know a whole ton about, to be honest.

Wes Bos

Yeah. So I went down the rabbit hole of trying to implement my own drag and drop f. With just vanilla JavaScript because, like Scott says, there is an API in the browser that allows you to do it, but you have to code Everything yourself.

Wes Bos

So drag and drop in the browser is the important thing to to set from the get go Is that it is a set of browser standards that allow you to communicate and pass data through the drag and drop API Between both inside of your own application, inside of your own website, but also from application to application, Browser tab to browser tab. And I think that's really the the main benefit here is that because it's a standard, Two different applications can talk to each other and send data between each other by the user drag and dropping, data. So That out of the way, I'll say, like, right away, if you are just trying to reorder a bunch of stuff in your application, You probably do wanna reach for an existing library that does this type of thing. But if you need you're building a desktop app or something like that, Then you do probably do need to reach for this JavaScript API because it is the standard, and the different standards can can talk to each other. Right? If you drag A link from Notion

Topic 2 06:47

Drag and drop allows communication between web apps

Scott Tolinski

into Versus Code, those are 2 web apps that should be able to talk to each other because they both know this this base API. A good example might be the, like, if you were let's say you have an application like Figma or something. Right? You're dragging an image onto it. It drops it on your canvas,

Wes Bos

adds it to your project, those types of things too. Totally. Like, That that's a really good a really good, example. If you've got an image that lives in Notion and you wanna add that to Figma, When you start dragging that sucker from Notion into Figma I I don't know if this works. It should because Their API is a variable on both ends, but you should be able to pass the actual image itself from one app to another, and we'll talk about how to do that in just a second.

Wes Bos

So I went down the rabbit hole of just trying to make a very basic unordered list with a bunch of items in it, and I wanted to be able to click and drag And reorder them in what whichever order that they wanted. So the very basic, what you do is you go on to your items that you want to be draggable, And you just add a, an HTML attribute called draggable equals true.

Wes Bos

And that will then make your your element draggable.

Wes Bos

Then when you drag each of those elements, you will be able to listen for a whole bunch of different drag and drop Events that happen. Just like you're used to listen for a key op or a, a click event, you can add event listener, And you can listen for drag start, drag, drag enter, drag exit, drag leave, drag over, and drag end. So There's well, I mean, 1, 2, 3, 4, 5, 6, 7 different drag events, plus there is a drop event. So 8 events in total that you can listen to with all of these things. These events, they do bubble up just like Most events in JavaScript, meaning that I was, like, listening for the drag on the list item, but I put the event listener on the unordered list. Mhmm. Yep. Because that allows you to, first, just have 1 event listener instead of 40. And second, You don't have to add and remove those event listeners as the list items are being deleted and created, which is sometimes a bit of a pain if you're not using something like React.

Wes Bos

Alright. So you've got these drag events. And when you start to drag your element, the important thing is is that you get this thing called a data transfer API.

Wes Bos

So the browser allows you to stick some information about what you are dragging into the drag event, which are is kinda interesting. So you can kinda think of it as, like, a a mini database In the drag event of when you start to drag something, you're able to say, okay. We're we're doing a drag right now. Let's stick Some information about the thing that is being dragged into it. So you could take the image In base 64, encode the image and put it in there. You can set MIME types of the actual image. You can just use regular text. You can Any type of data that you can imagine. I don't know what the actual limit is. So if you were to drag a video, would you There's probably that's probably too large to to stick into there. But images, sets of links, some files, Those things can all be encoded and stuck into the data transfer API, and then it has a get data and set data API. So on all of your drag events, there is a event dot data transfer dot get data and dot Set data, and those are the APIs that allow you to get and set the data based on the event. And I thought it was kinda interesting that the event is the carrier of all of this data.

Topic 3 09:17

Drag events allow you to store data about the drag

Scott Tolinski

It's interesting. Do you think that maybe could it, like, care? Like, maybe, like, what application this is coming from Type of deal? Is that, like, a a use case for this? Yeah. You can set multiple pieces of data. So you could say,

Topic 4 10:35

Can store metadata like what app data is coming from

Wes Bos

event dot data transfer dot set data, from app dot set data, and you could set the in my case, I was just using strings, And I was trying to reference the index of the element that was being transferred.

Wes Bos

So as you start to drag and drop, There's no way to tell what item is being dragged currently.

Wes Bos

You can only tell what item is being Dragged over and drag enter. You can only tell when something is being dragged into, over, and inside of it. So if you want to be able to reference the element that is currently being dragged, then you have to stick a reference string. So, whether that is a a class, an ID, query selector, You can just put that in there.

Wes Bos

Then it comes time to accept a drop.

Wes Bos

So when you when you drag over an element, If you take that element event, so you've got a let's call it the drop zone, which all my Canadian friends are gonna be really happy about.

Wes Bos

We have a theme park in Canada called Canada's I was gonna ask about that. Yeah. Canada's Wonderland, and they have, like, this, like The drop zone. The drop zone, which is like a tower that just you drop, and it's super fun. Mhmm. So let's say you have a drop zone. When somebody enters into the drop zone with a dragged element, it will fire a drag enter event Or a drag over event. Sorry. And if you want to accept items that are being dropped, you can Call event dot prevent default, and that will essentially allow items to be dropped on that thing. So, basically, you say, okay. Someone dragged over me. You can tell what is being dragged over because of the, data transfer API we just we just talked about.

Wes Bos

And then you can say, okay. I'll allow it. You may drop on me, and then you say, event dot prevent default. And that allow that then allows the user to, When they let go of their button, that will then trigger the last event, which is the the drop event. And then when before I get into that, Let's just talk about the a couple other things here.

Wes Bos

So, you know, when you drag something on a page, it gives you, like, That little ghost image of what it is that you are dragging?

Scott Tolinski

Yeah. Yeah. And and there's, like, the the default for the draggable. That's like the the default. It's like a little ghosty transparent version of it. Yeah. Yeah. And you can set

Topic 5 13:19

Can customize the drag image shown

Wes Bos

that to whatever you want, and it all it has to be is an image, f. Like an actual image tag. So you could create a canvas element and stick that into an image And then give it access to that, and that's what will show up. So you can literally set it to anything you want, which I thought was pretty nifty. But that is Kind of unfortunate if you were trying to build, like, a draggable, droppable list.

Scott Tolinski

You have to set that to be an image that goes, Like, if you're if you're dragging a list Oh, yeah. How do you picture that list item to be a nonimage, or is it always just an image? So by default, it will

Wes Bos

just make a ghost image of the actual element itself.

Wes Bos

So by default, you don't do anything because it does what what you're saying. But if you want it to be like, if you wanna show it moving around, what I ended up doing is just removing the the ghost image entirely,

Scott Tolinski

because as I was dragging the element around, I was inserting it into the DOM where I wanted it to be. K. That's what I'm wondering. Yeah. So that's the solution there. The is is that image that ghosting that's happened on the image, is that is that created by the browser's Yeah. Image like, is that opacity that's bit baked into the image, so you would have to physically

Wes Bos

you you couldn't just toggle change that with CSS. Right? That's a good question. The drop, let me let me look that up real quick. I did not see any way to,

Scott Tolinski

Specify that. Yeah. That's sort of where I've always been because I've tried it before. What I find most people were doing

Wes Bos

is that as soon as you drag and drop As soon as you drag an element, people set the drop image to nothing, and then they start absolutely positioning the actual element itself. Yep. And you use the x and the y coordinates of the mouse mouse move event, and you can set that. So as you drag it around, it literally is just moving The position of the absolutely position or maybe even fixed would be better in that case of the actual element. Because then Then it is literally the element that is moving and not the the ghost image. Right. It kinda stinks that you gotta do that yourself.

Topic 6 15:29

Have to handle drag UI yourself

Wes Bos

Well, like like, what else would you want it to be? Like, if you you either want it to be a ghost image, you want it to be the element itself, Or you're talking about having to position the thing itself. Yeah. Yeah. I'm just saying, like, it'd be great if, when you dragged a an element, it was It would figure it out for you, the DOM element, the type of things that, like, like, React library would do for you in that regard. Right? Yeah. I I've got a list of, like, the shortcomings here because it does it's so much work to just use this Yeah. Yeah. By itself. You know, like, there's there's no magic in this API at all. It's a very low level set of APIs.

Wes Bos

As you drag the thing in the data transfer API as well, You can set the effect allowed.

Wes Bos

So you know when you drag something and you let go of it and it you didn't actually drag it anywhere, it just it it kinda goes back. It goes back to where you dragged it from. There's a there's 4 or 5 different effects that you can set Oh. On the event So that when you drop it when you drop it, does it need to go back to where it was, or should it stay where you are? And then you can also specify What the cursor does when you're hovering over top of the the thing.

Scott Tolinski

Yeah. I thought I'm way more familiar with, like, the animation aspects of all of this process than I am The actual browser API. So it's really interesting to to hear this. That's what surprised me about it is that there's literally nothing

Wes Bos

About the UI in this API Yeah. Which is a pain because that is Probably the hardest part is that you wanna position the thing. You wanna show it. You wanna animate.

Wes Bos

Like, when you move 1 up, you wanna animate the other one down. Like, that's one thing that It works in Flip animation. In all the React libraries. Yeah. So nice. None of that exists in this drag and drop API.

Wes Bos

One thing I I was tweeting about it, and, Etienne from Misiv, Misiv uses drag and drop API a lot because you're literally drag and dropping Emails and and attachments and stuff all over. You're dragging, a you select 4 emails. You click it. You hold down shift, and you drag them into a tag in the sidebar.

Wes Bos

That all uses it. And it's huge for them to use this API because It works multiple windows. It works multiple apps as I said before. So if you've got 2 versions of if you got, An email and your main missive app open in 2 different windows.

Wes Bos

It just works from 1 window to another, which is Really, really nice. Mhmm.

Wes Bos

One thing I ran into is possible security concerns.

Topic 7 18:02

Security concerns around reading drag data

Wes Bos

So you know how I told you that you can use the data transfer API to set data and get data? You cannot get the data when you are simply dragging over. You can only access the data about The drag and drop once the user has let go of the key the the mouse and dropped it. And the reason behind that is because If you got a couple windows open on your computer and you accidentally drag your, like, taxes over top of syntax.fm on the way to another tab,

Scott Tolinski

They shouldn't be able to read that file. That makes a lot of sense. Hey. Do you ever, do this? I know you use TweetDeck occasionally.

Scott Tolinski

Where

Wes Bos

I occasionally, I've been using it full time for 10 years. Yeah. I know.

Scott Tolinski

I'm I've also been using it full time for, 11 years. So, There you go. Yeah.

Scott Tolinski

No. No. One of the one of the things that really bugs me about TweetDeck is when you have any kind of image and and you're doing exactly what you're talking about. You're you're dragging a file in. Maybe TweetDeck's just opened. I find her on top of TweetDeck. TweetDeck starts flipping out about the type of thing that you're dragging from one window to another. You're like, TweetDeck, this is not for you. I have not let go of this. Why why are you trying to parse this image or whatever? Yeah. That that always bugs me about tweet deck, but it's funny because it's they can't access the data, but they can access some things like what it is. Right? Like, Yes. Most likely the extension of the file filename. The MIME type. Yeah. Yeah. Yeah. They can get that. And, all in Firefox, I didn't See that limitation. So you might actually be able to do it in Firefox

Wes Bos

because I had it just worked in it just worked entirely. Because what I was doing is I was simply just storing the ID of the item I was dragging, and it I opened it up to test it in Chrome, and it didn't work. So the way to get around that is you can you can access the key of what you're dragging, but not the value.

Wes Bos

So what you can do is you can store the ID of the item that you're dragging in the key.

Wes Bos

So you can't store, like like, a A file in there. But if you need to store the reference to something, like the idea of an element that is being dragged, you can stick in the key and parse it out. Bit of a hack, but That's the thing with browser APIs. It's like, we have this amazing browser API, and here are the limitations because people will abuse it. Yeah.

Topic 8 20:27

Browser APIs have limitations to prevent abuse

Wes Bos

That's,

Scott Tolinski

that's the web. Right? That's, the web in a a nutshell. That's the web in general. Yep. So shortcomings,

Wes Bos

Edge cases out the wazoo. So 60 lines of code to make drag and drop work. And then All of a sudden, I added a couple nested elements inside.

Wes Bos

I added a bit of margin to my draggable items, and it just started flipping out because it's you're you're you're triggering drag out events all the time.

Wes Bos

Lots of if Statements, lots of, like, little gotchas there, and that was the point where I was like, okay. So, like, 60 lines of code to, like, make a fun little demo, But you probably wanna reach for a battle tested library at this point because by itself, it's very hard. And And then you also don't get a lot of the, like, niceties, which is the animation and whatnot. So I don't know if, like, React drag and drop uses the drag and drop API under the hood, But I know that a lot of these animation libraries, they're they don't use drag and drop because if you just wanna, like, reorder a list of things, you probably don't need this API. This is, I think what this is for is for sharing data between apps and and browser tabs and things like that. Yeah. I've done a a handful of, Like, UI based drag and drop stuff, for instance, in our Svelte animation course. It one of the things that we did in that course was build a A draggable action on an element,

Scott Tolinski

and it's funny just even with that, how many caveats you have to place on top of Yes. This works in this browser in this way, but if you want touch support, then we have to start thinking about touch events. If you want this, you gotta start thinking about this. It's like, yes. I can show you in a few videos how you can start this process, but, you you know, there's so much more to it if you want this thing to be fully compatible

Wes Bos

Even with those and that's not even using this API. That's just straight up CSS and JavaScript. Right? I think that's, like, not necessarily a bad thing either. Is that, like, Go ahead and build a very proof proof of concept yourself so you sorta understand how this stuff works. And then if you need to Build a fully fleshed out version of this, then probably at that point, you you reach for a library. You kinda get the best of both worlds. You actually understand What's going on under the hood? But then you've also benefited from

Scott Tolinski

somebody else figuring out this other 6 a thousand lines of code. I feel the same way about that with a lot of stuff, whether that is, like, even, like, auth. Right? Yeah. We we have 2 courses on auth, and that to me is like, Yes.

Scott Tolinski

It's important to understand how this stuff works, but it's maybe not as important to build it yourself.

Scott Tolinski

And so, like, when we you you teach that stuff Or you think about learning something like auth, it's it's more or less understanding the whys. So that way, when you do hit a you are using a library, whether it is, like, Passport order something, or you are using these things, you might understand a little bit more of some of the pitfalls that that you know, air an error pops up, you all of a sudden know Kinda what to do rather than just say, well, screw it. I guess I'm toast.

Wes Bos

Totally.

Wes Bos

Other things is it's up to you to do everything. That's CSS classes is dragging.

Wes Bos

Hover styles, all that is up to you to add or remove classes there. I did find 1 like Pseudo selector. I was gonna say, is there any sort of, like, attributes that you could use or anything? There was one that I found, but it was like a Moz prefix, and I couldn't find any reference To a standard for that, so what I ended up doing is just adding and removing classes of, like, drag. What I did is I took the event type of those 8 events that we said, and I just added and removed them as they were fired on and off.

Topic 9 23:34

Must handle CSS classes for drag states yourself

Wes Bos

And then the the big one, which is, like, Accessibility. So by default, just making random things draggable makes them inaccessible by default because Unless you're using the, like, mouse keys, which you can use on OSX to control your mouse, then it is not accessible at all. So Yeah. And I had, like, a 1000 people being like, wait till you try to make it accessible.

Wes Bos

And I was like, alright. I'll try it. And it was A 100 times easier than actually implementing the drag and drop API because it was literally it was tabbed to the item that you want, so you add a tab index to each of the items. And then whenever you you added some, like, ARIA dash live text to it, so it would announce Items. 40 items. Press space to reorder. And then every time you tab to 1, it would say item 2 of 42.

Topic 10 24:55

Implementing accessibility is easier than drag and drop

Wes Bos

Press space to reenter, and then you hit space. And then you entered you entered into the state where now you're listening for up and down arrows. And then every single time you press up and down, it just moves the item up and down, And then you you update the ARIA dash live paragraph tag, and it will read to the I I opened it up on Safari. It worked great. It say, like, item pizza In spot 6 of 40, press space to drop. And then you just press space. You dropped it, and then it say it'll say done. You've reordered them. And I I was like, man, This is way easier because there's with drag and drop, there's 8 different events. It's so fussy. It depends on the what the CSS is doing.

Wes Bos

And with the keyboard stuff, it was simply just like, are you currently reordering, and do you want to go up or down? It's so much easier to implement that type of stuff than the drag and drop, so I was happy to report that the accessibility.

Wes Bos

The last thing here is mobile. It is not Supported on mobile, specifically, it's not even in Ios Safari. Mhmm. And that's just because this again, this is a desktop. Mhmm. This is a desktop API, so that is not there. Again, another reason, if you're just trying to reorder a list of things, probably go for something that has built in mobile port as well. Yeah. Yeah. Last thing, and then I'll I'll, jump off. I know this is getting long. Google has a library called Transmat, And it says it's for seamless cross web interactions.

Wes Bos

It basically takes this whole data transfer API that I was talking about, and it puts a wrapper around that. So you can send files, text, HTML links From one app to another app, and it makes it I guess it just standardizes it. It makes it really, really simple. I thought I looked at it. It was pretty cool. And it's The data transfer API also works with, copy paste API.

Topic 11 26:25

Google's Transmat library wraps the data transfer API

Wes Bos

So, it's the same same sort of idea. If you if you copy an image from 1 app and you paste the image into another app, it's the same idea with the data transfer API.

Wes Bos

Man, There's so many cool APIs.

Scott Tolinski

I feel like you could have a career just exploring all of the in browser APIs that exist.

Wes Bos

I kinda do that. Yeah.

Wes Bos

I mean, yeah. You do kinda. It is. Yeah. It's nuts because, like, There's a whole set of audio APIs. There's a whole set of speech text to speech. There's a whole set of speech to text APIs. There's Drag and drop copy paste it. But, like, every single area that you get into, it's not something you use every day. But once you get into it, you're like, oh my gosh.

Scott Tolinski

This is a whole thing. It's a lot of fun, and I I had a lot of fun with a lot of the voice stuff too, the speech input. And, you know, I I, like, made an app that would, While I was dancing would, like, tell me a a a random move to try so that you would, like, try to, you know, knock you off your game a little bit. Here. Do this move. And then, like, I was like, I can't believe I built this, and it's just baked into the browser. It's way easier than you'd ever expect.

Wes Bos

Man. Yeah. We should do a a a show on that explaining how both speech to text and text to speech work in the browser because It's amazing that you as a developer can just add that to your app. I 1000%

Scott Tolinski

agree.

Wes Bos

Alright. Well, look forward to that. Anything else to add here, or should we drag on, drop out of here? We should drag on and drop out or yeah.

Wes Bos

Awesome. Well, thank you so much for tuning in, and we'll catch you on Wednesday. Peace.

Wes Bos

Peace.

Scott Tolinski

Head Turn over to syntax.fm for a full archive of all of our shows. And don't forget to subscribe in your podcast player or Drop a review if you like this show.

Share

Play / pause the audio
Minimize / expand the player
Mute / unmute the audio
Seek backward 30 seconds
Seek forward 30 seconds
Increase playback rate
Decrease playback rate
Show / hide this window