/*! * baguetteBox.js * @author feimosi * @version 0.7.0 * @url https://github.com/feimosi/baguetteBox.js */ var baguetteBox = (function() { // SVG shapes used in buttons var leftArrow = '', rightArrow = '', closeX = ''; // Main ID names var overlayID = 'baguetteBox-overlay'; var sliderID = 'baguetteBox-slider'; // Global options and their defaults var options = {}, defaults = { captions: true, buttons: 'auto', async: false, preload: 2, animation: 'slideIn' }; // 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; // 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 imagesArray = []; // forEach polyfill for IE8 if(!Array.prototype.forEach) { Array.prototype.forEach = function(callback, thisArg) { var len = this.length; for(var i = 0; i < len; i++) { callback.call(thisArg, this[i], i, this); } }; } // Script entry point function run(selector, userOptions) { buildOverlay(); // For each gallery bind a click event to every image inside it galleries = document.querySelectorAll(selector); [].forEach.call( galleries, function (galleryElement, galleryIndex) { var galleryID = imagesMap.length; imagesMap.push(galleryElement.getElementsByTagName('a')); imagesMap[galleryID].options = userOptions; [].forEach.call( imagesMap[galleryID], function (imageElement, imageIndex) { bind(imageElement, 'click', function(event) { /*jshint -W030 */ event.preventDefault ? event.preventDefault() : event.returnValue = false; prepareOverlay(galleryID); showOverlay(imageIndex); }); } ); } ); defaults.transforms = testTransformsSupport(); } function buildOverlay() { overlay = document.getElementById(overlayID); // Check if the overlay already exists if(overlay) { slider = document.getElementById(sliderID); previousButton = document.getElementById('previous-button'); nextButton = document.getElementById('next-button'); closeButton = document.getElementById('close-button'); return; } // Create overlay element overlay = document.createElement('div'); overlay.id = overlayID; document.getElementsByTagName('body')[0].appendChild(overlay); // Create gallery slider element slider = document.createElement('div'); slider.id = sliderID; overlay.appendChild(slider); // Create all necessary buttons previousButton = document.createElement('button'); previousButton.id = 'previous-button'; previousButton.innerHTML = leftArrow; overlay.appendChild(previousButton); nextButton = document.createElement('button'); nextButton.id = 'next-button'; nextButton.innerHTML = rightArrow; overlay.appendChild(nextButton); closeButton = document.createElement('button'); closeButton.id = 'close-button'; closeButton.innerHTML = closeX; overlay.appendChild(closeButton); previousButton.className = nextButton.className = closeButton.className = 'baguetteBox-button'; bindEvents(); } function bindEvents() { // When clicked on the overlay (outside displayed image) close it bind(overlay, 'click', function(event) { if(event.target && event.target.nodeName !== "IMG") hideOverlay(); }); // Add event listeners for buttons bind(document.getElementById('previous-button'), 'click', function(event) { /*jshint -W030 */ event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; showPreviousImage(); }); bind(document.getElementById('next-button'), 'click', function(event) { /*jshint -W030 */ event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; showNextImage(); }); bind(document.getElementById('close-button'), 'click', function(event) { /*jshint -W030 */ event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; hideOverlay(); }); // Add touch events bind(overlay, 'touchstart', function(event) { // Save x axis position touchStartX = event.changedTouches[0].pageX; }); bind(overlay, 'touchmove', function(event) { if(touchFlag) return; /*jshint -W030 */ event.preventDefault ? event.preventDefault() : event.returnValue = false; touch = event.touches[0] || event.changedTouches[0]; if(touch.pageX - touchStartX > 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); imagesArray.length = 0; // Prepare and append images containers for(var i = 0; i < imagesMap[galleryIndex].length; i++) { imagesArray.push(returnImageContainer()); slider.appendChild(imagesArray[i]); } } function setOptions(newOptions) { if(!newOptions) newOptions = {}; 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' : ''; // 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'; } // Return DOM element for image container