(function($){function hasScrollBar(){return $("body").height()>$(window).height()} var JustifiedGallery=function($gallery,settings){this.settings=settings;this.checkSettings();this.imgAnalyzerTimeout=null;this.entries=null;this.buildingRow={entriesBuff:[],width:0,height:0,aspectRatio:0};this.lastAnalyzedIndex=-1;this.yield={every:2,flushed:0};this.border=settings.border>=0?settings.border:settings.margins;this.maxRowHeight=this.retrieveMaxRowHeight();this.suffixRanges=this.retrieveSuffixRanges();this.offY=this.border;this.spinner={phase:0,timeSlot:150,$el:$('
'),intervalId:null};this.checkWidthIntervalId=null;this.galleryWidth=$gallery.width();this.$gallery=$gallery};JustifiedGallery.prototype.getSuffix=function(width,height){var longestSide,i;longestSide=(width>height)?width:height;for(i=0;i img');if($img.length===0)$img=$entry.find('> a > img');return $img.length===0?null:$img};JustifiedGallery.prototype.captionFromEntry=function($entry){var $caption=$entry.find('> .caption');return $caption.length===0?null:$caption};JustifiedGallery.prototype.displayEntry=function($entry,x,y,imgWidth,imgHeight,rowHeight){$entry.width(imgWidth);$entry.height(rowHeight);$entry.css('top',y);$entry.css('left',x);var $image=this.imgFromEntry($entry);if($image!==null){$image.css('width',imgWidth);$image.css('height',imgHeight);$image.css('margin-left',-imgWidth/2);$image.css('margin-top',-imgHeight/2);var imageSrc=$image.attr('src');var newImageSrc=this.newSrc(imageSrc,imgWidth,imgHeight,$image);$image.one('error',function(){$image.attr('src',$image.data('jg.originalSrc'))});var loadNewImage=function(){if(imageSrc!==newImageSrc){$image.attr('src',newImageSrc)}};if($entry.data('jg.loaded')==='skipped'){this.onImageEvent(imageSrc,$.proxy(function(){this.showImg($entry,loadNewImage);$entry.data('jg.loaded',!0)},this))}else{this.showImg($entry,loadNewImage)}}else{this.showImg($entry)} this.displayEntryCaption($entry)};JustifiedGallery.prototype.displayEntryCaption=function($entry){var $image=this.imgFromEntry($entry);if($image!==null&&this.settings.captions){var $imgCaption=this.captionFromEntry($entry);if($imgCaption===null){var caption=$image.attr('alt');if(!this.isValidCaption(caption))caption=$entry.attr('title');if(this.isValidCaption(caption)){$imgCaption=$('
'+caption+'
');$entry.append($imgCaption);$entry.data('jg.createdCaption',!0)}} if($imgCaption!==null){if(!this.settings.cssAnimation)$imgCaption.stop().fadeTo(0,this.settings.captionSettings.nonVisibleOpacity);this.addCaptionEventsHandlers($entry)}}else{this.removeCaptionEventsHandlers($entry)}};JustifiedGallery.prototype.isValidCaption=function(caption){return(typeof caption!=='undefined'&&caption.length>0)};JustifiedGallery.prototype.onEntryMouseEnterForCaption=function(eventObject){var $caption=this.captionFromEntry($(eventObject.currentTarget));if(this.settings.cssAnimation){$caption.addClass('caption-visible').removeClass('caption-hidden')}else{$caption.stop().fadeTo(this.settings.captionSettings.animationDuration,this.settings.captionSettings.visibleOpacity)}};JustifiedGallery.prototype.onEntryMouseLeaveForCaption=function(eventObject){var $caption=this.captionFromEntry($(eventObject.currentTarget));if(this.settings.cssAnimation){$caption.removeClass('caption-visible').removeClass('caption-hidden')}else{$caption.stop().fadeTo(this.settings.captionSettings.animationDuration,this.settings.captionSettings.nonVisibleOpacity)}};JustifiedGallery.prototype.addCaptionEventsHandlers=function($entry){var captionMouseEvents=$entry.data('jg.captionMouseEvents');if(typeof captionMouseEvents==='undefined'){captionMouseEvents={mouseenter:$.proxy(this.onEntryMouseEnterForCaption,this),mouseleave:$.proxy(this.onEntryMouseLeaveForCaption,this)};$entry.on('mouseenter',undefined,undefined,captionMouseEvents.mouseenter);$entry.on('mouseleave',undefined,undefined,captionMouseEvents.mouseleave);$entry.data('jg.captionMouseEvents',captionMouseEvents)}};JustifiedGallery.prototype.removeCaptionEventsHandlers=function($entry){var captionMouseEvents=$entry.data('jg.captionMouseEvents');if(typeof captionMouseEvents!=='undefined'){$entry.off('mouseenter',undefined,captionMouseEvents.mouseenter);$entry.off('mouseleave',undefined,captionMouseEvents.mouseleave);$entry.removeData('jg.captionMouseEvents')}};JustifiedGallery.prototype.prepareBuildingRow=function(isLastRow){var i,$entry,imgAspectRatio,newImgW,newImgH,justify=!0;var minHeight=0;var availableWidth=this.galleryWidth-2*this.border-((this.buildingRow.entriesBuff.length-1)*this.settings.margins);var rowHeight=availableWidth/this.buildingRow.aspectRatio;var justifiable=this.buildingRow.width/availableWidth>this.settings.justifyThreshold;if(isLastRow&&this.settings.lastRow==='hide'&&!justifiable){for(i=0;inewImgH)minHeight=newImgH} if(this.settings.fixedHeight&&minHeight>this.settings.rowHeight) minHeight=this.settings.rowHeight;this.buildingRow.height=minHeight;return justify};JustifiedGallery.prototype.clearBuildingRow=function(){this.buildingRow.entriesBuff=[];this.buildingRow.aspectRatio=0;this.buildingRow.width=0};JustifiedGallery.prototype.flushRow=function(isLastRow){var settings=this.settings;var $entry,buildingRowRes,offX=this.border,i;buildingRowRes=this.prepareBuildingRow(isLastRow);if(isLastRow&&settings.lastRow==='hide'&&this.buildingRow.height===-1){this.clearBuildingRow();return} if(this.maxRowHeight.isPercentage){if(this.maxRowHeight.value*settings.rowHeight0&&this.maxRowHeight.valuethis.settings.refreshSensitivity){this.galleryWidth=galleryWidth;this.rewind();this.startImgAnalyzer(!0)}}else{scrollBarOn=hasScrollBar();this.galleryWidth=galleryWidth}},this),this.settings.refreshTime)};JustifiedGallery.prototype.isSpinnerActive=function(){return this.spinner.intervalId!==null};JustifiedGallery.prototype.getSpinnerHeight=function(){return this.spinner.$el.innerHeight()};JustifiedGallery.prototype.stopLoadingSpinnerAnimation=function(){clearInterval(this.spinner.intervalId);this.spinner.intervalId=null;this.$gallery.height(this.$gallery.height()-this.getSpinnerHeight());this.spinner.$el.detach()};JustifiedGallery.prototype.startLoadingSpinnerAnimation=function(){var spinnerContext=this.spinner;var $spinnerPoints=spinnerContext.$el.find('span');clearInterval(spinnerContext.intervalId);this.$gallery.append(spinnerContext.$el);this.$gallery.height(this.offY+this.buildingRow.height+this.getSpinnerHeight());spinnerContext.intervalId=setInterval(function(){if(spinnerContext.phase<$spinnerPoints.length){$spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot,1)}else{$spinnerPoints.eq(spinnerContext.phase-$spinnerPoints.length).fadeTo(spinnerContext.timeSlot,0)} spinnerContext.phase=(spinnerContext.phase+1)%($spinnerPoints.length*2)},spinnerContext.timeSlot)};JustifiedGallery.prototype.rewind=function(){this.lastAnalyzedIndex=-1;this.offY=this.border;this.clearBuildingRow()};JustifiedGallery.prototype.updateEntries=function(norewind){this.entries=this.$gallery.find(this.settings.selector).toArray();if(this.entries.length===0)return!1;if(this.settings.filter){this.modifyEntries(this.filterArray,norewind)}else{this.modifyEntries(this.resetFilters,norewind)} if($.isFunction(this.settings.sort)){this.modifyEntries(this.sortArray,norewind)}else if(this.settings.randomize){this.modifyEntries(this.shuffleArray,norewind)} return!0};JustifiedGallery.prototype.insertToGallery=function(entries){var that=this;$.each(entries,function(){$(this).appendTo(that.$gallery)})};JustifiedGallery.prototype.shuffleArray=function(a){var i,j,temp;for(i=a.length-1;i>0;i--){j=Math.floor(Math.random()*(i+1));temp=a[i];a[i]=a[j];a[j]=temp} this.insertToGallery(a);return a};JustifiedGallery.prototype.sortArray=function(a){a.sort(this.settings.sort);this.insertToGallery(a);return a};JustifiedGallery.prototype.resetFilters=function(a){for(var i=0;i=this.yield.every){this.startImgAnalyzer(isForResize);return}} this.buildingRow.entriesBuff.push($entry);this.buildingRow.aspectRatio+=imgAspectRatio;this.buildingRow.width+=imgAspectRatio*this.settings.rowHeight;this.lastAnalyzedIndex=i}else if($entry.data('jg.loaded')!=='error'){return}} if(this.buildingRow.entriesBuff.length>0)this.flushRow(!0);if(this.isSpinnerActive()){this.stopLoadingSpinnerAnimation()} this.stopImgAnalyzerStarter();this.$gallery.trigger(isForResize?'jg.resize':'jg.complete');this.$gallery.height(this.galleryHeightToSet)};JustifiedGallery.prototype.stopImgAnalyzerStarter=function(){this.yield.flushed=0;if(this.imgAnalyzerTimeout!==null)clearTimeout(this.imgAnalyzerTimeout)};JustifiedGallery.prototype.startImgAnalyzer=function(isForResize){var that=this;this.stopImgAnalyzerStarter();this.imgAnalyzerTimeout=setTimeout(function(){that.analyzeImages(isForResize)},0.001)};JustifiedGallery.prototype.onImageEvent=function(imageSrc,onLoad,onError){if(!onLoad&&!onError)return;var memImage=new Image();var $memImage=$(memImage);if(onLoad){$memImage.one('load',function(){$memImage.off('load error');onLoad(memImage)})} if(onError){$memImage.one('error',function(){$memImage.off('load error');onError(memImage)})} memImage.src=imageSrc};JustifiedGallery.prototype.init=function(){var imagesToLoad=!1,skippedImages=!1,that=this;$.each(this.entries,function(index,entry){var $entry=$(entry);var $image=that.imgFromEntry($entry);$entry.addClass('jg-entry');if($entry.data('jg.loaded')!==!0&&$entry.data('jg.loaded')!=='skipped'){if(that.settings.rel!==null)$entry.attr('rel',that.settings.rel);if(that.settings.target!==null)$entry.attr('target',that.settings.target);if($image!==null){var imageSrc=that.extractImgSrcFromImage($image);$image.attr('src',imageSrc);if(that.settings.waitThumbnailsLoad===!1){var width=parseFloat($image.attr('width'));var height=parseFloat($image.attr('height'));if(!isNaN(width)&&!isNaN(height)){$entry.data('jg.width',width);$entry.data('jg.height',height);$entry.data('jg.loaded','skipped');skippedImages=!0;that.startImgAnalyzer(!1);return!0}} $entry.data('jg.loaded',!1);imagesToLoad=!0;if(!that.isSpinnerActive())that.startLoadingSpinnerAnimation();that.onImageEvent(imageSrc,function(loadImg){$entry.data('jg.width',loadImg.width);$entry.data('jg.height',loadImg.height);$entry.data('jg.loaded',!0);that.startImgAnalyzer(!1)},function(){$entry.data('jg.loaded','error');that.startImgAnalyzer(!1)})}else{$entry.data('jg.loaded',!0);$entry.data('jg.width',$entry.width()|parseFloat($entry.css('width'))|1);$entry.data('jg.height',$entry.height()|parseFloat($entry.css('height'))|1)}}});if(!imagesToLoad&&!skippedImages)this.startImgAnalyzer(!1);this.checkWidth()};JustifiedGallery.prototype.checkOrConvertNumber=function(settingContainer,settingName){if($.type(settingContainer[settingName])==='string'){settingContainer[settingName]=parseFloat(settingContainer[settingName])} if($.type(settingContainer[settingName])==='number'){if(isNaN(settingContainer[settingName]))throw 'invalid number for '+settingName}else{throw settingName+' must be a number'}};JustifiedGallery.prototype.checkSizeRangesSuffixes=function(){if($.type(this.settings.sizeRangeSuffixes)!=='object'){throw 'sizeRangeSuffixes must be defined and must be an object'} var suffixRanges=[];for(var rangeIdx in this.settings.sizeRangeSuffixes){if(this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx))suffixRanges.push(rangeIdx)} var newSizeRngSuffixes={0:''};for(var i=0;i0&&newMaxRowHeight.value1){throw 'justifyThreshold must be in the interval [0,1]'} if($.type(this.settings.cssAnimation)!=='boolean'){throw 'cssAnimation must be a boolean'} if($.type(this.settings.captions)!=='boolean')throw 'captions must be a boolean';this.checkOrConvertNumber(this.settings.captionSettings,'animationDuration');this.checkOrConvertNumber(this.settings.captionSettings,'visibleOpacity');if(this.settings.captionSettings.visibleOpacity<0||this.settings.captionSettings.visibleOpacity>1){throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'} this.checkOrConvertNumber(this.settings.captionSettings,'nonVisibleOpacity');if(this.settings.captionSettings.nonVisibleOpacity<0||this.settings.captionSettings.nonVisibleOpacity>1){throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'} if($.type(this.settings.fixedHeight)!=='boolean')throw 'fixedHeight must be a boolean';this.checkOrConvertNumber(this.settings,'imagesAnimationDuration');this.checkOrConvertNumber(this.settings,'refreshTime');this.checkOrConvertNumber(this.settings,'refreshSensitivity');if($.type(this.settings.randomize)!=='boolean')throw 'randomize must be a boolean';if($.type(this.settings.selector)!=='string')throw 'selector must be a string';if(this.settings.sort!==!1&&!$.isFunction(this.settings.sort)){throw 'sort must be false or a comparturn function'} if(this.settings.filter!==!1&&!$.isFunction(this.settings.filter)&&$.type(this.settings.filter)!=='string'){throw 'filter must be false, a string or a filter function'}};JustifiedGallery.prototype.retrieveSuffixRanges=function(){var suffixRanges=[];for(var rangeIdx in this.settings.sizeRangeSuffixes){if(this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx))suffixRanges.push(parseInt(rangeIdx,10))} suffixRanges.sort(function(a,b){return a>b?1:a=0?this.settings.border:this.settings.margins;this.maxRowHeight=this.retrieveMaxRowHeight();this.suffixRanges=this.retrieveSuffixRanges()};$.fn.justifiedGallery=function(arg){return this.each(function(index,gallery){var $gallery=$(gallery);$gallery.addClass('justified-gallery');var controller=$gallery.data('jg.controller');if(typeof controller==='undefined'){if(typeof arg!=='undefined'&&arg!==null&&$.type(arg)!=='object'){if(arg==='destroy')return;throw 'The argument must be an object'} controller=new JustifiedGallery($gallery,$.extend({},$.fn.justifiedGallery.defaults,arg));$gallery.data('jg.controller',controller)}else if(arg==='norewind'){}else if(arg==='destroy'){controller.destroy();return}else{controller.updateSettings(arg);controller.rewind()} if(!controller.updateEntries(arg==='norewind'))return;controller.init()})};$.fn.justifiedGallery.defaults={sizeRangeSuffixes:{},thumbnailPath:undefined,rowHeight:120,maxRowHeight:-1,margins:1,border:-1,lastRow:'nojustify',justifyThreshold:0.75,fixedHeight:!1,waitThumbnailsLoad:!0,captions:!0,cssAnimation:!1,imagesAnimationDuration:500,captionSettings:{animationDuration:500,visibleOpacity:0.7,nonVisibleOpacity:0.0},rel:null,target:null,extension:/\.[^.\\/]+$/,refreshTime:200,refreshSensitivity:0,randomize:!1,sort:!1,filter:!1,selector:'> a, > div:not(.spinner)'}}(jQuery))