A simple and customizable jQuery file manager, image picker and media gallery.

Includes full source, both frontend and backend (PHP)

Demo

In order to demo this gallery/image-picker I have used the free Oxygen icon set which can be found at https://github.com/pasnox/oxygen-icons-png.

Please note that I do allow live uploads of files, you can try all the features of my plugin right here. That said, please be respectful as to what content you upload here. I periodically wipe it clean and restore the sample data from oxygen, but if you encounter offensive images uploaded by other users I apologize, let me know and I will sanitize it.

About VanillaGallery

The VanillaGallery plugin provides a lightweight, simple, highly customizable image picker, media gallery and file organizer.

It is designed to be easily integrated into your webapp, and for simple implementations it comes with a ready-to-use PHP backend.

Work on the VanillaGallery jQuery plugin begun when I was developing a larger webApp and couldn't find any image picker (insert-image function) to suit my needs. I needed a light-weight, simple, customizable grid view of images (and later other filetypes) with the capability of organizing into a folder tree structure. Another requirement was searchability and possibility to upload images and then pick them to streamline the workflow.

Key features

  • List files/images from your filesystem OR a virtual filesystem provided by your own backend
  • Organize your files into a directory tree structure
  • Modify that tree structure or rename your files & folders
  • Filter on what types of files to display (directories, images, movies, audio, easily add your own types!)
  • Search your gallery by filename, filter the output as above
  • Really simple css, easy to customize
  • File picker (populate a form field of your choice with the id/path of the clicked file)
  • Smooth workflow - gallery updates on upload, so you can upload a file and instantly use it.
  • Optional image thumb for faster loading
  • Multiple instances of galleries with individual settings working independently

Getting started

