fancyBox - touch enabled, responsive and fully customizable lightbox script

- Introduction
- Setup
- How to Use
- Media types
  - Images
  - Inline
  - Ajax
  - Iframe
- Embedding
- Options
- Api
- Modules
- FAQ

## Introduction

fancyBox is a JavaScript library used to present images, videos and any html content in an elegant way. It has all features you would expect - touch enabled, responsive and fully customizable.

### Dependencies

jQuery 3+ is preferred, but fancyBox works with jQuery 1.9.1+ and jQuery 2+

#### Important

If you experience issues with image zooming, then update jQuery to the latest (at least v3.2.1).

### Compatibility

fancyBox includes support for touch gestures and even supports pinch gestures for zooming. It is perfectly suited for both mobile and desktop browsers.

fancyBox has been tested in following browsers/devices:

- Chrome
- Firefox
- IE10/11
- Edge
- iOS Safari
- Nexus 7 Chrome

## Setup

You can install fancyBox by linking `.css` and `.js` to your html file. Make sure you also load the jQuery library. Below is a basic HTML template to use as an example:

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>My page</title>

    	<!-- CSS -->
    	<link rel="stylesheet" type="text/css" href="jquery.fancybox.min.css">
    </head>
    <body>

    	<!-- Your HTML content goes here -->

    	<!-- JS -->
    	<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
    	<script src="jquery.fancybox.min.js"></script>
    </body>
    </html>

#### Important

- Make sure you add the jQuery library first
- If you already have jQuery on your page, you shouldn't include it second time
- Do not include both fancybox.js and fancybox.min.js files
- Some functionality (ajax, iframes, etc) will not work when you're opening local file directly on your browser, the code must be running on a web server

### Download fancyBox

You can download the latest version of fancyBox on GitHub.
Or just link directly to fancyBox files on cdnjs - https://cdnjs.com/libraries/fancybox.

### Package Managers

fancyBox can also be installed via Bower or npm.

    # NPM
    npm install @fancyapps/fancybox --save

    # Bower
    bower install fancybox --save

## How to Use

### Initialize with data attributes

The most basic way to use fancyBox is by adding the `data-fancybox` attribute to a link. A caption can be added using the `data-caption` attribute. Example:

    <a href="image.jpg" data-fancybox data-caption="My caption">
    	<img src="thumbnail.jpg" alt="" />
    </a>

View demo on CodePen

If you choose this method, default settings will be applied. See Options section for examples how to customize by changing defaults or using `data-options` attribute.

### Initialize with JavaScript

Select elements with a jQuery selector and call the `fancybox` method:

    <script type="text/javascript">
    	$("[data-fancybox]").fancybox({
    		// Options will go here
    	});
    </script>

View demo on CodePen

Using this method, click event handler is attached only to the currently selected elements.
To attach click event listener for elements that exist now or in the future, use `selector` option. Example:

    $().fancybox({
      selector : '[data-fancybox="images"]',
      loop     : true
    });

View demo on CodePen

### Manual calling of fancyBox

fancyBox can be activated at any point within Javascript and therefore does not necessarily need a trigger element. Example of displaying a simple message:

    $.fancybox.open('<div class="message"><h2>Hello!</h2><p>You are awesome!</p></div>');

View demo on CodePen

See API section for more information and examples.

### Grouping

If you have a group of items, you can use the same attribute `data-fancybox` value for each of them to create a gallery. Each group should have a unique value:

    <a href="image_1.jpg" data-fancybox="group" data-caption="Caption #1">
    	<img src="thumbnail_1.jpg" alt="" />
    </a>

    <a href="image_2.jpg" data-fancybox="group" data-caption="Caption #2">
    	<img src="thumbnail_2.jpg" alt="" />
    </a>

View demo on CodePen

#### Important

fancyBox attempts to automatically detect the type of content based on the given url. If it cannot be detected, the type can also be set manually using `data-type` attribute:

    <a href="images.php?id=123" data-type="image" data-caption="Caption">
    	Show image
    </a>

