2012-04-22
How to: Managing Galleries with MIGX
Some time ago @tlyczko suggested I write a how-to on using MIGX with image Galleries or Sliders. As I'm using MIGX all over the place, I guess it can't hurt to spread the love with this How-To! We'll go over the basics of MIGX and work towards the new slider I recently set up for use in my blog.
Try MoreGallery!
While you can still use MIGX for image galleries, I have recently released MoreGallery, a custom Gallery resource for MODX, as part of my new business modmore. The user experience is significantly better compared to using MIGX, so check it out.
The end-result of what we're doing will be the following slider which you may have seen in my MODX Meetup post recently:
Requirements
- A MODX Revolution site. This one is on 2.1.5, but MODX Revolution 2.2 will work fine..
- The MIGX custom TV input type installed (available via package management or from here).
- A slider or gallery script we'll want to integrate. I went for FlexSlider by WooThemes as it adjusts itself to its containers' width (which is quite important with a responsive design!). It's also quite configurable, supports swiping on smart phones and it looks pretty good out of the box.
- The phpthumbof snippet installed via the Package Manager for autocropping images.
- Some images!
Getting Started
There's a few parts involved. There's the back-end MIGX TV we'll need to set up, and we need to take that data to our front-end to put our slider to work. As this tutorial assumes WooThemes' FlexSlider, we will make sure the markup is exactly what that needs - but it should be easy enough to adapt for other sliders as well.
Step 1: Setting up the MIGX TV to manage Images
Let's start with setting up the TV. The beauty of MIGX is that you can define the fields you want. You should basically see it as a table, and you get to define the headers. In this case, I will want three different fields:
- An image input field to select an image from the file system (or in 2.2, from your media source).
- A simple text input to give a caption / tag-line / description. FlexSlider handles captions quite nicely, so we'll be using that.
- I'm also adding a text input for "Set". As we'll see later, I'm using this to manage an infinite amount of individual sliders which could be added at any point in the resource.
Now let's start creating the TV. Here's a quick slider with an overview of the things you should be seeing (in 2.1-UI style), in case the blurb of text catches you off-guard.
Create a new Template Variable via the left-hand Elements tab, and give it a proper name. I called it mh.images, so if you gave it a different name make sure to replace [[*mh.images]] with the right one further on in the tutorial. On the Input Options tab, choose the "migx" input type drop down. If you're not seeing it there, make sure you have installed the MIGX Package through Package Manager. You will notice that a couple of options have been added to the bottom of the screen, including Form Tabs and Grid Columns. If you're not seeing this and running MODX 2.0, sorry - it's slightly different there and you really should consider updating soon.
Note: Both the Form Tabs and Grid Columns field expect to be fed a valid JSON string. JSON is basically a way of showing objects, arrays or just key -> value combinations in a way that is supported in pretty much any programming language available. There's a technical specification and some examples available on the official JSON website.
Setting the Form Tabs
As the name implies, the form allows different tabs to be used. Every tab has a caption and a number of fields. There are some advanced things you can do with this, though most usages will only use a single tab so we'll keep it at that for now. Here's the Form Tabs JSON I am using:
Let's just briefly go through that per line:
- Line one shows us opening the array of tabs with a square bracket ( [ ), and opening the tab object with the curly bracket ( { ). After that we define our caption option with a value of Image. Note that it is important to use double quotes ( " " ) for both the properties and its values, as single quotes are not according to the spec and can have unexpected results. If you have any double quotes inside any properties or values, escape it with a slash ( \ ). After we defined our caption, we go ahead and start defining the "fields" array by opening it with the square bracket ( [ ).
- We define our first field, the set in this case. The "field" property defines we want to be able of accessing it in the code as "set" - this would be the name part of a regular text input as well. Next we give it a caption of "Set", which will be shown in the form as field label.
- Next we define the description field in the same way.
- Line 4 defines the image. What's special here is that it uses another TV (with the name "image") as input type. This is a very powerful feature of MIGX that allows you to use other TVs to build up your form. In this case, the "image" template variable is really simple. Input type is an image, and in 2.2 you would assign it to the right media source as well. You don't need to link it to a template to make this work. Another way you could use this (which I use in another MIGX powered TV) is to build radio boxes or select boxes.
- Line five closes the fields array. Also note that the last field definition line (image) does not end with a comma - this is important! If you leave a trailing comma in an array it will not be able to process your JSON, and your form would not work.
- Line six closes the tab object as well as the tabs array.
Setting the Grid Columns
The Grid Columns are what builds up the actual table (grid) in the resource's TV panel. You get to define the headers for that grid with the Grid Columns input option.
Here's the (again, JSON) definition I'm use:
Per line:
- Open the array of headers with the square bracket ( [ ), and the first column header object with the curly bracket ( { ).
- We give the header a title of "Set", say it can be sorted (optional), and tell it the dataIndex is "set", which corresponds with the Set Form Tabs definition which had "field":"set".
- End Set / start Description
- Give the header a title of "Description", sortable, and match it with the Descriptions' field with dataIndex.
- End Description / start Image
- Give the header a title of "Image", not sortable, and match it with the Images' field with dataIndex. We also define a renderer which is an ExtJS thing that allows you to change how the value is displayed. In this case, the "this.renderImage" renderer will automatically take the selected image URL, and show a thumbnail for it instead of the url itself.
- End Image object, end headers array.
Step 1a: Fill in some data!
Find some kitty or dog pictures and put them in through the new magical MIGX TV.
Step 2: Take the data to the Front End
Now you could do something funny to your visitors, and just throw your [[*mh.images]] TV somewhere in the template and telling them to imagine it's all images.If I would have done that to you, the example slider would have looked something like this (without the nice indentation I threw in for readability) instead:
Correct, that's a JSON array with our fields and values!
Now, luckily, MIGX comes with a snippet called getImageList which can help you make sense of that JSON. As I'm a developer and it's easier for me to write an 8 line piece of PHP to parse it, I tend to write that 8 line php myself and not use getImageList at all. If you do want to use getImageList, you can find the documation for it here.
Here's the snippet (which I called mh.parseMIGXToGallery) I'm using to generate the markup (from a &tpl chunk) based on the TV data:
That looks easy enough don't you think? Let's just go through it line by line again.
- We take the $input variable (which is populated by the data passed in by &input on the snippet call, more on that later), and parse the JSON into a php array.
- We set up an empty array to hold our output.
- We make sure the $input variable isn't NULL or false, which would mean there was either no JSON passed or it was not valid, as well as we check the $tpl variable (passed from &tpl in the snippet call) isn't empty. If either condition is true we'll return an error "no stuff' which is a hint for you, as content manager, that something's not set up right.
- Next we loop over each item in the $input array as $row.
- We check if the $set variable (which is set by calling &set on the snippet) is set, and if it's not empty we match it against what the value of "set" in the current row is. If it's not the same as what we want, we continue to the next item in the array.
- We get the chunk by the name of $tpl, and inject the values of the current row into it as placeholders.
- We close the foreach loop.
- Finally we glue together the $output array, separating every entry with a simple line break, and return it to the page.
Putting the Snippet to work
Now all we need is a snippet call where we want our images to appear and a chunk that matches the markup required for FlexSlider. Here's how we'd call the snippet:
and the mh.images.gallery.tpl chunk to match what FlexSlider is looking for is as follows:
and we will also need to wrap the entire snippet output in a div with an unordered list, according to the FlexSlider documentation. To make that easier (and a helluva lot more client friendly), is to put all that in a chunk. My chunk is called mh.slider and has the following contents:
With this chunk in place, I can simply reference the following in the content which is much easier to remember or to put on a cheat sheet.
We could also use a TV to have it type in the name of the set (gallery or collection) in a TV which, when filled in, puts that chunk in a predefined place in the template.
Now we've got our raw markup as FlexSlider wants.. but it's not doing much yet. Off to hook up FlexSlider!
Step 3: Hooking up FlexSlider
FlexSlider is relatively easy to use (download its files here), and there's a number of examples on its site to look at if you need help. You will need to include jQuery on the page, as well as its CSS file (found in the zip) and the FlexSlider plugin (also found in the zip). After having done that you will need to initiate it on the right element, using a code like the following:
The website advises to put all of it in the head of the file, though I personally put it in the bottom. If your slider will appear near the top of the page (above the fold), it can be better to put it in the <head> so it loads before the page shows, though that's just a preference.
And that sums it up for this very long article! I hope this how-to can help people getting started with MIGX and galleries like FlexSlider!