// # Microfiche.js v1.8.4
//
// ## Usage
//
// $('.my-slideshow').microfiche();
// $('.my-slideshow').microfiche({ cyclic: true, button: false });
// $('.my-slideshow').microfiche({ slideByPages: 1 });
//
// ## Options
//
// The following options can be passed the first time `microfiche` is called
// on an element.
//
// ### cyclic
//
// If true, microfiche wraps around at front and beginning of the slideshow.
// This option is false by default.
//
// $('.my-slideshow').microfiche({ cyclic: true });
//
// ### buttons
//
// If true, microfiche will create previous/next buttons.
// This option is true by default.
//
// $('.my-slideshow').microfiche({ buttons: false });
//
// ### bullets
//
// If true, microfiche will create bullets for the pages available.
// This option is also true by default.
//
// $('.my-slideshow').microfiche({ bullets: false });
//
// ## Commands
//
// The following commands can be run on a microfiche'd element at any point,
// including in the first call.
//
// ### slideByPages
//
// Slides `n` screenfuls (negative `n` goes backwards).
//
// $('.my-slideshow').microfiche({ slideByPages: n });
//
// ### slideToPage
//
// Slides to the `nth` screenful.
//
// $('.my-slideshow').microfiche({ slideToPage: n });
//
// ### slideToPoint
//
// Slides to point `x` (rounded and constrained appropriately).
//
// $('.my-slideshow).microfiche({ slideToPoint: x });
//
// ### jumpToPoint
//
// Jumps without animation to point x (again, rounded and constrained).
//
// $('.my-slideshow').microfiche({ jumpToPoint: x });
//
// ### autoplay
//
// Automatically advances every `n` seconds.
//
// $('.my-slideshow').microfiche({ autoplay: n });
//
// ### autopause
//
// Automatically pause autoplay when the user hovers over the carousel.
//
// $('.my-slideshow').microfiche({ autoplay: n, autopause: true });
//
// ### refresh
//
// To refresh an existing Microfiche’s controls and content to adjust
// to a new container size, call the `refresh` method.
//
// $('.my-slideshow').microfiche({ refresh: true });
//
// ### refreshOnResize
//
// Automatically refresh microfiche filmstrip and controls on window
// resize event. Set `true` to refresh with a 250ms debounce, or specify
// a custom debounce rate in ms. The default value is false.
//
// $('.my-slideshow').microfiche({ refreshOnResize: 100 });
//
// ### destroy
//
// Destroys the microfiche instance and clear related events
//
// $('my-slideshow').microfiche({ destroy: true });
// // or
// $('my-slideshow').data('microfiche').destroy();
//
// ### noScrollAlign
//
// Defines left, right, or center filmstrip alignment in the event that
// all items are visible on screen and no scrolling is required.
//
// $('.my-slideshow').microfiche({ noScrollAlign: 'left' });
//
(function() {
window.Microfiche = function(options) { this.initialize(options); return this; };
Microfiche.VERSION = '1.8.4';
CALIBRATE_FIRST_GUESS = 100000;
$.extend(Microfiche.prototype, {
// ## Default Options ##
//
// These may be overridden in the initializer.
options: {
autoplay : false,
autopause : false,
buttons : true,
bullets : true,
cyclic : false,
keyboard : false,
swipe : true,
clickToAdvance : false,
minDuration : 250,
duration : 500,
maxDuration : 500,
dragThreshold : 25,
elasticity : 0.5,
swipeThreshold : 0.125,
refreshOnResize : false,
prevButtonLabel : '←',
nextButtonLabel : '→',
noScrollAlign : 'left'
},
// Rather than relying on the literal position of `this.film`,
// we keep a tab on the current destination.
x: 0,
// ## Setup ##
// Build microfiche in steps.
initialize: function(options) {
this.options = $.extend({}, this.options, options);
this.el = $(options.el);
this.initialContents = this.el.contents();
this.el.data('microfiche', this);
this.createFilm();
this.createScreen();
this.calibrate(CALIBRATE_FIRST_GUESS);
if (this.film.width() <= this.screen.width()) {
this.noScrollAlign(this.options.noScrollAlign);
this.refreshOnResize(this.options.refreshOnResize);
return;
}
this.createControls();
this.enableTouch();
this.enableKeyboard();
this.enableClick();
this.prepareCyclic();
this.run(this.options);
},
// We create our film element, which we’ll slide back and forth in the screen.
// Before appending any extra elements, we detach the existing children,
// append them to film, and tell them to float so they’ll (hopefully) lay-out
// nicely along the horizontal.
createFilm: function() {
this.film = $('
').
css({ position: 'absolute' });
this.el.children().appendTo(this.film).css({ float: 'left' });
this.prepareFilm && this.prepareFilm();
},
// The screen is created and appended to our element, then the film is
// appended to the screen. Screen manually takes its height from film.
createScreen: function() {
this.screen = $('
').
css({ position: 'relative', overflow: 'hidden' }).
appendTo(this.el).
append(this.film);
},
// Prepare duplicate content at either end, for our cyclic behaviour.
prepareCyclic: function() {
if (!this.options.cyclic) return;
var cloneL = this.film.clone(),
cloneR = this.film.clone(),
w = this.film.width();
cloneL.prependTo(this.film).css({ position: 'absolute', left: -w + 'px' });
cloneR.appendTo(this.film).css({ position: 'absolute', left: w + 'px' });
},
// This slightly strange process tries to ensure we don’t get any wrapping
// in `this.film`, then fixes the dimensions of `this.film` and `this.screen`.
calibrate: function(width) {
this.screen.width(width);
var w = this.film.width(),
h = this.film.height();
if (w === width) {
return this.calibrate(width * 2);
}
this.film.width(w).height(h);
this.screen.width('auto').height(h);
},
// Create prev/next buttons and page bullets.
createControls: function() {
var self = this;
this.controls = $('').appendTo(this.el);
this.controls.on('click', 'a, button', function(e) { self.didClickControl(e) });
if (this.options.bullets) this.createBullets();
if (this.options.buttons) this.createButtons();
this.updateControls();
},
// Create page bullets.
createBullets: function() {
var container = $('').appendTo(this.controls);
for (var i = 0; i < this.totalPageCount(); i++) {
$('