Photoswipe Isotope

My Portfolio photo gallery's are built with Zen Gallery, Orchard Module isotope for sorting filtering and the item grid.

Media Profiles for the isotope thumbnails.

Photoswipe for the presentation of images in a Mobile touch friendly photo gallery.

I am using  Isotope v1.5.25 with Photoswipe v4.1.1 to make this work.

Add isotope, photoswipe and Parts.Zen.Gallery.cshtml to your theme folders adding photoswipe and isotope resources as references in your Theme.csproj and ResourceManifest.cs.

Parts.Zen.Gallery.cshtml in your Theme views folder.

The isotope instructions are for a newer version of isotope V2.

This uses V1 and it is on github at: https://github.com/metafizzy/isotope/tree/v1, isotope 2 instructions: Using isotope: http://isotope.metafizzy.co/

so you will have to read through the source to chage this to your liking, I use V1 has its grid structure is based on masonary.

Using photoswipe at: http://photoswipe.com/documentation/getting-started.html

I will be adding modules for a slide show and individual galleries base on the alt="" isotope sorting.

@using System.Linq;
@using Orchard.MediaLibrary.Models
 
@{
    Script.Require("Isotope");
    Script.Require("photoswipe");
    Script.Require("photoswipeUI");
 
    Style.Require("photoswipe");
    Style.Require("photoswipeSkin");
 
    var images = (IEnumerable<MediaPart>)Model.Images;
    
    var count = images.Count();
 
    string categories = string.Empty;
    
    foreach (var category in images.Where(x => !string.IsNullOrWhiteSpace(x.AlternateText)).Select(x => x.AlternateText)) {
        categories += category + ",";
    }
    
    char[] delimiters = new char[] { ',' };
    string[] categoryList = categories.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
    
    var distinctCategories = categoryList.Distinct().OrderBy(x => x).ToArray();
 
    if (images != null && count > 0) {
        <ul class="portfolio-filter nav nav-pills">
            <li class="active"><a href="#" data-filter="*">@T("All")</a></li>
            @foreach (var category in distinctCategories) {
                <li><a href="#" data-filter=".@category.Replace(" ", "-")">@category</a></li>
            }
        </ul>
        <div class="my-gallery" id="isotope-portfolio-container" itemscope itemtype="http://schema.org/ImageGallery">
            @foreach (var img in images.OrderBy(x => x.Title)) {
                   <figure class="portfolio-item portfolio-thumb col-xs-12 col-sm-6 col-md-3 portfolio-item-wrapper
                          @(string.IsNullOrWhiteSpace(img.AlternateText) ? 
                          string.Empty : img.AlternateText.Replace("", "-").Replace(",", ""))" itemprop="associatedMedia" 
                          itemscope="" itemtype="http://schema.org/ImageObject">
                            <a href="@img.MediaUrl" itemprop="contentUrl" data-size="1000x667" data-index="">
                            <img src="@img.MediaUrl" class="img-responsive rounded" itemprop="thumbnail"></a>
                        <figcaption itemprop="caption description" class="portfolio-details lg-sub-html">
                            <h4>@img.Title</h4>
                            <p class="hidden">@img.Caption</p>
                        </figcaption>
                  </figure>
            }
        </div>
    }
 
    using (Script.Foot()) {
        <script type="text/javascript">            
            var $container = $('#isotope-portfolio-container');
            var $filter = $('.portfolio-filter');
 
            $(window).load(function () {
                $container.isotope({
                    itemSelector: '.portfolio-item-wrapper'
                });
                $('.portfolio-filter a').click(function () {
                    var selector = $(this).attr('data-filter');
                    $container.isotope({ filter: selector });
                    return false;
                });
                $filter.find('a').click(function () {
                    var selector = $(this).attr('data-filter');
                    $filter.find('a').parent().removeClass('active');
                    $(this).parent().addClass('active');
                });
            });
 
            $(window).smartresize(function () {
                $container.isotope('reLayout');
            });            
</script>
    }
}
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="pswp__bg"></div>
    <div class="pswp__scroll-wrap">
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">                
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
    var initPhotoSwipeFromDOM = function(gallerySelector) {
 
    // parse slide data (url, title, size ...) from DOM elements 
    // (children of gallerySelector)
    var parseThumbnailElements = function(el) {
        var thumbElements = el.childNodes,
            numNodes = thumbElements.length,
            items = [],
            figureEl,
            linkEl,
            size,
            item;
 
        for(var i = 0; i < numNodes; i++) {
 
            figureEl = thumbElements[i]; // <figure> element
 
            // include only element nodes 
            if(figureEl.nodeType !== 1) {
                continue;
            }
 
            linkEl = figureEl.children[0]; // <a> element
 
            size = linkEl.getAttribute('data-size').split('x');
 
            // create slide object
            item = {
                src: linkEl.getAttribute('href'),
                w: parseInt(size[0], 10),
                h: parseInt(size[1], 10)
            };
 
 
 
            if(figureEl.children.length > 1) {
                // <figcaption> content
                item.title = figureEl.children[1].innerHTML; 
            }
 
            if(linkEl.children.length > 0) {
                // <img> thumbnail element, retrieving thumbnail url
                item.msrc = linkEl.children[0].getAttribute('src');
            } 
 
            item.el = figureEl; // save link to element for getThumbBoundsFn
            items.push(item);
        }
 
        return items;
    };
 
    // find nearest parent element
    var closest = function closest(el, fn) {
        return el && ( fn(el) ? el : closest(el.parentNode, fn) );
    };
 
    // triggers when user clicks on thumbnail
    var onThumbnailsClick = function(e) {
        e = e || window.event;
        e.preventDefault ? e.preventDefault() : e.returnValue = false;
 
        var eTarget = e.target || e.srcElement;
 
        // find root element of slide
        var clickedListItem = closest(eTarget, function(el) {
            return (el.tagName && el.tagName.toUpperCase() === 'FIGURE');
        });
 
        if(!clickedListItem) {
            return;
        }
 
        // find index of clicked item by looping through all child nodes
        // alternatively, you may define index via data- attribute
        var clickedGallery = clickedListItem.parentNode,
            childNodes = clickedListItem.parentNode.childNodes,
            numChildNodes = childNodes.length,
            nodeIndex = 0,
            index;
 
        for (var i = 0; i < numChildNodes; i++) {
            if(childNodes[i].nodeType !== 1) { 
                continue; 
            }
 
            if(childNodes[i] === clickedListItem) {
                index = nodeIndex;
                break;
            }
            nodeIndex++;
        }
   
        if(index >= 0) {
            // open PhotoSwipe if valid index found
            openPhotoSwipe( index, clickedGallery );
        }
        return false;
    };
 
    // parse picture index and gallery index from URL (#&pid=1&gid=2)
    var photoswipeParseHash = function() {
        var hash = window.location.hash.substring(1),
        params = {};
 
        if(hash.length < 5) {
            return params;
        }
 
        var vars = hash.split('&');
        for (var i = 0; i < vars.length; i++) {
            if(!vars[i]) {
                continue;
            }
            var pair = vars[i].split('=');  
            if(pair.length < 2) {
                continue;
            }           
            params[pair[0]] = pair[1];
        }
 
        if(params.gid) {
            params.gid = parseInt(params.gid, 10);
        }
 
        return params;
    };
 
    var openPhotoSwipe = function(index, galleryElement, disableAnimation, fromURL) {
        var pswpElement = document.querySelectorAll('.pswp')[0],
            gallery,
            options,
            items;
 
        items = parseThumbnailElements(galleryElement);
 
        // define options (if needed)
        options = {
 
            // define gallery index (for URL)
            galleryUID: galleryElement.getAttribute('data-pswp-uid'),
 
            getThumbBoundsFn: function(index) {
                // See Options -> getThumbBoundsFn section of documentation for more info
                var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail
                    pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
                    rect = thumbnail.getBoundingClientRect(); 
 
                return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
            }
 
        };
 
        // PhotoSwipe opened from URL
        if(fromURL) {
            if(options.galleryPIDs) {
                // parse real index when custom PIDs are used 
                // http://photoswipe.com/documentation/faq.html#custom-pid-in-url
                for(var j = 0; j < items.length; j++) {
                    if(items[j].pid == index) {
                        options.index = j;
                        break;
                    }
                }
            } else {
                // in URL indexes start from 1
                options.index = parseInt(index, 10) - 1;
            }
        } else {
            options.index = parseInt(index, 10);
        }
 
        // exit if index not found
        if( isNaN(options.index) ) {
            return;
        }
 
        if(disableAnimation) {
            options.showAnimationDuration = 0;
        }
 
        // Pass data to PhotoSwipe and initialize it
        gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
        gallery.init();
    };
 
    // loop through all gallery elements and bind events
    var galleryElements = document.querySelectorAll( gallerySelector );
 
    for(var i = 0, l = galleryElements.length; i < l; i++) {
        galleryElements[i].setAttribute('data-pswp-uid', i+1);
        galleryElements[i].onclick = onThumbnailsClick;
    }
 
    // Parse URL and open gallery if it contains #&pid=3&gid=1
    var hashData = photoswipeParseHash();
    if(hashData.pid && hashData.gid) {
        openPhotoSwipe( hashData.pid ,  galleryElements[ hashData.gid - 1 ], true, true );
    }
};
 
// execute above function
initPhotoSwipeFromDOM('.my-gallery');
 
</script>

2 Comments

  • al

    you rock....!

    Question how can I handle toggle size with ASP MVC?

    • Don Boulton

      Using bootstrap with MVC toggle answer somewhat vague.
      Stack overflow
      http://stackoverflow.com/questions/5336677/html-5-and-css-style-change-upon-screen-size

Comments are Moderated, from, "(Spam-bots)", before they are posted.

 1580440 Views