gallery plugin by Andreas Gohr
This Syntax Plugin allows you to embed an automatically created image gallery into a page.
Last updated on 2009-06-27. Provides Syntax.
Compatible with DokuWiki 2009-02-14.
Conflicts with galleryv1.5!
Similar to gallery2, galleryv1.5, jalbum.
Use the following link in the plugin manager or to download the plugin manually.
A basic gallery can be added by selecting a namespace like this:
{{gallery>namespace}}
All imagefiles in the selected namespace will be added to the image gallery.
Instead of using a whole namespace of images, you can also specify a single image – this makes most sense when combined with the lightbox mode (see below).
{{gallery>namespace:someimage.jpg}}
The created gallery can be aligned by using whitespace (defaults to centered):
{{gallery> namespace}} (right aligned)
{{gallery>namespace }} (left aligned)
{{gallery> namespace }} (centered)
A number of parameters can be set by appending them with ? character to the namespace or image. Each parameter needs to be separated with a & character. Defaults for all parameters can be set in the config manager. If a parameter is enabled by default it can be disabled in the syntax by prefixing it with the syllable no. E.g. the parameter cache is usually enabled and can be disabled using the keyword nocache. Below is a list of all recognized parameters
| Parameter | Default | Description |
|---|---|---|
<number>x<number> | 120x120 | Sets the size for thumbnails. Unless the crop option is set, this is a boundary box into which the thumbnail will be fitted, maintaining the correct aspect ratio. |
<number>X<number> | 800X600 | Sets the size for the linked images in direct mode. This is a boundary box into which the image will be fitted, maintaining the correct aspect ratio. Note the uppercase X. |
<number> | 5 | The number images per row in the gallery table. If you specify a 0 no table is used instead all thumbnails are added in a sequence. |
=<number> | =0 | Limits the output to the given number of images. 0 means all. |
+<number> | +0 | Skip the first number of images. Useful with the option above. |
~<number> | ~0 | Add a pagination for the thumbnails displaying the number of given thumbnails per page. 0 disables pagination. Pagination is added through JavaScript - when no JavaScript is available all thumbnails are displayed |
cache | enabled | Usually the output of the created gallery is cached. When the images in your selected namespace change, you have to manually force an update of the gallery page's cache. To disable the cache for the page showing the gallery, set nocache as option. |
crop | disabled | Make thumbnails the exact given thumbnail size big, cropping when needed. |
direct | disabled | Link thumbnails with the bigger sized images not with their detail page |
lightbox | disabled | Show images in a fancy JavaScript modal browsing window, see below for details. Setting this option automatically implies the direct mode |
reverse | disabled | Reverse the order of the displayed images |
random | disabled | Sort images randomly. You might want to use nocache as well |
modsort | disabled | Sort images by file modification date |
datesort | disabled | Sort images by EXIF date |
titlesort | disabled | Sort images by EXIF title |
showname | disabled | Show filename below thumbnails |
showtitle | disabled | Show EXIF title below thumbnails |
anything containing a * | jpg,gif,png images | This can be used to filter the list of files found in the given namespace. * work as simple wildcard symbol. |
Example:
{{gallery>images:vacation?image_*.jpg&80x80&crop&lightbox}}
This displays all images beginning with image_ and ending in .jpg from the namespace images:vacation. Thumbnails are cropped to 80×80 pixels and images will be opened in lightbox mode.
This mode will open the clicked picture inside the current browser window without leaving the current page1). You can close the picture view by clicking the little X in the upper right corner or anywhere in the picture. You can move to the next or previous image by using the arrow buttons in the lower corners.
The picture is downsized if necessary to fit into the current browser window. You can enlarge it with the arrow button in the top corner.
The following keys can be used to navigate:
| Key | Action |
|---|---|
→ or n | next image |
← or p | previous image |
x or c or ESC | close the image view |
The Lightbox feature will also be used for all images embedded using the standard DokuWiki image syntax and having set the direct parameter. This behavior can easily be disabled by changing the lightboxForEveryImg variable to 0 at the very top of the script.js file.
Note: The feature does not use Version 2 of the Lightbox script because of its heavy and DokuWiki-incompatible dependencies.
Uploading images is beyond the scope of this plugin. Do not request any features regarding this.
data/media directory. Keep in mind that image names need to be valid pagenames, all lowercase, no spaces or special chars!
The gallery output is cached by default. When you add pictures later, they may not show up in the gallery: add &purge=true to the end of the URL to clear the cache. See caching for details.
Optionally use the nocache parameter of the plugin (not recommended).
Problems with accessing EXIF or IPTC data in the images, should be reported as DokuWiki bugs and not for this plugin. All EXIF handling is in DokuWiki core. Currently EXIF Data is expected in UTF-8 encoding. There are some problems fetching the correct date from images, these are fixed in the current development version of DokuWiki.
When the lightbox mode doesn't work and instead images are simply opened in the same window, the JavaScript was not correctly loaded. This is most likely a Browser-Cache issue. Simply follow the steps described for fixing a similar problem with the toolbar.
When no thumbnails are created, then your PHP install is missing the libGD extension. Either install the extension or configure DokuWiki to use imagemagick instead.
Here are a few user provided examples of the gallery plugin in use:
Be sure to read the Known Limitations and Caveats section before asking questions here.
If multiple galleries are added to a page, the lightbox popup will scroll through all of the images in all of them. I would have expected it to only scroll through the images in the gallery where the first thumbnail was initially clicked to bring up the enlargement. –2009/06/23
Use this syntax.php if you want comments for your images.
<gallery images:vacation?image_*.jpg&80x80&crop&lightbox> image.jpg=Comment for image image2.jpg=second comment for another image </gallery>
<?php
/**
* Embed an image gallery
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
* @author Joe Lapp <joe.lapp@pobox.com>
* @author Dave Doyle <davedoyle.canadalawbook.ca>
* @author Gerry Weissbach <gerry.w@gammaproduction.de>
*/
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
require_once(DOKU_INC.'inc/search.php');
require_once(DOKU_INC.'inc/JpegMeta.php');
class syntax_plugin_gallery extends DokuWiki_Syntax_Plugin {
/**
* return some info
*/
function getInfo(){
return array(
'author' => 'Andreas Gohr',
'email' => 'andi@splitbrain.org',
'date' => '2007-11-06',
'name' => 'Gallery Plugin',
'desc' => 'Creates a gallery of images from a namespace',
'url' => 'http://wiki.splitbrain.org/plugin:gallery',
);
}
/**
* What kind of syntax are we?
*/
function getType(){
return 'substition';
}
/**
* What about paragraphs?
*/
function getPType(){
return 'block';
}
/**
* Where to sort in?
*/
function getSort(){
return 301;
}
/**
* Connect pattern to lexer
*/
function connectTo($mode) {
//$this->Lexer->addSpecialPattern('\{\{gallery>[^}]*\}\}',$mode,'plugin_gallery');
$this->Lexer->addSpecialPattern('<gallery.*?>.+?</gallery>',$mode,'plugin_gallery');
}
/**
* Parse option
*/
function parseOpt($params, $name) {
if(preg_match('/\b'.$name.'\b/i',$params,$match)) {
return true;
}else if(preg_match('/\bno'.$name.'\b/i',$params,$match)) {
return false;
}else{
return $this->getConf($name);
}
}
/**
* Handle the match
*/
function handle($all_match, $state, $pos, &$handler){
//$match = substr($match,10,-2); //strip markup from start and end
$data = array();
//handle params
//list($ns,$params) = explode('?',$match,2);
preg_match("#<gallery(.*?)>#", $all_match, $para);
list($ns,$params) = explode('?',$para[1],2);
/*if ( substr($ns, 0, 1) == ' ' )
$data['float']="right";
else if ( substr($ns, -1) == ' ' )
$data['float']="left";
else
$data['float'] = null;
*/
//namespace
$data['ns'] = $ns;
//max thumb dimensions
if(preg_match('/\b(\d+)x(\d+)\b/',$params,$match)){
$data['w'] = $match[1];
$data['h'] = $match[2];
}else{
$data['w'] = $this->getConf('thumbnail_width');
$data['h'] = $this->getConf('thumbnail_height');
}
//max lightbox dimensions
if(preg_match('/\b(\d+)X(\d+)\b/',$params,$match)){
$data['w_lightbox'] = $match[1];
$data['h_lightbox'] = $match[2];
}else{
$data['w_lightbox'] = $this->getConf('image_width');
$data['h_lightbox'] = $this->getConf('image_height');
}
//number of images per row
if(preg_match('/\b(\d+)\b/i',$params,$match)){
$data['cols'] = $match[1];
}else{
$data['cols'] = $this->getConf('cols');
}
//show the filename
$data['showname'] = $this->parseOpt($params, 'showname');
//lightbox style?
$data['lightbox'] = $this->parseOpt($params, 'lightbox');
//direct linking?
if($data['lightbox']) {
$data['direct'] = true; //implicit direct linking
}else{
$data['direct'] = $this->parseOpt($params, 'direct');
}
//reverse sort?
$data['reverse'] = $this->parseOpt($params, 'reverse');
//resize thing?
if(preg_match('/\bnoresize\b/i',$params,$match)) {
$data['noresize'] = true;
}else{
$data['noresize'] = false;
}
//Layout thing?
if(preg_match('/\bmagazine\b/i',$params,$match)) {
$data['magazine'] = true;
}else{
$data['magazine'] = false;
}
//Layout thing?
if(preg_match('/\bdiashow\b/i',$params,$match)) {
$data['diashow'] = true;
}else{
$data['diashow'] = false;
}
//Layout thing?
if(preg_match('/\bpageAmount=(\d+)\b/i',$params,$match)) {
$data['pageAmount'] = $match[1];
}else{
$data['pageAmount'] = -1;
}
$match = preg_replace('#<gallery.*?>|</gallery>#', '', $all_match);
$match = preg_split ('#\n#',$match);
foreach ($match as $line){
list($name,$comment) = explode('=',$line,2);
$data['comments'][$name]=$comment;
}
return $data;
}
/**
* Create output
*/
function render($mode, &$renderer, $data) {
if ( $data['pageAmount'] > 0 ) $renderer->info['cache'] = FALSE;
if($mode == 'xhtml'){
$renderer->doc .= $this->_gallery($data);
return true;
}
return false;
}
/**
* Does the gallery formatting
*/
function _gallery($data){
global $conf;
global $lang;
$ret = '';
//use the search to get all files
$ns = cleanID($data['ns']);
$dir = utf8_encodeFN(str_replace(':','/',$ns));
$files = array();
search($files,$conf['mediadir'],'search_media',array(),$dir);
//anything found?
if(!count($files)){
$ret .= '<div class="nothing"><pre>'.$lang['nothingfound'].print_r($data,$return=true).'</pre></div>';
return $ret;
}
//reverse if wanted
if($data['reverse']) rsort($files);
//startPoint of Pages
$startPoint = intval($_REQUEST['startPoint']);
// build magazine
if ($data['magazine'])
{
require_once(realpath(dirname(__FILE__)).'/inc/magazinelayout.class.php');
$template = '<img src="/lib/plugins/gallery/inc/image.php?size=[size]&file=[image]" alt="" />';
$mag = new magazinelayout($data['w'], $data['h']!=120?$data['h']:5, $template);
$cols = $data['cols'];
$cols = $cols > 8 ? 8 : $cols;
// $content = '<div class="gallery">';
$amount = 0;
foreach($files as $img){
if(!$img['isimg']) continue;
$amount ++;
if ( $amount < $startPoint ) continue;
if ( $data['pageAmount'] > 0 && $amount-$startPoint >= $data['pageAmount'] ) break;
$img['lightbox'] = $data['lightbox'];
$img['h_lightbox'] = $data['h_lightbox'];
$img['w_lightbox'] = $data['w_lightbox'];
$img['direct'] = $data['direct'];
$img['float'] = $data['float'];
$mag->addImage($img);
$cols --;
if ($cols <= 0 )
{
$content .= $mag->getHtml();
$mag = new magazinelayout($data['w'], $data['h']!=120?$data['h']:5, $template);
$cols = $data['cols'];
}
}
if ($mag->_numimages > 0) $content .= $mag->getHtml();
// $content .= '<br style="clear:both" /></div></div></div>';
$content .= $this->_pageSelect(count($files), $data['pageAmount'], $startPoint);
return $content;
}
// build gallery
if($data['cols'] > 0){ // format as table
$ret .= '<table class="gallery"' . (!empty($data['float']) ? ' style="float: '.$data['float'].';"' : '') . '>';
$i = 0;
$amount = 0;
foreach($files as $img){
if(!$img['isimg']) continue;
$amount ++;
if ( $amount < $startPoint ) continue;
if ( $data['pageAmount'] > 0 && $amount-$startPoint >= $data['pageAmount'] ) break;
if($i == 0){
$ret .= '<tr>';
}
$ret .= '<td>';
$ret .= $this->_image($img,$data);
$ret .= $this->_showname($img,$data);
$ret .= $this->_showcomment($img,$data);
$ret .= '</td>';
$i++;
$close_tr = true;
if($i == $data['cols']){
$ret .= '</tr>';
$close_tr = false;
$i = 0;
}
}
if ($close_tr){
// add remaining empty cells
for(;$i < $data['cols']; $i++){
$ret .= '<td></td>';
}
$ret .= '</tr>';
}
$ret .= '</table>';
}else{ // format as div sequence
$ret .= '<div class="gallery"' . (!empty($data['float']) ? ' style="float: '.$data['float'].';"' : '') . '>';
$amount = 0;
foreach($files as $img){
if(!$img['isimg']) continue;
$amount ++;
if ( $amount < $startPoint ) continue;
if ( $data['pageAmount'] > 0 && $amount-$startPoint >= $data['pageAmount'] ) break;
$ret .= '<div>';
$ret .= $this->_image($img,$data);
$ret .= $this->_showname($img,$data);
$ret .= $this->_showcomment($img,$data);
$ret .= '</div> ';
}
$ret .= '<br style="clear:both" /></div>';
}
$ret .= $this->_pageSelect(count($files), $data['pageAmount'], $startPoint);
return $ret;
}
/**
* Defines how a thumbnail should look like
*/
function _image($img,$data){
global $ID;
$w = $img['meta']->getField('File.Width');
$h = $img['meta']->getField('File.Height');
$dim = array();
if ( $data['noresize'])
{
$w = $data['w'];
$h = $data['h'];
}
else if($w > $data['w'] || $h > $data['h']){
$ratio = $img['meta']->getResizeRatio($data['w'],$data['h']);
$w = floor($w * $ratio);
$h = floor($h * $ratio);
$dim = array('w'=>$w,'h'=>$h);
}
//prepare img attributes
$i = array();
$i['width'] = $w;
$i['height'] = $h;
$i['border'] = 0;
$i['alt'] = $img['meta']->getField('Simple.Title');
$i['class'] = 'tn';
$iatt = buildAttributes($i);
$src = ml($img['id'],$dim);
// prepare lightbox dimensions
$w_lightbox = $img['meta']->getField('File.Width');
$h_lightbox = $img['meta']->getField('File.Height');
$dim_lightbox = array();
if($w_lightbox > $data['w_lightbox'] || $h_lightbox > $data['h_lightbox']){
$ratio = $img['meta']->getResizeRatio($data['w_lightbox'],$data['h_lightbox']);
$w_lightbox = floor($w_lightbox * $ratio);
$h_lightbox = floor($h_lightbox * $ratio);
$dim_lightbox = array('w'=>$w_lightbox,'h'=>$h_lightbox);
}
//prepare link attributes
$a = array();
$a['title'] = $img['meta']->getField('Simple.Title');
if($data['lightbox']){
$href = ml($img['id'],$dim_lightbox);
$a['class'] = "lightbox JSnocheck";
$a['rel'] = "lightbox";
}else{
$href = ml($img['id'],array('id'=>$ID),$data['direct']);
}
$aatt = buildAttributes($a);
// prepare output
$ret = '';
$ret .= '<a href="'.$href.'" '.$aatt.'>';
$ret .= '<img src="'.$src.'" '.$iatt.' />';
$ret .= '</a>';
return $ret;
}
/**
* Defines how a filename + link should look
*/
function _showname($img,$data){
global $ID;
if(!$data['showname']) { return ''; }
//prepare link
$lnk = ml($img['id'],array('id'=>$ID),false);
// prepare output
$ret = '';
$ret .= '<br /><a href="'.$lnk.'">';
$ret .= $img['file']; // see fix posted on the wiki
$ret .= '</a>';
return $ret;
}
/**
* Defines how a comment should look
*/
function _showcomment($img,$data){
global $ID;
// prepare output
$ret = '';
$ret .= '<br />';
$ret .= $data['comments'][$img['file']];
return $ret;
}
function _pageSelect($fileCount, $showCount, $startPoint)
{
global $ID;
$content = '<div id="pageSelect">';
$pages = ceil($fileCount / $showCount);
if ( $pages <= 1 ) return "";
for ($i=0; $i<$pages; $i++)
{
$lnk = wl($ID, array('startPoint'=>$i*$showCount));
$content .= '<a href="' . $lnk . '">';
$content .= $i+1;
$content .= '</a>';
if ( $i < $pages -1 )
$content .= ' - ';
}
$content .= '</div>';
return $content;
}
}
//Setup VIM: ex: et ts=4 enc=utf-8 :