Google-plus-like galleries with Image Store

If you are using the Image Store (ImStore) plugin just to display your images and will like to improve the way the galleries display or just like  Google+ galleries look. Here is the tutorial to do it. Here is an example gallery.

I am going to start by using the standard gallery page, but and the end of the tutorial I will show you how to use the short-code version. Make your you have Image Store 3.0.2 or greated installed.

jQuery Colorbox

First you will need to download and install the jQuery Colorbox plugin, this will help us change the standard Colorbox theme that is used with the Image Store plugin. Once installed go the the jQuery Colorbox settings and check

  • Automate hiding of flash objects
  • Remove link from Meta-box
  • Disable warning
  • Select theme #3.

You can change all the other settings as you like.

Linking to the image attachment page.

Next we have to change one thing the Image Store settings, we are going to link the image to the attachment page instead of the image file, by going to settings > gallery > “Link image to attachment”. What we want to do is load the image and the comment form using ajax (Colorbox).

Lets do some testing before continuing. Go to one of your galleries and click on on of the images you should get a page similar to this one. It should display the image and the comment form.

Moving the ims-image.php file ( if needed ).

If your page doesn’t display properly don’t worry, login into your server and locate the “theme” folder inside the Image Store pluign /wp-content/plugins/image-store/theme and find the file ims-image.php file. Move it into your theme’s folder and make the necessary adjustments to make your page look good.

The javascript – part 1.

Create a new javascript file and name it google_gal.js. Save it in your theme’s folder and add the following code to your theme’s fucntions.php file.  The code will load the file in the footer of you theme.

function print_theme_scripts( ){
  wp_enqueue_script( 'google_gals', TEMPLATEURL . '/jquery.google_gal.js', array( 'jquery' ), null, true );
} add_action( 'wp_print_scripts', 'print_my_theme_scripts' );

Lets start working with the google_gal.js file. First we need to be sure that Colobox and the page has loded and there is at least one image present.

jQuery(document).ready(function($){
  if( jQuery.colorbox && $('.ims-gallery .ims-img a')[0]){
  }
});

Now we’ll create an object called attr that will store the settings need by the colorbox.

jQuery(document).ready(function($){
  if( jQuery.colorbox && $('.single .ims-gallery .ims-img a')[0]){
    var attr = {
      width:'98%',
      height:'95%',
      maxWidth:'98%',
      maxHeight:'95%',
      href:function(){
      },
      onOpen: function(){
      },
      onComplete:function(){
      },
      onClosed: function(){
      }
    }
  }
});

We have to be sure that we only load the container  that has the image and the comments  from the image page and ignore the rest of the content. We do it by changing the default href and target the id “content” in the single image page. Change the href: property to

href:function(){
  return $(this).attr('href') + ' #content';
},

Let test and make use that colorbox is loading the right content. But first let be sure that there is no other colorbox function bind to the images. Add this code after the attr object.

$.colorbox.remove();
$('.single .ims-gallery .ims-img a').colorbox( attr );

Go to your gallery and click on one of the images, it should look like the image below, if not, add id=”content” to the element surrounding the image and comment form in the image.php or ims-image.php file.

Lets apply some styles

Modify your stylesheet to achieve a look similar to the image below, I aded my styles  to give you and idea. Download arrows.png image.

#cboxClose { right:-4px}
#cboxLoadedContent{ background:#000}
#cboxLoadedContent #content{ margin:0; background:#000; position:static; color:#666; padding:0; width:100%; margin:auto; height:90% }
#cboxLoadedContent #content a{ color:#999}

#cboxLoadedContent #reply-title,
#cboxLoadedContent h1.entry-title,
#cboxLoadedContent #nav-single{ display:none }

#cboxLoadedContent .ims_image{ width:65%; float:left; clear:none; position:static}
#cboxLoadedContent .ims_image .entry-content{ padding:0}
#cboxLoadedContent .ims_image img{ margin:auto; display:block; max-height:100%; max-width:100%; height:auto}
#cboxLoadedContent .ims_image .ims-img{ display:block; height:90%; text-align:center; padding:0; margin:0}
#cboxLoadedContent .gallery-caption { position:relative; padding:10px}
#cboxLoadedContent .attachment .expand{ display:block; width:60px; height:60px; background:#222 url(../_img/arrows.png) no-repeat 50% -267px; opacity:.7;
position:absolute; top:-68px; -khtml-border-radius:5px; -o-border-radius:5px; -moz-border-radius:5px; border-radius:5px; border:solid 1px #333 }
#cboxLoadedContent .attachment .expand:hover,
#cboxLoadedContent .attachment .expand:active,
#cboxLoadedContent .attachment .expand:focus{ opacity:.85; cursor:pointer}

