How To Build Sortable Drag & Drop With Vanilla Javascript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
nearly all websites need a little bit of drag-and-drop functionality so in this video I'm going to show you how to build a really simple sortable drag-and-drop system using just HTML CSS and vanilla JavaScript so let's get started now but before we get started I want to tell you how you can get an entire year of hosting for free by using today's video sponsor atlanticnet hosting atlanticnet is giving you an entire year of free hosting on their servers and these are powerful servers that are more powerful than the servers I host my own website on so if you go to atlanticnet linked in the description below and use the code kyle when you sign up you're gonna get an entire year of free hosting as well as an additional $50 of credit to use however you see fit so make sure you check that out because this is a great deal and you're not gonna find this much free hosting anywhere else welcome back to web dev simplified my name is Kyle and my job is to simplify the web for you so you can start building your dream project sooner so if that sounds interesting make sure you subscribe to the channel for more videos just like this now on the right I have the final version of the product we're gonna be building as you can see it's very simply styled but we can select any element in these lists and we can drag it around and you can see we get this nice little ghost image appearing on our cursor as well as an indicator of where the item is going to be placed and then when we release the item it's going to be put exactly where we want it and we can drag items between any of these containers back up to the container and it's really flexible and the amount of code to create this is actually pretty small so in order to get started I just have an empty project open up and Visual Studio code we're gonna create an index file called index.html we're gonna have a style sheet called styles dot CSS just for these really basic styles and then we're also going to have a script J's file for all of our different JavaScript and now in our index.html we just hit exclamation point hit tab or enter it's going to fill out all of this bully of the plate for us and we can come in here and link our style sheet which is called styles.css we can also linked our javascript which is just going to be called script a s and we're gonna make sure we give this the defer attribute so it loads after our HTML is done now inside of our HTML we're gonna build up an initial container that looks like this where we have one two in the top and three four in the bottom so we're gonna have a div with the class of container which is going to be this black box so we're gonna have two of those divs and then inside of these divs we're going to have a bunch of different P tags and these P tags are going to be one two three or four so we're gonna give them a class of draggable so that we know that these are draggable elements and then in order to make something draggable using javascript there's an attribute called draggable and we just need to set this to true so if we set this draggable attribute to true we're already partway there into making elements on our page draggable now let's just put the text of one in here copy this down and have another one for two and then we're gonna copy these into our bottom container so that we have a three and a four and we can save that and if we just right-click this and open with live server which is an extension for visual studio code you can download you can see we have one two three and four so now in order to style these properly let's just open up our style sheet and do a few really minor styles so the first thing I want to do is select our body and remove the margin so that we can get our black container pushed right up against the side of our screen and then we're gonna style our container to give it that black style look so we're gonna say a background color here so background color we're gonna make this background color three three three it's just gonna give us this nice grayish color as you can see over here and then we want to give it a little bit of padding so we'll say one rem and we'll give it a little margin on the top of one REM just to space these black containers out from one another and now we can select our different draggable elements and inside of our draggable elements we're gonna give them a little padding on their own a background color which is going to be white and if we save you can already see that starting to look good let's just give them a little bit of a border I'll say one pixel solid black just to give them a little bit of appearance like that and then lastly to get to this nice little moveable cursor what we can do is just change our cursor over here to be move and then we hover over any of these we get that nice little movable looking cursor and as you can see already we can drag these elements by just clicking on them and that's because of that draggable property but it doesn't matter where we drag them nothing's gonna happen they're not actually going to move so we're gonna need JavaScript to set that up so now inside of our script is let's actually just select the different elements we're going to need the first thing that we're gonna need is to get the different elements we can drag all these different P tags so we can just get an element called draggable x' which is going to be equal to document query selector of all and we know that these all have a class of draggable so we can just use that draggable class next we're going to need to get our different containers because the containers are where we're able to drop our different elements so when you're doing drag-and-drop with HTML one's JavaScript you need to know what your draggable elements are in our case these different P tags and you also need to know where you can drop these elements which are these black rectangles in our scenario so we need to get those containers so we can just do another document that query selector all and this one we're going to get for that dot container class which we already know is going to be these black containers so now once we have those we can set up all of our event listeners so let's do our draggable event listeners first we can say draggable x' dot for each so that we can loop through each of our draggable x' and when we loop through each one of these we want to add some event listeners so we can say draggable dot add event listener and the first event listener that we want to listen to is what happens as soon as we start dragging our element and this is going to be the drag start event and this gets fired as soon as we start dragging an element and I can prove that by just saying console dot log dragged start and now if we just inspect this real quick drag this over so we can see our console and if I start to drag this you're gonna see we get that drag start printed out every time we start to drag any of our different P tags so this happens only when we first initially click and start our dragging and it won't fire again at all until we start a new drag so that's really useful so with that drag start what we can do is just apply a class to tell us that we are currently dragging this element that way we can get this nice little opaque style where we have this element it's a little bit different color than the rest of the elements so in order to do that let's just say our draggable all we want to do is we want to come in here get our class list we want to add a class and we want to add a class called dragging and then in our Styles we can select any draggable that has that dragging class and we can just change the opacity down to 0.5 and now when we start our drag you can see that that opacity changes to 0.5 but when we release our drag it still stays at 0.5 so we need to set up another event listener on our draggable and this event listener is going to be one our drag stops so we can just come in here and say drag end which is the same thing as drag start but it calls as soon as we let go of the element and inside of here we want to just remove that class list so we can say class list remove that dragging in class and now when we hover this you see it gets that nice opaque class and when we release it you can see that class goes away and that's because these drag start and drag and events so now we have all of that nice stuff for dragging our element around changing the class so it changes its opacity but what we need to do next is actually be able to move this element around inside the container as well as drop it in other containers so we need to loop through our containers in order to determine how our dragging works for when we're dropping our element as well as how when we're moving our element around so we can just say containers for each container whoops there we go and inside it here we need to listen to an event called drag over so we can say container dot add event listener and this one is dragged over and then we can just run this function and just just show you what's happening let's just console dot log inside of here drag over and again if we inspect our page bring over that console we can see that as soon as we start dragging an element over our container it's printing out drag over all the time just repeatedly printing that over and whenever we go outside of our container you see that drag over stops but anytime we're in a container we get that drag over function being ran so this function is going to be really useful since we can actually determine which element we're over top of as well as if we're not over an element at all and it's gonna constantly run every single time we move our mouse so in order to actually take advantage of that what we need to do in here is as you can see over here we're determining what position our element is inside of the container based on our mouse and we're also determining which element is inside of so if it's in the second container or this first container so we need to do all of that logic inside of this drag over function the easy way to do this for now is to ignore all of this sorting and just determine if we're inside container one or inside container two so in order to do that what we want to do in here is get our dragging element essentially get the element we're currently dragging and that's pretty easy to do we can just say Const draggable which is going to be our current draggable is equal to document diet query selector and we know that only one element will have the dragging class at a given time since is the element we're currently dragging so that'll be this draggable element here whichever one we're currently dragging and then all we want to do is append it to whatever container we're inside of so we can say container dot append child we could just pass in our draggable now when we hover this you see if we're inside of container one it's gonna add it to the bottom of container one and if we go down to container two it's gonna add it to the bottom of container two and when we release you can see it stays inside that container same thing with up here and down here the one interesting thing you notice is that our cursor has the do not allow simple you see that kind of circle with the line through it in order to remove that what we need to do is inside of our event we actually need to take our event object and we need to just call prevent default because by default dropping inside of an element is disabled so in order to enable dropping we need to say a dot prevent default and this is going to change our cursor to have a curse that says we are able to drop inside of here as you can see when we're outside we get the do not allow cursor and when we're inside we get this drop is allowed cursor so now with that taken care of our next step is to determine the order of our elements based on where our mouse position is instead of just determining what container were in we need to figure out which element we're actually placing this in between whether it's in between three and four above three below four inside this container and so on so let's just create a simple function and inside of this function we're gonna call it get dry after element and this is going to take in our container as well as the wide position of our mouse so what this function is going to do it's going to determine our mouse position when we're dragging our element and it's going to return which ever element our mouse position is directly after so in this case when we're dragging our one you can see our mouse is right above number four so this get dragged actor would return this fourth element so we know to insert above number four if our mouse was up here it would return number three since we're close to two number three and right above it and if we are for some reason below all of our elements it would return nothing because it just knows we need to append to the end of our container so let's actually write out this function and the first thing we need to do is determine all of the elements inside of the container that we are currently hovering over which is this container we pass in so we can just come in here and say container dot queries selector all and we want to get all of our draggable elements so we can determine where we're gonna place this in our list but one problem with this is when we're hovering this one over top of this you can see we have elements three and four but also the element we're dragging number one is also in this container so we want to ignore everything that we're currently dragging so to do that we can just use the knot selector and just say dot dragging which is the current element we're dragging so this will get every draggable that we're not currently dragging so essentially if we're dragging element one it'll only get element three and four and not the one that we're dragging and now that we have this information we want to convert this to an array so that we can actually do array operations on it because query selector all doesn't return an array so in order to do that we can just use the spread operator to spread this out into a new array and with this we can just set this to a variable which we're just gonna call draggable elements just like that so this is all of our draggable elements inside of our container and now we want to call a function on draggable elements called reduce and what reduce is going to do is is essentially going to loop through this element list of dragged ball elements and we're going to determine which single element is the one that is directly after our mouse cursor based on this y position that we pass in and we can get this Y position from our event so actually let's just say const after element up here which is going to be the return of this get drag after element we're gonna set that equal to calling that function passing in our current container and then the e dot client why this is just going to be the y position of our mouse on the screen now this reduce function if you're not familiar with it I have a video covering it which you can find in the cards in the description down below but essentially this is going to take a function and then it is also going to take a second parameter which is essentially the initial value of our reduce so this function is going to take in two parameters the first parameter is going to be the value we're reducing down to so we're gonna call this closest because this is going to be the element that we're closest to that is directly after our mouse cursor and then the next parameter is going to be each one of these draggable elements we'll just call this child because each one of them are a child of the container were inside of so for each one of our draggable elements this function is going to be called and whatever this function returns is what is this closest section inside of this function and then this second parameter of reduce is just the initial value of closest so what we want to figure out inside of this function is which element is directly after our mouse cursor so to keep track of that we need to figure out the offset between our cursor and the element that comes directly after it as well as the element that's directly after it so initially we just want to have a value which has an offset which is going to be a really really large number we want it to be essentially infinitely far away from our mouse cursor or so we'll say number dot infinite and we can do positive infinity here so number dot positive infinity essentially it's going to be the largest number possible so every single number is going to be smaller than that and this is just so that initially we have a number that is way too large and every single other element in the list is going to be closer than this number not positive infinity now inside of this function we need to determine the actual position of the elements on our screen in relation to our mouse so we can get what's called the bounding box by just calling here child get bounding client rect which is a function and this is going to give us a rectangle for our box and let's just log this out real quick so we can console dot log box just to see exactly what's going on inside of this function and if we come over here inspect our page go to the console and we drag one of these elements you'll notice nothing's actually being logged out which means we probably have something wrong in our code so if we go over here and check our code we can just see we got draggable elements getting that from our query selector and you notice I forgot to put a period here for our class selector for draggable so when I add that in once again inspect our page over our console and if we drag this you now see we're getting a bunch of things printed out these are the rectangles of our children we have the x position the y position as well as width height and then the top right bottom hand left hand position so right and left are going to be x and top and bottom are going to be in Y so for our use case we essentially want to measure from the middle of our box so to do that we can just take the top and we could subtract out half of the height of our box and that's going to give us the dead center of our box so let's start doing that now so we have our box the next thing we want to do is get the offset this is essentially going to be the distance between the center of our box and our actual mouse cursor so we can say that our offset here is going to be equal to our Y position which is our mouse Y position and we want to subtract our box top so this is the top of our box and then since we want the middle of our box we again need to subtract out our box height and we need to divide that by 2 so half the height of our box will put us in the dead center of each one of our boxes and now if we print out this offset and then just come over here we'll inspect our page make sure that we go to our console and then inside of here if we drag number 2 you can see that when we're above our elements we get negative numbers when we're below an element we get a positive number which is why we have one positive and one negative number and we'll more below all of our elements you can see every number is positive so essentially when we're below an element our numbers are positive when we're above an element our numbers are negative so we only care about offsets that are negative because that means that we're currently hovering above that element so let's close out of this and we know for a fact we only want to be concerned with offsets that are less than zero essentially we're above the element that we're hovering over because if the offset is positive then that means that we're no longer hovering over that element and we are now below that element so now we know we only want offsets that are less than zero but we also want the offset that is the closest to zero because essentially if we're as close as possible to zero then that means we are barely having our cursor above that element so if we were for example hovering our cursor right here we're barely above element three so we know that this is going to be close to zero and since we're actually basing this on half right in the dead center here we know if we hover here right above the center of element three we know that this is going to be nearly zero so we always want to find the offset that is less than zero but as close to zero as possible so in order to determine which element is our new closest element we can say if our offset is less than zero and our offset is greater than our closest dot offset which in our case down here is infinity to start with so if our offset is closer than our closest offset essentially it's closer to zero then whatever offset we currently have then we know that this is going to be our new closest element so we can just come in here and we can return an object which is going to have an offset which is going to be our current offset and it's also going to have an element oops element which is going to be our child which is just the current element that we're iterating through and one thing to know here is since we always are checking for our offset being greater than our closest offset and our initial closest offset is positive infinity we need this to be negative infinity because we always want to make sure that this first initial offset is always going to be the smallest number so that way any offset is always initially greater than our default offset so now we can have an else statement instead of here so essentially else if our offset is either greater than zero or it's not larger than the closest offset that we previously had we just want to return our closest that we have for now we can close off that if just like that and let's make sure that we return this here and now we can just come up here do a console dot log of our after element and make sure we return whatever we're reducing so essentially return this entire reduce function and we should see this after element being whatever our mouse cursor is directly above but to make sure we're only getting the element here and the offset and the element as you can see here we're just gonna return the element that we get from our reduce function down here so now if we save this inspect our elements over here and go to our console you can see that when we hover this element for example when we're above r2 you can see that we're getting our draggable being returned for - as you can see over here and you're also seeing this offset being printed we just need to remove this log for that offset and now we can go back and inspect this go to our console and let's do another drag here we can see if we dragged our three when it's above four we get four being printed as our number as you can see we have four right here and if we drag this up here above our one we get one being printed above two we get two being printed and if we drag it above nothing we get undefined to be imprinted so that we can determine whether or above something for example one or two or four above nothing and we know we need to append to the end of our list so now what we can do is we can use that inside of this function here to determine where we're going to put our element so we can say if our after element equals null so exam for example we're not above anything then we can just do what we did before we can append our child to the end of the list and we can just move our draggable up to here so now this will currently work if our after element is not anything so if we drag one and we're not above anything it'll come to the bottom of our list as you can see here once we go below everything it goes to the bottom of our list so that is working the next thing we have to do is to actually determine which element we're inserting before so to do that we can just put in an else here and we can say container dot insert before and here we're going to pass in the new child which in our case is our draggable and then whichever element we're inserting before which is our after element and now we can save and if we drag one below - it'll go below to above - it'll go above to come down here and above three it'll be above three same thing with four same thing if it's below and we'll we let go it'll stay in that position so now we can move our elements around freely and put them wherever we want inside of our containers and that's all there is to creating this simple drag-and-drop sortable list if you enjoyed this video make sure to check out my other videos linked over here and subscribe to the channel for more videos just like this one thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 119,859
Rating: 4.97085 out of 5
Keywords: webdevsimplified, drag and drop, drag and drop js, drag and drop html, drag and drop javascript, drag and drop tutorial, drag and drop css, drag and drop js tutorial, drag and drop javascript tutorial, drag and drop html tutorial, drag and drop html js, drag and drop html javascript, drag and drop html js tutorial, drag and drop html javascript tutorial, drag & drop, drag & drop tutorial, drag & drop js, drag & drop js tutorial, drag & drop html js, drag & drop javascript, js
Id: jfYWwQrtzzY
Channel Id: undefined
Length: 22min 22sec (1342 seconds)
Published: Tue Mar 17 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.