1 of 1 found this page helpful

Slideshow: customizable slideshow of images attached to a page

    Table of contents
    1. 1. Overview
    2. 2. History
    3. 3. To Do
    4. 4. Examples
    5. 5. Template source

    This is a temporary documentation page for the Slideshow template.  The template is fully functional, the documentation is not yet finished.  I thought I'd publish it on the App Catalog in its current state, since it's quite usable and useful, and update the docs later as I have time.

    Discuss this template on the forums.

    Overview

    This is an optimized image slideshow, based on the glorious jQuery Cycle plugin.  It's just a beta for now, but still quite useful.

    Basically, the template will take all the images attached to a (selectable) page and make a slideshow out of them.  Features:

    1. Simple to use.  Just attach a bunch of images to a page, and call the template.
    2. Preserves image aspect ratio, unlike image.slideshow().  This was actually the primary motivation for creating this template in the first place.  The template will expand each image as large as possible to fit in the specified width and height while maintaining original aspect ratio.  Then the images are centered.
    3. Uses webview for each image, so it comes up quickly, even with a lot of images.
    4. Selectable image display order.  If the current page is the image source, then the order of the image gallery at the bottom of the page is automatically set to match the slideshow order (if your skin supports it).
    5. Auto slideshow title: If the source page for the images is not the current page, the title of the source page is placed above the slideshow as a title.  You can also force the title to be displayed or not, or set the title to your own choice.
    6. Links: each image can (optionally) link to the full-sized version of the image
    7. Captions: if you turn on captions, then the description of each image will be placed underneath as a caption.
    8. Transition Effects:  The cycle plug-in supports a lot of transition effects, some quite funky.  The template automatically selects the much smaller "Cycle lite" plug-in if the default "fade" effect is used, and loads the full plug-in if any other effect is selected.  Here are the available effects.  Also try them out using the control down below.
    9. Controls: you can optionally enable previous, next, and pause/resume controls, to be placed over or under the slideshow (may not be working correctly right now)
    10. Options: if you want to dig into the capabilities of the Cycle plug-in beyond what this template offers, you can pass options directly to the plug-in.

    History

    • 1.02     26-July-2010    neilw    Fixed for Mindtouch 2010
    • 1.0.1    11-May-2010    neilw    Added option for caption at top
    • 1.0.0    16-Nov-2009    neilw    Couple of remaining bug fixes
    • 0.9.3    16-Nov-2009    neilw    Added support for playback controls, and options pass-through to the plug-in
    • 0.9.2    13-Nov-2009    neilw    Now support effects.  Auto-select appropriate plug-in depending on selected effect
    • 0.9.1    13-Nov-2009    neilw    Added "effect", "title", "link", and "caption" options
    • 0.9.0    13-Nov-2009    Neilw    First published version

    To Do

    1. Fix controls
    2. better style control of title, controls, whole slideshow, etc.
    3. Figure out if there's a jQuery 1.3/1.2 sensitivity (I might be seeing one).

    If there's anything in particular you want, let me know in the comments below.

    Examples

    The options are described in the template source code.  Here is a simple example (note that the outline around the slideshow is added on this page, and not part of the template).

    slideshow {
        path:"en/docs/MindTouch",
        width:400,
        height:300,
        title:"Mindtouch 2010 Home Page",
        order:"+date",
        link:true,
        caption:true,
        effect:"scrollDown",   // by default, but you can change the effect below!
        controls:true
    }
    
    Try out different effects:

    Template source

    // Slideshow, by neilw, 2009
    //    Optimized photo slideshow based on the jQuery "cycle" plug-in
    //
    // Version History:
    //    1.02     26-July-2010   neilw        Fixed for Mindtouch 2010
    //    1.0.1    11-May-2010    neilw        Added option for caption on top
    //    1.0.0    16-Nov-2009    neilw        A couple of minor bug fixes
    //    0.9.3    16-Nov-2009    neilw        Added "controls" and "options" options
    //    0.9.2    13-Nov-2009    neilw        Added proper support for effects.  Automatically load the appropriate plug-in version
    //                                         depending on the selected effect.
    //    0.9.1    13-Nov-2009    neilw        Added "effect", "title", "link", and "caption" options
    //    0.9.0    13-Nov-2009    neilw        First beta version installed on dev wiki.  Still using "cycle lite"
    
    //
    // Usage:
    //    slideshow{ path:str, width:num, height:num, interval:num, speed:num, order:str,
    //               title:bool or string, link:bool, caption:bool, controls:bool or str }
    //
    //        path        Path to page containing attached slideshow images (default: page.path)
    //        width       display width, in pixels, of slideshow images (default: 320)
    //        height      display height, in pixels, of slideshow images (default: 240)
    //        interval    duration, in milliseconds, of each image (default: 3000)
    //        speed       speed of transitions, in milliseconds (default: 500)
    //        order       order of images to display; valid options are:
    //                        "name"            ascending order by name (DEFAULT)
    //                        "date" or "+date" ascending order by date (oldest first)
    //                        "-date"           descending order by date (newest first)
    //        effect      transition effect (default:'fade')
    //        title       display slideshow title (default:automatic)
    //        link        link each image to the original, full-sized (default:FALSE)
    //        caption     display each image's description as caption on bottom (default:FALSE).  May be set to true,
    //                    false, "top", or "bottom".  True is equivalent to "bottom".
    //        controls    display "prev", "pause/play", and "next" controls (default:FALSE).  May be set to true, false,
    //                    "top", or "bottom" (to control placement of the controls).  True is equivalent to "top".
    //        options     other options to be passed directly to the plugin
    
    var id = @id;
    
    //**************
    // Process args
    //**************
    var errors = [];
    // path
    var picpage = wiki.getpage($0 ?? $path ?? page.path);
    if (picpage is not map) {
        let errors ..= [ "ERROR: invalid path" ];
        let picpage = page;
    }
    var this_page = (picpage.id == page.id);
    
    // width and height
    var width = $1 ?? $width;
    if (width is not num || width <= 0) {
        if (width is not nil) let errors ..= [ "width must be a positive number" ];
        let width = 320;
    }
    var height = $2 ?? $height;
    if (height is not num || height <= 0) {
        if (height is not nil) let errors ..= [ "height must be a positive number" ];
        let height = 240;
    }
    var aspect = width/height;
    
    // interval
    var interval = $3 ?? $interval;
    if (interval is not num || interval <= 0) {
        if (interval is not nil) let errors ..= [ "interval must be a positive number" ];
        let interval = 3000;
    }
    
    // speed
    var speed    = $4 ?? $speed;
    if (speed is not num || speed < 0) {
        if (speed is not nil) let errors ..= [ "speed must be a non-negative number" ];
        let speed = 500;
    }
    
    // order
    var order = $5 ?? $order;
    if (order is str) let order = string.tolower(order);
    var allowed_orders = [ "name", "date", "+date", "-date" ];
    if (order is not str || !list.contains(allowed_orders, order)) {
        if (order is not nil) let errors ..= [ "order must be one of "..string.serialize(allowed_orders) ];
        let order = "name";
    }
    var char1 = string.substr(order,0,1);
    var descending = (char1 == "-");
    let order = string.substr(order, (char1 == "-" || char1 == "+") ? 1 : 0);
    
    // effect
    var effect = $6 ?? $effect;
    var allowed_effects = [ "fade" ];
    if (effect is not str) { // || !list.contains(allowed_effects, effect)) {
        if (effect is not nil) let errors ..= [ "effect must be one of "..string.serialize(allowed_effects) ];
        let effect = 'fade';
    }
    var plugin = (effect == "fade" ? 
        "http://developer.mindtouch.com/@api/deki/files/4938/=jquery.cycle.lite.min.js" :
        "http://developer.mindtouch.com/@api/deki/files/4936/=jquery.cycle.all.min.js"  );
    
    // title
    var title = $7 ?? $title;
    
    // link
    var link = $8 ?? $link ?? false;
    
    // caption
    var caption = $9 ?? $caption;
    if (caption is str) let caption = string.tolower(caption);
    var allowed_caption = [ "top", "bottom" ];
    if (caption is not bool && (caption is not str || !list.contains(allowed_caption, caption))) {
        if (caption is not nil)
            let errors ..= [ "caption must be one of true, false, "..string.join(allowed_caption,", ")];
        let controls = false;
    }
    if (caption == true) let caption = "bottom";
    
    // controls
    var controls = $10 ?? $controls;
    if (controls is str) let controls = string.tolower(controls);
    var allowed_controls = [ "top", "bottom" ];
    if (controls is not bool && (controls is not str || !list.contains(allowed_controls, controls))) {
        if (controls is not nil)
            let errors ..= [ "controls must be one of true, false, "..string.join(allowed_controls,", ")];
        let controls = false;
    }
    if (controls == true) let controls = "top";
    var next_id = id .. "next";
    var prev_id = id .. "prev";
    var pause_id = id .. "pause";
    var controls_div = <div style="width:100%; text-align:center; background-color:#dddddd;">
        <a href="#" id=(prev_id)  style="float:left; padding-left:10px"  > "prev"  </a>;
        <a href="#" id=(next_id)  style="float:right; padding-right:10px" > "next"  </a>;
        <a href="#" id=(pause_id)> "pause" </a>;
    </div>;
    
    // options
    var options = $11 ?? $options ?? {};
    let options ..= { timeout:interval, speed:speed, fx:effect };
    if (link) let options ..= { pause:1 };
    if (controls) let options ..= { next:"#"..next_id, prev:"#"..prev_id };
    
    //*************************
    // Prepare for the scripts
    //*************************
    
    // Create selector for image order in gallery at bottom of page
    var selector = order .. (order == "date" ? (descending ? "-desc" : "-asc") : "");
    
    <html>
    //********************
    // Output the scripts
    //********************
    <head>
    if (this_page) <script type="text/javascript"> "   // set gallery sort order to equal slideshow
        Deki.$(document).ready(function($) {
            var $select = $('#galleryOrderBy');
            $select.find('option').removeAttr('selected');
            $select.find('option[value=" .. selector .. "]').attr('selected','selected');
            $select.change();
        });
    " </script>;
    <script type="text/javascript" src=(plugin)></script>; 
    <script type="text/javascript"> "
        function setcaption_"..id.."() { $('#"..id.."caption".."').text($(this).find('div.caption').text()); }
        Deki.$(document).ready(function($) {
            var options = "..json.emit(options)..";
            if ("..json.emit(caption)..")
                options.after = setcaption_"..id..";
            var $slideshow = $('#' + "..json.emit(id)..");
            $slideshow.cycle(options);
            var $pause = $('#' + "..json.emit(pause_id)..");
            if ($pause.length)
                $pause.click(function() {
                    $slideshow.cycle($pause.text());
                    $pause.text($pause.text() == 'pause' ? 'resume' : 'pause');
                    return(false);
                });
        });
    " </script>;
    </head>;
    
    //**********************
    // Output the slideshow
    //**********************
    <body>
    if (#errors) <div style="color:red">
        <span style="font-weight:bold"> "Slideshow errors:" </span>;
        <ul> foreach (var e in errors) <li> e </li>; </ul>;
    </div>;
    // Output the images
    <div style=("width:" .. width .. "px;")>
        if ((!this_page && title is nil) || title) <div style="text-align:center; font-weight:bold"> title is str ? title : picpage.title </div>;
        if (controls == "top") controls_div;
        if (caption == "top") <div id=(id.."caption") style="text-align:center"> " " </div>;
        <div id=(id) style=("width:"..width.."px; height:"..height.."px;")>
            // generate the list of images
            var pics = list.select(map.values(picpage.files ?? { }),"$.imageHeight is num");
            let pics = [ { picture:p, name:p.name, date:date.format(p.date,"s") } foreach var p in pics ];
            let pics = list.collect(list.sort(pics,order,descending),"picture");
            // Spit them out!
            foreach (var p in pics) {
                var h = p.imageheight;
                var w = p.imagewidth;
                var a = w / h;
                var img;
                if (a >= aspect) {
                    var new_h = h * width / w;
                    var m = (height - new_h) / 2;
                    let img = <img style=("margin-top:"..m.."px; margin-bottom:"..m.."px;") src=(p.uri & {size:"webview"}) width=(width) />;
                }
                else {
                    var new_w = w * height / h;
                    var m = (width - new_w) / 2;
                    let img = <img style=("margin-left:"..m.."px; margin-right:"..m.."px;") src=(p.uri & {size:"webview"}) height=(height) />;
                }
                var caption = <div class="caption" style="display:none"> p.description </div>;
                link ?
                    <a href=(string.substr(p.uri,#site.uri-1)) target="_blank" style="display:none;"> img; caption; </a> :
                    <div style="display:none;"> img; caption; </div>;
            }
        </div>;
        if (caption == "bottom") <div id=(id.."caption") style="text-align:center"> " " </div>;
        if (controls == "bottom") controls_div;
    </div>;
    </body>
    </html>
    

    Was this page helpful?
    Tag page
    Viewing 13 of 13 comments: view all
    Possibly have the ability to allow each image to be a link also. Image Captions (using description?) And be able to turn next/prev/pause on or off. edited 09:46, 13 Nov 2009
    Posted 09:45, 13 Nov 2009
    I'll have to see how the plug-in behaves when I add links or captions or what-not. Though I like the idea (a lot), I foresee technical hurdles in adding the captions (due to some arcane CSS issues that I've already battled with). But I'll do some testing.
    Posted 11:14, 13 Nov 2009
    Never mind, I think I just figured out how to do it. :) Will start working through the new features one by one...
    Posted 11:17, 13 Nov 2009
    Anyone having luck getting this to work on Core release 10?
    Posted 08:14, 26 Jul 2010
    @bwhiting
    Should be fixed now.
    Posted 08:56, 26 Jul 2010
    Does only work as "admin" here. Slideshows created as "Contributer", does not show the slide. The html source lacks the first 2 text/javascript instances after "styles overwritten via control panel - load this css last".
    Anybody know how to fix this?
    Posted 09:19, 21 Sep 2011
    @tim
    That sounds like a problem with unsafecontent privileges. This should only affect the template itself; if an an admin is the last one to edit the template, then any contributor should be able to *use* the template. See this KB item: http://developer.mindtouch.com/en/kb/Using_templates_which_require_UNSAFECONTENT_permission, and come back if you can't get it straightened out.
    Posted 09:40, 21 Sep 2011
    Cool template! It will be even more useful if titles and descriptions could be edited with click on them. And those new titles and descriptions to be saved in the target attached file on the page.
    Is that possible?
    Posted 10:09, 26 Jun 2012
    @varosi
    That certainly is possible, but I must say honestly it's more work than I could justify right now. It's not too hard to add descriptions to attachments using Mindtouch's existing UI. This would be a bit nicer, but not a huge value (at least, not to me), and not enough to make it onto my "todo" list for the moment. I would of course invite anyone else to add this functionality! :) edited 11:17, 26 Jun 2012
    Posted 11:17, 26 Jun 2012
    The problem is when you have for example 100 photos in single page gallery. Then if you want to add/change picture title you have to scroll down and search for the picture file name in thumbnails section, after that you have to scroll up to files section, to edit the description then go back to gallery. It's harder to change the description than to pass next. And people tend to not do it.
    Second is that if the description could be edited directly from the gallery, then attachment and thumbnails sections could be hidden by other template. That way Deki will be much cleaner to be used as image gallery as a section.

    I hope someone could do something like that. edited 01:11, 27 Jun 2012
    Posted 01:10, 27 Jun 2012
    @neilw - only fade effect works? Even in the above example if I select another effect I still get fade. And captions only display for me at the top, even when I use caption:true
    Posted 18:56, 13 Oct 2012
    @dadeo
    Whoops, my bad. There are two versions of the cycle plugin: the simple one only does "fade". If you call the template with "fade" selected as the effect, then it loads the simple version of the plugin and then fade is all you get. That is what was happening on this page. I changed the default effect on this page to "scrollDown", and now it works as expected.

    So: if you want to have multiple selectable effects, don't call the template with "fade"!
    Posted 07:46, 9 Dec 2012
    @neilw - perfect - thanks!
    Posted 09:36, 27 Dec 2012
    Viewing 13 of 13 comments: view all
    You must login to post a comment.

    Copyright © 2011 MindTouch, Inc. Powered by