#cboxLoadedContent .form-submit{ text-align:left}
#cboxLoadedContent #comments-title{ margin-bottom:0; padding:0 10px; background:url(../_img/arrows.png) no-repeat 95% -185px; cursor:pointer }
#cboxLoadedContent #comments-title:hover,
#cboxLoadedContent #comments-title:active,
#cboxLoadedContent #comments-title:focus{ cursor:pointer; background-position:95% -115px}
#cboxLoadedContent #comments-title.active{ background-position:95% -162px}
#cboxLoadedContent #comments-title.active:hover,
#cboxLoadedContent #comments-title.active:active,
#cboxLoadedContent #comments-title.active:focus{ background-position:95% -137px}
#cboxLoadedContent #comments{ background:#eee;width:30%; max-width:280px; float:right; margin:0; clear:none; overflow:hidden; height:94%; margin-right:30px}
#cboxLoadedContent #comments p{ margin-bottom:.6em}
#cboxLoadedContent #comments #respond{ margin:0}
#cboxLoadedContent #comments #comment{ height:50px}
#cboxLoadedContent .cajax-mess.error{ color:#DD8080; padding:5px 0; width:100%; font-size:.9em; display:block}
#cboxLoadedContent #comments .comment-form-comment label{ display:none}

#cboxLoadedContent .commentlist { width:auto; padding-left:0}
#cboxLoadedContent .commentlist .avatar { left:0}
#cboxLoadedContent .commentlist > li.comment {padding: 1em 1em 0 4em; margin-bottom:0; border-top:none}
#cboxLoadedContent .commentlist > li.comment img{ width:30px; height:auto; margin:1em .9em}
#cboxLoadedContent .commentlist > li.comment .says{ display:none}
#cboxLoadedContent .comment-meta { font-size:11px; line-height:1.5em;}
#cboxLoadedContent .comment-notes{ font-size:9px}

#cboxLoadedContent .logged-in-as{ margin-bottom:5px}
#cboxLoadedContent #commentform{ padding:.95em}
#cboxLoadedContent .entry-meta{ position:absolute; bottom:0; left:0;padding:8px 0 0; font-size:.9em; z-index:100;text-align:left;background:#111; border-top:solid 1px #222; margin:0; width:100%}
#cboxLoadedContent .entry-meta .meta-prep{ margin-left:10px}

Javascript continue – part 2

Will continue working on the javascript file. Lets remove the scrolling bars from our window, this will keep our image in place. Change the following methods on the attr object.

onOpen: function(){
  $(window).scrollTop( 0 );
  $('body').css({overflow:'hidden'});
},
onClosed: function(){
  $('body').css({overflow:'auto'});
}

We want the gallery to resize itself when the user resizes the window; for that, we need a helper function to improve performance. enter the following code just before the document ready function jQuery(document).ready.

//samart window resize
(function($,sr){
  var debounce = function (func, threshold, execAsap) {
    var timeout;
    return function debounced () {
      var obj = this, args = arguments;
      function delayed () {
        if (!execAsap)
          func.apply(obj, args);
          timeout = null;
        };
      if (timeout) clearTimeout(timeout);
      else if (execAsap) func.apply(obj, args);
      timeout = setTimeout(delayed, threshold || 100);
    };
  }
  jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };
})(jQuery,'smartresize');

We move on into the main function, onComplete:. The first thing that we have to do is center the image vertically. But since the image takes a few millisecond to load we need to wait for it by using the setTimeout function.

onComplete:function(){
  setTimeout(function(){
    //lets get the image height and off set the almost half, it looks better is not completely center horizontally.
    imgh = ($('#cboxLoadedContent .ims_image img').height()/1.85);

    //get the box outer box height and calculate the center and set the image top attribute.
    $('#cboxLoadedContent .ims_image img').css({
      marginTop:$('#cboxLoadedContent #content').height()/2 - imgh
    });
  }, 150);
},

Test your gallery, you will see that there is a bounce affect happening when you click on next and previous image, we’ll fix that by applying a blend transition.

onComplete:function(){
  //hide image when it initially loads
  $('#cboxLoadedContent .ims_image').css({opacity:0});

  setTimeout(function(){
    //lets get the image height and off set the almost half, it looks better is not completely center horizontally.
    imgh = ($('#cboxLoadedContent .ims_image img').height()/1.85);

    //get the box outer box height and calculate the center and set the image top attribute.
    $('#cboxLoadedContent .ims_image img').css({
      marginTop:$('#cboxLoadedContent #content').height()/2 - imgh
    });

    //show image after the image has been centered
    $('#cboxLoadedContent .ims_image').animate({opacity:1},600);
  }, 150);
},

