/*! * baguettebox.js * @author feimosi * @version 1.3.1 * @url https://github.com/feimosi/baguettebox.js */ var baguettebox = (function() { // svg shapes used within the buttons var leftarrow = '' + '' + '', rightarrow = '' + '' + '', closex = '' + '' + '' + '' + ''; // global options and their defaults var options = {}, defaults = { captions: true, buttons: 'auto', async: false, preload: 2, animation: 'slidein', aftershow: null, afterhide: null, // callback when image changes with `currentindex` and `imageselements.length` as parameters onchange: null }; // object containing information about features compatibility var supports = {}; // dom elements references var overlay, slider, previousbutton, nextbutton, closebutton; // current image index inside the slider and displayed gallery index var currentindex = 0, currentgallery = -1; // touch event start position (for slide gesture) var touchstartx; // if set to true ignore touch events because animation was already fired var touchflag = false; // regex pattern to match image files var regex = /.+\.(gif|jpe?g|png|webp)/i; // array of all used galleries (dom elements) var galleries = []; // 2d array of galleries and images inside them var imagesmap = []; // array containing temporary images dom elements var imageselements = []; // foreach polyfill for ie8 // http://stackoverflow.com/a/14827443/1077846 if(![].foreach) { array.prototype.foreach = function(callback, thisarg) { for(var i = 0; i < this.length; i++) callback.call(thisarg, this[i], i, this); }; } // filter polyfill for ie8 // https://gist.github.com/eliperelman/1031656 if(![].filter) { array.prototype.filter = function(a, b, c, d, e) { /*jshint -w030 */ c=this;d=[];for(e=0;e 40) { touchflag = true; showpreviousimage(); } else if (touch.pagex - touchstartx < -40) { touchflag = true; shownextimage(); } }); bind(overlay, 'touchend', function(event) { touchflag = false; }); // activate keyboard shortcuts bind(document, 'keydown', function(event) { switch(event.keycode) { case 37: // left arrow showpreviousimage(); break; case 39: // right arrow shownextimage(); break; case 27: // esc hideoverlay(); break; } }); } function prepareoverlay(galleryindex) { // if the same gallery is being opened prevent from loading it once again if(currentgallery === galleryindex) return; currentgallery = galleryindex; // update gallery specific options setoptions(imagesmap[galleryindex].options); // empty slider of previous contents (more effective than .innerhtml = "") while(slider.firstchild) slider.removechild(slider.firstchild); imageselements.length = 0; // prepare and append images containers for(var i = 0, fullimage; i < imagesmap[galleryindex].length; i++) { fullimage = create('div'); fullimage.classname = 'full-image'; fullimage.id = 'baguette-img-' + i; imageselements.push(fullimage); slider.appendchild(imageselements[i]); } } function setoptions(newoptions) { if(!newoptions) newoptions = {}; // fill options object for(var item in defaults) { options[item] = defaults[item]; if(typeof newoptions[item] !== 'undefined') options[item] = newoptions[item]; } /* apply new options */ // change transition for proper animation slider.style.transition = slider.style.webkittransition = (options.animation === 'fadein' ? 'opacity .4s ease' : options.animation === 'slidein' ? '' : 'none'); // hide buttons if necessary if(options.buttons === 'auto' && ('ontouchstart' in window || imagesmap[currentgallery].length === 1)) options.buttons = false; // set buttons style to hide or display them previousbutton.style.display = nextbutton.style.display = (options.buttons ? '' : 'none'); } function showoverlay(index) { // return if overlay is already visible if(overlay.style.display === 'block') return; // set current index to a new value and load proper image currentindex = index; loadimage(currentindex, function() { preloadnext(currentindex); preloadprev(currentindex); }); updateoffset(); overlay.style.display = 'block'; // fade in overlay settimeout(function() { overlay.classname = 'visible'; if(options.aftershow) options.aftershow(); }, 50); if(options.onchange) options.onchange(currentindex, imageselements.length); } function hideoverlay() { // return if overlay is already hidden if(overlay.style.display === 'none') return; // fade out and hide the overlay overlay.classname = ''; settimeout(function() { overlay.style.display = 'none'; if(options.afterhide) options.afterhide(); }, 500); } function loadimage(index, callback) { var imagecontainer = imageselements[index]; // if index is invalid return if(typeof imagecontainer === 'undefined') return; // if image is already loaded run callback and return if(imagecontainer.getelementsbytagname('img')[0]) { if(callback) callback(); return; } // get element reference, optional caption and source path imageelement = imagesmap[currentgallery][index]; imagecaption = (typeof(options.captions) === 'function') ? options.captions.call(imagesmap[currentgallery], imageelement) : imageelement.getattribute('data-caption') || imageelement.title; imagesrc = getimagesrc(imageelement); // prepare image container elements var figure = create('figure'); var image = create('img'); var figcaption = create('figcaption'); imagecontainer.appendchild(figure); // add loader element figure.innerhtml = '
' + '
' + '
' + '
'; // set callback function when image loads image.onload = function() { // remove loader element var spinner = document.queryselector('#baguette-img-' + index + ' .spinner'); figure.removechild(spinner); if(!options.async && callback) callback(); }; image.setattribute('src', imagesrc); figure.appendchild(image); // insert caption if available if(options.captions && imagecaption) { figcaption.innerhtml = imagecaption; figure.appendchild(figcaption); } // run callback if(options.async && callback) callback(); } // get image source location, mostly used for responsive images function getimagesrc(image) { // set default image path from href var result = imageelement.href; // if dataset is supported find the most suitable image if(image.dataset) { var srcs = []; // get all possible image versions depending on the resolution for(var item in image.dataset) { if(item.substring(0, 3) === 'at-' && !isnan(item.substring(3))) srcs[item.replace('at-', '')] = image.dataset[item]; } // sort resolutions ascending keys = object.keys(srcs).sort(function(a, b) { return parseint(a) < parseint(b) ? -1 : 1; }); // get real screen resolution var width = window.innerwidth * window.devicepixelratio; // find the first image bigger than or equal to the current width var i = 0; while(i < keys.length - 1 && keys[i] < width) i++; result = srcs[keys[i]] || result; } return result; } // return false at the right end of the gallery function shownextimage() { var returnvalue; // check if next image exists if(currentindex <= imageselements.length - 2) { currentindex++; updateoffset(); preloadnext(currentindex); returnvalue = true; } else if(options.animation) { slider.classname = 'bounce-from-right'; settimeout(function() { slider.classname = ''; }, 400); returnvalue = false; } if(options.onchange) options.onchange(currentindex, imageselements.length); return returnvalue; } // return false at the left end of the gallery function showpreviousimage() { var returnvalue; // check if previous image exists if(currentindex >= 1) { currentindex--; updateoffset(); preloadprev(currentindex); returnvalue = true; } else if(options.animation) { slider.classname = 'bounce-from-left'; settimeout(function() { slider.classname = ''; }, 400); returnvalue = false; } if(options.onchange) options.onchange(currentindex, imageselements.length); return returnvalue; } function updateoffset() { var offset = -currentindex * 100 + '%'; if(options.animation === 'fadein') { slider.style.opacity = 0; settimeout(function() { /*jshint -w030 */ supports.transforms ? slider.style.transform = slider.style.webkittransform = 'translate3d(' + offset + ',0,0)' : slider.style.left = offset; slider.style.opacity = 1; }, 400); } else { /*jshint -w030 */ supports.transforms ? slider.style.transform = slider.style.webkittransform = 'translate3d(' + offset + ',0,0)' : slider.style.left = offset; } } // css 3d transforms test function testtransformssupport() { var div = create('div'); return typeof div.style.perspective !== 'undefined' || typeof div.style.webkitperspective !== 'undefined'; } // inline svg test function testsvgsupport() { var div = create('div'); div.innerhtml = ''; return (div.firstchild && div.firstchild.namespaceuri) == 'http://www.w3.org/2000/svg'; } function preloadnext(index) { if(index - currentindex >= options.preload) return; loadimage(index + 1, function() { preloadnext(index + 1); }); } function preloadprev(index) { if(currentindex - index >= options.preload) return; loadimage(index - 1, function() { preloadprev(index - 1); }); } function bind(element, event, callback) { if(element.addeventlistener) element.addeventlistener(event, callback, false); else // ie8 fallback element.attachevent('on' + event, callback); } function getbyid(id) { return document.getelementbyid(id); } function create(element) { return document.createelement(element); } return { run: run, shownext: shownextimage, showprevious: showpreviousimage }; })();