Creating Plugins for Easy 2 Gallery

The Easy 2 Gallery is a gallery module that has an almost alarming number of features, and its management module is an application all in itself. One of its most interesting features is a built-in commenting feature. But it's not limited to what it comes with. It was designed with hooks for custom plugins, so you can add your own features. I wanted to replace the default comment button (which displays a small button with the number of comments for the image and opens up an AJAX-based comment list with form) with just a button to allow visitors to vote for their favorite image. No form, no list, just the button with the number of votes the item has received. Click the button to vote for the item. This meant that I first disabled the commenting function in the module's Settings.

Disable Commenting

The Plugin

This turned out to be even easier than I had hoped. All you have to do is create a folder in the assets/libs/plugins folder for your plugin, and have an index.php file with your plugin code to set up your plugin. E2G comes with a sample plugin called "test", but I based my voting plugin on Goldsky's Facebook Like plugin.

I created a folder "voting" in the assets/libs directory, then created my plugin's index.php file and put it in the assets/libs/voting folder.

<?php
if (!isset($e2gEvtName)) return;

// set up javascript
$modx->regClientScript('assets/libs/plugins/voting/voting.js');

$table = $modx->getFullTableName('easy2_votes');
// create table if it doesn't exist - comment this out after successful first run
$modx->db->query("CREATE TABLE IF NOT EXISTS ".$table." 
        (pic_id INT(10) NOT NULL PRIMARY KEY, 
         num_votes INT(10) NOT NULL DEFAULT '0')");

switch ($e2gEvtName) {
    case 'OnE2GWebThumbRender':
// fetch vote data
foreach($e2gEvtParams as $pic) {
    $res = $modx->db->select('num_votes', $table, 'pic_id = ' . $e2gEvtParams['id']);
    $votes = $modx->db->getValue($res);
    $votes = $votes ? $votes : 0;
    $e2gEvtParams['votes'] = $votes;
}

// load the display of the plugin for each item
        echo '' . $e2gEvtParams['votes'] . '';
        break;
    default:
        break;
}
?>

Note - I already had the jQuery library, assets/js/jquery-1.6.1.min.js, loaded in my template head, since I tend to use a lot of jquery in all of my pages. This also means I have QuickManager configured to not load jquery in the front-end, as it is perfectly happy to use this library.

The Javascript

Thanks to JQuery, voting.js is really short and simple. I put it in a file voting.js in the assets/libs/voting directory, then used the regClientScript API function in the plugin code to load it into the page.

(function($) {
        $(".vote").click( function() {
            var pid = this.id;
            var data = {'vfid' : pid};
            $('#'+pid).load('add-votes.html', data);
        });    
})(jQuery);

This just sends the ID of the image voted for to the AJAX processor; in this case a MODx resource with a snippet. The trigger is the span I used in the plugin code above.

The AJAX Processor

As I prefer to do, I used a MODx resource with a 'blank' template, and only a snippet call [[process-vote]] as its content. It has to be published, but all the other settings are cleared.

The URL to this resource is what is used in the javascript AJAX request; in my case I gave the resource the alias 'add-votes', so the URL was 'add-votes.html'.

The process-vote snippet contains the code to process the AJAX request, and returns the updated number of votes for the item. The JQuery load() function was applied to the same button that was clicked on, so the snippet's return value is automatically loaded into it.

<?php
/ AJAX processor for easy2 votes
// Use in empty resource with blank template
// use the resource URL as the AJAX URL

$id = ltrim($_POST['vfid'], 'vfid_'); // clean the clicked item's ID
$ip = $_SERVER["REMOTE_ADDR"];
$table = $modx->getFullTableName('easy2_votes');
$sql = '
    INSERT INTO ' . $table . ' (pic_id, num_votes) 
    VALUES (' . $id . ', 1)
    ON DUPLICATE KEY UPDATE num_votes=num_votes+1
';
$modx->db->query($sql);
$res = $modx->db->select('num_votes', $table, 'pic_id = ' . $id);
$votes = $modx->db->getValue($res);
echo $votes;

The IP address will be used to control multiple votes; in Petshop's case there will be new voting every month or so, and the IP address and the date of the vote will be stored (actually, easy2 already has a table with all the data necessary for this, so I'll just use that) and the IP will be checked before the vote count is updated. That's not implemented yet; I'll add to this article once it is.

I used the INSERT INTO ... ON DUPLICATE KEY UPDATE query because initially the item voted for won't have an entry in the table. The first vote has to be an insert, then subsequent votes are just increments of the num_votes value. It's much more efficient to let MySQL deal with whether or not the item has an entry.

The CSS

Next we want to style the voting button.

.vote {
    display: block;
    position: absolute;
    right: 6px;
    bottom: 0px;
    height:1.2em;
    line-height:1.2em;
    text-align: center;
    padding:1px 4px;
    color: #beb934;
    border:1px solid #b7be54;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    cursor:pointer;
    cursor:hand;
}
.vote:after {
    content:" Votes";
}

The color and borders are of course specific to the template being used; it can even be given a background image if preferred. The important part is the first half, the positioning and sizing of the span that will be the voting "button". If you prefer, you can position it elsewhere in the thumbnail's display. The positioning probably also depends somewhat on the particular gallery display you use. The "Votes" content will appear inside the button's borders after the number of votes (at least in Firefox; other browsers may not handle the :after selector in the same way). You can put this in your general .css file, or create a specific .css file to load. I preferred to simply add it to my usual .css file since it's only a couple of lines and it would be more time-consuming for the browser to request, download and apply a separate .css file.

Register the Plugin

And finally, go to the Easy2 module and its Plugins menu, and register the plugin. Disable it unless you want it to run by default on all E2G gallery displays. The snippet &plugin parameter will override this setting for individual gallery displays.

Register Easy2Gallery plugin

The Snippet

The snippet call for the gallery display using the &plugin parameter:

[!easy2? &gid=`2` &plugin=`thumb: voting#render`!]

This usage of the &plugin parameter takes three attributes, the item to apply it to (thumb), the name of the plugin (voting), and the event applicable to the item to use (render; for the OnE2GWebThumbRender event).

And there you have it; with Easy 2 Gallery it really is easy to customize your gallery with your own plugins. See it in action here.