Click on the gallery image, the link will take you to the attachment page, and what we what is to display the next image without exiting colorbox. Add the following code after $(‘#cboxLoadedContent .ims_image’).animate({opacity:1},600);

$('#cboxLoadedContent .ims_image a.ims-image').bind( 'click', function(){
  $.colorbox.next( );
  return false;
});

We are almost finish, a neat functionally for Google+ galleries is the ability to hide the comments and expand you images, even if you close the image it saves your preferences; for that we will ned a couple of functions. Add the following code just bellow if( jQuery.colorbox && $(‘.ims-gallery .ims-img a’)[0])

//set the default status
var vstatus = 'open';

vclosed = function(){
  //hide link
  $('.attachment .expand').hide();

  // expand image set status
  $('#cboxLoadedContent .ims_image').animate({width:'100%'},300,function(){
    $('.attachment .expand').css({ left: img.offset().left + img.width()}).show(); vstatus = 'close';
  });

  //collapse comments
  if( vstatus == 'close' ) $('#comments').hide();
  else $('#comments').stop().animate({width:0},150,function(){ $(this).hide() })
}

vopened = function(){
  //hide link
  $('.attachment .expand').hide();

  // collapse image set status
  $('#cboxLoadedContent .ims_image').animate({width:'60%'},100,function(){
    $('.attachment .expand').css({ left: img.offset().left + img.width() - 83 }).show(); vstatus = 'open';
  });

  //expand comments
  $('#comments').stop().show().animate({width:'30%'},300);
}

We will add dynamically the expand image link. Add the following code just before $(‘#cboxLoadedContent .ims_image’).animate({opacity:1},600); in the onComplete method.

img = $('#cboxLoadedContent .ims_image img');
$('.attachment .expand').prependTo('.attachment .gallery-caption')
.css({ left: img.offset().left + img.width() - 83 }).click(function(){
  if( vstatus == 'close' ) vopened()
  else vclosed()
});

Finally add the following code before $(‘#cboxLoadedContent .ims_image’).css({opacity:0}). This will help us expand the image if the comments are hidden even after closing the colorbox window.

if( vstatus == 'close' ) vclosed();

That is it, you have now a full functioning Google+ like gallery. Here is the full javascript code just incase you missed something or you can download the file here. Please let me know if you have any question or you have any suggestions in how  to improve the gallery.

//samart window resize
(function($,sr){
  var debounce = function (func, threshold, execAsap) {
      var timeout;
      return function debounced () {
          var obj = this, args = arguments;
          function delayed () {
              if (!execAsap)
                  func.apply(obj, args);
              timeout = null;
          };
          if (timeout)
              clearTimeout(timeout);
          else if (execAsap)
              func.apply(obj, args);
          timeout = setTimeout(delayed, threshold || 100);
      };
  }
	jQuery.fn[sr] = function(fn){  return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };
})(jQuery,'smartresize');

 jQuery(document).ready(function($){

	//Google+ like gallery
		if( jQuery.colorbox && $('.single .ims-gallery .ims-img a')[0]){

			var vstatus = 'open';
			vclosed = function(){
				//hide link
				$('.attachment .expand').hide();

				// expand image set status
				$('#cboxLoadedContent .ims_image').animate({width:'100%'},300,function(){
					$('.attachment .expand').css({ left: img.offset().left + img.width()}).show();  vstatus = 'close';
				});

				//collapse comments
				if( vstatus == 'close' ) $('#comments').hide();
				else $('#comments').stop().animate({width:0},150,function(){ $(this).hide() })
			}

			vopened = function(){
				//hide link
				$('.attachment .expand').hide();

				// collapse image set status
				$('#cboxLoadedContent .ims_image').animate({width:'60%'},100,function(){
					$('.attachment .expand').css({ left: img.offset().left + img.width() - 83 }).show();  vstatus = 'open';
				});

				//expand comments
				$('#comments').stop().show().animate({width:'30%'},300);
			}

			var attr = {
				width:'98%',
				height:'95%',
				maxWidth:'98%',
				maxHeight:'95%',
				href:function(){
					return $(this).attr('href') + ' #content';
				},
				onOpen: function(){
					$(window).scrollTop( 0 );
					$('body').css({overflow:'hidden'});
				},
				onComplete:function(){
					if( vstatus == 'close' ) vclosed();

					//hide image when it initially loads
					$('#cboxLoadedContent .ims_image').css({opacity:0});

					setTimeout(function(){

						//lets get the image height and off set the almost half, it looks better is not completely center horizontally.
						imgh = ($('#cboxLoadedContent .ims_image img').height()/1.85);

						//get the box outer box height and calculate the center and set the image top attribute.
						$('#cboxLoadedContent .ims_image img').css({
							marginTop:$('#cboxLoadedContent #content').height()/2	- imgh
						});

						img = $('#cboxLoadedContent .ims_image img');
						$('.attachment .expand').prependTo('.attachment .gallery-caption')
						.css({ left: img.offset().left + img.width() - 83 }).click(function(){
							if( vstatus == 'close' )  vopened()
							else vclosed()
						});

						//show image after the image has been centered
						$('#cboxLoadedContent .ims_image').animate({opacity:1},600);

						//show next image
						$('#cboxLoadedContent .ims_image a.ims-image').bind( 'click', function(){
							$.colorbox.next( );
							return false;
						});

					}, 150);
				},
				onClosed: function(){
					$('body').css({overflow:'auto'});
				}
			}

			$.colorbox.remove();
			$('.single .ims-gallery .ims-img a').colorbox( attr );
			$(window).smartresize(function(){ $.fn.colorbox.load();});
		}

});

Shortcode

If you are planing to use the sortcode for your galleries, this is the code to use.

[ims-gallery id=GALLERYID number=NUMBER(8) linkto=attachment]

and you have to modify the following 2 lines to target the galleries

  • if( jQuery.colorbox && $(‘.single .ims-gallery .ims-img a’)[0])
  • $(‘.single .ims-gallery .ims-img a’).colorbox( attr );