Tuesday, November 8, 2011

Fancybox gallery for an element with a tooltip: why is the first title not showing?

Please, refer to this article as a reference how to create fancy tooltips for elements and to the Fancybox site to see how to configure it to display images and galleries.

The problem with the mentioned approach to create tooltips is that the "title" attribute gets reassigned and blanked out when we mouse over the element, but it could be used by other plugins such as Fancybox. Fancybox uses the "title" attribute to add a title to a zoomed in element. If this element also has a tooltip, then clicking on the element will result in the slide title not showing, since we didn't exit the element yet, and the "title" attribute value didn't get assigned back. If we have a gallery, then the titles are showing fine for the next elements since we didn't have the mouse over them.

We can fix this problem in a very simple way, force the mouse exit event once we click on the element. The "title" attribute is assigned back as the mouse leaves the element, as this way the problem will be fixed.

Fancybox has an onStart attribute where we can call this function.

(function ($) {

$(function() {

function closeTooltip() {
$(".slide-content:visible a").trigger("mouseleave");
}
$(".slide-content a").fancybox({
'transitionIn':'elastic',
'transitionOut':'none',
'speedIn':600,
'speedOut':200,
'overlayShow':true,
'overlayColor':'#000',
'cyclic':true,
'easingIn':'easeInOutExpo',
'margin':'10px',
'onStart':function() {closeTooltip();}
});
});
}) (jQuery);


"slide-content" is a wrapper for the slide (can be a different class name) and "a" is the link for the tooltip and the Fancybox element. Now the "title" attribute will get reassigned and the slide title will be showing fine.

Monday, November 7, 2011

Using Cloud Zoom with a slide show: why the lens doesn't work properly

I was trying to use the slideshow plugin from JQuery Tools with the Cloud Zoom plugin. In addition to having a slide show, I wanted to zoom in pictures in the slide show with Cloud Zoom. Please, refer to the links provided how to create a slideshow and configure Cloud Zoom for images.

But the lens didn't work for the slideshow, I was only able to catch a microscopic lens 2x2px in the top left corner of the image.

The reason why it works this way is that Cloud Zoom creates a wrapper and a "mousetrap" elements for an image after the image is loaded, with the size of the "mousetrap" corresponding to the image size. In my case, initially all the images in the slideshow are hidden ("display:none"), so the images sizes are 0, so the "mousetrap" element is created only 2x2px big.

To fix it, we need to activate Cloud Zoom for an image only when the corresponding slide is shown. To disable Cloud Zoom initially, replace 'class="cloud-zoom"' with 'class="_cloud-zoom"'.

We don't have any "show" events in Javascript, but luckily, we know that the slideshow uses the "show()" method to make a slide visible and we can override this method in JQuery in order to trigger an event.

//trigger an event on show
var _oldShow = $j.fn.show;
$j.fn.show = function() {
var hidden = this.find(":hidden").add(this.filter(":hidden"));
var result = _oldShow.apply(this, arguments);
hidden.filter(":visible").each(function(){
$j(this).triggerHandler("show"); //No bubbling
});
return result;
};


Add this function to the page and it will trigger an event when show() is called on an element or its children. I borrowed it from this discussion, other solutions can be also used.

We also need to catch this event when a slide is shown and activate Cloud Zoom for the image.

(function ($) {
function activateCloudZoom(elem) {
elem.attr("class", "cloud-zoom");
elem.CloudZoom();
elem.css("position", "static").css("display", "inline");

$j(function() {
//slideshow activation
$j(".slidetabs").tabs(".slides > div", {

// enable "cross-fading" effect
effect: 'fade',
fadeOutSpeed: "slow",

// start from the beginning after the last tab
rotate: true

// use the slideshow plugin. It accepts its own configuration
}).slideshow();

//Cloud Zoom activation
$(".slide-content").bind("show", function() {
activateCloudZoom($(this).find("._cloud-zoom"));
});
});
})(jQuery);


We change the image class name to "cloud-zoom" and attach the handler to it (it's normally done automatically on the document loading, but we didn't have that). I also changed some display parameters as the parameters set by Cloud Zoom interfere with the slide text. The "show" event is bound to the slide container on the document loading (it might have a different class name).

That's it! Now the lens will be showing normally corresponding to its configuration parameters.