Subscribe: RSS
  • In this tutorial I’d like to explain how to make a fancy overlay gallery with thumbnails slider for website based on MODx with the help of MIGx extension.
    Main aspects of my gallery are:


    • ease of use - every gallery is a single MODx resource, so you can add, remove, edit or disable galleries with a single click.
    • photos in galleries are organised with MIGx extension
    • photos, included in every single gallery are loaded via AJAX call after user clicks a thumbnail

    You can view an example at http://www.dopeless-design.de/migx-jquery-gallery-tutorial.html

    You can download source files at the bottom af this post.


    I’d like to notice, that I am web designer, not a coder, so all of my scripts are not very clean and surely could be written in some better way. The Jquery Script is not flexible. Maybe someday I’ll extend it to Jquery plugin, but today it is just a script to display photos in the way I needed it for my project. You can not set the size of overlay or the way thumbnails are scrolled without editing source code. But the main purpose of this tutorial is to show how easy it is to create nice image gallery using MODx capabilities. If you want to share my JS with your edits, please contact me before, but you can freely use it as is.

    So, first of all let’s talk about extensions you’ll need. In general, the only necessary extension is:

    • MIGx (I've used ver, 2.0.1pl for this tutorial).
    But I have also used:

    • GetResources (my ver, is 1.4.2pl) to display thumbnails of multiple galleries on a main page
    • phpThumbOf (my ver. is 1.3.2pl) to resize images

    If you don’t have this extensions installed, you’ll need to do it. My MODx version is 2.2.1pl.

    1. Create TV for MIGx list. Call it galleryPhotos. Set an Input type to mixg under Input Options. Now we have to setup Form Tabs and Grid Columns fields to define functionality of variable.

    Form Tabs:

    [
          {"caption":"Info", "fields": [
             {"field":"title","caption":"Name"}
          ]
       },
       {"caption":"Image", "fields":[
          {"field":"image","caption":"Image","inputTVtype":"image"}
       ]
    }
    ]

    Grid Columns
    [
       {"header": "Name", "width": "160", "sortable": "true", "dataIndex": "title"},
       {"header": "Image", "width": "50", "sortable":
       "false","dataIndex":"image","renderer":"this.renderImage"}
    ]


    2. Now create new template. Give it some name, for example galleryTpl. You do not have to enter any HTML code, but go to Template Variables tab in template settings and give access for TV we have created in step 1 (galleryPhotos) by checking it. You can also do it in TV settings under Template Access tab.

    3. Create new resource as a child of the page where your gallery should appear. Give it some name. For my example I have created two resources: “Fireworks” and “Some Photos”. Set “Hide from Menus” to true. Go to Template Variables Tab and add some photos.

    4. Now you have to create gallery thumbnails on your website. Add getResources call to the HTML of the resource parent to gallery.

    [[!getResources? 
    &limit=`0`
    &parents=`[[*id]]`
    &sortby={"menuindex":"ASC"}
    &tpl=`galleryGertes`
    &showHidden=`1`
    &includeTVs=`1`
    ]]

    if you are not familiar with getResources extension, it has very good documentation in RTFM.

    5. Let’s create a new Chunk. It will be a template for generating output markup of our getResources Call. Sure, you have to give it the name same as you’ve gave in &tpl value. In my case it is galleryGetres.

    6. In my case chunk code is:

    <div class='gallery_block'>
    <h3>[[+pagetitle]]</h3>
    <a class='home_gallery_link' href='[[~[[+id]]]]' uid='[[+id]]' title='[[+pagetitle]]'>[[!getImageList? &tvname=`galleryPhotos` &tpl=`galleryMigx` &docid=`[[+id]]` &limit=`1`]]</a>
    </div>

    as you can see, we have a MIGx call in this template to become the first data set of our gallery TV. It will be used to generate thumbnail link image. We add uid attribute to our <a> element. We will use it later in AJAX call to load data from the resource, where thumbnail belongs.

    7. Now we have to create another one chunk for MIGx call template. The chunk name in my case is galleryMigx.

    <img src='../[[+image:phpthumbof=`w=180&h=140&zc=1`]]'/>

    as you can see, the only thing we want to get is an image, resized with phpThumbOf extension.

    8. If you reload your page with gallery thumbnails, you should see a single thumbnail for every gallery, you have created. By the way, it is a first image from MIGx TV image list.

    9. Now add two div elements just before the closing <script type="text/javascript">
    var DISModifyPost = $(function() {
    DIS.config.attachments_max_per_post = 5;
    DIS.DISModifyPost.init({
    attachments: 2
    });
    });</script>
    <script type="text/javascript">
    var DISModifyPost = $(function() {
    DIS.config.attachments_max_per_post = 5;
    DIS.DISModifyPost.init({
    attachments: 2
    });
    });</script>
    <script type="text/javascript">
    var DISModifyPost = $(function() {
    DIS.config.attachments_max_per_post = 5;
    DIS.DISModifyPost.init({
    attachments: 2
    });
    });</script>
    <script type="text/javascript">
    var DISModifyPost = $(function() {
    DIS.config.attachments_max_per_post = 5;
    DIS.DISModifyPost.init({
    attachments: 2
    });
    });</script>
    <script type="text/javascript">
    var DISModifyPost = $(function() {
    DIS.config.attachments_max_per_post = 5;
    DIS.DISModifyPost.init({
    attachments: 2
    });
    });</script>
    <script type="text/javascript">
    var DISModifyPost = $(function() {
    DIS.config.attachments_max_per_post = 5;
    DIS.DISModifyPost.init({
    attachments: 2
    });
    });</script>
    </body> tag to the HTML of the page where the gallery should appear.

    <div id='full_overlay'></div>
    <div id='gallery_overlay'></div>

    The first one is to dim the page out and the second one is for gallery container.

    10. Let us add some CSS.

    #full_overlay{
        display:none;
        width:100%;
        height:100%;
        position:absolute;
        left:0px;
        top:0px;
        background:url(../images/full_overlay_bg.png) 0 0 repeat;
    }
    #gallery_overlay{
        display:none;
        width:670px;
        height:600px;
        position:absolute;
        top:100px;
        left:50%;
        margin-left:-335px;
        background: #e4e4e4;
    }

    I will exclude the CSS3 parts for rounded corners, shadows, etc to reduce the code amount and make it easier to understand, but they are all included in source files that you can download.

    We set the positions of the both DIVs and make them not visible by default.

    11. We have to create template for our gallery container. So create an empty file (in my case gallery.tpl) and add this code.

    <a href='#' class='close_overlay'></a>
    <a href='#' class='photo_left'></a>
    <a href='#' class='photo_right'></a>
    <h2 class='gallery_title'></h2>
    <div class='gallery_image'>
        <div class='loading_image'>
            <div class='circle'></div>
            <div class='circle1'></div>
        </div>
        <img src=''/>
    </div>
    <h3>More Images</h3>
    <div id='thumbs_holder'>
        <div id='loading_bg'>
            <div id='loading_bar_inside'></div>
        </div>
        <div id='carousel'>
            <a href='' class='nav_left'></a>
            <div class='gallery_thumbnails_holder'>
                <ul class='gallery_thumbnails'></ul>
            </div>
            <a href='' class='nav_right'></a>
        </div>
    </div>

    12. Now create an empty JS file (in my case dopelessGallery.js) and include it to your HTML after Jquery connection.

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></scrip>
    <script type="text/javascript" src="dopeless_gallery/scripts/dopelessGallery.js"></script>


    13. Let’s add some JS to the file we have created. Sure, we start with

    $(document).ready(function(){

    now let us define document size to set the overlay background to full height and width

    var docHeight = $(document).height();
    var docWidth = $(document).width();

    load HTML from our gallery template (that we have created in step 11) and append it to #gallery_overlay container. Than set width and height of #full_overlay element.

    $.get("dopeless_gallery/scripts/gallery.tpl", function(data){
    $('#gallery_overlay').html(data);
    });
    $("#full_overlay").css({
    "height":docHeight,
    "width":docWidth
    });

    Add some action to click event on our thumbnail. First we prevent default action of click event, define some variables, add content to our gallery HTML and fade in gallery overlay.

    $('.home_gallery_link').click(function(openOverlay){
    openOverlay.preventDefault();
    var pageTitle = $(this).attr('title');
          var galleryId = $(this).attr('uid');
          var leftOffset = parseInt($('.gallery_thumbnails').css('left'));
          var newBigSrc;
         	... 
    var mainImage = $('#gallery_overlay').find('.gallery_image img');
          ...
      
          $('#gallery_overlay').find('.gallery_title').append(pageTitle);
          $('.gallery_image').find('img').css({'display':'none'});
          $('#gallery_overlay').find('#carousel').css({'display':'none'});
          $('#full_overlay').fadeIn('fast');
          $('#gallery_overlay').fadeIn('fast');
          $('.loading_image').fadeIn();
    ...

    14. Now our AJAX Call:

    $.getJSON("../dopeless_gallery/scripts/loadGallery.php", {resid: galleryId}, function(output) {
                 $('#gallery_overlay').find('.gallery_thumbnails').html(output.content);    
    var imageCount = $('.gallery_thumbnail').length;
    ulLength = imageCount*114 + (imageCount - 1)*10;
    loadGallery(imageCount, ulLength);

    here we first load a PHP script, we will discuss in step 15 and send the ID of resource (see step 6 for more details), containing the photos from gallery we want to load. Then we add data, we become generated by PHP to our HTML. This would be our gallery thumbnails. After that we count the number of images in our gallery (number of thumbnails, we became from PHP), we count length of our <ul> element, holding all the thumbs, in pixels for CSS and further JS calculation. And call function loadGaleery to display the contents of gallery to our users (see step 17).

    15. Create an empty PHP file with the name, you have specified in step 14. In our case loadGallery.php. Add this content:

    <?php
    require_once '../../config.core.php';
    require_once MODX_CORE_PATH.'model/modx/modx.class.php';
    $modx = new modX();
    $modx->initialize('web');
    $modx->getService('error','error.modError');
    $resId  = $_GET['resid'];
    $resource = $modx->getObject('modResource',array('id'=>$resId));
    $strJSON = $resource->getTVValue('galleryPhotos');
    $arrJSON = $modx->fromJSON($strJSON);
    $output = '';
    foreach($arrJSON as $arrJSONDataSet){
    if(!empty($arrJSONDataSet['image'])){
    $output .= $modx->getChunk('renderGalleryThumbnails', $arrJSONDataSet);
    }
    }
    echo json_encode(array("content" => $output));
    ?>

    So, first of all we initialize connection with MODx, then define an ID of resource we want to load. Then load all the values of our galleryPhotos MIGx TV to array. After that we generate HTML for every data set based on renderGalleryThumbnails template (see step 16) and add it to output data. This output will be a piece of HTML with generated thumbnails for our gallery, we have used in step 14. At the very end we send it back to JS.

    16. Create a new chunk in MODx, give it the name, we have used in step 15. In my case renderGalleryThumbnails. Add this HTML.

    <li class='gallery_thumbnail'>
    <a class='gallery_thumbnail_link' href="../[[+image:phpthumbof=`w=640&h=425&zc=1&q=85`]]" title="[[+title:default=`[[*pagetitle]]`]]">
    <img src='[[+image:phpthumbof=`w=110&h=70&zc=1&q=75`]]'>
    </a>
    </li>

    as you can see, we just use the values of our MIGx TV. We also use phpThumbOf to resize thumbnails.

    17. Now back to Jquery. As we have stated in step 14, we write a function to load our gallery contents.

    function loadGallery(imageCount, ulLength){
    
    imgSrc = $(".gallery_thumbnails li:first-child").find('.gallery_thumbnail_link').attr('href');
    
    var loadImg = new Image();
    
    loadImg.src = imgSrc;
    
    loadImg.onload = function() {
    
    $('.loading_image').fadeOut();
    $(mainImage).attr('src', imgSrc).load(function(){
    $(mainImage).fadeIn();
    });
    }
    
    loadThumbs(imageCount, ulLength);
    
    }

    the JS is pretty straight forward and I will not go deep in it - after all it’s not the main purpose of this tutorial.
    We also write another function - loadThumbs to view our thumbnails.

    function loadThumbs(imageCount, ulLength){
    
    var enumLi = 1;
    
    var perc = 0;
    
    var cache = [];
    
    $(".gallery_thumbnails li").each(function(){
    
    if(enumLi == 1){
    
    $(this).find('.gallery_thumbnail_link').addClass('active');
    
    }
    
    if(enumLi == imageCount){
    
    $(this).addClass('last');
    
    }
    
    $(this).find('.gallery_thumbnail_link').attr('id', enumLi);
    
    var thumbSrc = $(this).find('.gallery_thumbnail_link').attr('href');
    
    var im = $("<img>").attr("src",thumbSrc).load(function(){
    
    perc = perc + 100/imageCount;
    
    var loaderWidth = Math.round(246*perc/100);
    
    $('#loading_bar_inside').css({'width':loaderWidth});
    
    if(Math.round(perc) >= 100){
    
    $('#loading_bg').fadeOut();
    
    ulLength = imageCount*114 + (imageCount - 1)*10;
    
    $('.gallery_thumbnails').css({'width':ulLength});
    
    
    $('#carousel').fadeIn(function(){
    imgId = parseInt($('.gallery_thumbnail_link[href="'+imgSrc+'"]').attr('id'));
    if(imgId == 1 && imgId < imageCount){
    $('.photo_right').addClass('active');
    }
    if(imgId > 1){
    $('.photo_left').addClass('active');
    }
    });
    }
    });
    enumLi++;
    cache.push(im);
    });
    $('.gallery_thumbnail_link:not(.active)').css({'opacity':0.7});
    if((ulLength - 610) > 0){
    $('.nav_right').addClass('active');
    }
    }

    maybe it looks a little complicated, but again it is pretty straight forward and all about preloader and adding classes to navigation buttons.

    The rest of JS file is all about navigating between images. I will not explain it in this tutorial, but you can find all the code in attached files. Same about CSS.

    That’s all. Hope this tutorial will help you in MODx development. [ed. note: Bruno17 last edited this post 6 years, 8 months ago.]
    • awesome work. i will have to play around with this one. thank you
      • Very cool. Thanks for telling the folks here how you did this—keep on sharing! smiley
          Ryan Thrash, MODX Co-Founder
          Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
        • I was trying to make this one sticky by editing the first post and click the checkbox 'sticky' , but this doesn't seem to work.

          Is there another way for moderators to make threads sticky?

          [Edit]

          I see there is a nice stick on the top now, which seems to work well.
          great!

          is it new? [ed. note: Bruno17 last edited this post 6 years, 8 months ago.]
            -------------------------------

            you can buy me a beer, if you like MIGX

            http://webcmsolutions.de/migx.html

            Thanks!
          • HI dopeles,
            Nice work! and thanks for sharing...
            I have a question, is possible to use the arrow key on my keyboard instead of clicking the arrow and also i wanted to make a full screen preview for the image.

            Thanks in advance
            • Hi, thx, sure it's possible. But it's all about Jquery )
              • If you have a free time, can you do this?

                Actually i tried this http://rtfm.modx.com/display/ADDON/MIGX.Fancybox-images+with+seperate+placeholders+in+Richtext-Content
                and it works fine. But only thing that i don't like is by putting manually the placeholder tags on resources.


                Regards
                • Sorry, but I really do not have much time to modify Jquery script for this gallery right now. The main purpose of tutorial was to show MODx capabilities not Jquery )
                  • can I add some image description the photos?
                    • If you need a description-field in your gallery you can add it in MIGX with:

                      [
                            {"caption":"Info", "fields": [
                               {"field":"title","caption":"Name"}
                               ,{"field":"description","caption":"Description","inputTVtype":"textarea"}
                            ]
                         },
                         {"caption":"Image", "fields":[
                            {"field":"image","caption":"Image","inputTVtype":"image"}
                         ]
                      }
                      ]


                      additional you will need to add a function to the javascript which can read and display the description, or find another javascript gallery, which can display desriptions.
                        -------------------------------

                        you can buy me a beer, if you like MIGX

                        http://webcmsolutions.de/migx.html

                        Thanks!