prettyGallery & Magento

I really like the stuff that Stephane Caron does at No-Margin-For-Errors, he’s published some awesome jQuery plugins. For my money prettyPhoto is the best lightbox out there, and I recently had need to put a small image slider in a Magento site for a client in West Yorkshire.

The main Magento product image was to load in as a background image into a version of Scott Robbin’s jQuery plugin Backstretch which I customised to work on a container

rather than the body tag.

The designs from the agency (who I can’t mention – NDA) showed that additional images were loaded into a scrollable container further down the page, so I decided to use prettyGallery. It’s very small at 7KB, and having customised Stephan’s work before I knew it would be well laid out and coded, so if I needed to modify it I’d be able to.

So, putting it into the system. First of all, the prettyGallery documentation isn’t aimed at Magento users. It suggests you put the following code into the footer of each page;

<script type="text/javascript" charset="utf-8">
	$(document).ready(function(){
		$("ul.gallery").prettyGallery();
	});
</script>

First problem is that that isn’t written in jQuery noConflict mode, there will be problems with that piece of code and the Prototype library Magento uses. It should be written as;

<script type="text/javascript" charset="utf-8">
	var $j = jQuery.noConflict();
	$j(document).ready(function(){
		$j('.prettyGallery:first').prettyGallery();
		$j('.prettyGallery:last').prettyGallery({
			'navigation':'bottom',
			'itemsPerPage':2
		});
	});
</script>

The second point is that you really don’t want to be hardcoding script like this into the footer of the document. Only last night I was fixing the checkout on a Magento site for a client, there were conflicts stopping SagePay from working properly, so as a quick and dirty fix I removed the offending scripts in the checkout using a local.xml file. I couldn’t have done that if the script was in the footer.phtml template.

So I would include the initialisation of prettyGallery in it’s own file. As it’s likely to be with other $(document).ready functions I wil call it custom.js and include it as a file in page.xml.

Just as an aside – for anyone wanting to remove js in the checkout, the local.xml file would read;

<?xml version="1.0"?>
<layout version="0.1.0">
<default>
</default>

<checkout_onepage_index translate="label">
    <reference name="head">
        <action method="removeItem">
            <type>js</type>
            <name>jquery1.4.2.js</name>
        </action>
        <action method="removeItem">
            <type>js</type>
            <name>jquery.nivo.slider.js</name>
        </action>
        <action method="removeItem">
            <type>js</type>
            <name>jquery.prettyPhoto.js</name>
        </action>		
    </reference>
</checkout_onepage_index>

</layout>

So, next thing to note -> You have to modify the prettyGallery code. I modified it as shown below (I’ve only showed the start and the end of the file, the bit in the middle was untouched);


(function ($) {
	$.fn.prettyGallery = function(settings) {
	settings = jQuery.extend({
		itemsPerPage : 2,
		animationSpeed : 'normal', /* fast/normal/slow */
		navigation : 'top',  /* top/bottom/both */
		of_label: ' of ', /* The content in the page "1 of 2" */
		previous_title_label: 'Previous page', /* The title of the previous link */
		next_title_label: 'Next page', /* The title of the next link */
		previous_label: 'Previous', /* The content of the previous link */
		next_label: 'Next' /* The content of the next link */
	}, settings);
	return this.each(function(){
		// Global variables needed in multiple functions.	
		var currentPage = 1,
			itemWidth = 0,
			itemMargin = 0,
			itemHeight = 0,
			galleryWidth = 0,
			pageCount = 0,
			animated = false,
			$gallery = $(this);


...............  The main body of the code ..........................

		// Check if we need the gallery
		if($(this).find('li').size() > settings.itemsPerPage) {		
			// Set the number of pages
			pageCount = Math.ceil($(this).find('li').size() / settings.itemsPerPage);
			
			// Format the gallery properly
			_formatGallery();
			
			// Build and display the nav
			_applyNav();
			
			// Display the proper paging
			_displayPaging(this);
			currentPage = 1;
		};
	});
	};
})(jQuery);

I then just scrapped pretty much the whole of the template/catlog/product/view/media.phtml and replaced it with;

/**
 * Product media data template
 *
 * @see Mage_Catalog_Block_Product_View_Media
 */
?>
<?php
    $_product = $this->getProduct();
    $_helper = $this->helper('catalog/output');
?>
<?php if (count($this->getGalleryImages()) > 0): ?>
<div class="more-views">
    <ul class="prettyGallery">
    <?php foreach ($this->getGalleryImages() as $_image): ?>
        <li>
            <a href="<?php echo $this->helper('catalog/image')->init($this->getProduct(), 'image', $_image->getFile()); ?>"><img src="<?php echo $this->helper('catalog/image')->init($this->getProduct(), 'thumbnail', $_image->getFile())->resize(83,67); ?>" width="83" height="67" alt="<?php echo $this->htmlEscape($_image->getLabel()) ?>" /></a>
        </li>
    <?php endforeach; ?>
    </ul>
</div>
<?php endif; ?>

Voila, in business. Just a case of customising the look of it using the associated CSS>