jQuery Gallerific Again – Adding a Callback Property

If you’re not aware, jQuery Gallerific plugin supports keyboard navigation for navigating through the images by using the arrow keys, space bar, end and home keys. I have added feature on my page so that captions can be edited in place. However, when you press any of the navigation keys (space bar for example), the navigation event is triggered thus jumping to the next image. My edit-in-place will not work.

Overview

This page has been working for several months already using a hacked jQuery Gallerific plugin to display the picture gallery. Recently I need to add a feature that allows the uploader to edit the caption or to delete the image. To make it nicer, I make it possible to edit the caption in-place (the caption transforms into a textbox).

Because jQuery Gallerific’s keyboard navigation is turned on, it triggers every time the user presses keys like arrow keys, space bar, home or end keys. Sure e.stopPropagation() is a workaround, however, since those elements under the caption container are re-located by the plugin as new image is selected, it must use live binding. And with live binding, e.stopPropagation() will not work.

There are ways that I think will be a viable workaround. First, to add a property on the plugin that allows the outsider script to turn on or off the keyboard navigation. The problem is that those properties cannot be accessed directly from the outside because of scoping issues and of course that is by design. So I throw away the idea.

The next option is to pass a callback function as a parameter / plugin property. That callback is accessible at global scope and that a flag can be set to on or off anytime. So that’s it!

How do we do it?

First, we need to modify the jQuery gallerific plugin. That’s the only way to extend it. On this first step, there are two sub-steps.

  1. Add the callback property to the default properties.
  2. Modify the keyboard navigation to check for the callback property return value.

1.1 Add callback default property. Below is the code snippet where I added a new property enableKeyboardNavFunc and initialized with undefined.

syncTransitions:           false,
defaultTransitionDuration: 1000,
onSlideChange:             undefined,
onTransitionOut:           undefined,
onTransitionIn:            undefined,
onPageTransitionOut:       undefined,
onPageTransitionIn:        undefined,
onImageAdded:              undefined,
onImageRemoved:            undefined,
enableKeyboardNavFunc: 	   undefined  // allows toggling keyboard navigation outside the plugin

1.2 Modify the keyboard navigation event so that it checks first if the keyboard navigation is turned on or off outside by calling the callback property. Added / modified lines are lines 5 to 15. In line 11, it calls the callback function to check if there’s a request to disable the keyboard navigation temporarily.

// Setup Keyboard Navigation
if (this.enableKeyboardNavigation) {
	$(document).keydown(function(e) {
		var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
		var possibleKeys = [32, 33, 34, 35, 36, 37, 39];
		
		// Check if keyboard navigation event is enabled/disabled
		// outside the plugin
		if (typeof gallery.enableKeyboardNavFunc != "undefined")
		{
			if ($.inArray(key, possibleKeys) != -1 && gallery.enableKeyboardNavFunc() === false)
			{
				return;
			}
		}
		
		switch(key) {
			case 32: // space
				gallery.next();
				e.preventDefault();
				break;
			case 33: // Page Up
				gallery.previousPage();
				e.preventDefault();
				break;
			case 34: // Page Down
				gallery.nextPage();
				e.preventDefault();
				break;

Second, create a callback function on your script that is of global scope so that other scripts can access and alter its values. Well, what I did was to create an object with a function on it. The flag property is accessible to my other scripts that handlers the in-place edit feature. I make it as an object to avoid name clashes. The isEnabled() method will be used as a callback.

/**
 * Callback for gallerific keyboard navigation so that it can be turned on or off
 *
 */
var GKeyboardNav = {
	flag: true,
	
	/**
	 * Returns whether or not the keyboard navigation must be enabled
	 * 
	 * @returns boolean
	 */
	isEnabled: function()
	{
		return this.flag;
	}
};

Third, inject the callback during Gallerific’s initialization. Notice the key enableKeyboardNavFunc. That is our plugin’s property discussed on step 1. I used an anonymous function since I cannot pass the function name directly. I haven’t tried enclosing them with quotes but this may also work enableKeyboardNavFunc: "GKeyboardNav.isEnabled()".

// Initialize Advanced Galleriffic Gallery
var gallery = $('#thumbs').galleriffic({
	delay:                     2000,
	numThumbs:                 10,
	preloadAhead:              10,
	enableTopPager:            true,
	enableBottomPager:         true,
	maxPagesToShow:            7,
	imageContainerSel:         '#slideshow',
	controlsContainerSel:      '#controls',
	captionContainerSel:       '#caption',
	loadingContainerSel:       '#loading',
	onSlideChange:             function(prevIndex, nextIndex) {
		// 'this' refers to the gallery, which is an extension of $('#thumbs')
		this.find('ul.thumbs').children()
			.eq(prevIndex).fadeTo('fast', onMouseOutOpacity).end()
			.eq(nextIndex).fadeTo('fast', 1.0);
			
		// Re-enable keyboard navigation globally
		GKeyboardNav.flag = true;
	},
	...
	...
	,
	enableKeyboardNavFunc: function(){
		return GKeyboardNav.isEnabled();
	}
});

Now that it is finally set up, we will go to our other scripts. The script that handles in-place editing of caption. This is how I integrate it to my caption manager object.

/**
 * Provides various helpers for manipulating the image captions
 * and controls
 */
var CaptionManager = {
	/**
	 * Shows the edit caption controls
	 *
	 * @param int spotImageNo
	 * @returns this
	 */
	showEditCaption: function(spotImageNo)
	{
		// Disable keyboard navigation for a while
		GKeyboardNav.flag = false;
		
		// Fill the textbox with values and show the container
		$("#photo-caption-" + spotImageNo).val(this.getCaption(spotImageNo));
		$("#photo-category-" + spotImageNo).val(this.getOriginalCategory(spotImageNo));
		
		$("#spot_image_caption-" + spotImageNo + " span.editable-caption").show();
		
		return this;
	},
	
	/**
	 * Hides the edit caption controls
	 *
	 * @param int spotImageNo
	 * @returns this
	 */
	hideEditCaption: function(spotImageNo)
	{
		// Re-enable keyboard navigation
		// Disable keyboard navigation for a while
		GKeyboardNav.flag = true;
		
		// There's nothing special to do here but just hide it
		$("#spot_image_caption-" + spotImageNo + " span.editable-caption").hide();
		
		return this;
	},

When the editable caption is shown, we write GKeyboardNav.flag = false; to disable keyboard navigation while typing something for the caption. Once the editing finished, the editable caption is hidden and the keyboard navigation is re-enabled.

However, we have a problem. When the editable caption is shown, but the user suddenly clicks on another image from the thumbnails, the keyboard navigation is still disabled this time. To solve that, we will re-enable keyboard navigation when the slide changes. This was actually written but unexplained above.

On gallerific’s onSlideChange callback event, we re-enables the keyboard navigation. That was also written on step 3 but not explained thouroughly.

autoStart:                 false,
syncTransitions:           true,
defaultTransitionDuration: 900,
onSlideChange:             function(prevIndex, nextIndex) {
	// 'this' refers to the gallery, which is an extension of $('#thumbs')
	this.find('ul.thumbs').children()
		.eq(prevIndex).fadeTo('fast', onMouseOutOpacity).end()
		.eq(nextIndex).fadeTo('fast', 1.0);
		
	// Re-enable keyboard navigation globally
	GKeyboardNav.flag = true;
},

That’s all.

This entry was posted in Uncategorized and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *