thriveweb / photoswipe-masonry-v2

PhotoSwipe Masonry takes advantage of the built in gallery features of WordPress. The gallery is built using PhotoSwipe from Dmitry Semenov.
http://thriveweb.com.au
23 stars 6 forks source link

Requested: Link multi images on a page separated by content #10

Open thriveweb opened 8 years ago

Jon007 commented 7 years ago

Actually it seems about there with almost no code changes, e.g. the photoswipe will work on any images and text inside a container element of class="psgal" Testing both this and an actual image gallery, it supports both on the same page.

However at the moment the relevant code section: $('.psgal').each( function() { [in photoswipe-masonry.js] isn’t error tolerant and will fail if there is any link which doesn’t include a data attribute with a size element as per <a data-size="1280x1280" [These attributes are added by the plugin at save-time but obviously don’t apply to links which don’t contain images for example, or posts that were saved when the plugin was not activated.]

So to make the Photoswipe more flexible we could do the following:

thriveweb commented 7 years ago

Thanks for looking into this. I plan on doing some plugin updates over Christmas!

Jon007 commented 7 years ago

no probs... I've hacked a version that works for me, in the theme adding a psgal class to the body for the post types where I want to enable this feature and a new version of photoswipe-masonry.js (dequeueing the plugin version and queuing a theme version).

In this case I allow swipe-through of all linked images and galleries on the page, which might not be what everyone wants - to add to the plugin it should tie in with some options that could be set on the plug-in to control the behaviour.

If you've got any thoughts on how that should be done I'll take a quick look, otherwise I'll post the revise js up here when I've soak-tested it a bit more.

Jon007 commented 7 years ago

Hi, I put this live over the weekend on a chinese art website, it seems to be working fine. There were a few more issues and ideas on the way which I will report separately.

Note, in this implementation:

Steps taken were: 1) in the theme:

2) one tiny hack to the plugin detailed on https://github.com/thriveweb/photoswipe-masonry/issues/13

3) the new .js, which is somewhat some fault tolerant, so it only applies to links which contain both an image and an href to an image, and also assume the zoomed image will be the same ratio as the small image if no size detail is set...

jQuery(function($) {
    photoswipe_masonry($);
});

var photoswipe_masonry = function($){

  var $pswp = $('.pswp')[0];
  var image = [];

  /////////////////////////////////////////////////////////////////////////////////////////////
  // Gallery
    //in this case the psgal class is actually on the <body> 
    //so only the first gallery is used to swipe through all the images
    //If you want separate galleries within article gallery of images in the text, 
    //then you need to decide how to handle nested galleries and image index numbers
    var $psgal     = $('.psgal').first();
    $galleryUID = $psgal.attr('id');
    if (undefined===$galleryUID) {
      $psgal.attr('id', 'psgalmain');
      $galleryUID = 'psgalmain';
    }
    getItems = function() {
      var items = [];
      $psgal.find('a').each(function() {
        //only if the link actually contains an image
        var $img = $(this).find('img').first();
        if ($img.length){
          var $href   = $(this).attr('href');
          var $ext = $href.split('.').pop();
          switch($ext) {
          case "jpg":
          case "png":
          case "jpeg":

            //default src width and height: TODO: alternative way of getting real dimensions if size missing
            var $width = 1800;
            var $height = 1800;
            var $size   = $(this).attr('data-size');
            if ($size){
              $size=$size.split('x');
              if ($size.length>1){
                $width  = $size[0];
                $height = $size[1];
              }
            }
            else{
              //if no saved size, use the ratio of the small image as basis for calculation..
              //..works great for images within an article
              var $imgWidth = $img.attr('width');
              var $imgHeight = $img.attr('height');
              try {
                $height=$width*$imgHeight/$imgWidth;
              }
              catch(e){}
            }

            //ADDED: set item photoswipe index to avoid recalculating it later
            $(this).attr('data-psindex', items.length);

            var item = {
              src   : $href,
              w     : $width, 
              h     : $height,
              el        : $(this),
              msrc  : $img.attr('src'),
              title : $(this).attr('data-caption')
            }
            items.push(item);

          break;
          default:
            //If the link is to a separate document, don't use the photoswipe
            //(unless the photoswipe supports popup pages not just images
            // - actually http://photoswipe.com/ does support html in the gallery, 
            // that could be a cool enhancement late..)
          }
        }
      });
      return items;
    }

    var items = getItems();
    $.each(items, function(index, value) {
      image[index]     = new Image();
      image[index].src = value['src'];
    });

    $psgal.on('click', 'a[data-psindex]', function(event) {

      event.preventDefault();
      var $index = 0;
      try{
        $index=Number($(this).attr('data-psindex'));
      }
      catch(e){
      }

      var options = {
        index: $index,
        bgOpacity: 0.9,
        showHideOpacity: false,
        galleryUID: $galleryUID,
        getThumbBoundsFn: function(index) {
          var image = items[index].el.find('img'),
          offset = image.offset();
          return {x:offset.left, y:offset.top, w:image.width()};
        }
      }

      var lightBox = new PhotoSwipe($pswp, PhotoSwipeUI_Default, items, options);
      lightBox.init();

    });

    /////////////////////////////////////////////////////////////////////////////////////////////
    // Parse URL and open gallery if it contains #&pid=3&gid=1
    var hashData = parseHash();

    if(hashData.gid) {

        $('#' + hashData.gid).each( function() {

      $index=Number(hashData.pid);

      try{

      }
      catch(e){
      }

            var options = {
                index: $index,
                bgOpacity: 0.9,
                showHideOpacity: false,
                galleryUID: hashData.gid,
                getThumbBoundsFn: function(index) {
                    var image = items[index].el.find('img'),
                    offset = image.offset();
                    return {x:offset.left, y:offset.top, w:image.width()};
                }
            }

            var lightBox = new PhotoSwipe($pswp, PhotoSwipeUI_Default, items, options);
            lightBox.init();

        });
    }
};

var parseHash = 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];
    }

    params.pid = parseInt(params.pid, 10);
    return params;
};

Disclaimer: this isn't perfect and might not suit everyone but it does work and I'm out of time for further improvements for now.

thriveweb commented 7 years ago

Thanks for posting this, I will try it out soon!

Jon007 commented 7 years ago

Following up on my disclaimer, a specific limitation on not setting the size attributes is that if your small image is square but your full size image is a different shape you will get distortions... typically this doesn't happen with medium sized images, as the shape of the thumbnail is the same as the large image, and with shops that use square images not a problem. Even then there could be a solution, to unset the height once the large image has loaded so the browser can resize the image to the correct proportional height for the current width.