-
-
Notifications
You must be signed in to change notification settings - Fork 178
057 Drag and Drop Upload functionality in JCB
00:00:00(Click on these time links to see Youtube video)
This tutorial deals with the Drag and Drop Automated Crop Functionality, which could also be used instead of this implementation(how to use the file field type to upload a file in JCB). This implementation would be much more limited. 00:00:47 A crop can be done with this(how to use the file field type to upload a file in JCB) as well, and since it has not been demonstrated before it will be done in this tutorial. There is a link to this library that I am going to use below this video.
You need to be familiar with UIKit. UIkit has a very nice file uploading front-end, which I have used quite often. 00:01:29 I am going to demonstrate this by using UIkit upload. If you are familiar with JavaScript, it would not be hard to plug-in Bootstrap or any other library which you want to use. 00:01:47 JCB can be scaled to use other libraries. You can go to libraries and set up the new library and then include the files in your Admin View. In this presentation, I will be using the older Uikit version which is the same one that I am using in some of my projects. 00:02:43 Go to get UIkit Version 2, to Components. There is an Upload at the very bottom that explains to you how to use this library.
This is the JavaScript that we will be using. It has a nice progress bar and everything. This is the HTML that we will be using. It has a nice drag and drop and selecting area. You can give some information to the user as well as have them drop in the file right there. It works very well. 00:03:37 It have some events. It is very similar to Version 3. If you want to see the Version 3 option, simply click on Version 3 documentation. Scroll to the bottom where it says Upload. Then Select, there is Markup for the Select. [00:04:01](https://www.youtube.com/waAnd stch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h04m01s) There is the Markup for the Drag and Drop. You could use this(see video), and then JavaScript. It looks very much the same except for a few changes. For the most part, it is generally the same kind of approach. You would be able to plug-in this if instead, you want to use UIkit 3, or any other library. 00:04:26 This, for example, I will make dynamic(Follow on video). The URL is going to be dynamic as to whether it is going to be allowing multiple or single. This one allows what type of image or file you want to permit to be uploaded. The action is where the URL is. 00:05:02 You will see me make some of this dynamic with the script that I am using and of course here is Ajax involved. You can upload the file without saving the item whenever this area is available. You can simply use a note to add this script to your page. 00:05:24 That is what I usually do, I use a note and add this(see video). If somebody drops something here, it is going to be posted to the server. If the item has an ID, I passed the ID that it gets stored in the database immediately.
If you save it or not, the file is added to that item. If it is a new item which means no ID, we will add a hidden field to the form. The actual value is returned that must go to the database and is put in that hidden field. When the item is saved, it stores it in the correct place. That is the approach that will be demonstrated step-by-step with an existing component that is out there and which is in use. It is available in JCB.
There is a new Import JCB Packages. Either click on Import JCB Packages go to Joomla Components and click on Import Components, it is the same thing. Return to the Dashboard and click on Import JCB packages. There has been a release fix, I think it was been in the previous release. If you click on Import JCB Packages it didn't give you this VDM Package tab. 00:06:53 It only gave you Upload, Directory, and URL. It is a little broken. The best then go to Joomla Components and click on Import Components to be sure that it gives you this VDM Packages tab. 00:07:12 This VDM Packages tab is a new extension on the Import of Components. It is the only part of the import of the components that already validates the package integrity. For each of these packages that are here, we do have a validation. For example, Hello World is not here. If I was to select Hello World and click Get Package it will fetch it from GitHub.
It has a method of getting a hash, a checksum of the package. You can make sure that it tells you that ' This package PASSED checksum validation! '. On this point, the package is on your server. You can click 'Cancel' and that will delete the package from your server. On the top of the page, it tells you that the validation is passed. The actual package that we are distributing is the one you have now. You can verify that by clicking on this link http://raw.githubusevomponent.com/vdm-oi/JCB-Packages/master/JCB_helloWorld.sha. It should open a simple text string. This text string should be the same as the one you see In Data Importer. 00:08:32 That is just a heads up and its an area where we started to add some checksum validation. It is not military-grade but it is fair enough.
The package which has been imported is displayed here, and if you click Quiet, all the things that it is going to do will be hidden. I would suggest that you say 'No'. Force Local Update, means that if it finds a similar Fieldtype or Field or Admin View or anything similar, 00:09:29 and the creation date is later in your system, it will overwrite it because it had been forced. If it finds it and the actual current date in your system is earlier and the one that is imported is later, it will automatically update it with the latest version. 00:09:52 NB. That is why it is important to make backups. The other advantage is if you get to Fieldtype that had been overwritten, and it is not really what you expected, you can go back one step in your history. Say 'Yes', Force that and then click 'Continue'. That simply adds a whole list of what has been imported, and it moved an image. Hello World is now in the system.
We are going to look at something completely different. It is the Document Manager which is a paid package that VDM distributes. It has all this functionality that I am going to demonstrate in it. I am going to use that, and add a key and click 'Continue'. 00:11:02 Then install this component in JCB. From there we will demonstrate its functionality. We have Document Manager installed. Let me quickly show you how it looks in action. I am going to install it in this component Joomla website and demonstrate it. 00:11:32 We have Document Manager and we can create a document quite easily by clicking a new document. There is: 'Allowed image formats are not set in the global settings, please notify your system administrator'. You can not at this point upload anything, neither Image, neither Documents, neither any Media.
Go out of this and in the Options of the Component there is a Media tab, that says what type of documents you want to allow. For our purpose I am going to say in Allow Document Format, 'PDF' for now, with the Media, 'MP3' and with the Images, 'jpeg'. With the images in this component, there is one image and I want it to be a specific dimension. 00:12:28 For instance make the width to be 200 and the heights to be 350 and use that to crop my image('Crop All Doc Images'). 00:12:45 I am using a library, which gets these values to decide how to crop the image if it is an image. If it is any of these it will not do anything. Only if it is an image it does use the cropping mechanism. It does it via an Ajax. Save and close. 00:13:11 If we now click on 'New documents', we see this Drag and Drop area. In UIkit we see this in action. It says Upload Your Image, it tells you what the dimensions should be, if not the doc will be cropped to this size. 00:13:35
That means if it is not this dimension it will be cropped to the desired size.' By dropping the file or selecting a file from your computer, and formats allowed.jpeg '. So it tells you what formats are allowed. This is all done dynamically through this Script. 00:13:59 Then the same applies to the document. It tells your 'PDF' is allowed and with the media, it tells you 'mp3' is allowed. In the image, I am allowing one image. Whereas with the documents, multiple documents are allowed, and multiple media for one document. It displays and works on the front-end without problems. I am going to demonstrate this functionality of uploading a file. 00:14:30 You need to use this in your Component, and need to extend that and use it and make it more functional as it should be in your Component.
Let's go and look at the code and first focus on the document area. It is necessary to look at some of its fields that are attached. Some of them are JavaScript. The Ajax area is where everything happens. Custom code placeholders are used almost everywhere since a lot of the scripts are reused everywhere under components. 00:15:15 It is therefore adapted so that it could be used in multiple places. Here is 'uploadfile' and 'removeFile' functions. It have 'target', 'type', 'field', 'filename', 'target', 'flush' and 'type'. It has values, all these values play a role within the behavior that I eventually have to demonstrate.
You will also see here I've got this setVastDevMod
, which is a function that generates for us some variables. Which in this case it is called VDM
which gets placed in a variable called 'VastDevMod
'. This formation is what is used to identify the view from which the query is made. This is a long string that is related to the cache at that stage of the view ID and name. 00:16:33 This is how I passed the view name and ID, so it is not passed via the Ajax query. I have it in session memory only if these keys validate that it does work. Sort of another layer, and another layer. There are many layers to 00:16:54 try and make this secure. Then this adminKittwo
is where all the Uikit files are loaded. I am manually adding it to the
Admin View. The admin back-end does not work as the Site Views where we can select a library and then it dynamically answers the view on compilation. You have to manually add it to the view and it is done in the Custom Script of the document.
I can show you some of these Snippets and then take it further. In the Custom Buttons area, is the getVDM
which I have explained. Again we have some custom script. In the JavaScript area, we again have setfile
which is part of the script that we will have to look at. I am using setfile
in different places because we have image
, documents
and media
. 00:18:15 They are all using the setfile
method. It is a JavaScript function and is declared in this customScript.
Individual Concepts - Notes - Main Media Uploader Note - Main Document Uploader note - Document Image Uploader note
At the bottom of the footer, we have what is known as getfile
snippet which again deals with some of the automated integration of the file, when drag and drop. It immediately displays on the page, this takes care of that. We will look at those individual concepts and will also see, as mentioned previously that there is the Main Media Uploader note and the Main Document Uploader note and the Document Image Uploader note. 00:18:56 This is where I have added the HTML for the drag and drop that you see in the Admin View. Then we have for each of those correspondingly a hidden value for the Document Image key and the Main Document key and the Main Media key.00:19:26 All of these are hidden fields which is where we store these values. 00:19:40
Let's look at the code that is used by starting in the interface. Let's first look at one of these Uploading Concepts. Since I know what is happening there, I am already aware that the code is not there. It is also a custom Placeholder snippet. Before we dive in, open the custom code area and go back into documents and look at the code snippet. 00:20:28 Let's use this Documents Uploader Note and open that. We have the Document Uploader Note, the a div
all the way down there(see video). Which has an id
It has the class
for the placeholder, and some icons. 00:20:52 Here is upload your documents once more and a span
tag, that says main-documents-formats
. It is going to be the place where we load the formats with JavaScript.Then there is Selecting the file from your computer
. It is this snippet with a little bit of extra flavor. 00:21:29 That's all we are looking at. There are some conventions, like main_documents_uploader
, that again upload-drop-main-documents
. There are conventions that make this reusable. In the scripts area, I add JavaScript to the view-footer.
The JavaScript I'm using is this uikitFileUploader
custom code. Let's look at that first. We can search for it and open 'uikitFileUploader'. This is the code that gets added have a little bit of PHP, and it is saying [[[arg0]]]_formats'
. We are asking getting the global parameters of the formats we set. Remember it is set in the global settings. We are saying that document
is the first parameter that is passed. 00:22:45 We are saying document formats
, to get the document formats. Here we have [[[arg2]]]
and [[[arg1]]]
progressbar
. If you think about the id, it says progressbar
which is the third argument that is main
. Documents are the first argument because we counting from zero.00:23:16 It's saying main documents
. If you look back at our thing here it says main-documents-formats
. This is all part of main documents
. It is the way we identify the progressbar. 00:23:44 Progressbar-main-documents
is an ID. There's only one of them on the page. It is targeting it here saying that is the progressbar
we are going to use.
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 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 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 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 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 if we have detected that no formats had been set, we are going to update the whole div, which is the upload drop area with 'allowed formats are not set in a global setting please notify system administrator
'. That's the final part of our JavaScript. We have JavaScript mixed in with HTML taking care of some of the behavior of the display on that page.
That is the reusable snippet. This same snippet uikitFileUploader is reused for various areas. If we were to close and open the Media Note, It may be seen that it is really just using the same snippet. If you go to Script, you will see it is the same snippet. 00:27:47 I am changing the variables that I am passing, it is saying media-media-main
. Where the other one was saying document-documents-main
. The same applies to the image. With the image there is also that kind of behavior. It says uikitImageUploader, this one is not using the FileUploader, it is using the ImageUploader which is a little different. 00:28:21 There is an 'ImageUploader' and there is 'ImagesUploader' in my custom Snippets. I'll show you why they are different. One allows one image and the file one allows more than one, this one only allows one. 00:28:45 So it has a little bit of a different flavor and behavior. I will also paste this out for you to look at. Always remember these arguments behaves the same as an array which means that the first argument will always be 0, the second argument 1, and so forth. I'm using arguments in this snippet. Everywhere where I declare it, I am passing the three arguments that are required, use this +
to pass it.
And the div
looks very similar except that it now would say images
and it is using different placeholders. You need to update those accordingly as needed. To set up the field you need to have that JavaScript in place and you need to have that div
in place.
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.
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 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.
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 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 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 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 if it is dealing with either images, documents, or media.
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 It is querying the removeFile
. It passes all the necessary variables to remove the correct file.00:35:42 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 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.
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 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 are 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 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 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 It is all part of sanitizing and validating and making sure everything is the way we expect.
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 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 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 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 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 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 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 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 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 end up adding the file to the page.
Let me demonstrate in our new document some of these function which I have explained. I have got a bunch of images, it is generic open source kind of images. I am going to grab one and dump it in 'Upload your image'. Let's use this house. 00:43:50 I am going to drag it and highlights it for a moment. It has this little Uploader. When it started it says 'Your doc images are set'. That was built by JavaScript. There is the document image on display.00:44:10 There is 'Remove document image'. I can click that and it will tell me 'are you sure you wanted to leave this document?', 'Yes', and it is gone. It doesn't only delete it from the page, it removed it from the server as well. Let's drag another one, just 00:44:33 drag it there and drops it on Uploads. There is our nicely cropped image. It crops in the center of the image, because how does it know the house is on the side. It not doing that kind of smart detection yet. We are cropping the image in the most sensible way.
With the uploading of a document, it is more or less the same. If you have a document, and you can Drag and Drop it in there. Again it uploads it, and with the upload, it generates those links I told you, you could copy.00:45:10 Put it in the description if you want. It can be tested. What is noteworthy here, is that the name of the document does not get lost, while the place where the documents are added, is in the same folder.00:45:25 You could add multiple documents to this document. I will just keep on stacking them though they have the same name. Each one will be uniquely tagged to not be the same as the other which means that on the server we are storing this document with a 00:45:53 long hash, sort of added onto the name. Which is an extra layer of security, that people if they could access the folder, they will at least know what the name is. The same applies to image. If we were to inspect the image, you will see that the image have this huge name: /doc_image_jpegxxxxxxxxxxxxxxxxxxxxxxxxxisland jpeg. 00:46:12 So it is no longer than the same name as the one you have uploaded. It changes it and preserves the name for example in the documents option. That when you give the document to someone that they will have the document that you expect them to have. 00:46:38 We do adapt the names for security, that it can not be allocated on the server if for some reason it is not a good document. You could test it by clicking here and it should then bring it up in and be available as a download.
How the download works here with the document, I'm using a controller. If we hovered over this link, it is not visible. So I have to copy the link, it is long because we are using an encrypted path to the file.00:47:25 It could sometimes being encrypted or sometimes just be basic64 encrypted. But the point is we have what we see here as a task and download document. There is a controller called 'download
' in my component, This is how this download document 00:47:54 concept works, but you will have to write that. You need to figure that one out if you want people to download your documents. If it is just to upload images, of course, you do not need any of this. But it is only when you are going to have a downloadable file or media.
Next is how to upload some media files. I have a bunch of audio files, and I am going to upload them. What I am going to do, is to select a whole bunch of them, and then upload them all at once. This is what the Uploader can do. After it is dropped it will upload. The page needs to be refreshed and a name given to it. 00:49:01 The 'Document. Description' say: 'More Soon'. Save this. 00:49:24 If it did not upload all of them, try again. I have 6 of them uploaded. There are 6 documents and you can download them and test them. See if they are still fine. 'Why the home?', 'The order of the home'. The media is working. Let us also do that with documents and add some more documents. 00:49:57
I've got a few selected and drag and drop them and it is uploaded. I need to check some of the JavaScript. I see it did not add the download button. Without saving, if we refresh the page, you will see that it has all those documents there because it used Ajax to store them in the database. At the end of day that is the behavior, we wanted here in our component. We wanted the option to upload multiple documents to one document, and multiple media files. 00:50:31 To be able to test them in the back-end, if you want to test any of them. Even be able to remove any of them at any time, just click on remove and it will be removed. In the front we will be able to use the file names, and the user would be able to identify the one he wants. 00:50:59 The filenames get preserved while it is being stored in the server with this hash behind it. We are seeing the JavaScript we looked at earlier in action, it is uploading, it is deleting. This one is cropping which we will deal with a bit more. That is our drag and drop options in action.
Now let's go look at the server-side of this implementation. The server side is in the documents Admin View. On opening the PHP tab, we have this Ajax area. Like I showed before you need to set up the Ajax where this area targets the controller. In the controller, it creates all these necessary script 00:51:54 to make this method. We are going to look at the inside of that custom code to make this method available to the Ajax call. There are some values that we set because every component I use this stuff in is different, so for some we are using images
, documents
and media
as the types and for some targets the main
and doc
.00:52:23 Regarding the allowedView
; there is only one view in this component that is allowed to use in the Uploader and that is the document view. The getViewID
is the function in which I get the actual view name and ID. It is using the session to throw that around to insure that nobody is able to tamper with that value through the front. So that is just extra gymnastics to add another layer.
We are going to look at this phpAjaxUploader
in the custom codes area. Let's Search for it in the custom code area. I am using custom code because I am reusing it. At the moment it does not look like I am reusing it in many places, it only says it is used in component. This is not the area where I am doing my work, this is just for tutorials. I am using a different Joomla website than this one. This one is only for demonstration. I am reusing this code in many components and we have image
formats that are allowed in the system, Document
formats that are allowed in the system and Media
formats that are allowed in the system.00:53:57 You can adapt this to allow whatever you like. This are the available formats. Remember in the options area of our component, it has a media area and there we have allowed documents, allowed media formats, and allowed image formats. These should be the same. It should be the same list, having the same values. But these are a field we created in Joomla, a List field. This is manually added to the components configuration area.
If you don't know what that is, let me quickly show you. In the component, it has this component config. If your component doesn't show one like this, Hello World, it doesn't show a component config, you can go into the component and then in 00:55:16 settings there is this button 'Create component config for this Joomla component'. Close, I do not want to do Hello World, I can show you with the Document Manager. We could use the same button in Settings. We can edit it if it has not had one, you can create one. You select fields with their custom values and the tabs in which they should be displayed.00:55:50 I have selected 'Allowed Document Formats(list)', which is just a list of the formats and I set it to allow multiple selection. That is how this Allowed Media, Allowed Image, and Allowed Documents are done. Then there is the crop document image. If you do not know how to create a field, and how to set radio buttons or list, then go review the videos about that. That is how we deal with that and that list we have looked at now is the same list as what we see here. 00:56:29 It should be the same because this is the allowed, and that list shows the user what is allowed for the system. 00:57:03 This is what you could say is available formats, and then those drop-downs is what you as the owner of this website, where this application will run, will allow. This list should be the same as the one there, but it also is going to be used if people post a specific type, as if it is allowed. We are going to be able to bounce this and make sure that security-wise we are safe.
Here is the 'uploadFile'function. The 'uploadFile' starts by first getting the view ID and checks it. Then making sure that there is a view set and that view is part of the 'allowedViews
' array. The 'allowedViews' array, if you remember 00:58:08 the 'allowedViews
' is documents. That is why I am setting that outside the custom code, because it depends on which component we are working in. If it is an 'allowedView', we then get the target, and the type and we set it to Global target in Global target type. 00:58:45 Then we check that this type that is the format that has been mentioned. That is the formats that we allow, the types, because we need to anticipate what a person is going to upload and to validate that. 00:59:17 It is setting the format
with the type
. If it is image
it will be images
. If it is images
it will be image
. If it is document
it will be documents
if it is documents
it will be document
, and media
will be media
. That is the types and we are setting that as the formatType
.
Then we are using a function getPackageFromUpload
. If you watched the previous tutorial on using the 'File type uploader', It is more or less the same kind of function. If I scroll down to, getPackageFromUpload
.01:00:02 The only differences we are doing the getApplication
and the input in the function. We are targeting files because we are passing those values in the file's place. We are seeing what is the file. We are checking whether these things are allowed: warning, import file error
. This kind of error is not thrown to Joomla, it is added to the error message. 01:00:35 Because we have to give it back to the view. This is an Ajax call, nobody will see it if we just use the array's warning. So we are actually grabbing the value and say we are done here get out of here if we are still going and you could go through this and it has very much the same implementation than the one we have demonstrated. The only difference though is our check method. It takes that view and again validates it. 01:01:12 The 2nd layer of validation is done and then it gets checked whether this specific user that is now logged in has the right to edit this item. It is doing some user validation. If not, it removes the archive. We still have that remove method with a little bit of the code that you saw me take out, that is still left in. In the previous tutorial, I used some of these codes. That is all very much the same, I will not go into depth. If you do not understand this watch the previous tutorial.
In our upload file, we at this point have the package. We pass the package to uploadNow
. Now move the file into place. Remember we had to do that here and a uploadNow
function is used. In the uploadNow
function, we return
and if any error still remains, it is going to be dealt with here. Whereas errors that might have occurred here, if this was false, we would use that. 01:02:36 That is the error message, put it in error and pass it out. If there are any other issues, we will see there has been an error and will pass it out, there is this error handling there.
In uploadPackage
, we check whether the package is there, the package name and starts from that, we are building the name. Remember I explained to you that we are using and preserving the filename but we are hiding the filename. We are using the targetType
, the fileFormat
and then this randomkey
generator. 01:03:17 I am not exactly sure I think all JCB helper classes comes out with this randomkey
. You could just use it in your component and you can decide how long this string should be. Then I am using a little placeholder which is little generic placeholder VDM
and then adds the actual name of the file after this placeholder that everything before this placeholder is really internal, my system uses this, but the client uses everything this side.(See video)
If it is a document we are going to need the folderpath for hiddenFilePath
. The getFolderPath is a function that I wrote. I am not going to share that with you, but you can build your own helper class function to get the path to where you want to put the file, this is up to you. I'm using a hiddenfilepath
, but there is a lot of discussion behind that. If I do not pass any values like in this case, it most probably returns a public path.01:04:28 It would be where the images go. Every document go in a hidden area, images go public. Usually, the image you want to load somewhere, you would not have it to be behind the root folder of your website.
We end up here with the fullPath
which is the filePath
and the fileName
and the fileFormat
. That becomes the fileName
and this becomes the fileFormat
. You will notice that at this stage the packagename
is what it has used to build this name. We are stripping the fileFormat
from that packagename
making sure 01:05:19 that it does not have a fileFormat
in it. To ensure that this file is stored in exactly the format that we detected it to be and not as what they said it is. We move the package. This is where it gets interesting to its final destination. If something fails at this point like it does not move, we remove the package and we say there was an error.01:05:45 We are done. We are not going to worry about it. If it succeeds then if it is an image, at this stage image, we definitely want to resize it. I have a resizeimage
helper Class. This is also something that you would need to write yourself. 01:06:12 It helps me to resize my image. I am passing it some values to target the image and resize it. It does not change anything with the image location or anything like that, I do not need any value back, I just need it to resize it and get it done. It is not necessary to know anything else.
I am doing some encryption to see whether the basic encryption is available in this program. To use that encryption, when I start storing the documents to the database. Here is a local file, and we are checking if it is a document or a media and then encrypt it. Again here we make sure that this ID value is greater than zero.01:07:04 Because if it is still an unsaved item, we do not have any place in the database to add this. We could skip this. If we realize this file or this Upload doesn't have an ID, then we skip this function, and we rather do an image. If it is a document or if it is a media, then we load the filename.01:07:29 We are going to pass it back to the view, taking the results as you see here formats, it got a 'lock
' value and a 'token
' and 01:07:46 'link
'. It has different behavior for different things. It all builds this result array and this is what we give them back. It gets started over here(see video). The fileformat is added, success gets the filename
which is this value here. Then we start building some other things which are necessary. 01:08:10 Like the 'tokenLink
' for the 'link
' as you want to have it downloadable, if it is media or document. If it is an image, we do not need any of this. We can skip that. Then the 'keyName
'. We are done. Whereas it is a safe item, we are going to update the database, 01:08:35 with this new 'targetType
' and 'target
'.
Remember I said that there is some convention in the hidden field name. Well, this is where that convention comes into play. The hidden field name is build up from 'target
' and 'targetType
'. If these two are not correct we are not going to save this value at all. We are building an object which then we will take, since we have validated that this is definitely the allowed view, and this object and ID, then we update the database. We are done. 01:09:13 We have the 'fileName
' and we are going to pass the 'fileName
' here in the same way, and return to the browser. That is the server side of this implementation. There are some things which I have not explained. 01:09:33 Like this resizing of the image. I did not give much explanation. 'GetFolderPath
', you do not need to write that all. You could make this work without knowing those things. 01:09:48 You could put a hardcoded path here as the filePath
. It is not necessary to do any cropping, let the user make sure about the cropping. 01:10:01 That is how I upload many of my documents and things. This is constantly improving because I am using the snippet across multiple places. It is very easy for me to come in here and say; this is not ideal and then fix it.01:10:17 Then I fix it everywhere for every place it has been used. There is sometimes the need for decoupling some of these functions in some, but I am trying to avoid that.
'setFileNameArray
' is another function that you saw in the upload where is it 'setFileNameArray
'. This 'setFileNameArray
' is key when you realize that the actual file already exists because the ID is there. That means that there are other files possibly still already in the database. With the add and basic view, we trigger the 'setFileNameArray
' function to check the database 01:11:16 for that specific target field, get the values, encrypt them, load new values to that and then pass it back to us. Where if the item does not exist, that means it does not have an ID. Remember when we 01:11:35 did some demonstration, I was adding multiple media files that only one ended up being remembered, that is sort of the downside of the current implementation. If the ID does not exist, we are not able to keep track of that. 01:11:55 It is only when the ID exists, that we are able to do multiple uploads at once.
Once you have saved the item, you are ready to expand upon it and to allow multiple upload at once. The 'setFileNameArray
' is dealing when you are having multiple. You'll see there are image
and document
. When the file I am using is plural, it tells me that it should allow multiple. 01:12:32 If it's singular, image
and document
, then I do not allow multiple. I am just going to remove the old one and add the new one. When it is plural, we are using the 'setFileNameArray
', and we are building it to be multiple.
One thing I did not emphasize here, is that we remove the files as well. There is a 'removeFile
'. It also at some point does a validation to check whether the user has the permission to remove files. It will remove the file. It also uses 01:13:23 this 'setFileNameArray
', but then it passes the remove variable to it which then means the action is not to add but to take away. You will see the action and the Add and the takeaway option. It behaves a little bit different. 01:13:41 We still get back the array, we still build an object, and we still updated the database, as well as removing the file. All of this code I will dump on GitHub and the gits for you to reuse as you see fit. You will obviously have to adapt it and keep it under an open-source license. That is the only requirement. 01:14:14 If all those things line-up and are in place, we return to our Admin View. 'CUSTOMCODE=phpAjaxUploader
' needs to be there. These things need to be here(see video). You could pause the video and make sure that you have the same kind of Ajax query calls option. Here I am doing some opening of the files. You will see that I'm building what I have called 'links
'. It is going a little beyond to show you a little bit of my implementation and these links eventually end up on the page. Return to our JavaScript, and scroll down, we will see this 'getFiledJS
'.
Let's again look at that 'getFileJS
'. You will see that those links come into play. You will see that here I have '/load the links to the page
' document links
, and I am adding it to a variable called, 'documentLinks
'. 01:15:37 In the Custom script, 'getFileJS' you will see if I will take this copy and search, you will see that I am using that array and saying,' is this property there?' 01:16:03 and then create a link. That is how we deal with some of that. It works very well, to sort of pass value from JavaScript to PHP, and have it available there.
I know this was a lot of things to take in, and I would expect you to realize that the previous implementation is much easier. But like you have seen when someone does create a document, and they are able to easily drag and drop stuff, it crops it and gives your component a much easier feel to it. 01:16:52 You could still do the old select, but the drag and drop have become quite popular. This implementation is very nice to have. You should be able to get this going in your component. 01:17:14 I am not going to give support on to this, meaning that if you get stuck, you are on your own. You will need to know your JavaScript, and your PHP, and you will need to know how to debug, and how to line-up these concepts that they all 01:17:36 I work in synergy together. It is not going to be easy for me to do that, especially since I do not see the code. But if there is not any of the code that I have share on Gits, which I will also put in the description below this video. Even if that code has issues in it, 01:17:57 or errors that are a very big problem or something. Then please do feel free to give me a heads up over there. We can collaborate and improve it as necessary. At the end of the day, this feature is way behind what you really need. 01:18:19 There is a media manager in Joomla which is ideal. The advantage of this way is that your user is never going to interfere with other users documents or images or stuff. If you use this concept, they will not ever go to look on your server at a list and select stuff. This is why I think people would like this, 01:18:43 because they can upload stuff in and it does not affect other people. It does not make you more vulnerable as the owner of the system or who uses the application, it is a better approach. But like I said there is a Media Manager. If you go to content, there is a Media Manager and a media file type which 01:19:07 works very well, and you can also add this kind of functionality to your component, if this is a little bit too a big of a challenge to you.
- Home
- Beta Testing
- Custom Code
- PHP Settings
- Demo Component
-
Tutorials
- Hello World JCB
- Intro JCB Guide
- JCB Installation Steps
- Planning Components
- Field Type Overview
- Basic Fields Creation
- Admin View Management
- Advanced Field Usage
- Admin Component Integration
- Component Setting Customization
- Scripting Components
- Component FTP Options
- Dynamic Get Method
- Site View DynamicGet
- Site View Templates
- Template Setup Guide
- Layout Configuration Steps
- Custom Admin Management
- Adding Site Views
- Custom Admin Integration
- MySQL Demo Tweaking
- Global JCB Settings
- Custom Time Field
- User Helper Integration
- Email Helper Usage
- Message Store Email
- List View Unescape
- Export Import Customization
- Overwrite Custom Fields
- List Field Filtering
- Automatic Code Import
- Manual Code Implementation
- Component Export Import
- Custom Admin Buttons
- Translation Management
- Site View Permissions
- Component SQL Updates
- Site Edit Configuration
- JCB Backup System
- Helper Structure Integration
- JCB v2.5 Upgrade
- Tab Setup Guide
- JCB v2.6 Release
- Extended HelloWorld
- Field Rule Validation
- Community Snippets Intro
- Snippet Forking Tutorial
- Pull Request Snippets
- Library Manager Area
- Excel-based Translation
- Dynamic Router Details
- Database Auto Updates
- Subform Quick Demo
- VDM Package Import
- Dynamic File Inclusion
- File Field Upload
- Drag-n-Drop Upload
- Quick HelloWorld JCB
- Non-database Fields
- Dashboard Customization
- Menu Prefix Toggle
- Community JCB Packages
- Collaborative JCB Workflow
- JCB Package Install
- JCB JAB18 Event
- Convenient New Fields
- Component Language Strings
- Library Functionality Anticipation
- Join Field Relations
- License Template Change
- Code Reusability
- Local Dev Environment
- Extended Field Types
- Joomla Custom Fields
- Custom Field Expansion
- Site View Listing
- Run Expansion Method
- Form Site View
- Field URL Update
- Additional Helper Methods
- Field Validation Rules
- New Placeholder Feature
- Component Config Params
- Per-field Default Values