To create a vanillaGallery instance like the one above, follow these four simple steps:

  1. Add these lines to your page (stylesheets usually go in your <head> and your scripts usually go at the bottom of the <body>.
  2. <link rel="stylesheet" href="plugins/vanillaGallery/themes/trueVanilla/styles.css?v=1.0">
    <script src="plugins/vanillaGallery/js/vanillaGallery.js"></script>
  3. Add the corresponding files to your project (note that the entire directory of your chosen themes must be added since there are a few image files to go along with it)
  4. Create a div that will hold a vanillaGallery instance
    <div id="VanillaGallery1"></div>
  5. Write the javascript to initialize your div as a vanillaGallery instance
    <script>
    $('#VanillaGallery1').VanillaGallery({
        //initialized without options
    });
    </script>

Samples

Click the sample name or the form field to display the vanillaGallery, chose an image or click outside the popped-open gallery to close it.

  • Sample1: vanillaGallery without the clickable breadcrumbs bar.
    $('#sample1').VanillaGallery({
        formFieldId: 'vanillaGallery_selectedImageField1',
        title: 'VanillaGallery sample 1',
        breadcrumbsDisplay: false,
    });
  • Sample2: simulating a typical vanillaGallery image picker with smaller thumbs and only displaying file type: image. Also hide the little label on top of the thumb indicating filetype, and hide action buttons (preview and edit) that normally appear on thumb hover.
    $('#sample2').VanillaGallery({
        title: 'VanillaGallery sample 2',
        filterDisplay: false, //hides the file type checkboxes from the top right corner
        filter: ["IMG"], //use ["IMG","DIR"] to display folders in the main area as well
        thumbnailSize: 60,
        labelDisplay: false, //hides the label on top of the thumbnail saying "IMG", "DIR" etc.
        actionsDisplay: false, //hides the preview- and edit buttons that normally appear upon hovering a thumbnail
    });
  • Sample3: bigger vanillaGallery with larger thumbs, wider sidebar and hiding both title bar and breadcrumbs, and showing the file type extension in the file name.
    $('#sample3').VanillaGallery({
        titleDisplay: false, //hides the title bar and thus also the filter buttons
        breadcrumbsDisplay: false, //hides the breadcrumbs
        thumbnailSize: 130, //larger thumbnails
        galleryHeight: 600,
        galleryWidth: 900,
        sidebarWidth: 300, //wider sidebar
        fileTitleExtension: true, //show the file type extension in the file name
    });
  • Sample4: Image name removed, and the label sitting on top of the image will display the actual file type, not just an abstraction to IMG, AUD etc.
    $('#sample4').VanillaGallery({
        fileTitleDisplay: false, //hides the image name that otherwise appears below each thumb
        labelExtension: true, //the label sitting on top of the image will display the actual file type, not just an abstraction to IMG, AUD etc.
    });
  • Please note that in all of the samples above I have omitted the backend connecting property ("pathBase") since in my case it is the default path (which points to http://www.vanillagallery.net/php_sample/). You will have to either specify pathBase upon instantiation of each vanillaGallery object or modify the defaults in your copy of vanillaGallery.js.

Options

As you have seen in the demo above, you don't need to specify any options, provided that you backend is set up according to the defaults. However, you probably want to customize the display and behavior of your vanillaGallery.

As you can see below, most of the "options" are strings that allow you to customize the language of the UI. Some are for the styling I couldn't do arbitrarily in css (ie. gallery height/width, breadcrumbsHeight etc.) and some are true/false flags for features. See samples below.

<script>
$('#VanillaGallery1').VanillaGallery({

    //Backend connections
    pathBase : "http://www.vanillagallery.net/php_sample/", //Basepath for routes below
    pathAllGet: "index.php", //serverside script/route to fetch the entire gallery contents
    pathUpload: "index.php?resource=upload", //serverside script/route to handle file uploads
    pathCreate: "index.php?resource=create", //serverside script/route to handle folder creation
    pathDelete: "index.php?resource=remove", //serverside script/route to handle file deletion
    pathUpdate: "index.php?resource=update", //serverside script/route to handle file updates


    //ID of Form field to associate picker (click) with
    formFieldId: null, //null by default, impossible to guess. Null means there is no onClick action.
    formFieldPropertyUseId: false, //if false, path to the image will be inserted in the form field upon click. If true, 'id' is instead used (in case you have a DB connected and wish to use the id of the image rather than the path/url)

    //Basic styling
    galleryWidth: 850,
    galleryHeight: 400,
    sidebarWidth: 180, //inside gallery width, not added to it
    thumbnailSize: 80,

    //Breadcrumbs
    breadcrumbsDisplay: true,
    breadcrumbsHeight: 22,
    breadcrumbsDivider: ' / ',
    breadcrumbsSearchLabel: 'Search: ',
    breadcrumbsTypeToSearch: '[Type to search]',

    //Title
    titleDisplay: true,
    titleHeight: 45,
    title: 'VanillaGallery',

    //Sidebar
    addFolderText: '+ Folder',
    rootItemName: 'Root',
    searchPlaceholder: 'Search',
    searchDelay: 250,

    //Image thumbs
    labelDisplay: true, //the top-left corner label for each thumb indicating type of media file (or file extension)
    labelExtension: false, //whether to display the exact file type extension (otherwise an abstraction to IMG, MOV and AUD will be made)
    filter: ["IMG", "MOV", "AUD", "DIR"], //files to display
    filterSelected: false, //init as above, but if set to false all above will be checked.
    filterDisplay: true, //show controls to choose filter or not? (a videopicker would for example be initialized with only MOV in the filter array, and filterDisplay false, in order to hide all videos.)
    displayUnknown: false, //whether to display files that your backend could not classify but left fileClass: FALSE on (IF included, remember there is no filtering for these, they will always be displayed)
    fileTitleDisplay: true, //whether to display the image title below the thumb
    fileTitleExtension: false, //whether to include the filetype extension in the title
    actionsDisplay: true, //whether to display the preview/edit buttons on image thumb hover
    previewText: 'Preview', //mouseover label for the preview icon
    editText: 'Edit', //mouseover label for the edit icon
    iconDIR: 'plugins/vanillaGallery/themes/trueVanilla/img/dir.png',
    iconIMG: 'plugins/vanillaGallery/themes/trueVanilla/img/img.png',
    iconAUD: 'plugins/vanillaGallery/themes/trueVanilla/img/aud.png',
    iconMOV: 'plugins/vanillaGallery/themes/trueVanilla/img/mov.png',
    iconUNKNOWN: 'plugins/vanillaGallery/themes/trueVanilla/img/unknown.png',

    //Overlay
    overlayType: 'mainOverlay', // 'overlay' will use entire gallery's area, 'mainOverlay' will use only main area
    overlayTypePreview: 'overlay', //see above. By default, an image preview uses entire gallery area.
    overlayCloseText: 'X',

    folderCreateHeading: 'Create folder in',
    folderCreateSubmitText: 'Create',
    folderNamePlaceholderText: 'Folder name',
    folderEditText: 'Edit folder',
    folderEditSubmitText: 'Save',

    uploadText: '↑ Upload',
    uploadHeading: 'Upload to',

    editHeading: 'Edit',
    editFolderText: 'folder',
    editFileText: 'file',
    editSubmitText: 'Save',
    deleteText: 'Delete',
 
});
</script>

FAQ

How do I open vanillaGallery when form field is clicked, like in the samples?

You attach a click event to the form field. The exact way of opening vanillaGallery in a popup depends on the popup-plugin you have chosen to go with, but here is how it's done with bPopup:

$("#vanillaGallery_selectedImageField1").click(function(){
    $('#sample1').bPopup();
});

Please note that the reason this works is that my vanillaGallery is wrapped in a DIV with id "sample1" (or it isn't wrapped in that DIV but rather when sample1 is initialized as vanillaGallery, that's when vanillaGallery become wrapped in sample1).

<div id="sample1" class="hideMe"></div>

This is how most popup plugins work - all the content you want inside the popup, you simply put in a DIV, and then you call the initialization method for the popup plugin on that DIV.

Hint - if you wish to avoid the flickering that may occur between page load and plugin initialization (your popup may display on the page for a fraction of a second before it is hidden) you add css to your wrapping div to hide it by default. I put this class on all my wrapping DIVs (sample1, sample2 etc.):

.hideMe {
    display:none;
}

My gallery doesn't close when I choose an image

The way you handle the closing of the dialog is: You attach a change event to the form field that gets populated upon image selection (the form field that you specified with the vanillaGallery option 'formFieldId'). The change event gets triggered when an image is selected in vanillaGallery.

In my Sample 1 above, the form field that vanillaGallery populates is "vanillaGallery_selectedImageField1". This form field will automatically get populated when an image is clicked, but to make the gallery also close I added this:

$('#vanillaGallery_selectedImageField1').change(function(){
    $('#sample1').bPopup().close();
});

Suggested plugins

No need to invent the wheel twice, eyh? If you like jQueryUI you could use that for a popup effect on the image picker.

Personally I prefer the bPopup jQuery plugin (that is also the one I have used for all my demos on this page).

If you have a lot of folders in your VanillaGallery sidebar some treeview plugin could easily be applied to your sidebar.

Drag'n'drop functionality could be added using jQueryUI or a similar library. I have not had the time to integrate that functionality yet.

On my wishlist is an integration with pixlr image editor for a quick and easy image editing function. If only time was had in abundance...

Backend integration

VanillaGallery comes with a sample ready-to-use PHP backend if you want it to work directly against your filesystem. You may modify this according to your needs. Below is also a reference for plugging vanillaGallery in to your database-driven webapp. It's very simple, all you really need to do is accept some POST data from vanillaGallery, and generate a JSON in response as outlined below.

Sample PHP backend

To set up the sample PHP backend, all you need to do is to open your php_sample/index.php and edit the first variable (if you want something else than the default upload folder name or folder icon, go ahead and edit the second and third variable as well):

//Configure YOUR base url
$baseUrl = 'http://www.vanillagallery.net/php_sample'; //url to correspond to the basePath

Make sure you also have the paths set up correctly when instantiating your vanillaGallery with jQuery:

$('#divToBecomeVanillaGallery').VanillaGallery({
    pathBase : "http://www.vanillagallery.net/php_sample/",
    
    // ...other options ...

});

Modifying the sample backend

Don't hesitate to contact me for a quote on customization or integration for your use case!

The best way to understand the backend is to simply read through the code, it is well commented and very simple and straightforward. A few comments nontheless:

  • Creating folders
    • When creating a folder, the form passes two fields. The "parent" field which designates what folder the new folder will be created in will have the string "null" if the new folder is to be created at the top level (in your upload folder's root). Just a heads up that it isn't a null value but the string "null".
    • The sample backend has no validation to check that the chosen parent is a valid folder, it just assumes that the user doesn't meddle with the options box by changing your page's html after it has loaded.
    • The sample only checks the name string for two illegal characters, "/" and ".." so you may want to add some of your own depending on the filesystem you are using (php can be run on windows as well so check your host).
    • The sample does have validation for if the folder you are trying to create already exists, or if the user lacks permission to the filesystem (check chmod).
  • Updating folders or files
    • In the sample, the "entityId" used to uniquely identify the file being updated is the full path to the file. For a database-driven backend this can easily be replaced with the DB id.
    • In addition to the create-validations above, when updating there is also validation to make sure you aren't moving your folder down into a child of the current folder (for obvious reasons, that wouldn't work...)
  • Removing folders or files
    • There is no permission system in the sample, but there is a comment where you could insert such logic.
    • There is validation to check if folder is empty when user tries to delete a folder (by default, a folder must be empty before it can be deleted).
    • As denoted by comments in the php file, you may want to add logics that check whether a file is being used by your webapp before you allow removal (I always have this in my webapps). Since I can't know how to check for that in your webapp, there is no such check by default.

      Don't hesitate to contact me for a quote on customization or integration for your use case!

  • In all above cases, once an operation is performed a new listing of everything in the uploads directory is passed back to the browser as a JSON, and the gallery is updated without a page refresh.
  • Scanning the upload directory
    • The scanning function resides in a separate file (vanillaGalleryScanner.php) and consists of a separate class (VanillaGalleryScanner) which can also be used independently.
    • By default, the scanner ignores files with the name "Thumbs.db" and files beginning with "._" (hidden/system files), you may want to add more rules for ignoring system files on your filesystem.
    • For each file encountered, data is compiled through the function VG_json_encode() and you might want to add additional info about the file here. The data is stored in JSON format in an array containing everything in the scanned folder.
    • VG_json_encode() in turn has a few helper functions (getFileName() and getFileType() ) to split the filename into actual name and filetype extension, and then a third helper function (getFileClass() ) to abstract that filetype extension into a category, by default IMG, AUD or MOV (or DIR). Here you may want to add more fileclasses for abstraction depending on what type of files you intend to use your file gallery/file organizer for.

Database-driven backend

Don't hesitate to contact me for a quote on customization or integration for your use case!

  1. The first thing to remember is to connect the paths in your vanillaGallery instantiation to your own backend paths if you change them from the defaults which are:

        $('#VanillaGallery1').VanillaGallery({
    
            //Backend connections
            pathBase : "http://www.vanillagallery.net/php_sample/", //Basepath for routes below
            pathAllGet: "index.php", //serverside script/route to fetch the entire gallery contents
            pathUpload: "imageUpload.php", //serverside script/route to handle file uploads
            pathCreate: "index.php?resource=create", //serverside script/route to handle folder creation
            pathDelete: "index.php?resource=remove", //serverside script/route to handle file deletion
            pathUpdate: "index.php?resource=update", //serverside script/route to handle file updates
    
        });

  2. The next thing to keep track of is what data is passed to each of these routes, and what data is expected to be passed back to the browser.

    • PathAllGet
      • Backend expects no parameters
      • Backend returns the galleryData-JSON

        The sample below shows only two objects, first a folder called "mimetypes" and second a file called "applicaiotn-epub+zip" located in that folder (you can go to the top of the page and use the search box in the vanillaGallery demo to find them). As you can see, the backend has abstracted the second file into "IMG" since it is a file of type "png".

        In front of every forward slash (/) there is a backslash (\), this is something that PHP does to "escape" the potentially dangerous slash, don't mind that.

        [  
           {  
              "isFolder":true,
              "fileId":"\/mimetypes",
              "name":"mimetypes",
              "fileType":false,
              "fileClass":"DIR",
              "parent":"",
              "path":null,
              "thumb":null
           },
           {  
              "isFolder":false,
              "fileId":"\/mimetypes\/application-epub+zip.png",
              "name":"application-epub+zip",
              "fileType":"png",
              "fileClass":"IMG",
              "parent":"\/mimetypes",
              "path":"http:\/\/www.vanillagallery.net\/php_sample\/uploadedImages\/mimetypes\/application-epub+zip.png",
              "thumb":null
           }
        ]
        
    • PathCreate
      • Backend expects form fields
        • "name"
        • "parent"
      • Backend returns a JSON with three properties:
        • "success" set to 1 or 0
        • "message" with a string to display to the user
        • "gallery" which contains the galleryData-JSON
        In the sample below we created a new folder named "myNewFolder" as stated by the message, and in the property "gallery" we pass the entire galleryData-JSON
        {  
           "success":1,
           "message":"Folder successfully created in \/VanillaGallery.net\/php_sample\/uploadedImages\/MyNewFolder",
           "gallery":[  
              {  
                  "isFolder":false,
                  "fileId":"\/mimetypes\/application-epub+zip.png",
                  "name":"application-epub+zip",
                  "fileType":"png",
                  "fileClass":"IMG",
                  "parent":"\/mimetypes",
                  "path":"http:\/\/www.vanillagallery.net\/php_sample\/uploadedImages\/mimetypes\/application-epub+zip.png",
                  "thumb":null
              },
        
              ... a lot more of those omitted from this sample ...
        
           ]
        }
        
    • PathDelete
      • Backend expects form fields
        • "entityId"
      • Backend returns a JSON with three properties:
        • "success" set to 1 or 0
        • "message" with a string to display to the user
        • "gallery" which contains the galleryData-JSON
        In the sample below we removed the file "plus.png" as stated by the message, and in the property "gallery" we pass the entire galleryData-JSON
        {  
           "success":1,
           "message":"entity \/plus.png was successfully removed!",
           "gallery":[  
              {  
                  "isFolder":false,
                  "fileId":"\/mimetypes\/application-epub+zip.png",
                  "name":"application-epub+zip",
                  "fileType":"png",
                  "fileClass":"IMG",
                  "parent":"\/mimetypes",
                  "path":"http:\/\/www.vanillagallery.net\/php_sample\/uploadedImages\/mimetypes\/application-epub+zip.png",
                  "thumb":null
              },
        
              ... a lot more of those omitted from this sample ...
        
           ]
        }
        
    • PathUpdate
      • Backend expects form fields
        • "entityId"
        • "name"
        • "entityParent"
        • "entityType"
      • Backend returns a JSON with three properties:
        • "success" set to 1 or 0
        • "message" with a string to display to the user
        • "gallery" which contains the galleryData-JSON
        In the sample below we renamed the folder "actions" to "actionz" as stated by the message, and in the property "gallery" we pass the entire galleryData-JSON
        {  
           "success":1,
           "message":"Update of \/actions => \/actionz successful",
           "gallery":[  
              {  
                  "isFolder":false,
                  "fileId":"\/mimetypes\/application-epub+zip.png",
                  "name":"application-epub+zip",
                  "fileType":"png",
                  "fileClass":"IMG",
                  "parent":"\/mimetypes",
                  "path":"http:\/\/www.vanillagallery.net\/php_sample\/uploadedImages\/mimetypes\/application-epub+zip.png",
                  "thumb":null
              },
        
              ... a lot more of those omitted from this sample ...
        
           ]
        }
        
    • PathUpload
      • Backend expects form fields
        • [file]
        • "parent"
      • Backend returns nothing (Immediately after the upload has finished, the gallery is updated by a separate call to the PathAllGet).

  3. That's about it. The comments above (under "Modifying the sample backend") should be helpful in remembering what validations you should use. Some of them will not apply in a database-driven environment (such as checking filename for illegal characters etc. assuming you save the name set by user as string in DB and generate some random value for the actual file to be stored on the filesystem).

License

Sold exclusively at Code Canyon, see product license there.

Contact me

Questions or concerns? Feel free to contact me!

plugins@mattiaswelander.se