Please note: This is an unpublished site and we are making changes - glitches still!!!

The gallery client code.

Please Notice: You must have the Gallery Administration end build before jumping into this part!

Now that we have everything in place at the admin end we have an easy task at the client end. A simple template

{* Gallery Grid template *}
<script type='text/javascript'>
<!--
{literal}
// redirect browser to the selected album
function selectAlbum(element){
   var aid = element.options[element.selectedIndex].value;
   document.location='?act=gallery_simple&aid='+aid;
}
{/literal}
-->
</script>
<h4 style='text-align:center'>
This is a sample of the Photo Gallery currently under development!
</h4>
{if $error ne ""}
    <div class='errormsg'>{$error}</div>
{/if}
{* first the dropdown for album selection *} 
<div class="album_select">
    Select a album  to view
    <select name="album_id" onchange="selectAlbum(this);">
    {foreach from=$albums item=album}
    <option 
      value="{$album.id}"
      {if $album.id eq $aid}selected='selected'{/if} 
      >{$album.name}</option>
    {/foreach}
    </select>
</div>
{* then display the thumbnails *}
{foreach from=$photos item=photo}
<div class="gallery_grid">
  <div>
    <p>{$photo.title}</p>
    <a href='?act=gallery_simple&amp;img_id={$photo.id}'>
        <img 
            src='{$thumbnail_dir}{$photo.imagepath}' 
            title='{$photo.title}' />
        </a>
  </div>
</div>
{/foreach}

The template for showing a single image is very simple. As above we have added an error message div in case something goes wrong.

<div class='gallery_single'>
{if $title ne ""}
   <p>{$title}</p>
{/if}
{if $error ne ""}
    <div class='errormsg'>{$error}</div>
{/if}
<a id="single_image" href='{$imagepath}'><img src='{$imagepath}' 
     width="{$width}" 
     height="{$height}" 
     alt="" /></a>
{if $description ne ""}
   <p class='description'>{$description}</p>
{/if}
<p style='font-size:0.8em'>Click the image to zoom to full size</p>
<p><a href='#' onclick='history.go(-1);'>{$back|default:"Back to list"}</a>
</div>

JavaScript/CSS additions

The FancyBox / JQuery includes must be added to the main template header:

    <script type="text/javascript" src="js/ajaxfuncs.js"></script>
    <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="js/jquery.easing.1.3.js"></script>
    <link rel="stylesheet" href="css/fancybox/jquery.fancybox.css" 
type="text/css" media="screen" />
<script type="text/javascript" src="js/jquery.fancybox-1.2.1.js"></script> <script type="text/javascript">  <!-- {literal} $(document).ready(function() { $("a#single_image").fancybox();   }); {/literal} -->  </script>

And you must, of course, install the respective files.In the example the CSS has been installed in /css/fancybox and the javascript in /js root..

We could (and possibly should) add some template conditional code which would only include the js/css when there is a single image to be displayed.. There is a hint later in the "main template logic" part on this page.

The client module

A relatively module handles both the grid view and the single image view. We could have written two modules but the task being so simple we can combine the two functions into one. As you can see we have added a bit error handling: if either the image id or the album id are non-numeric we assign an error message that is displayed on top of the template. If we are displaying a single image and we have a malformed image id a warning sign is displayed. You must, of course, provide an  'image missing'  image.

<?php
class gallery_simple_module extends CmsModule {
    var $root = "/";
    var $gallery_table = "gallery";
    var $gallery_path = "/gallery/";
    var $thumbnail_path= "/gallery/tn/";
    var $grid_template = "gallery_grid.tpl";
    var $single_template = "gallery_single.tpl";
    // warning sign image
    var $warning_sign = "icon/warning_sign.png";
 
    var $max_width = "500";
    var $default_album=1;
 
    function init(){
        parent::init();
        $this->root = $GLOBALS['cms_config']['root'];
        // max width from globals first
        if ($GLOBALS['cms_config']['gallery_image_max_width'] != "")
            $this->max_width =
                  $GLOBALS['cms_config']['gallery_image_max_width'];
        // can be overridden by template parameters
        if ($this->vars['max_width'] != "")
            $this->max_width = $this->vars['image_max_width'];
        if ($this->vars['warning_sign'] != "")
            $this->warning_sign = $this->vars['warning_sign'];
 
    }
    // get single value from an sql query or false if error or zero lines
    // this function is found in 'utils.php' as well
    function getSQLvalue($sql){
        $result = @mysql_query($sql);
        if (mysql_error()) {
            return false;
        } else {
            if (mysql_num_rows($result)==0) {
                return false;
        } else {
                $row=mysql_fetch_row($result);
                return $row[0];
            }
        }
    }
 