## Media types

### Images

The standard way of using fancyBox is with a number of thumbnail images that link to larger images:

    <a href="image.jpg" data-fancybox="images" data-caption="My caption">
    	<img src="thumbnail.jpg" alt="" />
    </a>

View demo on CodePen

By default, fancyBox fully preloads an image before displaying it. You can choose to display the image right away. It will render and show the full size image while the data is being received. To do so, some attributes are necessary:

- `data-width` - the real width of the image
- `data-height` - the real height of the image

    <a href="image.jpg" data-fancybox="images" data-width="2048" data-height="1365">
        <img src="thumbnail.jpg" />
    </a>

View demo on CodePen

fancyBox supports "scrset" so I can display different images based on viewport width. You can use this to improve download times for mobile users and over time save bandwidth. Example:

    <a href="medium.jpg" data-fancybox="images" data-srcset="large.jpg 1600w, medium.jpg 1200w, small.jpg 640w">
    	<img src="thumbnail.jpg" />
    </a>

View demo on CodePen

It is also possible to protect images from downloading by right-click. While this does not protect from truly determined users, it should discourage the vast majority from ripping off your files.

    $('[data-fancybox]').fancybox({
    	protect: true
    });

View demo on CodePen

### Inline HTML

For inline content, create a hidden element with unique id:

    <div style="display: none;" id="hidden-content">
    	<h2>Hello</h2>
    	<p>You are awesome.</p>
    </div>

