Updated 057 Drag and Drop Upload functionality in JCB (markdown)

Amigo 2019-09-24 11:16:54 +02:00
parent 9830242441
commit d634ed360a

@ -97,13 +97,13 @@ The JavaScript I'm using is this `uikitFileUploader` custom code. Let's look at
[00:24:06](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h24m06s) [00:24:06](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h24m06s)
Then it has some settings which is the action. We are using `JRouter` that is JavaScript trick that I wrote because oftentimes you have this Site View or the Admin View in the back-end and in the front-end. This takes care of whether it is a back-end or front-end call and that it executes it correctly. That is your component name. The `[[[arg1]]]` again would be the second argument, which is in our case documents. [00:24:52](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h24m52s) It says `documents`, the type. The third argument which is showing as `[[[arg2]]]` is `main`. It's passing the target as `main`. `Raw is true`, it has the `token`. There is our key(`vastDevMod`) which is being used to identify the view. It is making a query on this area and is set dynamically. Then it has some settings which are the action. We are using `JRouter` that is JavaScript trick that I wrote because oftentimes you have this Site View or the Admin View in the back-end and in the front-end. This takes care of whether it is a back-end or front-end call and that it executes it correctly. That is your component name. The `[[[arg1]]]` again would be the second argument, which is in our case documents. [00:24:52](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h24m52s) It says `documents`, the type. The third argument which is showing as `[[[arg2]]]` is `main`. It's passing the target as `main`. `Raw is true`, it has the `token`. There is our key(`vastDevMod`) which is being used to identify the view. It is making a query on this area and is set dynamically.
### Adding Formats ### Adding Formats
[00:25:21](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h25m21s) [00:25:21](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h25m21s)
Then over here we know that the formats must be added to this'.(`<?php echo implode`) area with pipe(|) between it. You remember it adds the formats with a pipe(|). We're exploding the array we have from the global parameters for documents, and it displays it in here(See video). [00:25:48](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h25m48s) This snippet, will I add under this name 'uikitFileUploader' on a GitHub gist. You could copy and paste it from there and adapted for your purpose. Again we are also imploding the formats because we want to display it, want to show the use of the formats. We have third and the second argument formats, which would be documents and main. [00:26:16](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h26m16s) If we look at our div, we will see the formats is `documents-main-formats`, it's targeting this `span` tag and adds it in there. That is adding the formats HTML to this id. Then over here we know that the formats must be added to this'.(`<?php echo implode`) area with pipe(|) between it. You remember it adds the formats with a pipe(|). We're exploding the array we have from the global parameters for documents, and it displays it in here(See video). [00:25:48](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h25m48s) This snippet, will I add under this name 'uikitFileUploader' on a GitHub gist. You could copy and paste it from there and adapted for your purpose. Again we are also imploding the formats because we want to display it, want to show the use of the formats. We have a third and the second argument formats, which would be documents and main. [00:26:16](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h26m16s) If we look at our div, we will see the formats is `documents-main-formats`, it's targeting this `span` tag and adds it in there. That is adding the formats HTML to this id.
### If No Formats - Update div - Upload Drop Area ### If No Formats - Update div - Upload Drop Area
@ -127,37 +127,37 @@ And the `div` looks very similar except that it now would say `images` and it is
[00:29:52](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h29m52s) [00:29:52](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h29m52s)
Regarding the hidden fields, for instance, the Documents Hidden field, there are some naming conventions that you need to follow. It says main-documents, it does not say documents. when we add the value back to the page, we are able to target it based on these naming conventions. That is quite important.<<<<< Regarding the hidden fields, for instance, the Documents Hidden field, there are some naming conventions that you need to follow. It says main-documents, it does not say documents. when we add the value back to the page, we are able to target it based on these naming conventions. That is quite important.
### Security - Different Encryption Options ### Security - Different Encryption Options
[00:30:21](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h30m21s) [00:30:21](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h30m21s)
Then for some security, which is a little extra layer. There are different encryption options. This Medium Encryption (local-file-key) is better than the Basic Encyption(local-DB-key), which stores the key in the database, which in that case means that if somebody sweeps your database, they do have the key. It could happen that they are able to get hold of your database, but not all of your files. Especially those that are behind the public repository. The Medium Encryption option can generate a file behind the public folder, which therefore is not publicly accessible. That makes it just that little bit more difficult to get a key to open the value. [00:31:19](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h31m19s) The reason is for instance thst your documents are not available to every group on your system, maybe some groups can access that document, then this is another layer of security that is already by default built into the field behavior. That is just looking at the fields. Then for some security, which is a little extra layer. There are different encryption options. This Medium Encryption (local-file-key) is better than the Basic Encyption(local-DB-key), which stores the key in the database, which in that case means that if somebody sweeps your database, they do have the key. It could happen that they are able to get hold of your database, but not all of your files. Especially those that are behind the public repository. The Medium Encryption option can generate a file behind the public folder, which therefore is not publicly accessible. That makes it just that little bit more difficult to get a key to open the value. [00:31:19](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h31m19s) The reason is, for instance, your documents are not available to every group on your system, maybe some groups can access that document, then this is another layer of security that is already by default built into the field behavior. That is just looking at the fields.
### Admin View Documents - setFileJS ### Admin View Documents - setFileJS
[00:31:38](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h31m38s) [00:31:38](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h31m38s)
The Admin View Documents have some Custom Script in it. We have here the `setFileJS` which is the JavaScript that fires when it gets the request back from the Ajax call. You'll see, let me show you if we go back on '`allcomplete`' there is a function. At some point when everything is satisfied it has a `setFilekey`, and it passes a bunch of variables to it. It is this function that we are going to look at. [00:32:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h32m36s) Let's use that `setFileJS` and search it. We'll see there is a `setFilekey` function in the document, and in your Ajax, which you're using Uikits [00:33:03](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h33m03s) function. It has an '`allcomplete`'. Even if you look at '`allcomplete`' which is a place where the server tells you it has been done. You can do some house cleaning in the browser. Checking if it has been done, remove the `progressbar`, and if it has an `error`, we pop out the `errors` and `alert`. If it is successful because we can decide what this response should be. So we will decide to give a `successful` value in the array.[00:33:43](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h33m43s) Then we fire the `setFilekey`, which is looking at our Admin View. We are adding this custom code in here, and it is adding all this code. It is quite a lot of code, but it is all being added to the Admin View and it can be used for different Admin Views, [00:34:13](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h34m13s) if it is dealing with either images, documents, or media. The Admin View Documents have some Custom Script in it. We have here the `setFileJS` which is the JavaScript that fires when it gets the request back from the Ajax call. You'll see, let me show you if we go back on '`allcomplete`' there is a function. At some point when everything is satisfied it has a `setFilekey`, and it passes a bunch of variables to it. It is this function that we are going to look at. [00:32:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h32m36s) Let's use that `setFileJS` and search it. We'll see there is a `setFilekey` function in the document, and in your Ajax, which you're using Uikits [00:33:03](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h33m03s) function. It has an '`allcomplete`'. Even if you look at '`allcomplete`' which is a place where the server tells you it has been done. You can do some house cleaning in the browser. Checking if it has been done, remove the `progressbar`, and if it has an `error`, we pop out the `errors` and `alert`. If it is successful because we can decide what this response should be. So we will decide to give a `successful` value in the array. [00:33:43](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h33m43s) Then we fire the `setFilekey`, which is looking at our Admin View. We are adding this custom code in here, and it is adding all this code. It is quite a lot of code, but it is all being added to the Admin View and it can be used for different Admin Views, [00:34:13](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h34m13s) if it is dealing with either images, documents, or media.
### JavaScript Does Some Checking and Validating ### JavaScript Does Some Checking and Validating
[00:34:33](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h34m33s) [00:34:33](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h34m33s)
The JavaScript does some checking and validating. I will put it out there and when it discovers that everything is fine the file was added. Then it goes ahead, and checks the length of the filename, and see if the '`currentFileName`' length is not greater than 20. If it is not an `image` or a `document`, then it must be removed. The return values are here of quite key importance. To make sure that we have this remove file from server function in place as I showed you in the Admin View those remove file tasks and methods.[00:35:21](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h35m21s) It is querying the `removeFile`. It passes all the necessary variables to remove the correct file.[00:35:42](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h35m42s) It is also checking if a person who is trying to remove the files, is a logged in user. On the file at which we will look at in a moment, at the actual PHP. It will again validate that the user has permission to remove the file. There are all these checks and balances across every step of this implementation. By now you might realize this implementation is far more complicated than the normal file upload, that is simple. This really gets into the nitty gritty of some of these things, because you want to give a real easy behavior for your user. [00:36:32](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h36m32s) But that will mean that you need to do more to protect them. Once we are satisfied that the file is correct and it does not need to be removed, we trigger a few things which puts the file in the page that we want to end up doing. The JavaScript does some checking and validating. I will put it out there and when it discovers that everything is fine the file was added. Then it goes ahead, and checks the length of the filename, and see if the '`currentFileName`' length is not greater than 20. If it is not an `image` or a `document`, then it must be removed. The return values are here of quite key importance. To make sure that we have this '_remove file from server_' function in place as I showed you in the Admin View those remove file tasks and methods.[00:35:21](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h35m21s) It is querying the `removeFile`. It passes all the necessary variables to remove the correct file.[00:35:42](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h35m42s) It is also checking if a person who is trying to remove the files, is a logged-in user. On the file at which we will look at in a moment, at the actual PHP. It will again validate that the user has permission to remove the file. There are all these checks and balances across every step of this implementation. By now you might realize this implementation is far more complicated than the normal file upload, that is simple. This really gets into the nitty-gritty of some of these things, because you want to give a real easy behavior for your user. [00:36:32](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h36m32s) But that will mean that you need to do more to protect them. Once we are satisfied that the file is correct and it does not need to be removed, we trigger a few things which put the file on the page that we want to end up doing.
### SetFile ### SetFile
[00:37:05](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h37m05s) [00:37:05](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h37m05s)
This '`setFile`' is what we are moving towards, because we want to make sure that the file, after you have dragged and dropped it on the page, shows in the page once it is on the server. It is doing a little bit of checking to make sure everything is fine. We end up with what we called '`filename`', and it get passed. [00:37:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h37m36s) We are moving into '`setFile`', and the '`setFile`' is going to take the target and it is going to determine what kind of target it is and get the format, etc. We can build the '`filename`' correctly. There is some functions which you may not need, you can look through this and decide what to keep. We end up building a notice which has been set. [00:38:20](https://www.youtube.com/watch?eventuallyv=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h38m20s) It triggers the '`getFile`'. The '`getFile`' is the other function which if you look at the Admin View, go back to the JavaScript. We have the '`setFile`' and the '`getFile`'. [00:38:38](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h38m38s) The '`getFile`' gets another layer of validation and also make sure that everything behaves as it should. The rest of the snippet is a '`removefile`', and '`isJsonString`'. There is a little snippet to check if it is a JsonString and if it is empty.[00:39:05](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h39m05s) It is all part of sanitizing and validating and making sure everything is the way we expect. <<<<<<<<< This '`setFile`' is what we are moving towards, because we want to make sure that the file after you have dragged and dropped it on the page, shows in the page once it is on the server. It is doing a little bit of checking to make sure everything is fine. We end up with what we called '`filename`', and it get passed. [00:37:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h37m36s) We are moving into '`setFile`', and the '`setFile`' is going to take the target and it is going to determine what kind of target it is and get the format, etc. We can build the '`filename`' correctly. There is some functions which you may not need, you can look through this and decide what to keep. We end up building a notice which has been set. [00:38:20](https://www.youtube.com/watch?eventuallyv=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h38m20s) It triggers the '`getFile`'. The '`getFile`' is the other function which if you look at the Admin View, go back to the JavaScript. We have the '`setFile`' and the '`getFile`'. [00:38:38](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h38m38s) The '`getFile`' gets another layer of validation and also make sure that everything behaves as it should. The rest of the snippet is a '`removefile`', and '`isJsonString`'. There is a little snippet to check if it is a JsonString and if it is empty. [00:39:05](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h39m05s) It is all part of sanitizing and validating and making sure everything is the way we expect.
### GetFile ### GetFile
[00:39:16](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h39m16s) [00:39:16](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h39m16s)
We want to look at the getFileJS which has different implementation and as you can see it is in the view footer. We have PHP in that area of the JavaScript. This is the getFile. In the getFile we have again a link that was echoed. [00:39:44](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h39m44s) We are going to use to load the file, to make it that it can be downloaded. That's the issue. If it's a document or if it's a media, we don't want to display it but we want to have you to be able to download it. We have different behaviors for image and images, as well as for [00:40:04](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h40m04s) documents and for media. It has different behaviors. It continues building buttons and displays. I'll pop this code also out on the Gits, and you can look at it, and see if you can make sense out of it. The DOCLINK or the DOCBUTTON is [00:40:26](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h40m26s) the potential idea about this if we go to the Document Manager. In the Document Manager, when you create a document, you will have what we call description. If you add a document you can use those placeholders in the description. It's the beginning of [00:40:58](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h40m58s) using these documents across the website, and not just in the component. We'll eventually write a little plugin, and if you use this placeholder which it generates. If you use that anywhere the plugin will identify it, [00:41:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h41m17s) and will load either a link or a button depending on which one you're using, the button or the link. That's what it's doing. You might say I don't need placeholders and you can grab that part and take it out also then wherever the 'var placeholder' [00:41:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h41m36s) is being used and need to be removed for example over there. We have a 'fileBox' that we are building. It's getting the placeholders, the download and the delete buttons, all of them get loaded into the 'fileBox'. [00:41:53](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h41m53s) If we are having more than one file, we are treating it differently than just having one file. That is what we are doing here, the document has a little different behavior but somewhat the same. That is what the final stretch is, it is like a relay race, one carries it this far and then the other one takes it over, [00:42:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h42m17s) carries it a little further. This one is at the very last end of the match. Where it is finally putting the image back into the page, and all of the nice little thrills, bells and whistles happens here. This is where you can spice it up with some JavaScript. [00:42:37](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h42m37s) You can see I'm using Uikit to deal with most of the styling. Now you've seen the front-end as we would call it of the behavior of our Drag an Drop. [00:42:53](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h42m53s) You've seen how I set up the field. You've seen when the Ajax has finished it's request. It runs this setFilekey. The setFilekey triggers a whole bunch of things which ends up adding the file to the page. We want to look at the getFileJS which has a different implementation and as you can see it is in the view footer. We have PHP in that area of the JavaScript. This is the getFile. In the getFile there is again a link that was echoed which will be used to load the file, to make it that it can be downloaded. [00:39:44](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h39m44s) If it is a document or if it is media, we do not want to display it but we want to have you to be able to download it. There are different behaviors for image and images, as well as for documents and for media. [00:40:04](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h40m04s) It has different behaviors. It continues building buttons and displays. I will pop this code out on the Gits, and you can look at it, and see if you can make sense out of it. The `DOCLINK` or the `DOCBUTTON` is the potential idea about this if we go to the Document Manager. [00:40:26](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h40m26s) In the Document Manager, when you create a document, you will have what is called 'Description'. If you add a document you can use those placeholders in the description. It is the beginning of using these documents across the website, and not just in the component. We will eventually write a little plugin, and if you use this placeholder which it generates. If you use that anywhere the plugin will identify it and will load either a link or a button depending on which one you are using, the button or the link. That is what it is doing. You might say I do not need placeholders and you can grab that part and take it out also then wherever the '`var placeholder`' is being used and need to be removed for example over there. [00:41:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h41m36s) There is a '`fileBox`' that we are building. It is getting the placeholders, the download and the delete buttons, all of them get loaded into the '`fileBox`'. [00:41:53](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h41m53s) If we are having more than one file, we are treating it differently than just having one file. That is what we are doing here, the document has a little different behavior but somewhat the same. That is what the final stretch is, it is like a relay race, one carries it this far and then the other one takes it over, carries it a little further. [00:42:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h42m17s) This one is at the very last end of the track, where it is finally putting the image back into the page, and all of the nice little thrills, bells and whistles take place here. This is where you can enhance it with some JavaScript. [00:42:37](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h42m37s) You can see I am using Uikit to deal with most of the styling. Now you have seen the front-end as we would call it of the behavior of our Drag an Drop. [00:42:53](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h42m53s) You've seen how I set up the field. You've seen when the Ajax has finished its request. It runs this `setFilekey` which triggers a whole bunch of things that ends up adding the file to the page. <<<<<<<<<<<<<<<<
### Demostration - Uploading An Image (see video) ### Demostration - Uploading An Image (see video)