/** * @projectDescription JsFlickrGallery - Simple JavaScript Flickr gallery, * http://petejank.github.io/js-flickr-gallery/ * * @version 1.24 * @author Peter Jankowski http://likeadev.com * @license MIT license. */ ;(function ( $, window, document, undefined ) { 'use strict'; // "Constants" var FORMAT = 'json', SEARCH_API_METHOD = 'flickr.photos.search', SETS_API_METHOD = 'flickr.photosets.getPhotos', API_KEY = '62525ee8c8d131d708d33d61f29434b6', // Tag attributes DATA_TAGS_ATTR = 'data-tags', DATA_USER_ID_ATTR = 'data-user-id', DATA_SET_ID_ATTR = 'data-set-id', DATA_PER_PAGE_ATTR = 'data-per-page', DATA_GALLERY_ID_ATTR = 'data-gallery-id', DATA_TOGGLE_ATTR = 'jsfg', // Minor stuff RESPONSIVE_WIDTH = 767, FLICKR_REQUEST_TIMEOUT = 10000, // Generated modal window stuff GEN_HEADER_CONTAINER_CLASS = 'modal-header', GEN_TITLE_TAG = 'h3', GEN_BODY_CONTAINER_CLASS = 'modal-body', GEN_IMAGE_CONTAINER_CLASS = 'modal-image', GEN_FOOTER_CONTAINER_CLASS = 'modal-footer' ; // Plugin name declaration var pluginName = 'jsFlickrGallery', defaults = { 'fetchImages' : true, 'animation' : 'fade', 'animationSpeed' : 250, 'preload' : { // false to disable 'range' : 2 }, 'structure' : { 'ulClass' : '.thumbnails', 'liClass' : '.span1', 'aClass' : '.thumbnail' }, 'modal' : { // false to disable 'generate' : true, 'id' : 'jsfg-modal', 'title' : '.' + GEN_HEADER_CONTAINER_CLASS + ' ' + GEN_TITLE_TAG, 'imageContainerClass' : '.' + GEN_IMAGE_CONTAINER_CLASS, 'onContainerNext' : true, 'imageFadeTime' : 250, 'prevClass' : '.btn.modal-prev', 'nextClass' : '.btn.modal-next', 'prevText' : 'Previous image', 'nextText' : 'Next image', 'offsetWidth' : 100, 'offsetHeight' : 200 }, 'pagination' : { // false to disable 'generate' : true, 'containerClass' : '.pagination', 'prevClass' : '.btn.pagination-prev', 'nextClass' : '.btn.pagination-next', 'prevText' : 'Previous page', 'nextText' : 'Next page' }, 'loader' : { // false to disable 'animation' : true, 'loaderClass' : '.jsfg-loader', 'text' : 'Loading', 'interval' : 200, 'mark' : '.', 'markClass': '.animation-marks', 'maxMarks' : 3 }, 'url' : { 'per_page' : 30, 'tag_mode' : 'all' }, 'error' : { 'text' : 'No photos found', 'tagClass' : 'error' }, 'imageSizes' : { 'small' : 's', // small (up to 75 x 75) 'medium_100' : 't', // medium (up to 100 x 75) 'medium' : 'q', // medium (up to 150 x 150) 'medium_640' : 'z', // medium (up to 620 x 640) 'large' : 'b', // large (up to 1024 in any of two dimensions) 'original' : 'o' // original image size }, 'apiUrl' : 'https://api.flickr.com/services/rest/?jsoncallback=?', 'setDefaultSize' : function() { this.thumbnailSize = this.imageSizes.medium; this.imageSize = this.imageSizes.large; } }; /** * Plugin constructor * * @param Object element * @param Object options * @return Plugin * @constructor */ function Plugin( element, options ) { this.element = element; // Select this DOM element with jQuery - for future use this.$element = $( element ); // Merge passed options with defaults this.options = $.extend( true, {}, defaults, options ); // Set contexts for pagination and modal this.paginationContext = this.options.pagination && this.options.pagination.generate ? this.element : document; if ( !this.options.thumbnailSize && !this.options.imageSize ) { this.options.setDefaultSize(); } // Assign gallery instance id this.galleryId = this.element.id || Math.random().toString( 36 ); // Starting page value this.page = 1; this.init(); } // Define Plugin init method Plugin.prototype = { /** * Creates gallery structure for the node * * @return void * @method * @memberOf Plugin */ init : function() { if ( this.options.fetchImages ) { // Add gallery loader if available if ( this.options.loader ) { this.loaderInterval = this._createLoader(this.element); } this.createGallery(); // async, rest of the init code will be shot before this } else { // Assign anchors selector to local instance this.anchors = this._getAnchors(); } if ( this.options.pagination && this.options.fetchImages ) { if ( this.options.pagination.generate ) { this._createPagination(); } this._bindPaginationEvents(); } if ( this.options.modal ) { if ( this.options.modal.generate ) { this._createModal(); } this._bindModalEvents(); } }, /** * Get JSON image data using JSONP from flickr and create an gallery instance. * Does NOT clear the container content but appends to it * * @param Integer page Starting pagination page * @return Plugin * @method * @memberOf Plugin */ createGallery : function( page ) { // Assign constants to url options this.options.url.format = FORMAT; this.options.url.api_key = API_KEY; this.options.url.photoset_id = this.$element.attr( DATA_SET_ID_ATTR ) || this.options.url.photoset_id; if ( this.options.url.photoset_id ) { // Fetch data for certain photo set this.options.url.method = SETS_API_METHOD; delete this.options.url.tag_mode; } else { // Fetch photos by tags/user_id criteria this.options.url.method = SEARCH_API_METHOD; delete this.options.url.photoset_id; // Tags are mandatory when fetching photos from Flickr this.options.url.tags = this.$element.attr( DATA_TAGS_ATTR ) || this.options.url.tags; // Check if only certain user's photos should be fetched this.options.url.user_id = this.$element.attr( DATA_USER_ID_ATTR ) || this.options.url.user_id; if ( !this.options.url.user_id ) { delete this.options.url.user_id; } } // Set displayed page this.options.url.page = this.page = page || this.page; // How many photos should be fetched? this.options.url.per_page = this.$element.attr( DATA_PER_PAGE_ATTR ) || this.options.url.per_page; // Get images using ajax and display them on success this._getPhotos(); return this; }, /** * Hide gallery items and remove them * * @param Integer page * @return Plugin * @method * @memberOf Plugin */ clearGallery : function( page ) { var $galleryEl = $( this.options.structure.ulClass, this.element ), self = this ; switch( this.options.animation ) { case 'fade': $galleryEl.fadeOut( this.options.animationSpeed, _replaceWithLoader ); break; case 'show': $galleryEl.hide( this.options.animationSpeed, _replaceWithLoader ); break; case false: $galleryEl.hide( 0 , _replaceWithLoader ); } /** * Replace gallery content with loader * * @return void * @internal * @memberOf Plugin */ function _replaceWithLoader() { if ( self.options.loader ) { self.loaderInterval = self._createLoader( self.element ); } // Init creation of new gallery if page is present if ( page ) { self.createGallery(page); } $galleryEl.remove(); } return this; }, /** * Check if current page is the last page of the gallery * * @return boolean * @method * @memberOf Plugin */ isLastPage : function() { return ( !this.anchors || this.anchors.length < this.options.url.per_page ) ? true : false; }, /** * Display next page of the gallery * * @return Plugin | boolean False when current page is last one * @method * @memberOf Plugin */ nextPage : function() { if ( !this.isLastPage() ) { return this.clearGallery( this.page + 1 ); } else { return false; } }, /** * Display previous page of the gallery * * @return Plugin | boolean False when page < 1 * @method * @memberOf Plugin */ prevPage : function() { if ( this.page > 1 ) { return this.clearGallery( this.page - 1 ); } else { return false; } }, /** * Display previous gallery image in modal window * * @return Plugin * @method * @memberOf Plugin */ prevImage : function() { this.index -= 1; if (this.index < 0) { this.index = this.anchors.length - 1; } return this._loadImage( false ); }, /** * Diplay next gallery image in modal window * * @return Plugin * @method * @memberOf Plugin */ nextImage : function() { this.index += 1; if ( this.index > this.anchors.length - 1 ) { this.index = 0; } return this._loadImage( false ); }, /** * Fetch photos from Flickr * * @return Plugin * @private * @memberOf Plugin */ _getPhotos : function( ) { var self = this; $.ajax({ type: 'GET', url: self.options.apiUrl, data: self.options.url, dataType: 'jsonp', timeout: FLICKR_REQUEST_TIMEOUT }).done(function( data ) { // Once data is returned, create gallery instance self._renderGalleryContent( data.photos || data.photoset ); }).always(function( data, textStatus ) { // Try again if (textStatus === 'timeout') { self._getPhotos(); } }); }, /** * Create and render gallery instance. Not for public consumption * * @param Object photos * @return Plugin * @private * @method * @memberOf Plugin */ _renderGalleryContent : function( photos ) { var self = this, $images, $ul, listItems = '', loadedImg = 0, link, title, error, liClassNoDots = this._replaceDots( self.options.structure.liClass ), aClassNoDots = this._replaceDots( self.options.structure.aClass ) ; // Check if there's more than one gallery item returned if ( photos.photo.length > 0 ) { // Gallery is hidden by default for image loading purposes $ul = $( '