    /**
* Combine showing the image grid and a single image
* to one module due to the simplicity of the task.
*/
function fetch(){ $mySmarty = new Smarty(); // first the single image case: we get the image id in $_GET $error = ''; if ($_GET['img_id'] != ''){ $id=mysql_real_escape_string($_GET['img_id']); // filter out breaking/XSS attempts // more checks needed for error handling, though if (!ctype_digit($id)){ $error = 'Error: image id is not valid'; $mySmarty->assign('imagepath',$this->warning_sign); $mySmarty->assign('error',$error); } else { $query = "SELECT id,imagepath,title,description " . "FROM $this->gallery_table WHERE id=$id"; $result = mysql_query($query); $obj = mysql_fetch_object($result); $abs_image_path = $this->root.$this->gallery_path.$obj->imagepath; $img = imagecreatefromjpeg($abs_image_path); $width = imagesx($img); $height= imagesy($img); // calculate new dimensions if necessary if ($width > $this->max_width){ $proportion = $width / $height; $width = $this->max_width; $height= floor($width / $proportion); } $mySmarty->assign("imagepath",$this->gallery_path. $obj->imagepath); $mySmarty->assign("title",$obj->title); $mySmarty->assign("description",$obj->description); $mySmarty->assign("width",$width); $mySmarty->assign("height",$height); }   return $mySmarty->fetch($this->single_template);   // Then the grid case - show several images } else { // do we have album id in the URL if (isset($_GET['aid'])){ $aid = mysql_real_escape_string($_GET['aid']); // filter out possible breaking attempt if (!ctype_digit($aid)){ $error = "Error: Gallery id '$aid' is not valid"; $mySmarty->assign('error',$error); // get default album $aid = $this->getSQLvalue( "SELECT id FROM gallery_albums " . "WHERE default_album=1"); } if (!($aid > 0)){ // if empty or <= zero get default $aid = $this->getSQLvalue( "SELECT id FROM gallery_albums " . "WHERE default_album=1"); } } else { // get the default album $aid = $this->getSQLvalue( "SELECT id FROM gallery_albums " . "WHERE default_album=1"); } // first get all the images in the album and add to array $query = "SELECT gallery.id, gallery.imagepath, gallery.title " . "FROM images_albums, gallery " . "WHERE images_albums.album_id=$aid " . "AND gallery.id = images_albums.photo_id "; $result = mysql_query($query); $photos = array(); while ($obj = mysql_fetch_object($result)){ $photo = array(); $photo['id'] = $obj->id; $photo['imagepath'] = $obj->imagepath; $photo['title'] = $obj->title; $photos[] = $photo; } // now let's list all the albums that have photos in them // for the dropdown above the image grid $query ="SELECT album_id AS id,name " . "FROM images_albums,gallery_albums " . "WHERE gallery_albums.id=album_id " . "GROUP BY album_id "; $result = mysql_query($query); while ($obj=mysql_fetch_object($result)){ $album = array(); $album['id'] = $obj->id; $album['name'] = $obj->name; $albums[] = $album; } // now we have evetything in place, assign and fetch! $mySmarty->assign("aid",$aid); $mySmarty->assign('photos',$photos); $mySmarty->assign('albums',$albums); $mySmarty->assign("thumbnail_dir",$this->thumbnail_path); return $mySmarty->fetch($this->grid_template); } }   } ?>

Changes in the main template logic

You must add the following code to the conditional chain:

{elseif $smarty.get.act eq "gallery_simple"}
    {cmsmodule name="gallery_simple" path="modules/gallery"} 

and if you wish to have the FancyBox JavaScript/CSS parts only included when we are dealing with a gallery you can add the respective logic around the includes in the <head> section. Something like this might work:

{if $smarty.get.act eq "gallery_simple"}
    <link rel="stylesheet" href="css/fancybox/jquery.fancybox.css" 
type="text/css" media="screen" />
.. add the script inclusion here but do the tinkering yourself... {/if}

The CSS for the gallery

We need to have a nice style sheet, of course and here is a starting point - go ahead and make it nicer:

/**** image gallery definitions ****/

div.gallery_select{
   padding:0.5em 0.5em 0.5em 2em;
   font-weight:bold;
   font-size:1em;
   background-color:#FFF;
   border:1px dotted #888;
}
div.gallery_select select {
  font-weight:bold;
  background-color: #FFF3CF;
}
div.gallery_grid {
    display:inline;
    float: left;
    margin-left: 0px;
    margin-right:0px;
    width: 190px;
    height:180px;
    margin-bottom: 10px;
    border:0px dotted;  
}
div.gallery_grid p {
   text-align:center;
   font-weight:bold;
   line-height: 90%;
   margin-bottom:5px;
}
div.gallery_grid img, div.gallery_single img {
    display: block;
    border: 1px solid #000;
    margin-left:auto;
    margin-right: auto;
}
div.gallery_grid a, div.gallery_grid a:hover,
div.gallery_single a, div.gallery_single a:hover {
    border: 0px solid #000;
}
div.gallery_single p{
   display:block;
   font-weight:bold;
   text-align:center;
}

div.gallery_single p.description {
  text-align:left;
  font-weight:normal;
  margin-left:30px;
  margin-right:30px;
}

Things to do

Now that we have the information in the database we can add a simple text search facility to filter the images. That part will be added in  the future, hopefully.