-
-
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 to 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. There's in the Custom Buttons area, there is the getVDM which I have explained. Again we have some custom script. That's all that we have there. In the JavaScript area, we again have setfile which is part of the script that will have to look at. You will see I'm using setfile on 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'll go and look at those individual concepts. We are also going to see, like I said previously notes. 00:18:56 There is the Main Media Uploader note and the Main Document Uploader note and the Document Image Uploader note. This is where I've 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 00:19:26 the Main Document key and the Main Media key. All of these are hidden fields which is where we store these values. 00:19:40 We'll look at that as well.
Let's go and see the code that is used. Let's start in the interface. Let's first look at one of these Uploading Concepts. But since I know what's happening there, I am already aware that the code is not there. It's also custom Placeholder snippet. Before we dive in, let me open the custom code area and go back into documents. We can go 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, we have a div all the way down there(see video). Which has an id It has the class for the placeholder, some icons. 00:20:52 You'll see that I again have here upload your documents. I've got a span tag, that says main documents formats. It's going to be the place where we load the formats with JavaScript. Select the file from your computer. It's this snippet with a little bit of extra 00:21:29 flavor. That's all we are looking at. There are some conventions, like main documents uploader, that again upload-drop-main-documents. There are conventions which if we go over the code, eventually you'll see that those conventions is what really makes 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. We can open uikitFileUploader. This is the code that gets added. It 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 I showed you, we set it in the global settings. We are saying document is the first parameter we are passing. 00:22:45 We are saying document formats, and we are getting 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 is the first argument because we counting from 00:23:16 zero. 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's targeting it here saying that's the progressbar we are going to use.
Then it have some settings. The settings is the action, we are using JRouter. JRouter is a little JavaScript trick that I wrote because often times you have this Site View or the Admin View in the back-end and in the front-end. This takes care of whether it's a back-end or front-end call, that it executes it correctly. That is your component name. The [arg1] again would be the second argument, which is in our case 00:24:52 documents. 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 which is being used to identify the view. It's making a query on this area. It 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. Again we have other. 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 third and the second argument 00:26:16 formats, which would be documents and main. If we look at our div, we will see the formOk so tats is documents-main-formats, it's targeting this span tag, basically adding it in there. That is adding the formats html to this id.
Then if we've detected that you don't have any formats 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 displays behavior on that page.
That is the reusable snippet. I'm reusing this same snippet uikitFileUploader for various areas. If we were to close out here, and I was then to open the Media Note, You'll see that it's really just using the same snippet. If you go to Script, you will see it's the same snippet. 00:27:47 I'm changing the variables I'm passing, it is saying media-media-main. Where's the other one was saying document-documents-main. The same goes with the image. The image we also have that kind of behavior. It says uikitImageUploader, this one is not using the FileUploader, it's 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 there 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 are behaving the similar way 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 is required, use this + to pass it.
And the div looks very similar except that it now would say images. And images you will see there it's using different placeholders. You need to update those accordingly as it's needed. That's to set up the field. 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 if I was to take one of the hidden fields, let's say the Documents Hidden field, you'll see there is some naming conventions that you need to follow. It says main-documents, it doesn't say documents. You'll see when we add the value back to the page, we're able to target it based on these naming conventions. That's quite important.
Then for some security, which is a little extra layer. Like the one guy said, that it's not that we can really stop them, we can just make it very hard. There are different encryption options. This medium encryption (local-file-key) is better than the basic. The basic stores the key in the database, which in that case means that if somebody swiped 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. Specially 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 let's say 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's 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're 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 has told you it's done, everything is good. You can do some house cleaning in the browser. That's what we doing. We're checking if it's done, we take away the progressbar, and if it has an error, we pop out the errors and alert. If it's successful, because we decide what this response going to be. So we will decide to give a successful 00:33:43 value in the array. 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 that you see is being added. It's quite a lot of code, but it's all being added to the Admin View and it can be used for different Admin Views, 00:34:13 if it's dealing with either images, documents, or media. I'm not going to try and explain all this, it is almost as if I'm going to end up teaching you some JavaScript.
The JavaScript does some checking and validating. I'll just put it out there and when it discovers that everything is fine the file was added. Then it goes ahead, it's checking the length of the filename, see if the 'currentFileName' length is not greater than 20. If it's not an image or a document, then it must be removed. The return values are here quite key. To make sure that we have this remove file from server function in place where I showed you in the Admin 00:35:21 View where we've these remove file tasks and methods. It's querying the removeFile. It's passing all the necessary variables 00:35:42 to remove the correct file. It's also checking if a person who is trying to remove the files, is a logged in user, and on the file where we will look at in a moment, at the actual PHP. Which will again validate that the user has permission to remove the file. There are all these checks and balances across every step of the this implementation. By now you might realize this implementation is far more complicated than the normal file upload, that's simple. This really gets into the nitty gritty of some of these things, because you want to give a real easy 00:36:32 behavior for your user. But that will mean that you need to do more them and protect them. So they would not become vulnerable at any time. Once we are satisfied that the file is correct and it doesn't need to be removed, we trigger 00:36:55 a few things which puts the file in 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've dragged and dropped it on the page, boom, it shows in the page once it's on the server. It's doing a little bit of checking to make sure their are all good, everything's fine. We end up with what we now 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's going to determine what kind of target it is and get the format, get the this, get the that. We can build the 'filename' correctly. I've got some functions which you may not need, 00:38:02 I mean you can look through this and decide what to keep, what to through out. 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, let's go back to the JavaScript. We've the 'setFile' 00:38:38 and we have the 'getFile'. The 'getFile' is getting another layer of validation and also make sure that everything is behaving as we would want and expect it to behave. The rest of the snippet is a 'removefile', and 'isJsonString'. We also have a little snippet to check if it's a JsonString 00:39:05 and if it's empty. It's all part of sanitizing and validating and making sure everything is the way we expect.
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 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 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 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 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 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 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 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 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 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 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.
Let me demonstrate in our little new document some of these function which I now explained, and do exactly what it does. I've got a bunch of images, it is generic open source kind of images. I'm just going to grab one and dump it in Upload your image. You didn't see that, let me scroll down get that image, put it down a little lower, let me get another one. Let's use this house. 00:43:50 I'm going to drag it there and highlights it for a moment. It has this little Uploader because we are on local network. It's very fast. When it started it says 'Your doc images is set'. That was built by JavaScript. There is the document 00:44:10 image on display. There is 'Remove document image'. I can click that and it'll tell me are you sure you wanted to leave this document? Yes, and boom it gone. We back at Square One as if we had nothing. 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. Let me just get a document. We 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 00:45:10 copy. Put it in the description if you want. You could test it. What is noteworthy here? Is that the name of the document doesn't get lost, while 00:45:25 the place where the documents are added, is in the same folder. You could add multiple documents to this document. I'll just keep on stacking them though they even 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. Same with the image, if we were to inspect the image, you'll see 00:46:12 that the image have this huge name: /doc_image_jpegxxxxxxxxxxxxxxxxxxxxxxxxxisland jpeg. So it's no longer than same name as the one you uploaded. It changes it and preserve the name for example in the documents option. That you giving to someone the document they have, what you expect. We do 00:46:38 adapt the names for security, that you can't 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, you will see, you can't see that. I'll just show you. I have copy the link, it's a little huge because we are using 00:47:25 an encrypted path to the file. 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, I will show you how this download document 00:47:54 concept works, but you'll need to write that. You need to figure that one out. That's unto you, that's if you want people to download your documents. If it's just to upload images of course 00:48:09 you don't need any of this. But it is only when you are going to have a downloadable file or media.
Next one we wanted to show you here, is to upload some media file. I have a bunch of audio files, and I'm going to upload them. What I'm going to do is, I'm going to select a whole bunch of them, and then upload them all at once. This is what the Uploader can do. Let me see, there we go drop it there, I can't see it yet, but it's uploading. I need to refresh the page. Let's give it a name. 00:49:01 The Document. In Description say: More Soon. Save this. It didn't upload all of them. Interesting. 00:49:24 Let me try again. I've got 6 of them uploaded. I can see 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. We see that the media is working. Let's also do that with documents. Let's add some more documents. 00:49:57 I've got a few selected and drag and drop them there. 123 and is uploaded. I need to check some of the JavaScript. I see it didn't add the download button. Without saving, if we refresh the page, you'll 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 00:50:31 documents to one document, and multiple media files. To be able to test them in the back-end, if you wanted 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'll be able to use the file names, and the user would be able to identify this is what I want. 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 look at it a little more. That is seeing our drag and drop options in action.
Now let's go look at the server side of this implementation. The server side we have in the documents Admin View. We're opening the PHP tab, have this Ajax area. Like I showed before you would need to set up the Ajax in 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. Make this method available to the Ajax call. There are some values that we set because every component I used, this stuff is different. For some we're using images, documents and media as the types. For some 00:52:23 target the main and doc. The allowedView, there's 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 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. Little extra little gymnastics to add another layer there.
We are going to look at this phpAjaxUploader in the custom codes area. Let's Search for it in the custom code area. Why am I using custom code? Because I'm reusing this. At the moment it doesn't look like I'm reusing it many places, it only says it's used in component. This is not the area where I'm doing my work, this is just for tutorials. I'm using a whole different developing environment 00:53:33 or rather a developing system Joomla website than this one. This one is explaining and demonstrating. I'm 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. 00:53:57 Media formats that are allowed in the system. You can adapt this to whatever you need. At the end of the day it is up to you to decide what you want to allow and what you wouldn't. The reality is this is the available formats. If you 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. We manually added this 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. I'm going to close out, I don't want to do Hello World, I can show you with the Document Manager. We could use the same button in settings. We can edit if it hasn't have one, you can create one. You select fields 00:55:50 with their custom values and the tabs in which they should be display. As you can see I've selected Allowed Document Formats(list), which is just a list of the formats and I set it to allow multiple selection. That's how I'm doing this Allowed Media, Allowed Image, and Allowed Documents. Then here's 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. I'm not going to explain that now. That's how we deal with that and that list we have looked at now 00:56:29 is the same list as what we see here. 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 as available formats, and then those drop downs is what you as the owner of this website, where this application will run, is what you will allow. This list should be the same as the one there, but it also is going to be use if people post a specific type, 00:57:38 as if it is allowed. We're 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, checking 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 'allowedView' is documents. That's why I'm saying I'm setting that outside of 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, What is the format that we are talking about? That is the formats that we allow, the types, because we want to 00:59:17 validate that the person and who is uploading the things, we anticipate. It is setting the format with the type. If it's image it will be images. If it's images it will be image. If it's document it will be document, if it's documents it'll be document, and media will be media. That's the types and we are setting that is the formatType.
Then we are using a function getPackage from upload. now if you watch the previous tutorial of using the file type uploader, Then it's more or less the same kind of functio. If I scroll down, 01:00:02 We'll find 'getPackageFromUpload. The only differences we are doing the application at get and the input in the function. We are targeting files because we are passing those values in the files place. We are seeing what is the file. We are checking whether these things are allowed: warning, import file error. This kind of error, you'll see I'm not throwing it to Joomla, I'm adding it to the error message. 01:00:35 Because we are grab the value and say we are done here get out of here, if we are still going and you could go through this. the same implementation than the one we've demonstrated. The only difference though is our check method. It is a little bit more taking that view 01:01:12 and validating it. We are doing a 2nd layer of validation. Then checking 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 can 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 use some of these codes. That's all the same I'm not going to go into depth. If you don't understand what I've just looked at here then please go back to the 01:01:56 the previous tutorial, watch that. It gives you enough information. 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 in the the previous here. I'm using a function uploadNow. In the uploadNow function, we are returning and if any error still remains, it's going to be doubt here. Where as errors that might have a occurred here, if this was false, we would use that. 01:02:36 That's the error message put it in error and pass it out. If we having any other issues, we will seen there has been an error and will pass it out, there is this error handling there.
Now in uploadPackage, we are checking whether the package is there, the package name and we're starting from that, we are building the name. Now remember I showed you or explain 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 Now I'm 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'm using a little placeholder which is little generic placeholder VDM. I'm adding 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. If it's a document 01:03:56 we are going to need the folderpath for hiddenFilePath. Again getFolderPath is a function which I wrote. I'm 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 don't pass any values like in this case, 01:04:28 it most probably return a public path. It would be where the images go. Every documents go in a hidden area, images go public. Usually the image you wanted to load somewhere, you don't want 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's used to build this name. We are stripping the fileFormat from that packagename making sure 01:05:19 that it doesn't have a fileFormat in it. To ensure that this file is stored in exactly the format, we detected as and not as what I 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 doesn't move, 01:05:45 we remove the package and we say there was an error. We are done. We are not going to worry about it. If it succeeds then if it's an image, at this stage image, we definitely want to resize it. I've a resize image 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 doesn't change anything with the image location or anything like that, I don't need any value back, I just need it to resize it and get it done. I don't need to know anything else.
I'm 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's a document or a media. We are going to encrypt it. Again here we make sure that this ID value 01:07:04 is greater than zero. Because if it's still a unsaved item, we don't 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's a document or if it's a media, 01:07:29 then we load the filename. We are going to pass it back to the view, taking the results as you see here formats, it's 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'. Because you want to have it downloadable, if it is media or document. If it's an image, we don't need any of this. We can skip that. Then the 'keyName'. We are done. Where as it is a safe item, we are going to update the database, 01:08:35 with this new 'targetType' and 'target'.
This is where the hidden field name, remember I said to you there's some convention in the hidden field name. Well this is where that convention comes into to 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 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're done. 01:09:13 We've the 'fileName' and we are going to pass the 'fileName' here in the same way, and return to the browser. That's the service side of this implementation. There are some things which I haven't explained. Like 01:09:33 this resizing of the image. I didn't give much explanation. 'GetFolderPath' you don't need to write that all up. You could make this work without knowing those things. 01:09:48 You could put a hardcoded path here as the filePath. You will not have 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'm using the snippet across multiple places. It's very easy for me to come in here and say oh this is not 01:10:17 ideal and then fix it. Then I it fix it everywhere for every place it's been used. There is sometimes the need of decoupling some of these functions in some, but I'm trying to do as much as I can to not to that.
'setFileNameArray' is another function that you saw in the upload where is it 'setFileNameArray'. This 'setFileNameArray' is a 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 doesn't exist, that means it doesn't have an ID, I don't know if you 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 doesn't exist, we're not able to keep track of that. 01:11:55 It's only when the ID exist, that we are able to do multiple uploads at once.
I should give a little bit heads up about that. Once you have save the item, you're 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 is image and document. When the file I'm using is plural, it tells me that it should allow multiple. 01:12:32 If it's singular, image and document, then I don't allow multiple. I'm just going to remove the old one, and add the new, done. When it is plural, we are using the 'setFileNameArray', and we are building it to be multiple.
One thing I didn't 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's 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 take away 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'll obviously have to Adapt it, And Keep it under an open source licence. That's Only requirement. 01:14:14 That if all those things line-up and are in place, going back to our Admin View. 'CUSTOMCODE=phpAjaxUploader' needs to be there. These things need to be here(see video). You could pause the video 01:14:31 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 showing you a little bit of my implementation and these links eventually end up on the page. We've go back to our JavaScript, and scroll down, we will see this 'getFiledJS'.
Let's again look at that 'getFileJS'. You'll see that those links come in to play. You will see that here I have 'load the links to the page' document links, and I'm adding it to a variable called 'documentLinks'. 01:15:37 In the Custom script, 'getFileJS' you'll see if I'll take this copy and search, you'll see that I'm using that array and saying, is this property there? 01:16:03 And then creating 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 01:16:22 things to take in, and I would expect you to realize that the previous implementation is much easier. But like you've 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 Instead of the old you could still do the old select, but the drag and drop has become quite popular. This implementation is very nice to have. I'm sure from what I've shown you, you should be able to get this going in your component. 01:17:14 I'm 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's not going to be easy for me to do that, especially since I do not see the code. But if there isn't any of the code that I've 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'll collaborate and improve it as necessary. At the end of the day this feature is way behind what 01:18:19 you really need. There is a media manager in Joomla which is ideal. The advantage about 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 going 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 doesn't affect other people. It doesn't 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 can also add these kind of functionality to your component, if this is a little bit too a big of a challenge for 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