');
}
}
};
/** @function NanoConsoleLog */
/* write message to the browser console */
NGY2Tools.NanoConsoleLog = function(context, msg) {
if (window.console) { console.log('nanogallery2: ' + msg + ' [' + context.baseEltID + ']'); }
// debugger;
};
/** @function PreloaderDisplay() */
/* Display/hide preloader */
NGY2Tools.PreloaderDisplay = function(display) {
if( display === true ) {
// loading bar at the top of the gallery
this.$E.conLoadingB.removeClass('nanoGalleryLBarOff').addClass('nanoGalleryLBar');
// spinner over album thumbnail
if( this.GOM.albumIdxLoading != undefined && this.GOM.albumIdxLoading != -1 ) {
let item = this.I[this.GOM.albumIdxLoading];
item.$Elts['.nGY2TnImg'].addClass('nGY2GThumbnailLoaderDisplayed');
}
}
else {
// loading bar at the top of the gallery
this.$E.conLoadingB.removeClass('nanoGalleryLBar').addClass('nanoGalleryLBarOff');
// spinner over album thumbnail
if( this.GOM.albumIdxLoading != undefined && this.GOM.albumIdxLoading != -1 ) {
let item = this.I[this.GOM.albumIdxLoading];
item.$Elts['.nGY2TnImg'].removeClass('nGY2GThumbnailLoaderDisplayed');
}
}
};
// Scrambles the elements of an array
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/array/shuffle [v1.0]
NGY2Tools.AreaShuffle = function (o) {
for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
/** @function GetImageTitleFromURL() */
/* retrieve filemane */
NGY2Tools.GetImageTitleFromURL = function( imageURL ) {
if( this.O.thumbnailLabel.get('title') == '%filename' ) {
return (imageURL.split('/').pop()).replace('_',' ');
}
if( this.O.thumbnailLabel.get('title') == '%filenameNoExt' ) {
var s=imageURL.split('/').pop();
return (s.split('.').shift()).replace('_',' ');
}
// return imageURL;
return '';
};
/** @function AlbumPostProcess() */
/* post process one album based on plugin general parameters --> sorting/maxItems*/
NGY2Tools.AlbumPostProcess = function(albumID) {
// this function can probably be optimized....
var sortOrder = this.gallerySorting[this.GOM.curNavLevel];
var maxItems = this.galleryMaxItems[this.GOM.curNavLevel];
if( sortOrder != '' || maxItems > 0 ) {
// copy album's items to a new array
var currentAlbum = this.I.filter( function( obj ) {
return( obj.albumID == albumID && obj.kind != 'albumUp' );
});
// sorting options
switch( sortOrder ) {
case 'RANDOM':
currentAlbum = NGY2Tools.AreaShuffle(currentAlbum);
break;
case 'REVERSED':
currentAlbum = currentAlbum.reverse();
break;
case 'TITLEASC':
currentAlbum.sort(function (a, b) {
return( (a.title.toUpperCase() < b.title.toUpperCase()) ? -1 : ((a.title.toUpperCase() > b.title.toUpperCase()) ? 1 : 0) );
});
break;
case 'TITLEDESC':
currentAlbum.sort(function (a, b) {
return( (a.title.toUpperCase() > b.title.toUpperCase()) ? -1 : ((a.title.toUpperCase() < b.title.toUpperCase()) ? 1 : 0) );
});
break;
}
// max Items
if( maxItems > 0 && currentAlbum.length > maxItems ) {
currentAlbum.splice(maxItems - 1, currentAlbum.length-maxItems );
}
// remove the albums's items from the global items array
this.I.ngy2removeIf( function( obj ) {
return( obj.albumID == albumID && obj.kind != 'albumUp' );
});
// add the sorted items back to the album
this.I.push.apply(this.I, currentAlbum);
}
};
return NGY2Tools;
})();
// ====================
// ===== NGY2Item =====
// ====================
window.NGY2Item = (function() {
var nextId = 1; // private static --> all instances
// constructor
function NGY2Item( itemID ) {
//window.NGY2Item = function( itemID ) {
var ID = 0; // private
// public (this instance only)
if( itemID === undefined || itemID === null ) {
ID = nextId++;
}
else {
ID = itemID;
}
this.GetID = function () { return ID; };
// public
this.kind = ''; // 'image', 'album' or 'albumUp'
this.mediaKind = 'img'; // 'img', 'iframe', 'video'
this.mediaMarkup = '';
this.G = null; // pointer to global instance
this.title = ''; // image title
this.description = ''; // image description
this.albumID = 0; // ID of the parent album
this.src = ''; // full sized image URL
this.width = 0; // image width
this.height = 0; // image height
this.destinationURL = ''; // thumbnail destination URL --> open URL instead of displaying image
this.downloadURL = ''; // thumbnail download URL --> specify the image for download button
this.author = ''; // image/album author
this.left = 0; // store position to animate from old to new
this.top = 0;
this.width = 0; // store size to avoid setting width/height if not required
this.height = 0;
this.resizedContentWidth= 0; // store size of content (image) to avoid setting width/height if not required
this.resizedContentHeight= 0;
this.thumbs = { // URLs and sizes for user defined
url: { l1: { xs: '', sm:'', me: '', la: '', xl: '' }, lN: { xs: '', sm: '', me: '', la:'', xl: '' } },
width: { l1: { xs: 0, sm: 0, me: 0, la: 0 , xl: 0 }, lN: { xs: 0 , sm: 0, me: 0, la: 0, xl: 0 } },
height: { l1: { xs: 0, sm: 0, me: 0, la: 0 , xl: 0 }, lN: { xs: 0, sm: 0, me: 0, la: 0, xl: 0 } }
};
this.thumbnailImgRevealed = false; // thumbnail image already revealed
this.imageDominantColors = null; // base64 GIF
this.imageDominantColor = null; // HEX RGB
this.featured = false; // featured element
this.flickrThumbSizes = {}; // store URLs for all available thumbnail sizes (flickr)
this.picasaThumbs = null; // store URLs and sizes
this.hovered = false; // is the thumbnail currently hovered?
this.hoverInitDone = false;
this.contentIsLoaded = false; // album: are items already loaded?
this.contentLength = 0; // album: number of items (real number of items in memory)
this.numberItems = 0; // album: number of items (value returned by data source)
this.mediaNumber = 0; // media number in the album
this.mediaCounter = 0; // number of medias in an album
this.eltTransform = []; // store the CSS transformations
this.eltFilter = []; // store the CSS filters
this.eltEffect = []; // store data about hover effects animations
this.paginationLastPage = 0; // for albums
this.paginationLastWidth = 0; // for albums
this.customData = {};
this.selected = false;
this.imageWidth = 0; // image natural (real) width
this.imageHeight = 0; // image natural (real) height
this.$elt = null; // pointer to the corresponding DOM element
this.$Elts = []; // cached pointers to the thumbnail content -> to avoid jQuery().find()
this.tags = []; // list of tags of the current item
this.albumTagList = []; // list of all the tags of the items contained in the current album
this.albumTagListSel = []; // list of currently selected tags (only for albums)
this.exif = { exposure: '', flash: '', focallength: '', fstop: '', iso: '', model: '', time: '', location: ''};
this.deleted = false; // item is deleted -> do not display anymore
this.rotationAngle = 0; // image display rotation angle
}
// public static
NGY2Item.Get = function( instance, ID ) {
var l = instance.I.length;
for( var i = 0; i < l; i++ ) {
if( instance.I[i].GetID() == ID ) {
return instance.I[i];
}
}
return null;
};
NGY2Item.GetIdx = function( instance, ID ) {
var l = instance.I.length;
for( var i = 0; i < l; i++ ) {
if( instance.I[i].GetID() == ID ) {
return i;
}
}
return -1;
};
// create new item (image, album or albumUp)
NGY2Item.New = function( instance, title, description, ID, albumID, kind, tags ) {
var album = NGY2Item.Get( instance, albumID );
// title translation
if( instance.O.titleTranslationMap !== null ) {
let obj = instance.O.titleTranslationMap.find(o => o.title === title);
if( obj !== undefined ) {
title = obj.replace;
}
}
if( albumID != -1 && albumID != 0 && title !='image gallery by nanogallery2 [build]' ) {
if( instance.O.thumbnailLevelUp && album.getContentLength(false) == 0 && instance.O.album == '' ) {
// add navigation thumbnail (album up)
let item = new NGY2Item('0');
instance.I.push( item );
album.contentLength += 1;
item.title = 'UP';
item.albumID = albumID;
item.kind = 'albumUp';
item.G = instance;
jQuery.extend( true, item.thumbs.width, instance.tn.defaultSize.width);
jQuery.extend( true, item.thumbs.height, instance.tn.defaultSize.height);
}
}
var item = NGY2Item.Get(instance, ID);
if( item === null ){
// create a new item (otherwise, just update the existing one)
item = new NGY2Item(ID);
instance.I.push(item);
if( albumID != -1 && title !='image gallery by nanogallery2 [build]' ) {
album.contentLength+=1;
}
}
item.G = instance;
item.albumID = albumID;
item.kind = kind;
if( kind == 'image' ) {
album.mediaCounter += 1;
item.mediaNumber = album.mediaCounter;
}
// check keyword to find features images/albums
var kw = instance.O.thumbnailFeaturedKeyword;
if( kw != '' ) {
// check if item featured based on a keyword in the title or in the description
kw = kw.toUpperCase();
var p = title.toUpperCase().indexOf(kw);
if( p > -1) {
item.featured = true;
// remove keyword case unsensitive
title = title.substring(0, p) + title.substring(p+kw.length, title.length);
}
p = description.toUpperCase().indexOf(kw);
if( p > -1) {
item.featured=true;
// remove keyword case unsensitive
description=description.substring(0, p) + description.substring(p + kw.length, description.length);
}
}
// TAGS
// if( instance.galleryFilterTags.Get() != false ) {
// if( instance.galleryFilterTags.Get() == true ) {
// if( tags != '' && tags != undefined ) {
// use set tags
// item.setTags(tags.split(' '));
// }
// }
// else {
// extract tags starting with # (in title)
if( typeof instance.galleryFilterTags.Get() == 'string' ) {
switch( instance.galleryFilterTags.Get().toUpperCase() ) {
case 'TITLE': {
let re = /(?:^|\W)#(\w+)(?!\w)/g, match, matches = [];
// let tags = "";
while (match = re.exec(title)) {
matches.push(match[1].replace(/^\s*|\s*$/, '')); //trim trailing/leading whitespace
}
item.setTags(matches); //tags;
title = title.split('#').join(''); //replaceall
break;
}
case 'DESCRIPTION': {
let re = /(?:^|\W)#(\w+)(?!\w)/g, match2, matches2 = [];
// let tags = "";
while (match2 = re.exec(description)) {
matches2.push(match2[1].replace(/^\s*|\s*$/, '')); //trim trailing/leading whitespace
}
item.setTags(matches2); //tags;
description = description.split('#').join(''); //replaceall
break;
}
}
}
else {
if( tags != '' && tags != undefined ) {
// use set tags
item.setTags(tags.split(' '));
}
}
// }
// }
// set (maybe modified) fields title and description
item.title = escapeHtml(instance, title);
item.description = escapeHtml(instance, description);
return item;
};
// removes logically current item
NGY2Item.prototype.delete = function( ) {
this.deleted = true;
// update content length of parent album
this.G.I[NGY2Item.GetIdx(this.G, this.albumID)].contentLength--;
this.G.I[NGY2Item.GetIdx(this.G, this.albumID)].numberItems--;
// check if in GOM and removes it
var nbTn = this.G.GOM.items.length;
var ID = this.GetID();
var foundIdx = -1;
var foundGOMidx = -1;
for( var i = 0; i < nbTn ; i++ ) {
var curTn = this.G.GOM.items[i];
var item=this.G.I[curTn.thumbnailIdx];
if( item.GetID() == ID ) {
// FOUND
if( !curTn.neverDisplayed ) {
foundIdx = curTn.thumbnailIdx;
foundGOMidx = i;
}
}
else {
if( foundIdx != -1 ) {
if( !curTn.neverDisplayed ) {
// update index value
item.$getElt('.nGY2GThumbnail').data('index', i-1);
item.$getElt('.nGY2GThumbnailImg').data('index', i-1);
}
}
}
}
if( foundIdx != -1 ) {
// delete item in GOM and delete thumbnail
var G = this.G;
if( this.selected == true ) {
this.selected = false;
G.GOM.nbSelected--; // update the global counter
}
if( G.I[foundIdx].$elt !== null ) {
G.I[foundIdx].$elt.remove(); // delete thumbnail DOM object
}
G.GOM.items.splice(foundGOMidx, 1); // delete in GOM
if( G.GOM.lastDisplayedIdx != -1 ) {
G.GOM.lastDisplayedIdx -= 1;
}
}
// TODO: update media-number of the other item in the same album
}
NGY2Item.prototype.addToGOM = function( ) {
// retrieve index
var ID = this.GetID();
var l = this.G.I.length;
for( var idx = 0; idx < l; idx++ ) {
var item = this.G.I[idx];
if( item.GetID() == ID ) {
var w = item.thumbImg().width;
var h = item.thumbImg().height;
// set default size if required
if( h == 0 ) {
h = this.G.tn.defaultSize.getHeight();
}
if( w == 0 ) {
w = this.G.tn.defaultSize.getWidth();
}
// add to GOM -> will be displayed on next refresh/resize
var tn = new this.G.GOM.GTn(idx, w, h);
this.G.GOM.items.push(tn);
break;
}
}
}
// function to avoid XSS issue - Cross Site Scripting
// original: https://github.com/janl/mustache.js/blob/master/mustache.js#L55
var entityMap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' };
function escapeHtml (instance, string) {
if( instance.O.allowHTMLinData == true ) {
return string;
}
else {
return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
return entityMap[s];
});
}
}
NGY2Item.get_nextId = function () {
return nextId;
};
//=== public (shared across instances)
//--- cached sub elements
NGY2Item.prototype.$getElt = function( elt, forceRefresh ) {
if( this.$elt == null ) { return null; }
if( this.$Elts[elt] !== undefined && !forceRefresh == true ) {
return this.$Elts[elt];
}
else {
if( elt == '.nGY2GThumbnail' ) {
this.$Elts[elt]=this.$elt;
}
else {
this.$Elts[elt]=this.$elt.find(elt);
}
return this.$Elts[elt];
}
};
// remove one element (in DOM and in cache)
NGY2Item.prototype.removeElt = function( elt ) {
if( this.$elt == null ) { return; }
if( this.$Elts[elt] == undefined) { return; }
this.$Elts[elt].remove();
var index = this.$Elts.indexOf(elt);
this.$Elts.splice(index, 1);
};
//--- returns the album containing the item
NGY2Item.prototype.album = function() {
return this.G.I[NGY2Item.GetIdx(this.G, this.albumID)];
};
//--- viewer - transition can be disabled per media kind - returns true if current media supports transition (swipe)
NGY2Item.prototype.mediaTransition = function( ) {
if( this.G.O.viewerTransitionMediaKind.indexOf( this.mediaKind ) > -1 ) {
return true;
}
return false;
};
//--- set one image (url and size)
NGY2Item.prototype.imageSet = function( src, w, h ) {
this.src = src;
this.width = w;
this.height = h;
};
//--- set one thumbnail (url and size) - screenSize and level are optional
NGY2Item.prototype.thumbSet = function( src, w, h, screenSize, level ) {
var lst=['xs','sm','me','la','xl'];
if( typeof screenSize === 'undefined' || screenSize == '' || screenSize == null ) {
for( var i=0; i< lst.length; i++ ) {
if( typeof level === 'undefined' || level == '' ) {
this.thumbs.url.l1[lst[i]]=src;
this.thumbs.height.l1[lst[i]]=h;
this.thumbs.width.l1[lst[i]]=w;
this.thumbs.url.lN[lst[i]]=src;
this.thumbs.height.lN[lst[i]]=h;
this.thumbs.width.lN[lst[i]]=w;
}
else {
this.thumbs.url[level][lst[i]]=src;
this.thumbs.height[level][lst[i]]=h;
this.thumbs.width[level][lst[i]]=w;
}
}
}
else {
if( typeof level === 'undefined' || level == '' || level == null ) {
this.thumbs.url.l1[screenSize]=src;
this.thumbs.height.l1[screenSize]=h;
this.thumbs.width.l1[screenSize]=w;
this.thumbs.url.lN[screenSize]=src;
this.thumbs.height.lN[screenSize]=h;
this.thumbs.width.lN[screenSize]=w;
}
else {
this.thumbs.url[level][screenSize]=src;
this.thumbs.height[level][screenSize]=h;
this.thumbs.width[level][screenSize]=w;
}
}
for( var i=0; i< lst.length; i++ ) {
this.thumbs.height.l1[lst[i]]=h;
}
for( var i=0; i< lst.length; i++ ) {
if( this.G.tn.settings.height.lN[lst[i]] == this.G.tn.settings.getH() && this.G.tn.settings.width.l1[lst[i]] == this.G.tn.settings.getW() ) {
this.thumbs.height.lN[lst[i]]=h;
}
}
};
//--- set thumbnail image real height for current level/resolution, and for all others level/resolutions having the same settings
NGY2Item.prototype.thumbSetImgHeight = function( h ) {
var lst=['xs','sm','me','la','xl'];
for( var i=0; i< lst.length; i++ ) {
if( this.G.tn.settings.height.l1[lst[i]] == this.G.tn.settings.getH() && this.G.tn.settings.width.l1[lst[i]] == this.G.tn.settings.getW() ) {
this.thumbs.height.l1[lst[i]]=h;
}
}
for( var i=0; i< lst.length; i++ ) {
if( this.G.tn.settings.height.lN[lst[i]] == this.G.tn.settings.getH() && this.G.tn.settings.width.l1[lst[i]] == this.G.tn.settings.getW() ) {
this.thumbs.height.lN[lst[i]]=h;
}
}
};
//--- set thumbnail image real width for current level/resolution, and for all others level/resolutions having the same settings
NGY2Item.prototype.thumbSetImgWidth = function( w ) {
var lst=['xs','sm','me','la','xl'];
for( var i=0; i< lst.length; i++ ) {
if( this.G.tn.settings.height.l1[lst[i]] == this.G.tn.settings.getH() && this.G.tn.settings.width.l1[lst[i]] == this.G.tn.settings.getW() ) {
this.thumbs.width.l1[lst[i]]=w;
}
}
for( var i=0; i< lst.length; i++ ) {
if( this.G.tn.settings.height.lN[lst[i]] == this.G.tn.settings.getH() && this.G.tn.settings.width.l1[lst[i]] == this.G.tn.settings.getW() ) {
this.thumbs.width.lN[lst[i]]=w;
}
}
};
//--- Returns Thumbnail image (depending of the screen resolution)
NGY2Item.prototype.thumbImg = function () {
var tnImg = { src: '', width: 0, height: 0 };
if( this.title == 'image gallery by nanogallery2 [build]' ) {
tnImg.src = this.G.emptyGif;
tnImg.url = this.G.emptyGif;
return tnImg;
}
tnImg.src = this.thumbs.url[this.G.GOM.curNavLevel][this.G.GOM.curWidth];
tnImg.width = this.thumbs.width[this.G.GOM.curNavLevel][this.G.GOM.curWidth];
tnImg.height = this.thumbs.height[this.G.GOM.curNavLevel][this.G.GOM.curWidth];
return tnImg;
};
//--- Set tags to items and add these tags to the album
NGY2Item.prototype.setTags = function( tags ) {
if( tags.length > 0 ) {
this.tags = tags;
var lstTags = this.album().albumTagList;
for( var i = 0; i < tags.length; i++ ) {
var tfound = false;
for( var j = 0; j < lstTags.length; j++ ) {
if( tags[i].toUpperCase() == lstTags[j].toUpperCase() ) {
tfound = true;
}
}
if( tfound == false) {
this.album().albumTagList.push(tags[i])
// this.album().albumTagListSel.push(tags[i])
}
}
}
};
//--- check if 1 of current item's tags is selected (tag filter)
NGY2Item.prototype.checkTagFilter = function() {
if( this.G.galleryFilterTags.Get() != false && this.album().albumTagList.length > 0 ) {
if( this.G.O.thumbnailLevelUp && this.kind == 'albumUp' ) {
return true;
}
var found = false;
var lstTags = this.album().albumTagListSel;
if( lstTags.length == 0 ) {
// no tag is selected -> display all items
return true;
}
for( var i = 0; i < this.tags.length; i++ ) {
for( var j = 0; j < lstTags.length; j++ ) {
if( this.tags[i].toUpperCase() == lstTags[j].toUpperCase() ) {
found = true;
break;
}
}
}
return found;
}
else
return true;
};
//--- check if 1 of current item's tags is found using API search
NGY2Item.prototype.isSearchTagFound = function() {
if( this.G.GOM.albumSearchTags == '' ) { return true; }
if( this.G.O.thumbnailLevelUp && this.kind == 'albumUp' ) { return true; }
//var lstTags=this.album().albumTagListSel;
for( var i = 0; i < this.tags.length; i++ ) {
if( this.tags[i].toUpperCase().indexOf( this.G.GOM.albumSearchTags ) >= 0 ) {
return true;
}
}
return false;
};
//--- set the URL of the media to display in the viewer
//--- markup is defined for images
NGY2Item.prototype.setMediaURL = function( url, mediaKind ) {
this.src = url;
this.mediaKind = mediaKind;
if( mediaKind == 'img' ) {
this.mediaMarkup = '';
}
};
//--- check if current item should be displayed
NGY2Item.prototype.isToDisplay = function( albumID ) {
return this.albumID == albumID && this.checkTagFilter() && this.isSearchFound() && this.isSearchTagFound() && this.deleted == false;
};
//--- returns the number of items of the current album
//--- count using tags filter
NGY2Item.prototype.getContentLength = function( filterTags ) {
if( filterTags == false || this.albumTagList.length == 0 || this.G.galleryFilterTags.Get() == false ) {
return this.contentLength;
}
else {
var l = this.G.I.length;
var cnt = 0;
var albumID = this.GetID();
for( var idx = 0; idx < l; idx++ ) {
var item = this.G.I[idx];
if( item.isToDisplay(albumID) ) {
cnt++;
}
}
return cnt;
}
};
NGY2Item.prototype.isSearchFound = function() {
if( this.G.GOM.albumSearch != '' ) {
if( this.title.toUpperCase().indexOf( this.G.GOM.albumSearch ) == -1 ) {
return false;
}
}
return true;
}
//--- for future use...
NGY2Item.prototype.responsiveURL = function () {
var url = '';
switch(this.G.O.kind) {
case '':
url = this.src;
break;
case 'flickr':
url = this.src;
break;
case 'picasa':
case 'google':
case 'google2':
default:
url = this.src;
break;
}
return url;
};
//--- Reveal the thumbnail image with animation on opacity
NGY2Item.prototype.ThumbnailImageReveal = function () {
if( this.thumbnailImgRevealed == false ) {
this.thumbnailImgRevealed = true;
new NGTweenable().tween({
from: { opacity: 0 },
to: { opacity: 1 },
attachment: { item: this },
delay: 30,
duration: 400,
easing: 'easeOutQuart',
step: function (state, att) {
var $e=att.item.$getElt('.nGY2TnImg');
if( $e != null ) {
$e.css( state );
}
}
});
}
};
// In case of thumbnails with stacks - apply a percent to a value which include a unit
function ValueApplyPercent( str, percent ) {
str=String(str);
if( str === '0' || percent == 1 ) { return str; }
var n = Number(str.replace(/[a-zA-Z]/g, ''));
var ar = str.match(/([^\-0-9\.]+)/g);
var a = '';
if( ar != null && ar.length > 0 ) {
a = ar.join();
}
if( isNaN(n) || n == 0 ) {
return str;
}
n = n * percent;
return n + a;
}
//--- 2D/3D CSS transform - apply the cached value to element
NGY2Item.prototype.CSSTransformApply = function ( eltClass ) {
var obj = this.eltTransform[eltClass];
if( eltClass == '.nGY2GThumbnail' ) {
// thumbnail
var nbStacks = obj.$elt.length-1;
var pTranslateX = 1;
var pTranslateY = 1;
var pTranslateZ = 1;
var pTranslate = 1;
var pRotateX = 1;
var pRotateY = 1;
var pRotateZ = 1;
var pRotate = 1;
var pScale = 1;
for( var n = nbStacks; n >= 0; n-- ) {
// units must be given with
var v = 'translateX(' + ValueApplyPercent(obj.translateX,pTranslateX) + ') translateY(' + ValueApplyPercent(obj.translateY,pTranslateY) + ') translateZ(' + ValueApplyPercent(obj.translateZ,pTranslateZ) + ') scale(' + ValueApplyPercent(obj.scale,pScale) + ') translate(' + ValueApplyPercent(obj.translate,pTranslate) + ')';
if( !(this.G.IE <= 9) && !this.G.isGingerbread ) {
v += ' rotateX(' + ValueApplyPercent(obj.rotateX,pRotateX) + ') rotateY(' + ValueApplyPercent(obj.rotateY,pRotateY) + ') rotateZ(' + ValueApplyPercent(obj.rotateZ,pRotateZ) + ') rotate(' + ValueApplyPercent(obj.rotate,pRotate) + ')';
}
else {
v += ' rotate(' + ValueApplyPercent(obj.rotateZ,pRotateZ) + ')';
}
obj.$elt[n].style[this.G.CSStransformName] = v;
if( nbStacks > 0 ) {
// apply a percent to the stack elements
pTranslateX -= this.G.tn.opt.Get('stacksTranslateX');
pTranslateY -= this.G.tn.opt.Get('stacksTranslateY');
pTranslateZ -= this.G.tn.opt.Get('stacksTranslateZ');
pRotateX -= this.G.tn.opt.Get('stacksRotateX');
pRotateY -= this.G.tn.opt.Get('stacksRotateY');
pRotateZ -= this.G.tn.opt.Get('stacksRotateZ');
pScale -= this.G.tn.opt.Get('stacksScale');
}
}
}
else {
// thumbnail sub element
if( obj.$elt != null ) {
for( var n = 0; n < obj.$elt.length; n++ ) {
if( obj.$elt[n] != undefined ) {
// units must be given with
var v = 'translateX(' + obj.translateX + ') translateY(' + obj.translateY + ') translateZ(' + obj.translateZ + ') scale(' + obj.scale + ') translate(' + obj.translate + ')';
if( !(this.G.IE <= 9) && !this.G.isGingerbread ) {
v += ' rotateX(' + obj.rotateX + ') rotateY(' + obj.rotateY + ') rotateZ(' + obj.rotateZ + ') rotate(' + obj.rotate + ')';
}
else {
v += ' rotate(' + obj.rotateZ + ')';
}
obj.$elt[n].style[this.G.CSStransformName] = v;
}
}
}
}
};
//--- 2D/3D CSS transform - set a value in cache
NGY2Item.prototype.CSSTransformSet = function ( eltClass, transform, value, forceRefresh ) {
if( this.eltTransform[eltClass] == undefined ) {
this.eltTransform[eltClass] = { translateX: 0, translateY: 0, translateZ: 0, rotateX: 0, rotateY: 0, rotateZ: 0, scale: 1, translate: '0px,0px', rotate: 0 };
this.eltTransform[eltClass].$elt = this.$getElt(eltClass);
}
this.eltTransform[eltClass][transform] = value;
if( forceRefresh === true ) {
this.eltTransform[eltClass].$elt = this.$getElt(eltClass, true);
}
};
//--- CSS Filters - apply the cached value to element
NGY2Item.prototype.CSSFilterApply = function ( eltClass ) {
var obj = this.eltFilter[eltClass];
var v = 'blur(' + obj.blur + ') brightness(' + obj.brightness + ') grayscale(' + obj.grayscale + ') sepia(' + obj.sepia + ') contrast(' + obj.contrast + ') opacity(' + obj.opacity + ') saturate(' + obj.saturate + ')';
if( obj.$elt != null ) {
for( var n = 0; n < obj.$elt.length; n++ ) {
if( obj.$elt[n] != undefined ) {
obj.$elt[n].style.WebkitFilter = v;
obj.$elt[n].style.filter = v;
}
}
}
};
//--- CSS Filters - set a value in cache
NGY2Item.prototype.CSSFilterSet = function ( eltClass, filter, value, forceRefresh ) {
if( this.eltFilter[eltClass] == undefined ) {
this.eltFilter[eltClass] = { blur: 0, brightness: '100%', grayscale: '0%', sepia: '0%', contrast: '100%', opacity: '100%', saturate: '100%' };
this.eltFilter[eltClass].$elt = this.$getElt(eltClass);
}
this.eltFilter[eltClass][filter] = value;
if( forceRefresh === true ) {
this.eltTransform[eltClass].$elt = this.$getElt(eltClass, true);
}
};
//--- thumbnail hover animation
NGY2Item.prototype.animate = function ( effect, delay, hoverIn ) {
if( this.$getElt() == null ) { return; }
var context = {};
context.G = this.G;
context.item = this;
context.effect = effect;
context.hoverIn = hoverIn;
context.cssKind = '';
if( hoverIn ) {
// HOVER IN
if( this.eltEffect[effect.element] == undefined ) {
this.eltEffect[effect.element] = [];
}
if( this.eltEffect[effect.element][effect.type] == undefined ) {
this.eltEffect[effect.element][effect.type] = { initialValue: 0, lastValue: 0 };
}
if( effect.firstKeyframe ) {
// store initial and current value -> for use in the back animation
this.eltEffect[effect.element][effect.type] = { initialValue: effect.from, lastValue: effect.from};
}
context.animeFrom = effect.from;
context.animeTo = effect.to;
context.animeDuration = parseInt(effect.duration);
context.animeDelay = 30 + parseInt(effect.delay + delay); // 30ms is a default delay to avoid conflict with other initializations
context.animeEasing = effect.easing;
}
else {
// HOVER OUT
// if( effect.firstKeyframe ) {
context.animeFrom = this.eltEffect[effect.element][effect.type].lastValue;
context.animeTo = this.eltEffect[effect.element][effect.type].initialValue;
// context.animeTo=effect.from;
// }
// else {
// // context.animeFrom=effect.from;
// context.animeFrom = this.eltEffect[effect.element][effect.type].lastValue;
// context.animeTo = this.eltEffect[effect.element][effect.type].initialValue;
// //context.animeTo=effect.to;
// }
context.animeDuration = parseInt(effect.durationBack);
context.animeDelay = 30 + parseInt(effect.delayBack + delay); // 30ms is a default delay to avoid conflict with other initializations
context.animeEasing = effect.easingBack;
}
// detect if animation on CSS transform
var transform=['translateX', 'translateY', 'translateZ', 'scale', 'rotateX', 'rotateY', 'rotateZ'];
for( var i = 0; i < transform.length; i++ ) {
if( effect.type == transform[i] ) {
context.cssKind = 'transform';
break;
}
}
// detect if animation on CSS filter
var filter=['blur', 'brightness', 'grayscale', 'sepia', 'contrast', 'opacity', 'saturate'];
for( var i = 0; i < filter.length; i++ ) {
if( effect.type == filter[i] ) {
context.cssKind = 'filter';
break;
}
}
// handle some special cases
if( hoverIn && effect.element == '.nGY2GThumbnail' && ( effect.type == 'scale' || effect.type == 'rotateX') ) {
this.G.GOM.lastZIndex++;
this.$getElt(effect.element).css('z-index', this.G.GOM.lastZIndex);
// setElementOnTop(this.G.$E.base, this.$getElt(effect.element) );
}
// animation
var tweenable = new NGTweenable();
context.tweenable=tweenable;
tweenable.tween({
attachment: context,
from: { 'v': context.animeFrom },
to: { 'v': context.animeTo },
duration: context.animeDuration, //parseInt(effect.duration),
delay: context.animeDelay, //parseInt(effect.delay),
easing: context.animeEasing, //'easeOutQuart',
step: function (state, att) {
if( att.item.$getElt() == null ) {
// the thumbnail may be destroyed since the start of the animation
att.tweenable.stop(false);
// att.tweenable.dispose();
return;
}
if( att.hoverIn && !att.item.hovered ) {
// thumbnail no more hovered
att.tweenable.stop(false);
// att.tweenable.dispose();
return;
}
if( att.G.VOM.viewerDisplayed ) {
att.tweenable.stop(false);
// att.tweenable.dispose();
return;
}
// test if in delay phase
if( state.v == att.animeFrom ) { return; }
switch( att.cssKind ) {
case 'transform':
// window.ng_draf( function() {
att.item.CSSTransformSet(att.effect.element, att.effect.type, state.v);
att.item.CSSTransformApply( att.effect.element );
// });
break;
case 'filter':
// window.ng_draf( function() {
att.item.CSSFilterSet(att.effect.element, att.effect.type, state.v);
att.item.CSSFilterApply( att.effect.element );
// });
break;
default:
var v=state.v;
if( state.v.substring(0,4) == 'rgb(' || state.v.substring(0,5) == 'rgba(' ) {
// to remove values after the dot (not supported by RGB/RGBA)
// v=ngtinycolor(state.v).toRgbString();
v = ShadeBlendConvert(0, v);
}
// window.ng_draf( function() {
att.item.$getElt( att.effect.element ).css( att.effect.type, v );
// });
break;
}
if( hoverIn ) {
// store value for back animation
att.item.eltEffect[att.effect.element][att.effect.type].lastValue = state.v;
}
},
finish: function (state, att) {
if( hoverIn ) {
// store value for back animation
att.item.eltEffect[att.effect.element][att.effect.type].lastValue = state.v;
}
if( att.item.$getElt() == null ) {
// the thumbnail may be destroyed since the start of the animation
return;
}
if( att.hoverIn && !att.item.hovered ) {
// thumbnail no more hovered
return;
}
if( att.G.VOM.viewerDisplayed ) {
return;
}
// window.ng_draf( function() {
switch( att.cssKind ) {
case 'transform':
att.item.CSSTransformSet(att.effect.element, att.effect.type, att.animeTo);
att.item.CSSTransformApply(att.effect.element);
break;
case 'filter':
att.item.CSSFilterSet(att.effect.element, att.effect.type, att.animeTo);
att.item.CSSFilterApply(att.effect.element);
break;
default:
att.item.$getElt(att.effect.element).css(att.effect.type, att.animeTo);
break;
}
// });
}
});
};
return NGY2Item;
})();
}
_this.options = jQuery.extend(true, {}, jQuery.nanogallery2.defaultOptions, options);
// Initialization code
_this.nG2 = null;
_this.nG2 = new nanoGALLERY2();
_this.nG2.initiateGallery2(_this.e, _this.options );
};
// PUBLIC EXPOSED METHODS
_this.test = function() {
//alert('test');
// console.dir(_this.nG.G.I.length);
// console.dir(_this.nG);
// debugger;
//privateTest();
}
// Run initializer
_this.init();
};
jQuery.nanogallery2.defaultOptions = {
kind : '',
userID : '',
photoset : '',
album: '',
blockList : 'scrapbook|profil|auto backup',
tagBlockList: '',
allowList : '',
albumList : '',
albumList2 : null,
RTL : false,
flickrSkipOriginal : true,
flickrAPIKey: '',
breadcrumbAutoHideTopLevel : true,
displayBreadcrumb : true,
breadcrumbOnlyCurrentLevel : true,
breadcrumbHideIcons : true,
theme : 'nGY2',
galleryTheme : 'dark',
viewerTheme : 'dark',
items : null,
itemsBaseURL : '',
thumbnailSelectable : false,
dataProvider: '',
allowHTMLinData: false,
locationHash : true,
slideshowDelay : 3000,
slideshowAutoStart : false,
debugMode: false,
titleTranslationMap: null,
galleryDisplayMoreStep : 2,
galleryDisplayMode : 'fullContent',
galleryL1DisplayMode : null,
galleryPaginationMode : 'rectangles', // 'dots', 'rectangles', 'numbers'
galleryPaginationTopButtons : true,
galleryMaxRows : 2,
galleryL1MaxRows : null,
galleryLastRowFull: false,
galleryL1LastRowFull: null,
galleryLayoutEngine : 'default',
paginationSwipe: true,
paginationVisiblePages : 10,
galleryFilterTags : false, // possible values: false, true, 'title', 'description'
galleryL1FilterTags : null, // possible values: false, true, 'title', 'description'
galleryFilterTagsMode : 'single',
galleryL1FilterTagsMode : null,
galleryMaxItems : 0, // maximum number of items per album --> only flickr, google2, nano_photos_provider2
galleryL1MaxItems : null, // maximum number of items per gallery page --> only flickr, google2, nano_photos_provider2
gallerySorting : '',
galleryL1Sorting : null,
galleryDisplayTransition : 'none',
galleryL1DisplayTransition : null,
galleryDisplayTransitionDuration : 1000,
galleryL1DisplayTransitionDuration : null,
galleryResizeAnimation : false,
galleryRenderDelay : 10,
thumbnailCrop : true,
thumbnailL1Crop : null,
thumbnailCropScaleFactor : 1.5,
thumbnailLevelUp : false,
thumbnailAlignment : 'fillWidth',
thumbnailWidth : 300,
thumbnailL1Width : null,
thumbnailHeight : 200,
thumbnailL1Height : null,
thumbnailBaseGridHeight : 0,
thumbnailL1BaseGridHeight : null,
thumbnailGutterWidth : 2,
thumbnailL1GutterWidth : null,
thumbnailGutterHeight : 2,
thumbnailL1GutterHeight : null,
thumbnailBorderVertical : 2,
thumbnailL1BorderVertical : null,
thumbnailBorderHorizontal : 2,
thumbnailL1BorderHorizontal : null,
thumbnailFeaturedKeyword : '*featured',
thumbnailAlbumDisplayImage : false,
thumbnailHoverEffect2 : 'toolsAppear',
thumbnailBuildInit2 : '',
thumbnailStacks : 0,
thumbnailL1Stacks : null,
thumbnailStacksTranslateX : 0,
thumbnailL1StacksTranslateX : null,
thumbnailStacksTranslateY : 0,
thumbnailL1StacksTranslateY : null,
thumbnailStacksTranslateZ : 0,
thumbnailL1StacksTranslateZ : null,
thumbnailStacksRotateX : 0,
thumbnailL1StacksRotateX : null,
thumbnailStacksRotateY : 0,
thumbnailL1StacksRotateY : null,
thumbnailStacksRotateZ : 0,
thumbnailL1StacksRotateZ : null,
thumbnailStacksScale : 0,
thumbnailL1StacksScale : null,
thumbnailDisplayOutsideScreen: true,
thumbnailWaitImageLoaded: true,
thumbnailSliderDelay: 2000,
galleryBuildInit2 : '',
portable : false,
eventsDebounceDelay: 10,
touchAnimation : false,
touchAnimationL1 : undefined,
touchAutoOpenDelay : 0,
thumbnailLabel : {
position : 'overImage',
align: 'center',
valign: 'bottom',
display : true,
displayDescription : false,
titleMaxLength : 0,
titleMultiLine : false,
descriptionMaxLength : 0,
descriptionMultiLine : false,
hideIcons : true,
title : ''
},
thumbnailToolbarImage : { topLeft: 'select', topRight : 'featured' },
thumbnailToolbarAlbum : { topLeft: 'select', topRight : 'counter' },
thumbnailDisplayOrder : '',
thumbnailL1DisplayOrder : null,
thumbnailDisplayInterval : 15,
thumbnailL1DisplayInterval : null,
thumbnailDisplayTransition : 'fadeIn',
thumbnailL1DisplayTransition : null,
thumbnailDisplayTransitionEasing : 'easeOutQuart',
thumbnailL1DisplayTransitionEasing : null,
thumbnailDisplayTransitionDuration: 240,
thumbnailL1DisplayTransitionDuration: null,
thumbnailOpenInLightox : true,
thumbnailOpenOriginal : false,
lightboxStandalone: false,
viewer : 'internal',
viewerFullscreen: false,
imageTransition : 'swipe2',
viewerTransitionMediaKind : 'img',
viewerZoom : true,
viewerImageDisplay : '',
openOnStart : '',
viewerHideToolsDelay : 4000,
viewerToolbar : {
display : false,
position : 'bottom',
fullWidth : false,
align : 'center',
autoMinimize : 0,
standard : 'minimizeButton,label',
minimized : 'minimizeButton,label,infoButton,shareButton,fullscreenButton'
},
viewerTools : {
topLeft : 'pageCounter,playPauseButton',
topRight : 'rotateLeft,rotateRight,fullscreenButton,closeButton'
},
viewerGallery: 'bottomOverMedia',
viewerGalleryTWidth: 40,
viewerGalleryTHeight: 40,
breakpointSizeSM : 480,
breakpointSizeME : 992,
breakpointSizeLA : 1200,
breakpointSizeXL : 1800,
fnThumbnailInit : null,
fnThumbnailHoverInit : null,
fnThumbnailHover : null,
fnThumbnailHoverOut : null,
fnThumbnailDisplayEffect : null,
fnViewerInfo : null,
fnImgToolbarCustInit : null,
fnImgToolbarCustDisplay : null,
fnImgToolbarCustClick : null,
fnProcessData : null,
fnThumbnailSelection : null,
fnGalleryRenderStart : null,
fnGalleryRenderEnd : null,
fnGalleryObjectModelBuilt : null,
fnGalleryLayoutApplied : null,
fnThumbnailClicked : null,
fnShoppingCartUpdated : null,
fnThumbnailToolCustAction : null,
fnThumbnailOpen : null,
fnImgDisplayed : null,
fnPopupMediaInfo : null,
i18n : {
'breadcrumbHome' : 'Galleries', 'breadcrumbHome_FR' : 'Galeries',
'thumbnailImageTitle' : '', 'thumbnailAlbumTitle' : '',
'thumbnailImageDescription' : '', 'thumbnailAlbumDescription' : '',
'infoBoxPhoto' : 'Photo', 'infoBoxDate' : 'Date', 'infoBoxAlbum' : 'Album', 'infoBoxDimensions' : 'Dimensions', 'infoBoxFilename' : 'Filename', 'infoBoxFileSize' : 'File size', 'infoBoxCamera' : 'Camera', 'infoBoxFocalLength' : 'Focal length', 'infoBoxExposure' : 'Exposure', 'infoBoxFNumber' : 'F Number', 'infoBoxISO' : 'ISO', 'infoBoxMake' : 'Make', 'infoBoxFlash' : 'Flash', 'infoBoxViews' : 'Views', 'infoBoxComments' : 'Comments'
},
icons : {
// example for font awesome:
thumbnailAlbum: '',
thumbnailImage: '',
breadcrumbAlbum: '',
breadcrumbHome: '',
breadcrumbSeparator: '',
breadcrumbSeparatorRtl: '',
navigationFilterSelected: '',
navigationFilterUnselected: '',
navigationFilterSelectedAll: '',
navigationPaginationPrevious: '',
navigationPaginationNext: '',
thumbnailSelected: '',
thumbnailUnselected: '',
thumbnailFeatured: '',
thumbnailCounter: '',
thumbnailShare: '',
thumbnailDownload: '',
thumbnailInfo: '',
thumbnailShoppingcart: '',
thumbnailDisplay: '',
thumbnailCustomTool1: 'T1',
thumbnailCustomTool2: 'T2',
thumbnailCustomTool3: 'T3',
thumbnailCustomTool4: 'T4',
thumbnailCustomTool5: 'T5',
thumbnailCustomTool6: 'T6',
thumbnailCustomTool7: 'T7',
thumbnailCustomTool8: 'T8',
thumbnailCustomTool9: 'T9',
thumbnailCustomTool10: 'T10',
thumbnailAlbumUp: '',
paginationNext: '',
paginationPrevious: '',
galleryMoreButton: ' ',
buttonClose: '',
viewerPrevious: '',
viewerNext: '',
viewerImgPrevious: '',
viewerImgNext: '',
viewerDownload: '',
viewerToolbarMin: '',
viewerToolbarStd: '',
viewerPlay: '',
viewerPause: '',
viewerFullscreenOn: '',
viewerFullscreenOff: '',
viewerZoomIn: '',
viewerZoomOut: '',
viewerLinkOriginal: '',
viewerInfo: '',
viewerShare: '',
viewerRotateLeft: '',
viewerRotateRight: '',
viewerShoppingcart: '',
user: '',
location: '',
picture: '',
config: '',
shareFacebook: '',
shareTwitter: '',
// shareGooglePlus: '',
shareTumblr: '',
sharePinterest: '',
shareVK: '',
shareMail: '',
viewerCustomTool1: 'T1',
viewerCustomTool2: 'T2',
viewerCustomTool3: 'T3',
viewerCustomTool4: 'T4',
viewerCustomTool5: 'T5',
viewerCustomTool6: 'T6',
viewerCustomTool7: 'T7',
viewerCustomTool8: 'T8',
viewerCustomTool9: 'T9',
viewerCustomTool10: 'T10'
}
};
jQuery.fn.nanogallery2 = function (args, option, value) {
if( typeof jQuery(this).data('nanogallery2data') === 'undefined'){
if( args == 'destroy' ) {
// command to destroy but no instance yet --> exit
return;
}
return this.each( function(){
(new jQuery.nanogallery2(this, args));
});
}
else {
// no options -->
// This function breaks the chain, but provides some API methods
var nG2 = $(this).data('nanogallery2data').nG2;
// Lightbox standalone
// (Another click on an already opened media)
if( args !== undefined && args.lightboxStandalone === true ) {
// items exist already (G.I is populated) -> just open the lightbox again
nG2.LightboxReOpen();
return;
}
switch(args){
case 'displayItem':
nG2.DisplayItem(option);
break;
case 'search':
return( nG2.Search(option));
break;
case 'search2':
return nG2.Search2(option, value);
break;
case 'search2Execute':
return nG2.Search2Execute();
break;
case 'refresh':
nG2.Refresh();
break;
case 'resize':
nG2.Resize();
break;
case 'instance':
return nG2;
break;
case 'data':
nG2.data= {
items: nG2.I,
gallery: nG2.GOM,
lightbox: nG2.VOM,
shoppingcart: nG2.shoppingCart
};
return nG2.data;
break;
case 'reload':
nG2.ReloadAlbum();
return $(this);
break;
case 'itemsSelectedGet':
return nG2.ItemsSelectedGet();
break;
case 'itemsSetSelectedValue':
nG2.ItemsSetSelectedValue(option, value);
break;
case 'option':
if(typeof value === 'undefined'){
return nG2.Get(option);
}else{
nG2.Set(option,value);
if( option == 'demoViewportWidth' ) {
// force resize event -> for demo purposes
$(window).trigger('resize');
}
}
break;
case 'destroy':
nG2.Destroy();
$(this).removeData('nanogallery2data');
break;
case 'shoppingCartGet':
// returns the content of the shoppingcart
return nG2.shoppingCart;
break;
case 'shoppingCartUpdate':
// parameters :
// - option = item's ID
// - value = new quantity
if( typeof value === 'undefined' || typeof option === 'undefined' ){
return false;
}
var item_ID = option;
var new_qty = value;
for( var i=0; i < nG2.shoppingCart.length; i++) {
if( nG2.shoppingCart[i].ID == item_ID ) {
// updates counter
nG2.shoppingCart[i].qty = new_qty;
let item = nG2.I[nG2.shoppingCart[i].idx];
// updates thumbnail
nG2.ThumbnailToolbarOneCartUpdate( item );
if( new_qty == 0 ) {
// removes item from shoppingcart
nG2.shoppingCart.splice(i, 1);
}
var fu = nG2.O.fnShoppingCartUpdated;
if( fu !== null ) {
typeof fu == 'function' ? fu(nG2.shoppingCart, item, 'api') : window[fu](nG2.shoppingCart, item, 'api');
}
break;
}
}
return nG2.shoppingCart;
break;
case 'shoppingCartRemove':
// parameters :
// - option = item's ID
if( typeof option === 'undefined' ){
return false;
}
var ID = option;
for( var i=0; i < nG2.shoppingCart.length; i++) {
if( nG2.shoppingCart[i].ID == ID ) {
var item = nG2.I[nG2.shoppingCart[i].idx];
// updates thumbnail
nG2.shoppingCart[i].qty = 0;
nG2.ThumbnailToolbarOneCartUpdate( item );
// removes item from shoppingcart
nG2.shoppingCart.splice(i, 1);
var fu = nG2.O.fnShoppingCartUpdated;
if( fu !== null ) {
typeof fu == 'function' ? fu(nG2.shoppingCart, item, 'api') : window[fu](nG2.shoppingCart, item, 'api');
}
break;
}
}
return nG2.shoppingCart;
break;
case 'closeViewer':
nG2.CloseViewer();
break;
case 'minimizeToolbar':
nG2.MinimizeToolbar();
break;
case 'maximizeToolbar':
nG2.MaximizeToolbar();
break;
case 'paginationPreviousPage':
nG2.PaginationPreviousPage();
break;
case 'paginationNextPage':
nG2.paginationNextPage();
break;
case 'paginationGotoPage':
nG2.PaginationGotoPage( option );
break;
case 'paginationCountPages':
nG2.PaginationCountPages();
break;
}
return $(this);
}
};
// ###############################
// ##### nanogallery2 script #####
// ###############################
/** @function nanoGALLERY2 */
function nanoGALLERY2() {
"use strict";
/**
* Force reload the current album, if provided by Json
*/
this.LightboxReOpen = function(){
LightboxStandaloneDisplay();
}
/**
* Force reload the current album, if provided by Json
*/
this.ReloadAlbum = function(){
if( G.O.kind === '' ) {
throw 'Not supported for this content source:' + G.O.kind;
}
var albumIdx = G.GOM.albumIdx;
if( albumIdx == -1 ) {
throw ('Current album not found.');
}
var albumID = G.I[albumIdx].GetID();
// unselect everything & remove link to album (=logical delete)
var l = G.I.length;
for( var i = 0; i < l ; i++ ) {
var item = G.I[i];
if( item.albumID == albumID ) {
item.selected = false;
}
}
G.I[albumIdx].contentIsLoaded = false;
DisplayAlbum('-1', albumID);
};
/**
* Set one or several items selected/unselected
* @param {array} items
*/
this.ItemsSetSelectedValue = function(items, value){
var l = items.length;
for( var j = 0; j < l ; j++) {
ThumbnailSelectionSet(items[j], value);
}
};
/**
* Returns an array of selected items
* @returns {Array}
*/
this.ItemsSelectedGet = function(){
var selectedItems = [];
var l = G.I.length;
for( var i = 0; i < l ; i++ ) {
if( G.I[i].selected == true ) {
selectedItems.push(G.I[i]);
}
}
return selectedItems;
};
/**
* Returns the value of an option
* @param {string} option
* @returns {nanoGALLERY.G.O}
*/
this.Get = function(option){
return G.O[option];
};
/**
* Set a new value for a defined option
* @param {string} option
*/
this.Set = function(option, value){
G.O[option] = value;
switch( option ) {
case 'thumbnailSelectable':
ThumbnailSelectionClear();
// refresh the displayed gallery
GalleryRender( G.GOM.albumIdx );
break;
}
};
/**
* Refresh the current gallery
*/
this.Refresh = function() {
// Refresh the displayed gallery
GalleryRender( G.GOM.albumIdx );
};
/**
* Resize the current gallery
*/
this.Resize = function() {
// resize the displayed gallery
GalleryResize();
};
/**
* display one item (image or gallery)
* itemID syntax:
* - albumID --> display one album
* - albumID/imageID --> display one image
*/
this.DisplayItem = function( itemID ) {
var IDs=parseIDs( itemID );
if( IDs.imageID != '0' ) {
DisplayPhoto( IDs.imageID, IDs.albumID );
}
else {
DisplayAlbum( '-1', IDs.albumID );
}
};
this.ThumbnailToolbarOneCartUpdate = function ( item ) {
ThumbnailBuildToolbarOneCartUpdate( item );
}
var CountItemsToDisplay = function( gIdx ) {
if( G.I[gIdx] == undefined ) { return 0; }
var albumID = G.I[gIdx].GetID();
var l = G.I.length;
var cnt = 0;
for( var idx = 0; idx < l; idx++ ) {
var item = G.I[idx];
if( item.isToDisplay(albumID) ) {
cnt++;
}
}
return cnt;
}
/**
* Search in the displayed gallery (in thumbnails title)
*/
this.Search = function( search ) {
G.GOM.albumSearch = search.toUpperCase();
var gIdx = G.GOM.albumIdx;
GalleryRender( G.GOM.albumIdx );
return CountItemsToDisplay( gIdx );
};
/**
* Search2 in title and tags - set search values
*/
this.Search2 = function( searchTitle, searchTags ) {
if( searchTitle != undefined && searchTitle != null ) {
G.GOM.albumSearch = searchTitle.toUpperCase().trim();
}
else {
G.GOM.albumSearch = '';
}
if( searchTags != null && searchTags != undefined ) {
G.GOM.albumSearchTags = searchTags.toUpperCase().trim();
}
else {
G.GOM.albumSearchTags = '';
}
return CountItemsToDisplay( G.GOM.albumIdx );
};
/**
* Search2 - execute the search on title and tags
*/
this.Search2Execute = function() {
var gIdx = G.GOM.albumIdx;
GalleryRender( G.GOM.albumIdx );
return CountItemsToDisplay( gIdx );
};
/**
* Destroy the current gallery
*/
this.Destroy = function(){
if( G.GOM.hammertime != null ) {
G.GOM.hammertime.destroy();
G.GOM.hammertime = null;
}
if( G.VOM.hammertime != null ) {
G.VOM.hammertime.destroy();
G.VOM.hammertime = null;
}
// color scheme
$('#ngycs_' + G.baseEltID).remove()
G.GOM.items = [];
NGY2Item.New( G, G.i18nTranslations.breadcrumbHome, '', '0', '-1', 'album' );
G.GOM.navigationBar.$newContent = null;
G.$E.base.empty();
G.$E.base.removeData();
if( G.O.locationHash ) {
jQuery(window).off('hashchange.nanogallery2.' + G.baseEltID);
}
jQuery(window).off('resize.nanogallery2.' + G.baseEltID);
jQuery(window).off('orientationChange.nanogallery2.' + G.baseEltID);
jQuery(window).off('scroll.nanogallery2.' + G.baseEltID);
if( G.$E.scrollableParent !== null ) {
G.$E.scrollableParent.off('scroll.nanogallery2.' + G.baseEltID);
}
G.GOM.firstDisplay = true;
};
/**
* CloseViewer - close the media viewer
*/
this.CloseViewer = function() {
LightboxClose(null);
return false;
};
/**
* MinimizeToolbar - display the minimized lightbox main toolbar
*/
this.MinimizeToolbar = function() {
ViewerToolbarForVisibilityMin();
return false;
};
/**
* MaximizeToolbar - display the maximized/standard lightbox main toolbar
*/
this.MaximizeToolbar = function() {
ViewerToolbarForVisibilityStd();
return false;
};
/**
* PaginationPreviousPage - gallery paginate to previous page
*/
this.PaginationPreviousPage = function() {
paginationPreviousPage();
return false;
};
/**
* PaginationNextPage - gallery paginate to next page
*/
this.PaginationNextPage = function() {
paginationNextPage();
return false;
};
/**
* PaginationGotoPage - gallery paginate to specific page
*/
this.PaginationGotoPage = function( page ) {
// var aIdx = G.$E.conPagin.data('galleryIdx');
if( page > 1 ) { page--; }
G.GOM.pagination.currentPage = page;
// scroll to top of gallery if not displayed
G.GOM.ScrollToTop();
GalleryDisplayPart1();
GalleryDisplayPart2( true );
return false;
};
/**
* PaginationCountPages - gallery pagination - returns the number of pages
*/
this.PaginationCountPages = function() {
if( G.GOM.items.length == 0 ) { return 0; } // no thumbnail to display
var nbPages = Math.ceil((G.GOM.items[G.GOM.items.length - 1].row + 1) / G.galleryMaxRows.Get());
return nbPages;
};
/**
* PaginationCountPages - gallery pagination - returns the number of pages
*/
// throttle()
// author: underscore.js - http://underscorejs.org/docs/underscore.html
// Returns a function, that, when invoked, will only be triggered at most once during a given window of time.
// Normally, the throttled function will run as much as it can, without ever going more than once per wait duration;
// but if you�d like to disable the execution on the leading edge, pass {leading: false}.
// To disable execution on the trailing edge, ditto.
var throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function() {
var now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};
// DEBOUNCE
// author: John Hann - http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
// execAsap - false means executing at the end of the detection period
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
// clearRequestTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
// timeout = requestTimeout(delayed, threshold || 100);
};
}
// Double requestAnimationFrame
window.ng_draf = function (cb) {
return requestAnimationFrame(function() {
window.requestAnimationFrame(cb)
})
}
// REQUESTTIMEOUT - replace SETTIMEOUT - https://gist.github.com/joelambert/1002116
/**
* Behaves the same as setTimeout except uses requestAnimationFrame() where possible for better performance
* @param {function} fn The callback function
* @param {int} delay The delay in milliseconds
*/
window.requestTimeout = function(fn, delay) {
if( !window.requestAnimationFrame &&
!window.webkitRequestAnimationFrame &&
!(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support
!window.oRequestAnimationFrame &&
!window.msRequestAnimationFrame)
return window.setTimeout(fn, delay);
var start = new Date().getTime(),
handle = new Object();
function loop(){
var current = new Date().getTime(),
delta = current - start;
// delta = delay;
delta >= delay ? fn.call() : handle.value = requestAnimFrame(loop);
};
handle.value = requestAnimFrame(loop);
return handle;
};
// requestAnimationFrame() shim by Paul Irish
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback, /* DOMElement */ element){
window.setTimeout(callback, 1000 / 60);
};
})();
// CLEARREQUESTTIMEOUT - to replace CLEARTIMEOUT - https://gist.github.com/joelambert/1002116
/**
* Behaves the same as clearTimeout except uses cancelRequestAnimationFrame() where possible for better performance
* @param {int|object} fn The callback function
*/
window.clearRequestTimeout = function(handle) {
window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) :
window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) :
window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : /* Support for legacy API */
window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) :
window.oCancelRequestAnimationFrame ? window.oCancelRequestAnimationFrame(handle.value) :
window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) :
clearTimeout(handle);
};
/*
** Global data for this nanogallery2 instance
**/
var G=this;
G.I = []; // gallery items
G.Id = []; // gallery items
G.O = null; // user options
G.baseEltID = null; // ID of the base element
G.$E = {
base: null, // base element
conTnParent: null, // $g_containerThumbnailsParent
conLoadingB: null, // loading bar - nanoGalleryLBarOff
conConsole: null, // console for error messages
conNavigationBar: null, // gallery navigation bar
conTnBottom: null, // container on the bottom of the gallery
scrollableParent: null // first scrollable parent container
};
G.shoppingCart = [];
G.layout = { // Layout informations
internal : true,
engine : '',
support : { rows: false },
prerequisite : { imageSize: false },
SetEngine: function() {
if( G.layout.internal ) {
if( G.tn.settings.width[G.GOM.curNavLevel][G.GOM.curWidth] == 'auto' || G.tn.settings.width[G.GOM.curNavLevel][G.GOM.curWidth] == '' ) {
// do not use getH() / getW() here!
G.layout.engine = 'JUSTIFIED';
G.layout.support.rows = true;
G.layout.prerequisite.imageSize = true;
return;
}
if( G.tn.settings.height[G.GOM.curNavLevel][G.GOM.curWidth] == 'auto' || G.tn.settings.height[G.GOM.curNavLevel][G.GOM.curWidth] == '' ) {
// do not use getH() / getW() here!
G.layout.engine = 'CASCADING';
G.layout.support.rows = false;
G.layout.prerequisite.imageSize = true;
return;
}
if( G.tn.settings.getMosaic() != null ) {
G.layout.engine = 'MOSAIC';
G.layout.support.rows = true;
G.layout.prerequisite.imageSize = false;
return;
}
G.layout.engine = 'GRID';
G.layout.support.rows=true;
// if( G.tn.opt.Get('crop') === true ) {
// G.layout.prerequisite.imageSize = true;
// }
// else {
G.layout.prerequisite.imageSize = false;
// }
}
}
};
G.galleryResizeEventEnabled = false;
G.galleryMaxRows = { l1: 0, lN: 0,
Get: function() {
return G.galleryMaxRows[G.GOM.curNavLevel];
}
};
G.galleryMaxItems = { l1: 0, lN: 0,
Get: function() {
return G.galleryMaxItems[G.GOM.curNavLevel];
}
};
G.galleryFilterTags = { l1: 0, lN: 0,
Get: function() {
return G.galleryFilterTags[G.GOM.curNavLevel];
}
};
G.galleryFilterTagsMode = { l1: 0, lN: 0,
Get: function() {
return G.galleryFilterTagsMode[G.GOM.curNavLevel];
}
};
G.galleryDisplayMode = { l1: 'FULLCONTENT', lN: 'FULLCONTENT',
Get: function() {
return G.galleryDisplayMode[G.GOM.curNavLevel];
}
};
G.galleryLastRowFull = { l1: false, lN: false,
Get: function() {
return G.galleryLastRowFull[G.GOM.curNavLevel];
}
};
G.gallerySorting = { l1: '', lN: '',
Get: function() {
return G.gallerySorting[G.GOM.curNavLevel];
}
};
G.galleryDisplayTransition = { l1: 'none', lN: 'none',
Get: function() {
return G.galleryDisplayTransition[G.GOM.curNavLevel];
}
};
G.galleryDisplayTransitionDuration = { l1: 500, lN: 500,
Get: function() {
return G.galleryDisplayTransitionDuration[G.GOM.curNavLevel];
}
};
G.$currentTouchedThumbnail = null;
// ##### GENERAL THUMBNAILS PROPERTIES -->
G.tn = {
// levell specific options
opt: {
l1: { crop: true, stacks: 0, stacksTranslateX: 0, stacksTranslateY: 0, stacksTranslateZ: 0, stacksRotateX: 0, stacksRotateY: 0, stacksRotateZ: 0, stacksScale: 0, borderHorizontal: 0, borderVertical: 0, baseGridHeight: 0, displayTransition: 'FADEIN', displayTransitionStartVal: 0, displayTransitionEasing: 'easeOutQuart', displayTransitionDuration: 240, displayInterval: 15 },
lN: { crop: true, stacks: 0, stacksTranslateX: 0, stacksTranslateY: 0, stacksTranslateZ: 0, stacksRotateX: 0, stacksRotateY: 0, stacksRotateZ: 0, stacksScale: 0, borderHorizontal: 0, borderVertical: 0, baseGridHeight: 0, displayTransition: 'FADEIN', displayTransitionStartVal: 0, displayTransitionEasing: 'easeOutQuart', displayTransitionDuration: 240, displayInterval: 15 },
Get: function(opt) {
return G.tn.opt[G.GOM.curNavLevel][opt];
}
},
scale: 1, // image scale depending of the hover effect
labelHeight: { // in case label on bottom, otherwise always=0
l1: 0, lN: 0,
get: function() {
return G.tn.labelHeight[G.GOM.curNavLevel];
}
},
defaultSize: { // default thumbnail size
// label height is not included
width: { l1 : { xs:0, sm:0, me:0, la:0, xl:0 }, lN : { xs:0, sm:0, me:0, la:0, xl:0 } },
height: { l1 : { xs:0, sm:0, me:0, la:0, xl:0 }, lN : { xs:0, sm:0, me:0, la:0, xl:0 } },
getWidth: function() {
return G.tn.defaultSize.width[G.GOM.curNavLevel][G.GOM.curWidth];
},
getOuterWidth: function() { // width including border
G.tn.borderWidth = G.tn.opt.Get('borderHorizontal');
G.tn.borderHeight = G.tn.opt.Get('borderVertical');
var w = G.tn.defaultSize.width[G.GOM.curNavLevel][G.GOM.curWidth] + G.tn.opt.Get('borderHorizontal') * 2;
if( G.O.thumbnailLabel.get('position') == 'right' || G.O.thumbnailLabel.get('position') == 'left' ) {
w += G.tn.defaultSize.width[G.GOM.curNavLevel][G.GOM.curWidth];
}
return w;
},
getHeight: function() {
return G.tn.defaultSize.height[G.GOM.curNavLevel][G.GOM.curWidth];
},
getOuterHeight: function() { // height, border included
return G.tn.defaultSize.height[G.GOM.curNavLevel][G.GOM.curWidth]+G.tn.opt.Get('borderVertical')*2;
}
},
settings: { // user defined width/height of the image to display depending on the screen size
width: { l1 : { xs:0, sm:0, me:0, la:0, xl:0, xsc:'u', smc:'u', mec:'u', lac:'u', xlc:'u' },
lN : { xs:0, sm:0, me:0, la:0, xl:0, xsc:'u', smc:'u', mec:'u', lac:'u', xlc:'u' } },
height: { l1 : { xs:0, sm:0, me:0, la:0, xl:0, xsc:'u', smc:'u', mec:'u', lac:'u', xlc:'u' },
lN : { xs:0, sm:0, me:0, la:0, xl:0, xsc:'u', smc:'u', mec:'u', lac:'u', xlc:'u' } },
getH: function(l, w) {
var cl = (l == undefined ? G.GOM.curNavLevel : l);
var cw = (w == undefined ? G.GOM.curWidth : w);
if( G.layout.engine == 'MOSAIC' ) {
return this.height[cl][cw] * this.mosaic[cl+'Factor']['h'][cw];
}
else {
return this.height[cl][cw];
}
},
getW: function(l, w) {
var cl = (l == undefined ? G.GOM.curNavLevel : l);
var cw = (w == undefined ? G.GOM.curWidth : w);
if( G.layout.engine == 'MOSAIC' ) {
return this.width[cl][cw] * this.mosaic[cl+'Factor']['w'][cw];
}
else {
return this.width[cl][cw];
// return G.tn.settings.width[G.GOM.curNavLevel][G.GOM.curWidth];
}
},
mosaic: { l1 : { xs: null, sm: null, me: null, la: null, xl: null },
lN : { xs: null, sm: null, me: null, la: null, xl: null },
l1Factor : { h :{ xs: 1, sm: 1, me: 1, la: 1, xl: 1 }, w :{ xs: 1, sm: 1, me: 1, la: 1, xl: 1 }},
lNFactor : { h :{ xs: 1, sm: 1, me: 1, la: 1, xl: 1 }, w :{ xs: 1, sm: 1, me: 1, la: 1, xl: 1 }}
},
getMosaic: function() {
return this.mosaic[G.GOM.curNavLevel][G.GOM.curWidth];
},
mosaicCalcFactor: function(l, w) {
// retrieve max size multiplicator
var maxW = 1;
var maxH = 1;
for( var n = 0; n < G.tn.settings.mosaic[l][w].length; n++ ) {
maxW = Math.max(maxW, this.mosaic[l][w][n]['w']);
maxH = Math.max(maxH, this.mosaic[l][w][n]['h']);
}
this.mosaic[l + 'Factor']['h'][w] = maxH;
this.mosaic[l + 'Factor']['w'][w] = maxW;
},
gutterHeight: { l1 : { xs:0, sm:0, me:0, la:0, xl:0 }, lN : { xs:0, sm:0, me:0, la:0, xl:0 } },
gutterWidth: { l1 : { xs:0, sm:0, me:0, la:0, xl:0 }, lN : { xs:0, sm:0, me:0, la:0, xl:0 } },
GetResponsive: function( setting ) {
return this[setting][G.GOM.curNavLevel][G.GOM.curWidth];
}
},
// thumbnail hover effects
hoverEffects : {
std : [],
level1: [],
get: function() {
if( G.GOM.curNavLevel == 'l1' && this.level1.length !== 0 ) {
return this.level1;
}
else {
return this.std;
}
}
},
// thumbnail init
buildInit : {
std : [],
level1: [],
get: function() {
if( G.GOM.curNavLevel == 'l1' && this.level1.length !== 0 ) {
return this.level1;
}
else {
return this.std;
}
}
},
// thumbnail toolbars
toolbar: {
album : { topLeft : '', topRight: '', bottomLeft: '', bottomRight: '' },
image : { topLeft : '', topRight: '', bottomLeft: '', bottomRight: '' },
albumUp : { topLeft : '', topRight: '', bottomLeft: '', bottomRight: '' },
get: function( item ) {
return this[item.kind];
},
},
style: {
// inline CSS
l1 : { label: '', title: '', desc: '' },
lN : { label: '', title: '', desc: '' },
getTitle : function() {
return ('style="' + this[G.GOM.curNavLevel].title + '"');
},
getDesc : function() {
return ('style="' + this[G.GOM.curNavLevel].desc + '"');
},
getLabel: function() {
var s='style="'+ this[G.GOM.curNavLevel].label;
s+= (G.O.RTL ? '"direction:RTL;"' :'');
s+='"';
return s;
}
}
};
G.scrollTimeOut = 0;
G.i18nTranslations = {'paginationPrevious':'Previous', 'paginationNext':'Next', 'breadcrumbHome':'List of Albums', 'thumbnailImageTitle':'', 'thumbnailAlbumTitle':'', 'thumbnailImageDescription':'', 'thumbnailAlbumDescription':'' };
G.emptyGif = 'data:image/gif;base64,R0lGODlhEAAQAIAAAP///////yH5BAEKAAEALAAAAAAQABAAAAIOjI+py+0Po5y02ouzPgUAOw==';
G.CSStransformName = FirstSupportedPropertyName(["transform", "msTransform", "MozTransform", "WebkitTransform", "OTransform"]);
// G.CSSfilterName = FirstSupportedPropertyName(["filter", "WebkitFilter"]);
G.CSStransformStyle = FirstSupportedPropertyName(["transformStyle", "msTransformStyle", "MozTransformStyle", "WebkitTransformStyle", "OTransformStyle"]);
G.CSSperspective = FirstSupportedPropertyName(["perspective", "msPerspective", "MozPerspective", "WebkitPerspective", "OPerspective"]);
G.CSSbackfaceVisibilityName = FirstSupportedPropertyName(["backfaceVisibility", "msBackfaceVisibility", "MozBackfaceVisibility", "WebkitBackfaceVisibility", "OBackfaceVisibility"]);
G.CSStransitionName = FirstSupportedPropertyName(["transition", "msTransition", "MozTransition", "WebkitTransition", "OTransition"]);
G.CSSanimationName = FirstSupportedPropertyName(["animation", "msAnimation", "MozAnimation", "WebkitAnimation", "OAnimation"]);
G.GalleryResizeThrottled = throttle(GalleryResize, 15, {leading: false});
G.blockList = null; // album names - block list
G.allowList = null; // album names - allow list
G.albumList = []; // album list
G.locationHashLastUsed = '';
G.custGlobals = {};
G.touchAutoOpenDelayTimerID = 0;
G.i18nLang = '';
G.timeLastTouchStart = 0;
G.custGlobals = {};
G.markupOrApiProcessed = false;
//------------------------
//--- Gallery Object Model
G.GOM = {
albumIdx : -1, // index (in G.I) of the currently displayed album
clipArea : { top: 0, height: 0 }, // area of the GOM to display on screen
displayArea : { width: 0 , height: 0 }, // size of the GOM area (=used area, not available area)
displayAreaLast : { width: 0 , height: 0 }, // previous size of the GOM area
displayedMoreSteps : 0, // current number of displayed steps (moreButton mode)
items: [], // current items of the GOMS
$imgPreloader: [],
thumbnails2Display: [],
itemsDisplayed : 0, // number of currently displayed thumbnails
firstDisplay : true,
firstDisplayTime : 0, // in conjunction with galleryRenderDelay
navigationBar : { // content of the navigation bar (for breadcrumb, filter tags and next/previous pagination)
displayed: false,
$newContent: ''
},
cache : { // cached data
viewport: null,
containerOffset: null,
areaWidth: 100 // available area width
},
nbSelected : 0, // number of selected items
pagination : { currentPage: 0 }, // pagination data
panThreshold: 60, // threshold value (in pixels) to block horizontal pan/swipe
panYOnly: false, // threshold value reach -> definitively block horizontal pan until end of pan
lastFullRow : -1, // number of the last row without holes
lastDisplayedIdx: -1, // used to display the counter of not displayed items
displayInterval : { from: 0, len: 0 },
hammertime: null,
curNavLevel: 'l1', // current navigation level (l1 or LN)
curWidth: 'me',
albumSearch: '', // current search string -> title (used to filter the thumbnails on screen)
albumSearchTags: '', // current search string -> tags
lastZIndex: 0, // used to put a thumbnail on top of all others (for exemple for scale hover effect)
lastRandomValue: 0,
slider : { // slider on last thumbnail
hostIdx: -1, // idx of the thumbnail hosting the slider
hostItem: null, // item hosting the slider
currentIdx: 0, // idx of the current displayed item
nextIdx: 0, // idx of the next item to display in the slider
timerID: 0,
tween: null // tranistion tween instance
},
NGY2Item: function( idx ) { // returns a NGY2Item or null if it does not exist
if( G.GOM.items[idx] == undefined || G.GOM.items[idx] == null ) { return null; }
var i = G.GOM.items[idx].thumbnailIdx;
return G.I[i];
},
// One GOM item (thumbnail)
// function GTn(index, width, height) {
GTn: function(index, width, height) {
this.thumbnailIdx = index;
this.width = 0; // thumbnail width
this.height = 0; // thumbnail height
this.top = 0; // position: top
this.left = 0; // position: left
this.row = 0; // position: row number
this.imageWidth = width; // image width
this.imageHeight = height; // image height
this.resizedContentWidth = 0;
this.resizedContentHeight = 0;
this.displayed = false;
this.neverDisplayed = true;
this.inDisplayArea = false;
},
// Position the top of the gallery to make it visible, if not displayed
ScrollToTop: function() {
if( G.GOM.firstDisplay ) {
// do no scroll to top on first display
return;
}
if( G.$E.scrollableParent === null && !topInViewportVert(G.$E.base, 20) ) {
// $('html, body').animate({scrollTop: G.$E.base.offset().top}, 200);
G.$E.base.get(0).scrollIntoView();
}
if( G.$E.scrollableParent !== null ) {
// gallery in a scrollable container: check if we have to scroll up so that the top of the gallery is visible
// vertical position of the scrollbar
var scrollTop = G.$E.scrollableParent.scrollTop();
// top of the gallery relative to the top of the scrollable container
var dist = Math.abs(G.$E.scrollableParent.offset().top - G.$E.base.offset().top - scrollTop);
if( scrollTop > dist ) {
window.ng_draf( function() {
// we need a little delay before setting the new scrollbar (but why?....)
G.$E.scrollableParent.scrollTop(dist);
});
}
}
}
};
//------------------------
//--- Viewer Object Model
G.VOM = {
viewerDisplayed: false, // is the viewer currently displayed
viewerIsFullscreen: false, // viewer in fullscreen mode
infoDisplayed: false, // is the info box displayed
toolbarsDisplayed: true, // the toolbars are displayed
toolsHide: null,
zoom : {
posX: 0, // position to center zoom in/out
posY: 0,
userFactor: 1, // user zoom factor (applied to the baseZoom factor)
isZooming: false
},
padding: { H: 0, V: 0 }, // padding for the image
window: { lastWidth: 0, lastHeight: 0 },
$viewer: null,
$toolbar: null, // viewerToolbar
$toolbarTL: null, // viewer toolbar on top left
$toolbarTR: null, // viewer toolbar on top right
toolbarMode: 'std', // current toolbar mode (standard, minimized)
playSlideshow : false, // slide show mode status
playSlideshowTimerID: 0, // slideshow mode time
slideshowDelay: 3000, // slideshow mode - delay before next image
albumID: -1,
viewerMediaIsChanged: false, // media display is currently modified
items: [], // current list of images to be managed by the viewer
panMode: 'off', // if panning, which element -> media, gallery, or zoom - if not -> off
$baseCont: null, // lightbox container
$content: null, // pointer to the 3 media in the viewer
content: {
previous : {
vIdx: -1,
$media: null,
NGY2Item: function() {
return G.I[ G.VOM.items[G.VOM.content.previous.vIdx].ngy2ItemIdx ];
}
},
current : {
vIdx: -1,
$media: null,
NGY2Item: function() {
return G.I[ G.VOM.items[G.VOM.content.current.vIdx].ngy2ItemIdx ];
}
},
next : {
vIdx: -1,
$media: null,
NGY2Item: function() {
return G.I[ G.VOM.items[G.VOM.content.next.vIdx].ngy2ItemIdx ];
}
}
},
IdxNext: function() {
var n = 0;
// if( G.VOM.currItemIdx <= (G.VOM.items.length-1) ) {
if( G.VOM.content.current.vIdx < (G.VOM.items.length-1) ) {
n = G.VOM.content.current.vIdx + 1;
}
return n;
},
IdxPrevious: function() {
var n = G.VOM.content.current.vIdx - 1;
if( G.VOM.content.current.vIdx == 0 ) {
n = G.VOM.items.length - 1;
}
return n;
},
gallery: {
$elt: null, // Base container
$tmbCont: null, // Thumbnail container
gwidth: 0, // thumbnail container width (all thumbnails)
vwidth: 0, // visible width of the gallery (just for the visible thumbnails)
oneTmbWidth: 0,
firstDisplay: true,
posX: 0,
SetThumbnailActive() {
if( G.O.viewerGallery == 'none' ) { return; }
this.$tmbCont.children().removeClass('activeVThumbnail');
this.$tmbCont.children().eq( G.VOM.content.current.vIdx ).addClass('activeVThumbnail');
this.firstDisplay = false;
},
Resize: function() {
if( G.O.viewerGallery == 'none' ) { return; }
if( !this.firstDisplay ) {
var viewerW = G.VOM.$viewer.width();
// Center base element
var maxTmb = Math.trunc(viewerW / this.oneTmbWidth); // max thumbnail that can be displayed
this.vwidth = maxTmb * this.oneTmbWidth;
this.$elt.css({ width: this.vwidth, left: (viewerW - this.vwidth)/2 });
// Set the position the thumbnails container (if there's no enough space for all thumbnails)
if( G.VOM.items.length >= maxTmb ) {
var tmbPos = this.oneTmbWidth * G.VOM.content.current.vIdx; // left position of the selected thumbnail
if( (tmbPos + this.posX) < this.vwidth ) {
if( tmbPos + this.posX < 0 ) {
this.posX = -tmbPos;
}
}
else {
if( tmbPos + this.posX >= this.vwidth ) {
this.posX = this.vwidth - (tmbPos + this.oneTmbWidth)
}
}
}
this.PanGallery(0);
}
else {
// first display of the gallery -> opacity transition
new NGTweenable().tween({
from: { opacity: 0 },
to: { opacity: 1 },
easing: 'easeInOutSine',
duration: 1000,
step: function (state) {
// G.VOM.gallery.$elt.css( state );
},
finish: function (state) {
// G.VOM.gallery.$elt.css({ opacity: 1});
}
});
}
},
PanGallery: function( panX ){
// all thumbnails are visible -> center the base element
if( this.gwidth < G.VOM.$viewer.width() ) { // this.oneTmbWidth
this.posX = (G.VOM.$viewer.width() - this.gwidth) / 2;
panX = 0; // block pan
}
// if( this.posX > (this.vwidth - this.oneTmbWidth) ) {
if( this.posX > (this.vwidth - this.oneTmbWidth) ) {
// gallery is outside of the screen, right side
this.posX = this.vwidth - this.oneTmbWidth;
}
if( (this.posX+this.gwidth) < this.oneTmbWidth ) {
// gallery is outside of the screen, left side
this.posX = -this.gwidth + this.oneTmbWidth;
}
this.$tmbCont.css( G.CSStransformName , 'translateX(' + (this.posX + panX) + 'px)');
},
PanGalleryEnd: function( velocity ) { // velocity = pixels/millisecond
var d = velocity * 100; // distance
new NGTweenable().tween({
from: { pan: G.VOM.gallery.posX },
to: { pan: G.VOM.gallery.posX + d },
easing: 'easeOutQuad',
duration: 500,
step: function (state) {
G.VOM.gallery.posX = state.pan;
G.VOM.gallery.PanGallery( 0 );
}
});
}
},
hammertime: null, // hammer.js manager
swipePosX: 0, // current horizontal swip position
panPosX: 0, // position for manual pan
panPosY: 0,
panThreshold: 60, // threshold value (in pixels) to block vertical pan
panXOnly: false, // threshold value reach -> definitively block vertical pan until end of pan
singletapTime: 0,
viewerTheme: '',
timeImgChanged: 0,
ImageLoader: {
// fires a callback when image size is know (during download)
// inspired by ROB - http://stackoverflow.com/users/226507/rob
maxChecks: 1000,
list: [],
intervalHandle : null,
loadImage : function (callback, ngitem) {
if( ngitem.mediaKind != 'img' ) { return; } // ignore - only for images
var img = new Image ();
img.src = ngitem.responsiveURL();
if (img.width && img.height) {
callback (img.width, img.height, ngitem, 0);
}
else {
var obj = {image: img, url: ngitem.responsiveURL(), ngitem: ngitem, callback: callback, checks: 1};
var i;
for (i=0; i < this.list.length; i++) {
if (this.list[i] == null)
break;
}
this.list[i] = obj;
if (!this.intervalHandle)
this.intervalHandle = setInterval(this.interval, 50);
}
},
// called by setInterval
interval : function () {
var count = 0;
var list = G.VOM.ImageLoader.list, item;
for (var i=0; i G.VOM.ImageLoader.maxChecks) {
G.VOM.ImageLoader.list[i] = null;
item.callback (0, 0, item.ngitem, item.checks);
}
else {
count++;
item.checks++;
}
}
}
if (count == 0) {
G.VOM.ImageLoader.list = [];
clearInterval (G.VOM.ImageLoader.intervalHandle);
delete G.VOM.ImageLoader.intervalHandle;
}
}
}
}
// One VOM item (image)
function VImg( index ) {
this.$e = null;
this.ngy2ItemIdx = index;
this.mediaNumber = G.VOM.items.length + 1;
this.posX = 0; // to center the element
this.posY = 0;
}
//------------------------
//--- popup
G.popup = {
isDisplayed: false,
$elt: null,
close: function() {
if( this.$elt != null ) {
var tweenable = new NGTweenable();
tweenable.tween({
from: { opacity:1 },
to: { opacity:0 },
attachment: { t: this },
easing: 'easeInOutSine',
duration: 100,
step: function (state, att) {
if( att.t.$elt != null ) {
att.t.$elt.css('opacity',state.opacity);
}
},
finish: function (state, att) {
if( att.t.$elt != null ) {
att.t.$elt.remove();
att.t.$elt=null;
}
att.t.isDisplayed=false;
}
});
}
}
}
// Color schemes - Gallery
// Gradient generator: https://www.grabient.com/
G.galleryTheme_dark = {
navigationBar : { background: 'none', borderTop: '', borderBottom: '', borderRight: '', borderLeft: '' },
navigationBreadcrumb : { background: '#111', color: '#fff', colorHover: '#ccc', borderRadius: '4px' },
navigationFilter : { color: '#ddd', background: '#111', colorSelected: '#fff', backgroundSelected: '#111', borderRadius: '4px' },
navigationPagination : { background: '#111', color: '#fff', colorHover: '#ccc', borderRadius: '4px' },
thumbnail : { background: '#444', backgroundImage: 'linear-gradient(315deg, #111 0%, #445 90%)', borderColor: '#000', borderRadius: '0px', labelOpacity : 1, labelBackground: 'rgba(34, 34, 34, 0)', titleColor: '#fff', titleBgColor: 'transparent', titleShadow: '', descriptionColor: '#ccc', descriptionBgColor: 'transparent', descriptionShadow: '', stackBackground: '#aaa' },
thumbnailIcon : { padding: '5px', color: '#fff', shadow:'' },
pagination : { background: '#181818', backgroundSelected: '#666', color: '#fff', borderRadius: '2px', shapeBorder: '3px solid #666', shapeColor: '#444', shapeSelectedColor: '#aaa'}
};
G.galleryTheme_light = {
navigationBar : { background: 'none', borderTop: '', borderBottom: '', borderRight: '', borderLeft: '' },
navigationBreadcrumb : { background: '#eee', color: '#000', colorHover: '#333', borderRadius: '4px' },
navigationFilter : { background: '#eee', color: '#222', colorSelected: '#000', backgroundSelected: '#eee', borderRadius: '4px' },
navigationPagination : { background: '#eee', color: '#000', colorHover: '#333', borderRadius: '4px' },
thumbnail : { background: '#444', backgroundImage: 'linear-gradient(315deg, #111 0%, #445 90%)', borderColor: '#000', labelOpacity : 1, labelBackground: 'rgba(34, 34, 34, 0)', titleColor: '#fff', titleBgColor: 'transparent', titleShadow: '', descriptionColor: '#ccc', descriptionBgColor: 'transparent', descriptionShadow: '', stackBackground: '#888' },
thumbnailIcon : { padding: '5px', color: '#fff' },
pagination : { background: '#eee', backgroundSelected: '#aaa', color: '#000', borderRadius: '2px', shapeBorder: '3px solid #666', shapeColor: '#444', shapeSelectedColor: '#aaa'}
};
// Color schemes - lightbox
G.viewerTheme_dark = {
background: '#000',
barBackground: 'rgba(4, 4, 4, 0.2)',
barBorder: '0px solid #111',
barColor: '#fff',
barDescriptionColor: '#ccc'
};
G.viewerTheme_light = {
background: '#f8f8f8',
barBackground: 'rgba(4, 4, 4, 0.7)',
barBorder: '0px solid #111',
barColor: '#fff',
barDescriptionColor: '#ccc'
};
// shortcut with G context to NGY2TOOLS
// var NanoAlert = NGY2Tools.NanoAlert.bind(G);
// var NanoConsoleLog = NGY2Tools.NanoConsoleLog.bind(G);
var NanoAlert = NGY2Tools.NanoAlert;
var NanoConsoleLog = NGY2Tools.NanoConsoleLog;
/** @function initiateGallery2 */
this.initiateGallery2 = function( element, params ) {
// GLOBAL OPTIONS
G.O = params;
// Base element
G.$E.base = jQuery(element);
G.baseEltID = G.$E.base.attr('id');
if( G.baseEltID == undefined ) {
// set a default ID to the root container
var base_id = 'my_nanogallery';
var c = '';
var f = true;
while( f ) {
if (document.getElementById(base_id + c)) {
// ID already exists
if( c == '' ) {
c = 1;
}
else {
c++;
}
}
else {
f = false;
G.baseEltID = 'my_nanogallery' + c;
}
}
G.$E.base.attr('id', G.baseEltID)
}
G.O.$markup = [];
DefineVariables();
SetPolyFills();
BuildSkeleton();
G.GOM.firstDisplayTime = Date.now();
SetGlobalEvents();
// check if only one specific album will be used
if( !G.O.lightboxStandalone ) {
var albumToDisplay = G.O.album;
if( albumToDisplay == '' && G.O.photoset != '' ) {
albumToDisplay = G.O.photoset;
G.O.album = G.O.photoset;
}
if( albumToDisplay != '' ) {
G.O.displayBreadcrumb = false; // no breadcrumb since only 1 album
if( albumToDisplay.toUpperCase() != 'NONE' ) {
// open a public album
if( G.O.kind == "nano_photos_provider2") {
if( albumToDisplay == decodeURIComponent(albumToDisplay)) {
// album ID must be encoded
albumToDisplay = encodeURIComponent(albumToDisplay);
G.O.album = albumToDisplay;
}
}
NGY2Item.New( G, '', '', albumToDisplay, '-1', 'album' );
if( !ProcessLocationHash() ) {
DisplayAlbum('-1', albumToDisplay);
}
return;
}
}
}
// use full content
// add base album
NGY2Item.New( G, G.i18nTranslations.breadcrumbHome, '', '0', '-1', 'album' );
processStartOptions();
}
/** @function processStartOptions */
function processStartOptions() {
// open image or album
// 1. load hidden albums
// 2. check if location hash set (deep linking)
// 3. check openOnStart parameter
// 4. open root album (ID=-1)
// hidden/private albums are loaded on plugin start (Picasa) --> no more available in Google Photos
// if( G.albumListHidden.length > 0 ) {
// jQuery.nanogallery2['data_'+G.O.kind](G, 'GetHiddenAlbums', G.albumListHidden, processStartOptionsPart2);
// return;
//}
if( !ProcessLocationHash() ) {
processStartOptionsPart2();
}
}
/** @function processStartOptionsPart2 */
function processStartOptionsPart2() {
// Check location hash + start parameters -> determine what to do on start
if( G.O.lightboxStandalone ) {
LightboxStandaloneFindContent();
}
else {
// openOnStart parameter
if( G.O.openOnStart != '' ) {
var IDs = parseIDs(G.O.openOnStart);
if( IDs.imageID != '0' ) {
DisplayPhoto(IDs.imageID, IDs.albumID);
}
else {
DisplayAlbum('-1', IDs.albumID);
}
}
else {
// open root album (ID = -1)
DisplayAlbum('-1', 0);
}
}
}
// Lightbox standaone -> retrieve the items to display
// Each item needs at least a thumbnail image and a big image
// ONLY IMAGES SUPPORTED
function LightboxStandaloneFindContent() {
G.GOM.curNavLevel = 'l1';
if( G.O.items == null ) {
// retrieve all element having "data-nanogallery2-lightbox" and from the same group if defined
var elts = jQuery('[data-nanogallery2-Lightbox');
// element group
var g = G.$E.base[0].dataset.nanogallery2Lgroup;
GetContentMarkup( elts, g );
}
else {
// Content defined in the starting parameters
GetContentApiObject();
}
LightboxStandaloneDisplay();
}
// Populate G.VOM.items + open the lightbox
function LightboxStandaloneDisplay() {
G.VOM.items = [];
G.VOM.albumID = '0';
G.GOM.curNavLevel = 'l1';
var vcnt = 0;
var elt = G.$E.base[0].attributes;
var thumbsrc = '';
// src attribute (img element)
if( elt.hasOwnProperty('src') ) {
thumbsrc = elt['src'].nodeValue;
}
// data-ngthumb attribute
if( thumbsrc == '' && elt.hasOwnProperty('data-ngthumb') ) {
thumbsrc = elt['data-ngthumb'].nodeValue;
}
var displayIdx = undefined;
for( var idx = 0; idx < G.I.length; idx++ ) {
if( G.I[idx].kind == 'image' ) {
var vimg = new VImg(idx);
G.VOM.items.push(vimg);
if( G.I[idx].thumbImg().src == thumbsrc ) {
// same thumbnail URL
displayIdx = vcnt;
}
vcnt++;
}
}
if( G.VOM.items.length > 0 ) {
LightboxOpen( displayIdx );
}
else {
NanoConsoleLog(G, 'No content for Lightbox standalone.');
}
}
// Parse string to extract albumID and imageID (format albumID/imageID)
function parseIDs( IDs ) {
var r = { albumID: '0', imageID: '0' };
var t = IDs.split('/');
if( t.length > 0 ) {
r.albumID = t[0];
if( t.length > 1 ) {
r.imageID = t[1];
}
}
return r;
}
/** @function DisplayAlbum */
function DisplayAlbum( imageID, albumID ) {
// close viewer if already displayed
if( G.VOM.viewerDisplayed ) {
LightboxClose(null);
}
// set current navigation level (l1 or lN)
var albumIdx = NGY2Item.GetIdx(G, albumID);
G.GOM.curNavLevel = 'lN';
if( albumIdx == 0 ) {
G.GOM.curNavLevel = 'l1';
}
G.layout.SetEngine();
G.galleryResizeEventEnabled = false;
if( albumIdx == -1 ) {
NGY2Item.New( G, '', '', albumID, '0', 'album' ); // create empty album
albumIdx = G.I.length - 1;
}
if( !G.I[albumIdx].contentIsLoaded ) {
// get content of the album if not already loaded
AlbumGetContent( albumID, DisplayAlbum, imageID, albumID );
return;
}
ThumbnailSelectionClear();
G.GOM.pagination.currentPage = 0;
SetLocationHash( albumID, '' );
GalleryRender( albumIdx );
}
//----- manage the bottom area of the gallery -> "pagination" or "more button"
function GalleryBottomManage() {
switch( G.galleryDisplayMode.Get() ) {
case 'PAGINATION':
if( G.layout.support.rows && G.galleryMaxRows.Get() > 0 ) {
ManagePagination();
}
break;
case 'MOREBUTTON':
G.$E.conTnBottom.off('click');
var nb = G.GOM.items.length-G.GOM.itemsDisplayed;
if( nb == 0 ) {
G.$E.conTnBottom.empty();
}
else {
G.$E.conTnBottom.html('
+'+nb+' ' + G.O.icons.galleryMoreButton +'
');
G.$E.conTnBottom.on('click', function(e) {
G.GOM.displayedMoreSteps++;
GalleryResize();
});
}
break;
case 'FULLCONTENT':
default:
break;
}
}
// add one album/folder to the breadcrumb
function breadcrumbAdd( albumIdx ) {
var ic='';
if( !G.O.breadcrumbHideIcons ) {
ic=G.O.icons.breadcrumbAlbum;
if( albumIdx == 0 ) {
ic=G.O.icons.breadcrumbHome;
}
}
var $newDiv =jQuery('
'+ic + G.I[albumIdx].title+'
').appendTo(G.GOM.navigationBar.$newContent.find('.nGY2Breadcrumb'));
if( G.O.breadcrumbOnlyCurrentLevel ) {
// link to parent folder (only 1 level is displayed in the breadcrumb)
if( albumIdx == 0 ) {
// no parent level -> stay on current one
jQuery($newDiv).data('albumID','0');
}
else {
jQuery($newDiv).data('albumID',G.I[albumIdx].albumID);
}
}
else {
// link to current folder
jQuery($newDiv).data('albumID',G.I[albumIdx].GetID());
}
$newDiv.click(function() {
var cAlbumID = jQuery(this).data('albumID');
DisplayAlbum('-1', cAlbumID);
return;
});
}
// add one separator to breadcrumb
function breadcrumbAddSeparator( lastAlbumID ) {
var $newSep=jQuery('
';
// image size
var w = G.tn.settings.getW();
var h = G.tn.settings.getH();
if( G.tn.settings.getMosaic() !== null ) {
// mosaic layout ->
w = G.GOM.items[GOMidx].width;
h = G.GOM.items[GOMidx].height;
}
var bgSize = 'contain';
if( G.tn.opt.Get('crop') ) {
bgSize = 'cover'; // thumbnail image will be cropped to fit in the thumbnail (no black border)
}
// ##### layer for image background (color, dominant color, blurred preview)
var s1 = "position: absolute; top: 0px; left: 0px; width:" + w + "px; height:" + h + "px;"+ bg + bgImg + " background-position: center center; background-repeat: no-repeat; background-size:" + bgSize + "; overflow: hidden;";
newElt[newEltIdx++]='';
// #### layer for image
// for url in CSS: single backslashes are replaced by double backslashes
var s2 = op + "position: absolute; top: 0px; left: 0px; width:" + w + "px; height:" + h + "px; background-image: url('" + src.replace(/\\/g, '\\\\') + "'); background-position: center center; background-repeat: no-repeat; background-size:" + bgSize + "; overflow: hidden;";
newElt[newEltIdx++]='
';
newElt[newEltIdx++]=' ';
newElt[newEltIdx++]='
';
// ##### layer for user customization purposes
newElt[newEltIdx++]='';
// ##### layer for labels (title + description and their icons)
if( G.O.thumbnailLabel.get('display') == true ) {
// Labels: title and description
newElt[newEltIdx++]= '
';
cnt++;
break;
case 'CUSTOM1':
case 'CUSTOM2':
case 'CUSTOM3':
case 'CUSTOM4':
case 'CUSTOM5':
case 'CUSTOM6':
case 'CUSTOM7':
case 'CUSTOM8':
case 'CUSTOM9':
case 'CUSTOM10':
var cust = tIcon.replace('CUSTOM', '');
toolbar += '