And then simply create a link having `data-src` attribute that matches ID of the element you want to open (preceded by a hash mark (#); in this example - `#hidden-content`):

    <a data-fancybox data-src="#hidden-content" href="javascript:;">
    	Trigger the fancyBox
    </a>

View demo on CodePen

The script will append small close button (if you have not disabled by `smallBtn:false`) and will not apply any styles except for centering. Therefore you can easily set custom dimensions using CSS.

### Ajax

To load content via AJAX, you need to add a `data-type="ajax"` attribute to your link:

    <a data-fancybox data-type="ajax" data-src="my_page.com/path/to/ajax/" href="javascript:;">
    	AJAX content
    </a>

View demo on CodePen

Additionally it is possible to define a selector with the `data-filter` attribute to show only a part of the response. The selector can be any string, that is a valid jQuery selector:

    <a data-fancybox data-type="ajax" data-src="my_page.com/path/to/ajax/" data-filter="#two" href="javascript:;">
    	AJAX content
    </a>

View demo on CodePen

### Iframe

If the content can be shown on a page, and placement in an iframe is not blocked by script or security configuration of that page, it can be presented in a fancyBox:

    <a data-fancybox data-type="iframe" data-src="http://codepen.io/fancyapps/full/jyEGGG/" href="javascript:;">
    	Webpage
    </a>

    <a data-fancybox data-type="iframe" data-src="https://mozilla.github.io/pdf.js/web/viewer.html" href="javascript:;">
    	Sample PDF
    </a>

View demo on CodePen

To access and control fancyBox in parent window from inside an iframe:

    // Adjust iframe height according to the contents
    parent.jQuery.fancybox.getInstance().update();

    // Close current fancyBox instance
    parent.jQuery.fancybox.getInstance().close();

Iframe dimensions can be controlled by CSS:

    .fancybox-slide--iframe .fancybox-content {
    	width  : 800px;
    	height : 600px;
    	max-width  : 80%;
    	max-height : 80%;
    	margin: 0;
    }

These CSS rules can be overridden by JS, if needed:

    $("[data-fancybox]").fancybox({
    	iframe : {
    		css : {
    			width : '600px'
    		}
    	}
    });

If you have not disabled iframe preloading (using `preload` option), then the script will atempt to calculate content dimensions and will adjust width/height of iframe to fit with content in it. Keep in mind, that due to same origin policy, there are some limitations.

This example will disable iframe preloading and will display small close button next to iframe instead of the toolbar:

    $('[data-fancybox]').fancybox({
    	toolbar  : false,
    	smallBtn : true,
    	iframe : {
    		preload : false
    	}
    })

View demo on CodePen

## Embedding

Supported sites can be used with fancyBox by just providing the page URL:

    <a data-fancybox href="https://www.youtube.com/watch?v=_sI_Ps7JSEk">
      YouTube video
    </a>

    <a data-fancybox href="https://vimeo.com/191947042">
      Vimeo video
    </a>

    <a data-fancybox href="https://www.google.com/maps/search/Empire+State+Building/">
    	Google Map
    </a>

    <a data-fancybox href="https://www.instagram.com/p/BNXYW8-goPI/?taken-by=jamesrelfdyer" data-caption="<span title=&quot;Edited&quot;>balloon rides at dawn ✨🎈<br>was such a magical experience floating over napa valley as the golden light hit the hills.<br><a href=&quot;https://www.instagram.com/jamesrelfdyer/&quot;>@jamesrelfdyer</a></span>">
    	Instagram photo
    </a>

View demo on CodePen

### Video dimensions

Resize video display with the following CSS:

    .fancybox-slide--video .fancybox-content {
    	width  : 800px;
    	height : 600px;
    	max-width  : 80%;
    	max-height : 80%;
    }

View demo on CodePen

Obviously, you can choose any size you like, any combination with `min`/`max` values.
Aspect ratio lock for videos is not implemented yet, but if you wish, you can use this snippet.

### Video parameters

Controlling a video via URL parameters:

    <a data-fancybox href="https://www.youtube.com/watch?v=_sI_Ps7JSEk&amp;autoplay=1&amp;rel=0&amp;controls=0&amp;showinfo=0">
      YouTube video - hide controls and info
    </a>

    <a data-fancybox href="https://vimeo.com/191947042?color=f00">
      Vimeo video - custom color
    </a>

View demo on CodePen

Via JavaScript:

    $('[data-fancybox]').fancybox({
    	youtube : {
    		controls : 0,
    		showinfo : 0
    	},
    	vimeo : {
    		color : 'f00'
    	}
    });

View demo on CodePen

## Options

Quick reference for all default options as defined in the source:

    var defaults = {

        // Enable infinite gallery navigation
        loop : false,

        // Space around image, ignored if zoomed-in or viewport width is smaller than 800px
        margin : [44, 0],

        // Horizontal space between slides
        gutter : 50,

        // Enable keyboard navigation
        keyboard : true,

        // Should display navigation arrows at the screen edges
        arrows : true,

        // Should display infobar (counter and arrows at the top)
        infobar : true,

        // Should display toolbar (buttons at the top)
        toolbar : true,

        // What buttons should appear in the top right corner.
        // Buttons will be created using templates from `btnTpl` option
        // and they will be placed into toolbar (class="fancybox-toolbar"` element)
        buttons : [
            'slideShow',
            'fullScreen',
            'thumbs',
            'share',
            //'download',
            //'zoom',
            'close'
        ],

        // Detect "idle" time in seconds
        idleTime : 3,

        // Should display buttons at top right corner of the content
        // If 'auto' - they will be created for content having type 'html', 'inline' or 'ajax'
        // Use template from `btnTpl.smallBtn` for customization
        smallBtn : 'auto',

        // Disable right-click and use simple image protection for images
        protect : false,

        // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
        modal : false,

        image : {

            // Wait for images to load before displaying
            // Requires predefined image dimensions
            // If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
            preload : "auto"

        },

        ajax : {

            // Object containing settings for ajax request
            settings : {

                // This helps to indicate that request comes from the modal
                // Feel free to change naming
                data : {
                    fancybox : true
                }
            }

        },

        iframe : {

            // Iframe template
            tpl : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',

            // Preload iframe before displaying it
            // This allows to calculate iframe content width and height
            // (note: Due to "Same Origin Policy", you can't get cross domain data).
            preload : true,

            // Custom CSS styling for iframe wrapping element
            // You can use this to set custom iframe dimensions
            css : {},

            // Iframe tag attributes
            attr : {
                scrolling : 'auto'
            }

        },

        // Default content type if cannot be detected automatically
        defaultType : 'image',

        // Open/close animation type
        // Possible values:
        //   false            - disable
        //   "zoom"           - zoom images from/to thumbnail
        //   "fade"
        //   "zoom-in-out"
        //
        animationEffect : "zoom",

        // Duration in ms for open/close animation
        animationDuration : 500,

        // Should image change opacity while zooming
        // If opacity is "auto", then opacity will be changed if image and thumbnail have different aspect ratios
        zoomOpacity : "auto",

        // Transition effect between slides
        //
        // Possible values:
        //   false            - disable
        //   "fade'
        //   "slide'
        //   "circular'
        //   "tube'
        //   "zoom-in-out'
        //   "rotate'
        //
        transitionEffect : "fade",

        // Duration in ms for transition animation
        transitionDuration : 366,

        // Custom CSS class for slide element
        slideClass : '',

        // Custom CSS class for layout
        baseClass : '',

        // Base template for layout
        baseTpl	:
            '<div class="fancybox-container" role="dialog" tabindex="-1">' +
                '<div class="fancybox-bg"></div>' +
                '<div class="fancybox-inner">' +
                    '<div class="fancybox-infobar">' +
                        '<span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span>' +
                    '</div>' +
                    '<div class="fancybox-toolbar">{{buttons}}</div>' +
                    '<div class="fancybox-navigation">{{arrows}}</div>' +
                    '<div class="fancybox-stage"></div>' +
                    '<div class="fancybox-caption-wrap"><div class="fancybox-caption"></div></div>' +
                '</div>' +
            '</div>',

        // Loading indicator template
        spinnerTpl : '<div class="fancybox-loading"></div>',

        // Error message template
        errorTpl : '<div class="fancybox-error"><p>{{ERROR}}<p></div>',

        btnTpl : {

            download : '<a download data-fancybox-download class="fancybox-button fancybox-button--download" title="{{DOWNLOAD}}">' +
                        '<svg viewBox="0 0 40 40">' +
                            '<path d="M20,23 L20,8 L20,23 L13,16 L20,23 L27,16 L20,23 M26,28 L13,28 L27,28 L14,28" />' +
                        '</svg>' +
                    '</a>',

            zoom : '<button data-fancybox-zoom class="fancybox-button fancybox-button--zoom" title="{{ZOOM}}">' +
                        '<svg viewBox="0 0 40 40">' +
                            '<path d="M 18,17 m-8,0 a 8,8 0 1,0 16,0 a 8,8 0 1,0 -16,0 M25,23 L31,29 L25,23" />' +
                        '</svg>' +
                    '</button>',

            close : '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}">' +
                        '<svg viewBox="0 0 40 40">' +
                            '<path d="M10,10 L30,30 M30,10 L10,30" />' +
                        '</svg>' +
                    '</button>',

            // This small close button will be appended to your html/inline/ajax content by default,
            // if "smallBtn" option is not set to false
            smallBtn   : '<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"></button>',

            // Arrows
            arrowLeft : '<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}">' +
                            '<svg viewBox="0 0 40 40">' +
                              '<path d="M10,20 L30,20 L10,20 L18,28 L10,20 L18,12 L10,20"></path>' +
                            '</svg>' +
                          '</button>',

            arrowRight : '<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}">' +
                          '<svg viewBox="0 0 40 40">' +
                            '<path d="M30,20 L10,20 L30,20 L22,28 L30,20 L22,12 L30,20"></path>' +
                          '</svg>' +
                        '</button>'
        },

        // Container is injected into this element
        parentEl : 'body',

        // Focus handling
        // ==============

        // Try to focus on the first focusable element after opening
        autoFocus : false,

        // Put focus back to active element after closing
        backFocus : true,

        // Do not let user to focus on element outside modal content
        trapFocus : true,

        // Module specific options
        // =======================

        fullScreen : {
            autoStart : false,
        },

        // Set `touch: false` to disable dragging/swiping
        touch : {
            vertical : true,  // Allow to drag content vertically
            momentum : true   // Continue movement after releasing mouse/touch when panning
        },

        // Hash value when initializing manually,
        // set `false` to disable hash change
        hash : null,

        // Customize or add new media types
        // Example:
        /*
        media : {
            youtube : {
                params : {
                    autoplay : 0
                }
            }
        }
        */
        media : {},

        slideShow : {
            autoStart : false,
            speed     : 4000
        },

        thumbs : {
            autoStart   : false,                  // Display thumbnails on opening
            hideOnClose : true,                   // Hide thumbnail grid when closing animation starts
            parentEl    : '.fancybox-container',  // Container is injected into this element
            axis        : 'y'                     // Vertical (y) or horizontal (x) scrolling
        },

        // Use mousewheel to navigate gallery
        // If 'auto' - enabled for images only
        wheel : 'auto',

        // Callbacks
        //==========

        // See Documentation/API/Events for more information
        // Example:
        /*
            afterShow: function( instance, current ) {
                 console.info( 'Clicked element:' );
                 console.info( current.opts.$orig );
            }
        */

        onInit       : $.noop,  // When instance has been initialized

        beforeLoad   : $.noop,  // Before the content of a slide is being loaded
        afterLoad    : $.noop,  // When the content of a slide is done loading

        beforeShow   : $.noop,  // Before open animation starts
        afterShow    : $.noop,  // When content is done loading and animating

        beforeClose  : $.noop,  // Before the instance attempts to close. Return false to cancel the close.
        afterClose   : $.noop,  // After instance has been closed

        onActivate   : $.noop,  // When instance is brought to front
        onDeactivate : $.noop,  // When other instance has been activated

        // Interaction
        // ===========

        // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
        // each option can be string or method that returns value.
        //
        // Possible values:
        //   "close"           - close instance
        //   "next"            - move to next gallery item
        //   "nextOrClose"     - move to next gallery item or close if gallery has only one item
        //   "toggleControls"  - show/hide controls
        //   "zoom"            - zoom image (if loaded)
        //   false             - do nothing

        // Clicked on the content
        clickContent : function( current, event ) {
            return current.type === 'image' ? 'zoom' : false;
        },

        // Clicked on the slide
        clickSlide : 'close',

        // Clicked on the background (backdrop) element
        clickOutside : 'close',

        // Same as previous two, but for double click
        dblclickContent : false,
        dblclickSlide   : false,
        dblclickOutside : false,

        // Custom options when mobile device is detected
        // =============================================

        mobile : {
            idleTime : false,
            margin   : 0,

            clickContent : function( current, event ) {
                return current.type === 'image' ? 'toggleControls' : false;
            },
            clickSlide : function( current, event ) {
                return current.type === 'image' ? 'toggleControls' : 'close';
            },
            dblclickContent : function( current, event ) {
                return current.type === 'image' ? 'zoom' : false;
            },
            dblclickSlide : function( current, event ) {
                return current.type === 'image' ? 'zoom' : false;
            }
        },

        // Internationalization
        // ============

        lang : 'en',
        i18n : {
            'en' : {
                CLOSE       : 'Close',
                NEXT        : 'Next',
                PREV        : 'Previous',
                ERROR       : 'The requested content cannot be loaded. <br/> Please try again later.',
                PLAY_START  : 'Start slideshow',
                PLAY_STOP   : 'Pause slideshow',
                FULL_SCREEN : 'Full screen',
                THUMBS      : 'Thumbnails',
                DOWNLOAD    : 'Download',
                SHARE       : 'Share',
                ZOOM        : 'Zoom'
            },
            'de' : {
                CLOSE       : 'Schliessen',
                NEXT        : 'Weiter',
                PREV        : 'Zurück',
                ERROR       : 'Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es später nochmal.',
                PLAY_START  : 'Diaschau starten',
                PLAY_STOP   : 'Diaschau beenden',
                FULL_SCREEN : 'Vollbild',
                THUMBS      : 'Vorschaubilder',
                DOWNLOAD    : 'Herunterladen',
                SHARE       : 'Teilen',
                ZOOM        : 'Maßstab'
            }
        }

    };

Set instance options by passing a valid object to `fancybox()` method:

    $("[data-fancybox]").fancybox({
    	thumbs : {
    		autoStart : true
    	}
    });

Plugin options / defaults are exposed in `$.fancybox.defaults` namespace so you can easily adjust them globally:

    $.fancybox.defaults.animationEffect = "fade";

Custom options for each element individually can be set by adding a `data-options` attribute to the element. This attribute should contain the properly formatted JSON object:

    <a data-fancybox data-options='{"caption" : "My caption", "src" : "https://codepen.io/about/", "type" : "iframe"}' href="javascript:;" class="btn">
    	Open external page
    </a>

View demo on CodePen

## API

The fancyBox API offers a couple of methods to control fancyBox. This gives you the ability to extend the plugin and to integrate it with other web application components.

### Core methods

Core methods are methods which affect/handle instances:

    // Close only the currently active or all fancyBox instances
    $.fancybox.close( true );

    // Open the fancyBox right away
    $.fancybox.open( items, opts, index );

Gallery items can be collection of jQuery objects or array containing plain objects. This can be used, for example, to create custom click event.

    var $links = $('.fancybox');

    $links.on('click', function() {

    	$.fancybox.open( $links, {
    		// Custom options
    	}, $links.index( this ) );

    	return false;
    });

When creating group objects manually, each item should follow this pattern:

    {
    	src  : '' // Source of the content
    	type : '' // Content type: image|inline|ajax|iframe|html (optional)
    	opts : {} // Object containing item options (optional)
    }

Example of opening image gallery programmatically:

    $.fancybox.open([
    	{
    		src  : '1_b.jpg',
    		opts : {
    			caption : 'First caption'
    		}
    	},
    	{
    		src  : '2_b.jpg',
    		opts : {
    			caption : 'Second caption'
    		}
    	}
    ], {
    	loop : false
    });

View demo on CodePen

It is also possible to pass only one object. Example of opening inline content:

    $.fancybox.open({
    	src  : '#hidden-content',
    	type : 'inline',
    	opts : {
    		afterShow : function( instance, current ) {
    			console.info( 'done!' );
    		}
    	}
    });

View demo on CodePen

If you wish to display some html content (for example, a message), then you can use a simpler syntax. It is advised to use a wrapper around your content.

    $.fancybox.open('<div class="message"><h2>Hello!</h2><p>You are awesome!</p></div>');

View demo on CodePen

### Instance methods

In order to use these methods, you need an instance of the plugin's object.

    var instance = $.fancybox.open(
    	// Your content and options
    );

Get reference to currently active instance:

    var instance = $.fancybox.getInstance();

The first argument of the callback is reference to instance:

    $("[data-fancybox]").fancybox({
    	afterShow : function( instance, current ) {
    		console.info( instance );
    	}
    });

Once you have a reference to fancyBox instance the following methods are available:

    // Go to next gallery item
    instance.next( duration );

    // Go to previous gallery item
    instance.previous( duration );

    // Switch to selected gallery item
    instance.jumpTo( index, duration );

    // Check if current image dimensions are smaller than actual
    instance.isScaledDown();

    // Scale image to the actual size of the image
    instance.scaleToActual( x, y, duration );

    // Check if image dimensions exceed parent element
    instance.canPan();

    // Scale image to fit inside parent element
    instance.scaleToFit( duration );

    // Update position and content of all slides
    instance.update();

    // Update slide position and scale content to fit
    instance.updateSlide( slide );

    // Update infobar values, navigation button states and reveal caption
    instance.updateControls( force );

    // Load custom content into the slide
    instance.setContent( slide, content );

    // Show loading icon inside the slide
    instance.showLoading( slide );

    // Remove loading icon from the slide
    instance.hideLoading( slide );

    // Try to find and focus on the first focusable element
    instance.focus();

    // Activates current instance, brings it to the front
    instance.activate();

    // Close instance
    instance.close();

You can also do something like this:

    $.fancybox.getInstance().jumpTo(1);

or simply:

    $.fancybox.getInstance('jumpTo', 1);

### Events

fancyBox fires several events:

    beforeLoad   : Before the content of a slide is being loaded
    afterLoad    : When the content of a slide is done loading

    beforeShow   : Before open animation starts
    afterShow    : When content is done loading and animating

    beforeClose  : Before the instance attempts to close. Return false to cancel the close.
    afterClose   : After instance has been closed

    onInit       : When instance has been initialized
    onActivate   : When instance is brought to front
    onDeactivate : When other instance has been activated

Event callbacks can be set as function properties of the options object passed to fancyBox initialization function:

    <script type="text/javascript">
    	$("[data-fancybox]").fancybox({
    		afterShow: function( instance, slide ) {

    			// Tip: Each event passes useful information within the event object:

    			// Object containing references to interface elements
    			// (background, buttons, caption, etc)
    			// console.info( instance.$refs );

    			// Current slide options
    			// console.info( slide.opts );

    			// Clicked element
    			// console.info( slide.opts.$orig );

    			// Reference to DOM element of the slide
    			// console.info( slide.$slide );

    		}
    	});
    </script>

Each callback receives two parameters - current fancyBox instance and current gallery object, if exists.

It is also possible to attach event handler for all instances. To prevent interfering with other scripts, these events have been namespaced to `.fb`. These handlers receive 3 parameters - event, current fancyBox instance and current gallery object.

Here is an example of binding to the `afterShow` event:

    $(document).on('afterShow.fb', function( e, instance, slide ) {
    	// Your code goes here
    });

If you wish to prevent closing of the modal (for example, after form submit), you can use `beforeClose` callback. Simply return `false`:

    beforeClose : function( instance, current, e ) {
    	if ( $('#my-field').val() == '' ) {
    		return false;
    	}
    }

## Modules

fancyBox code is split into several files (modules) that extend core functionality. You can build your own fancyBox version by excluding unnecessary modules, if needed. Each one has their own `js` and/or `css` files.

Some modules can be customized and controlled programmatically. List of all possible options:

    fullScreen : {
    	autoStart : false,
    },

    touch : {
    	vertical : true,  // Allow to drag content vertically
    	momentum : true   // Continuous movement when panning
    },

    // Hash value when initializing manually,
    // set `false` to disable hash change
    hash : null,

    // Customize or add new media types
    // Example:
    /*
    media : {
    	youtube : {
    		params : {
    			autoplay : 0
    		}
    	}
    }
    */
    media : {},

    slideShow : {
    	autoStart : false,
    	speed     : 4000
    },

    thumbs : {
    	autoStart   : false,                  // Display thumbnails on opening
    	hideOnClose : true,                   // Hide thumbnail grid when closing animation starts
    	parentEl    : '.fancybox-container',  // Container is injected into this element
    	axis        : 'y'                     // Vertical (y) or horizontal (x) scrolling
    }

Example (show thumbnails on start):

    $('[data-fancybox="images"]').fancybox({
    	thumbs : {
    		autoStart : true
    	}
    })

View demo on CodePen

If you would inspect fancyBox instance object, you would find that same keys ar captialized - these are references for each module object. Also, you would notice that fancyBox uses common naming convention to prefix jQuery objects with `$`.

This is how you, for example, can access thumbnail grid element:

    $.fancybox.getInstance().Thumbs.$grid

This example shows how to call method that toggles thumbnails:

    $.fancybox.getInstance().Thumbs.toggle();

List of available methods:

    Thumbs.focus()
    Thumbs.update();
    Thumbs.hide();
    Thumbs.show();
    Thumbs.toggle();

    FullScreen.request( elem );
    FullScreen.exit();
    FullScreen.toggle( elem );
    FullScreen.isFullscreen();
    FullScreen.enabled();

    SlideShow.start();
    SlideShow.stop();
    SlideShow.toggle();

If you wish to disable hash module, use this snippet (after including JS file):

    $.fancybox.defaults.hash = false;

## FAQ

### 1. Opening/closing causes fixed element to jump

Simply add `compensate-for-scrollbar` CSS class to your fixed positioned elements. Example of using Bootstrap navbar component:

    <nav class="navbar navbar-inverse navbar-fixed-top compensate-for-scrollbar">
    	<div class="container">
    		..
    	</div>
    </nav>

View demo on CodePen

The script measures width of the scrollbar and creates `compensate-for-scrollbar` CSS class that uses this value for `margin-right` property. Therefore, if your element has `width:100%`, you should positon it using `left` and `right` properties instead. Example:

    .navbar {
    	position: fixed;
    	top: 0;
    	left: 0;
    	right: 0;
    }

### 2. How to customize caption

You can use `caption` option that accepts a function and is called for each group element. Example of appending image download link:

    $( '[data-fancybox="images"]' ).fancybox({
        caption : function( instance, item ) {
            var caption = $(this).data('caption') || '';

            if ( item.type === 'image' ) {
                caption = (caption.length ? caption + '<br />' : '') + '<a href="' + item.src + '">Download image</a>' ;
            }

            return caption;
        }
    });

View demo on CodePen

Add current image index and image count (the total number of images in the gallery) right in the caption:

    $( '[data-fancybox="images"]' ).fancybox({
        infobar : false,
        caption : function( instance, item ) {
            var caption = $(this).data('caption') || '';

            return ( caption.length ? caption + '<br />' : '' ) + 'Image <span data-fancybox-index></span> of <span data-fancybox-count></span>';
        }
    });

View demo on CodePen

Inside `caption` method, `this` refers to the clicked element. Example of using different source for caption:

    $( '[data-fancybox]' ).fancybox({
    	caption : function( instance, item ) {
    		return $(this).find('figcaption').html();
    	}
    });

View demo on CodePen

### 3. How to create custom button in the toolbar

Example of creating reusable button:

    // Create template for the button
    $.fancybox.defaults.btnTpl.fb = '<button data-fancybox-fb class="fancybox-button fancybox-button--fb" title="Facebook">' +
        '<svg viewBox="0 0 24 24">' +
            '<path d="M22.676 0H1.324C.594 0 0 .593 0 1.324v21.352C0 23.408.593 24 1.324 24h11.494v-9.294h-3.13v-3.62h3.13V8.41c0-3.1 1.894-4.785 4.66-4.785 1.324 0 2.463.097 2.795.14v3.24h-1.92c-1.5 0-1.793.722-1.793 1.772v2.31h3.584l-.465 3.63h-3.12V24h6.115c.733 0 1.325-.592 1.325-1.324V1.324C24 .594 23.408 0 22.676 0"/>' +
        '</svg>' +
    '</button>';

    // Make button clickable using event delegation
    $('body').on('click', '[data-fancybox-fb]', function() {
      window.open("https://www.facebook.com/sharer/sharer.php?u="+encodeURIComponent(window.location.href)+"&t="+encodeURIComponent(document.title), '','left=0,top=0,width=600,height=300,menubar=no,toolbar=no,resizable=yes,scrollbars=yes');
    });

    // Customize buttons
    $( '[data-fancybox="images"]' ).fancybox({
      buttons : [
        'fb',
        'close'
      ]
    });

View demo on CodePen

### 4. How to reposition thumbnail grid

There is currenty no JS option to change thumbnail grid position. But fancyBox is designed so that you can use CSS to change position or dimension for each block (e.g., content area, caption or thumbnail grid). This gives you freedom to completely change the look and feel of the modal window, if needed. View demo on CodePen

### 5. How to disable touch gestures/swiping

When you want to make your content selectable or clickable, you have two options:

- disable touch gestures completely by setting `touch:false`
- add `data-selectable="true"` attribute to your html element

View demo on CodePen