Summary: "Yet Another Gallery tool" for PmWiki - An easy-to-use tool that creates and caches thumbnails of images, and displays them in gallery. Suited for creating a thumbnail gallery distributed over multiple pages for large number of images. Images can be within the PmWiki (page attachments) or can be in WWW. Range of images can be declared in single line using wildcard-like features.
Version: 1.9
Prerequisites: 'convert' (ImageMagick) utility installed on server.
Status: Working perfectly well
Questions answered by this recipe
Q: I have a large number of images in a folder, for which I need to create a thumbnail gallery. Since the number of images is large, I would like the gallery to be distributed over multiple pages. Is there a recipe that will do that for me?
A: Yes, YAG exactly does that. It is designed for creating large thumbnail galleries distributed over multiple pages. It is easy to use and can be customized with many features. You can include multiple images using range syntaxes in a single line. In addition, for a gallery you can mention a 'base URL' for the location of the images, thus avoiding the task of writing long URLs multiple times for every image. Display options include linking thumbnails to original images, or displaying the original images in a container in the gallery itself.
Description
YAG (Yet Another Gallery tool) for PmWiki enables creation of thumbnail galleries from a list of images. The gallery can be display over multiple pages. The thumbnails are created using the 'convert' utility and are cached in a cache folder. It comes with quite a few options, for example in a gallery it lets one mention a 'base URL' for the location of the images, thus relieving the task of writing long URLs multiple times for every image. The images can be located in the upload folder of PmWiki (attachment with the same or different page), as well as they can be located externally (images from the WWW). Multiple images (range of images with similar names) can be included using range/wildcard syntaxes. Display options include linking thumbnails to original images, or displaying the original images in a container in the same page as the gallery..
Δ A gallery with multiple pages
Δ A gallery with a 'div' container
Δ Hovering on an image displays caption(can be customized for different behavior)
Δ A gallery with style='nohead,nofoot,rightcaption' option displaying detailed caption on the right of thumbnails
|
Demonstrations
Live Demonstrations: For live demonstrations visit
Installation
Installing YAG is as simple as it can get:
- Download the attached YetAnotherGallery.phpΔ(check file consistency) file and place it in the cookbook/ folder.
- In /local/config.php add the line
include_once('cookbook/YetAnotherGallery.php');
Dependencies: convert : This utility is a part of the ImageMagick package. It is used to create the thumbnails and store the smaller images in the cache. To check if the utility is installed, just type 'convert' in a terminal. Ubuntu Linux hosts can simply install the 'imagemagick' package for installing the utility.
Upgrading to v1.9: If you had created a custom container type or redefined any of the '$YetAnotherGallery->' PHP variables in config.php for YAG v1.8 or earlier, you may need to update them. Refer to the PHP variables section for details.
Use
Syntax:
YAG [ option1=o1, option2=o2, ... ]
{
url | caption &&
url | caption &&
...
}
Features:
- One can mention the maximum number of thumbnails to display per page (number of rows and columns) of the gallery by setting the 'cols' and 'maxrows' options. Multiple pages are created automatically based on that.
- The thumbnails can be made to link to the original images (either open in a pop-up or in the same window) or can be made to display the original images in a container in the same page as the thumbnail gallery (see the 'container' markup option).
- 'url' can be local attachments (e.g.
Attach:file.jpg or Attach:Group.Page/file.bmp) or URL from the web (e.g. http://mysite.com/image.png).
- It is possible to specify a range of URLs in a single line. (e.g. files
IMG_001.jpg, IMG_002.jpg, IMG_003.jpg, ..., IMG_120.jpg can be included in a single line by using IMG_[%03d<<range:1,120].jpg for the 'url')
- The caption can contain '\n' for indicating line break as well as backreference from the url.
- One can specify a Base URL ('urlbase' option) for all (or some of) the images in a gallery.
- One can have multiple different galleries in the same page by using the "name" option.
- See Markup options and URL format & ranging for details on the available options and URL formattings.
|
Examples:
1. The basic use of 'urlbase' option:
YAG [ urlbase = "http://www.mysite.net/files/images/" , cols=3, maxrows=5]
{
IMG_001.jpg | The caption \n can be split \n into multiple lines &&
IMG_002.jpg | Another caption &&
-- http://www.anothersite.com/images/IMAGE_01.png |
This does not use <b>'urlbase'</b> due to the preceding "--"
}
2. One can use images from local attachments as well as images from WWW. Whitespaces do not matter.
YAG[style='div,nofoot', containerheight=300]
{ http://upload.wikimedia.org/wikipedia/en/c/ca/Pmwiki-32.png | PmWiki logo from Wikipedia &&
Attach:file.jpg | Uploaded image && Attach:Group.Page/file2.jpg | Uploaded image from a different group }
3. URL range - the following creates gallery using images fracday0.gif, fracday1.gif, ..., fracday9.gif from http://sprott.physics.wisc.edu/fractals/:
YAG [urlbase="http://sprott.physics.wisc.edu/fractals/",name="frac",cols=4,maxrows=1,container='self']
{ fracday[%d<<range:0,9].gif | Fractal number [*] }
Note: 'container' option has been superseded by 'style' option since v1.9. 'container' option is, however, still supported. See below for details.
Markup options
The following options can be used with the markup for any gallery.
| Option
| Description
| Default
|
| cols
| Number of columns to display in each page of the gallery.
| 4
|
| maxrows
| Maximum number of rows to be displayed in each page of the gallery. Set maxrows=0 for displaying all the images in a single page. This also removes the page indicator on the top and the page list at the bottom of the gallery.
| 5
|
| imgmaxwidth
| Maximum width of each image thumbnail (in pixels).
| 150
|
| imgmaxheight
| Maximum height of each image thumbnail (in pixels).
| 250
|
| urlbase
| The string to be appended at the beginning of every URL mentioned in the gallery. Base URL can be in uploads folder or an URL from WWW. e.g. urlbase=http://mysite.com/ or urlbase=Attach:Group.Page/. It is possible to exclude one or more urls from 'urlbase' being appended to the beginning by preceding the urls with "--" (without the quotes).
| (empty)
|
| containerwidth
| Width of the container. (not applicable for 'self' container)
| 500
|
| containerheight
| Height of the container. (not applicable for 'self' container)
| 600
|
container ['container' option has been superseded by 'style' option since v1.9]
| Describes where to display the original image upon clicking a thumbnail. Valid values are:
popup - Displays original image in a pop-up window. The same pop-up window gets updated when another thumbnail is clicked.
div - Displays original image in a 'container' (div block) in the same page as the gallery. The image is displayed above the gallery. Upon clicking a thumbnail the content of the container gets updated.
lfloat - Similar to 'div'. The image is displayed on the left of the gallery. Upon clicking a thumbnail the content of the container gets updated.
self - Displays the original image in the same window as the gallery (unlike 'div' and 'lfloat', this does not show the image along with the thumbnails).
custom - It is possible to create a custom container style. It requires adding an array value with the custom key to the $YetAnotherGallery->GalleryDivContainerFmt and $YetAnotherGallery->HandleClick_FunctionContent PHP variables.
| "popup"
|
style [supersedes 'container' option]
| A comma-separated list of style attributes. Each item in the list can be chosen from the following sets (at most one from each set). If no value is chosen from a set, the set's default is used.
Container type - Specifies the type of container. A valid value can be
popup
div
lfloat
self (default)
or a custom value. For custom value, one needs to add the custom key to the $YetAnotherGallery->GalleryDivContainerFmt and $YetAnotherGallery->HandleClick_FunctionContent PHP variables.
Caption position - Specifies the position and visibility of caption. A valid value can be
hiddencaption (default)
rightcaption
or a custom value. For custom value, one needs to add the custom key to the $YetAnotherGallery->imgDivStyle, $YetAnotherGallery->imgStyle, $YetAnotherGallery->imgMouseOverJavascript and $YetAnotherGallery->imgMouseOutJavascript PHP variables.
Header style - Specifies whether a header is displayed. A valid value can be
head (default)
nohead
Footer style - Specifies whether a footer is displayed. A valid value can be
foot (default)
nofoot
Examples: style='lfloat,rightcaption,nofoot' ; style='popup,nohead'
Note: Do not use the word 'default' in the style string. Just omit the style attribute for the corresponding set to use the default.
| "hiddencaption,popup"
|
| captiontype
| The type of the captions. It is a comma-separated list of two type attributes:
Whether the caption is linked: Possible values are linked or free.
Type of text in caption: Possible values are nohtml, wiki, basichtml or fullhtml
Examples: captiontype='free,wiki'
| "linked,basichtml"
|
| refreshcache
| Set this to yes to re-create every thumbnail in the gallery each time they are displayed. Valid values are "yes" and "no". Tip: When you are designing a gallery (i.e. have not finalized the number of columns/rows or the size of the thumbnails and are playing around with those options), always have refreshcache = yes set. This will ensure that the thumbnails are recreated with the changes you make.
| no
|
| name
| In case there are multiple galleries in the same page, an unique name needs to be declared for each gallery. The unique names enable proper navigation between the pages of the galleries. It can be any alphanumeric string.
| (empty)
|
| convertoptions
| The option string used by 'convert' utility for creating the thumbnails. One can use the placeholders {imgmaxwidth} and {imgmaxheight}. Refer to ImageMagick website for more details.
| "-resize {imgmaxwidth}x{imgmaxheight}"
|
URL format, range declaration and backreferences
An 'url' can contain a range or list for including multiple files in a single line. Below is a brief description of the syntax of 'url' and 'caption'
url:
- General format of 'url':
path/to/file.ext.
- 'urlbase', if defined in the options, will get appended to the beginning of each declared URL when the final URL is formed. However individual URLs can be exempted from this rule by preceding them with "--" (without the quotes).
- 'url' can contain a single sequence of wildcard enclosed in [...]: e.g.,
path/to/multiple[WildcardString]folders/or/files.ext, where,
[WildcardString] is of the format:
[sprintfString<< part1:p1,p2,...; part2:q1,q2,...; ... ] where,
sprintfString is a valid PHP sprintf format string (without quotes or whitespaces) with a single type specifier (see sprintf manual)
- ' partn ' can be 'range' or 'list'
- If it is 'range', the format is range:start,end,step (see PHP 'range' function)
- If it is 'list', the format is list:item1,item2,... (see PHP 'array' function)
One can have multiple of these specified in series.
Examples:
IMG_[%03d<<range:1,998].png will include all the images from IMG_001.png to IMG_998.png.
FILE[%s<<range:a,f].jpg will include all the images FILEa.jpg, FILEb.jpg, ... , FILEf.jpg.
SameName.[%s<<list:png,gif,jpg] will include the images SameName.png, SameName.gif and SameName.jpg.
IMG_[%d<<range:1,9,2].png will include the images IMG_1.png, IMG_3.png, IMG_5.png, IMG_7.png and IMG_9.png (i.e. 1 to 9, but with increment/step of 2).
Folder[%d<<range:1,3;list:7,9,13;range:20,24,2]/file.png will include images Folder1/file.png, Folder2/file.png, Folder3/file.png, Folder7/file.png, Folder9/file.png, Folder13/file.png, Folder20/file.png, Folder22/file.png, and Folder24/file.png in that sequence.
caption:
- Can contain '\n' to indicate line break as well as the basic HTML formatting tags like '<i>', '<font>', etc.
- Can contain [*] that is substituted by a simple backreference from url's [...] block (described above).
OR, can contain a single sequence of wildcard enclosed in [...]. This is similar in syntax to the one described above in 'url'. It creates an one-to-one ordered correspondences between the URLs and the captions. However in addition to the 'range:' and 'list:' parts, the following two values for 'part
n' can be used in caption:
- A string containing '*k ' - If k is an integer, this uses k backreferences from the url's [...] block in place of '*k' in the string. e.g.
[%s<< list: First, Second; Image no *2; list: Fifth, Sixth]. If k is omitted (or something other than an integer), all the captions corresponding to the rest of the URLs in the declaration are created using this format.
- '.m ' followed by a string - If m is an integer, this uses m instances of a constant string. e.g.
[%s<< list: First, Second; .2 Same Caption for 2 images; list: Fifth, Sixth]. If m is omitted (or something other than an integer), all the captions corresponding to the rest of the URLs in the declaration are created using this format.
Example:
1.
YAG [ urlbase="http://", name="myimages", cols=4, maxrows=1, style='div']
{
www.mysite.com/IMG_[%d<<range:0,9].jpg | This is image number [*] &&
www.anothersite.com/anotherImage.bmp | Another image &&
-- Attach:localImage.gif | This is an attachment image and is not to be started with "http://" }
is equivalent to writing
YAG [ urlbase="http://", name="myimages", cols=4, maxrows=1, style='div']
{ www.mysite.com/IMG_0.jpg | This is image number 0 &&
www.mysite.com/IMG_1.jpg | This is image number 1 &&
www.mysite.com/IMG_2.jpg | This is image number 2 &&
www.mysite.com/IMG_3.jpg | This is image number 3 &&
www.mysite.com/IMG_4.jpg | This is image number 4 &&
www.mysite.com/IMG_5.jpg | This is image number 5 &&
www.mysite.com/IMG_6.jpg | This is image number 6 &&
www.mysite.com/IMG_7.jpg | This is image number 7 &&
www.mysite.com/IMG_8.jpg | This is image number 8 &&
www.mysite.com/IMG_9.jpg | This is image number 9 &&
www.anothersite.com/anotherImage.bmp | Another image &&
-- Attach:localImage.gif | This is an attachment image and is not to be started with "http://" }
2.
YAG [ urlbase="http://", style='lfloat']
{ www.mysite.com/IMG_[%d<<range:0,11].jpg |
This is [%s<< image num *3; list: my photo, Bob's photo, Nancy's photo; .2 unknown; *th image]
}
is equivalent to writing
YAG [ container='lfloat' ]
{ http://www.mysite.com/IMG_0.jpg | This is image num 0 &&
http://www.mysite.com/IMG_1.jpg | This is image num 1 &&
http://www.mysite.com/IMG_2.jpg | This is image num 2 &&
http://www.mysite.com/IMG_3.jpg | This is my photo &&
http://www.mysite.com/IMG_4.jpg | This is Bob's photo &&
http://www.mysite.com/IMG_5.jpg | This is Nancy's photo &&
http://www.mysite.com/IMG_6.jpg | This is unknown &&
http://www.mysite.com/IMG_7.jpg | This is unknown &&
http://www.mysite.com/IMG_8.jpg | This is 8th image &&
http://www.mysite.com/IMG_9.jpg | This is 9th image &&
http://www.mysite.com/IMG_10.jpg | This is 10th image &&
http://www.mysite.com/IMG_11.jpg | This is 11th image
}
Note: The 'url' and 'caption' themselves cannot contain the character '}', and the character sequence '&&'. The 'url' cannot contain the character '|'. And, the contents inside the placeholder @[...]@ in 'url' or 'caption' themselves cannot contain the characters ']', ';', ',' and the sequence '<<'. Use hex encoding for special characters in 'url', and HTML special character encoding for those in the 'caption'.
If you intend to make basic use of YAG you may want to skip to the Troubleshoot & FAQs section.
PHP variables
The following PHP variables can be set in config.php:
| Variable
| Description
| Default
|
$YetAnotherGallery->cache
| The folder that is to be used as the cache.
| $FarmD.'/pub/YetAnotherGalleryCache/'
|
$YetAnotherGallery->cacheURL
| The URL to the cache folder accessible to the world.
| $PubDirUrl.'/YetAnotherGalleryCache/'
|
$YetAnotherGallery->cols
| Default value for the 'cols' option.
| 4
|
$YetAnotherGallery->maxrows
| Default value for the 'maxrows' option.
| 5
|
$YetAnotherGallery->imgmaxwidth
| Default value for the 'imgmaxwidth' option.
| 150
|
$YetAnotherGallery->imgmaxheight
| Default value for the 'imgmaxheight' option.
| 250
|
$YetAnotherGallery->thumbtype
| File type for the thumbnail images.
| "jpg"
|
$YetAnotherGallery->style
| Default value for the 'style' option.
| "hiddencaption,popup"
|
$YetAnotherGallery->captiontype
| Default value for the 'captiontype' option.
| "linked,basichtml"
|
$YetAnotherGallery->containerwidth
| Default value for the 'containerwidth' option.
| 500
|
$YetAnotherGallery->containerheight
| Default value for the 'containerheight' option.
| 600
|
$YetAnotherGallery->convertoptions
| Default value for the 'convertoptions' option.
| "-resize {imgmaxwidth}x{imgmaxheight}"
|
$YetAnotherGallery->cellStyle
| CSS style for each table cell containing the thumbnails.
| array( 'default' => "border: solid 2px #cccccc;" )
|
$YetAnotherGallery->imgDivStyle
| CSS style for the DIV block containing each thumbnail image.
| array(
'default' => "text-align: center; vertical-align: middle; margin: 0; padding: 0; cursor:hand; cursor:pointer; ",
'rightcaption' => "text-align: center; vertical-align: middle; margin: 0; padding: 0; display:inline" )
|
$YetAnotherGallery->imgStyle
| CSS style for each thumbnail image.
| array(
'default' => "border: 1px solid; border-color: #aaaabb #bbbbcc #bbbbcc #aaaabb; ",
'rightcaption' => "border: 1px solid; border-color: #aaaabb #bbbbcc #bbbbcc #aaaabb; float:left;" )
|
$YetAnotherGallery->captionDiv
| CSS style for the captions.
| array(
'default' => "",
'hiddencaption' => "<div style='position:relative; width:100%;'> <div style='width:100%; position:absolute; width:100%; display:none; padding: 5px; left: -6px; top: -5px; border: 1px solid; border-color: #ccc #888 #888 #ccc; color: #eeeeff; background-color: #333338;'> <b>\$Caption</b> </div></div>", 'rightcaption' => "<div style='margin: 0px 10px; text-align:left; float:left;'>\$Caption</div>" )
|
$YetAnotherGallery->imgMouseOverJavascript
| Javascript for MouseOver event.
| array(
'default' => "void(0);",
'hiddencaption' => "this.getElementsByTagName('img')[0].style.opacity=0.6; this.getElementsByTagName('img')[0].style.filter='alpha(opacity=60)'; this.getElementsByTagName('div')[0].getElementsByTagName('div')[0].style.display='block';" )
|
$YetAnotherGallery->imgMouseOutJavascript
| Javascript for MouseOut event.
| array(
'default' => "void(0);",
'hiddencaption' => "this.getElementsByTagName('img')[0].style.opacity=1.0; this.getElementsByTagName('img')[0].style.filter='alpha(opacity=100)'; this.getElementsByTagName('div')[0].getElementsByTagName('div')[0].style.display='none';" )
|
$YetAnotherGallery->GalleryHeaderFmt
| The header of a gallery. Can contain the variables $PageNo, $GalleryName and $PagesCount.
| array(
'default' => "<div style='font-weight: bold; color:#999999; padding: 5px;'>Displaying page \$PageNo of <a href='#YAGlink_\$GalleryName'>\$PagesCount</a></div>",
'nohead' => "" )
|
$YetAnotherGallery->GalleryFooterFmt
| An array describing the footer of a gallery. Can contain the variables $PageNo, $GalleryName and $PagesCount.
| array(
'default' => array('start'=>"<a name='YAGlink_\$GalleryName'></a> <br/>Pages: ", 'page-prefix'=>" ", 'page-suffix'=>" ", 'current-page-prefix'=>"<b> ", 'current-page-suffix'=>" </b>", 'end'=>""),
'nofoot' => array('start'=>"<div style='display:none;'>", 'page-prefix'=>"", 'page-suffix'=>"", 'current-page-prefix'=>"", 'current-page-suffix'=>"", 'end'=>"</div>") )
|
$YetAnotherGallery->GalleryDivContainerFmt
| An array containing the HTML of the different containers. Needs to be declared only for same-page containers (like 'div' and 'lfloat'). Can contain the variables $PageNo, $GalleryName, $PagesCount, $containerwidth and $containerheight.
| array(
'div' => "<center><div style='margin:0;padding:0;overflow:hidden;position:relative;' id='YAGdivContainer_\$GalleryName'> <img id='YAGdivContainerImg_\$GalleryName' height=\$containerheight style = 'border: 5px solid #ddddee;' /> <div id='YAGdivContainerCaption_\$GalleryName' style='font-weight:bold;'></div> <hr style='border:1px solid #bbb;background-color:#eee;height:5px;'/></div></center>",
'lfloat'=> "<div style='float:left;margin:5px;padding:0;overflow:hidden;position:relative;' id='YAGdivContainer_\$GalleryName'><center> <div id='YAGdivContainerCaption_\$GalleryName' style='font-weight:bold;margin:5px;'></div> <img id='YAGdivContainerImg_\$GalleryName' width=\$containerwidth style = 'border: 5px solid #ddddee;' /> </center></div>"
)
|
$YetAnotherGallery->HandleClick_FunctionContent
| An array containing the Javascript content of the thumbnail click handler function. Can use javascript variables url, caption, num, GalleryName
| array (
'popup' => " var thepop = window.open(url,'YAGwindow', ". " 'top=0,left=0,width=\$containerwidth,height=\$containerheight,". " location=1,menubar=0,resizable=1,scrollbars=1,status=1,toolbar=0' ); ". " thepop.focus(); " ,
'self' => " window.location = url; ",
'div' => " var containerImg = document.getElementById('YAGdivContainerImg_'+GalleryName); ". " var containerCaption = document.getElementById('YAGdivContainerCaption_'+GalleryName); ". " containerImg.style.opacity=0.4; containerImg.style.filter='alpha(opacity=40)'; ". " containerCaption.innerHTML='<font color=\\'#888\\'>Loading image...</font>'; ". " var pic = new Image(); pic.src = url;". " if(pic.complete) donePic(); else pic.onload= donePic;". " function donePic() { containerImg.src = pic.src; ". " containerImg.style.opacity=1.0; containerImg.style.filter='alpha(opacity=100)'; ". " containerCaption.innerHTML = caption; } ",
'lfloat' => " var containerImg = document.getElementById('YAGdivContainerImg_'+GalleryName); ". " var containerCaption = document.getElementById('YAGdivContainerCaption_'+GalleryName); ". " containerImg.style.opacity=0.4; containerImg.style.filter='alpha(opacity=40)'; ". " containerCaption.innerHTML='<font color=\\'#888\\'>Loading image...</font>'; ". " var pic = new Image(); pic.src = url;". " if(pic.complete) donePic(); else pic.onload= donePic;". " function donePic() { containerImg.src = pic.src; ". " containerImg.style.opacity=1.0; containerImg.style.filter='alpha(opacity=100)'; ". containerCaption.innerHTML = caption; } "
)
|
Troubleshoot & FAQs
Q: The thumbnails are not being displayed.
A: Most likely ImageMagick is not installed on the server. Read the
Dependencies section to learn more. If that's not the issue, check if your PHP has permission to modify the 'pub/YetAnotherGalleryCache' folder.
Q: I changes the values of 'cols' and 'maxrows'. The gallery is now looking weird (thumbnails overlap on each other, or are not of the right size).
A: Either the thumbnail size is not set properly, or the cache contains old thumbnails of incorrect size.
Make sure you do the following whenever you change the values of 'cols' or 'maxrows':
a. Change the values of 'imgmaxwidth' and 'imgmaxheight' to indicate the desired size of the thumbnails, and
b. Refresh the cache for all the pages of this gallery (i.e. set refrechcache=yes, followed by visiting each page of the gallery)
Q: I updated an image, but the old thumbnail is still showing.
Q: I changes the values of 'imgmaxwidth' and 'imgmaxheight'. But the size of the thumbnails has not changed!
Q: How do I clear the cache?
A: For an individual gallery simply set the option refreshcache = yes. Then, upon visiting every page of the gallery the thumbnails will be regenerated.
For completely clearing all the images in the cache you'll need to manually delete the files in the 'pub/YetAnotherGalleryCache' folder. To prevent accidental clearing of the cache no markup option is provided for this.
Tip: When you are designing a gallery (i.e. have not finalized the number of columns/rows or the size of the thumbnails and are playing around with those options), always have refreshcache = yes set. This will ensure that the thumbnails are recreated with the changes you make.
Q: An URL I need to use has the characters '[', ']' or '&&'. These conflict with the syntax. What can I do?
A: Use the ASCII encoding for writing the URL ('%' followed by the hexadecimal ascii code of the character)
Q: I see the same thumbnail for two different images!! What's going on?
Release notes
2010-07-19: Version 1.0 released.
2010-07-20: Version 1.5 released.
Restriction on syntax of options string relaxed;
URL range introduced;
Convert options, header format and footer formats introduced as parameters.
2010-07-21: Version 1.7 released.
Container options introduced.
2010-07-22: Version 1.8 released.
Some security enhancement made (for more reliable public use of YAG in blogs, etc.).
'lfloat' container introduced.
A few other minor additions.
2011-12-17: Version 1.9 released.
Some bug fixes. 'style' option introduced.
See also
Contributors
Comments
Please use the YAG-Talk page for comments and discussions.
User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.