nanogallery2
Version:
modern photo / video gallery and lightbox
1,164 lines (1,032 loc) • 624 kB
JavaScript
/* nanogallery2 - v3.0.5 - 2021-01-06 - https://nanogallery2.nanostudio.org */
/*!
* @preserve nanogallery2 - javascript photo / video gallery and lightbox
* Homepage: http://nanogallery2.nanostudio.org
* Sources: https://github.com/nanostudio-org/nanogallery2
*
* License: GPLv3 and commercial licence
*
* Requirements:
* - jQuery (http://www.jquery.com) - version >= 1.7.1
*
* Embeded components:
* - shifty (https://github.com/jeremyckahn/shifty)
* - imagesloaded (https://github.com/desandro/imagesloaded)
* - hammer.js (http://hammerjs.github.io/)
* - screenfull.js (https://github.com/sindresorhus/screenfull.js)
* Tools:
* - webfont generated with http://fontello.com - mainly based on Font Awesome Copyright (C) 2012 by Dave Gandy (http://fontawesome.io/)
* - ICO online converter: https://iconverticons.com/online/
*/
// ###########################################
// ##### nanogallery2 as a JQUERY PLUGIN #####
// ###########################################
// Expose plugin as an AMD module if AMD loader is present:
(function (factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
// define('nanogallery2', ['jquery'], factory);
define(['jquery'], factory);
} else if (typeof exports === 'object' && typeof require === 'function') {
// Browserify
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
// ;(function ($) {
"use strict";
//##### TOOLS/HELPERS ####
// Convert color to RGB/RGBA
function ColorHelperToRGB( color ) {
var obj = document.getElementById('ngyColorHelperToRGB');
if (obj === null) {
obj = document.createElement('div');
obj.id = "ngyColorHelperToRGB";
obj.style.cssText = 'display: none; color:' + color + ';';
document.body.appendChild(obj);
}
var rgb = getComputedStyle(obj).color;
// to get HEX value:
// var rgb = getComputedStyle(obj).color.match(/\d+/g);
// var r = parseInt(rgb[0]).toString(16);
// var g = parseInt(rgb[1]).toString(16);
// var b = parseInt(rgb[2]).toString(16);
// var hex = '#' + r + g + b;
return rgb;
}
// ##### helper for color handling
// - normalise RGB/RGBA/HEX format
// - lighten/darken color
// Inspired by:
// https://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors
// http://www.pimptrizkit.com/?t=20%20Shades
function ShadeBlendConvert (p, from, to) {
var rgba='';
if( from.toUpperCase().substring(0,5) == 'RGBA(' ) {
rgba='a';
from='rgb('+from.substring(5);
}
if(typeof(p)!="number"||p<-1||p>1||typeof(from)!="string"||(from[0]!='r'&&from[0]!='#')||(typeof(to)!="string"&&typeof(to)!="undefined"))return null;
//if(!this.sbcRip)this.sbcRip=function(d){
function sbcRip(d){
var l=d.length,RGB=new Object();
if(l>9){
d=d.split(",");
if(d.length<3||d.length>4)return null;
RGB[0]=i(d[0].slice(4)),RGB[1]=i(d[1]),RGB[2]=i(d[2]),RGB[3]=d[3]?parseFloat(d[3]):-1;
}else{
if(l==8||l==6||l<4)return null;
if(l<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(l>4?d[4]+""+d[4]:"");
d=i(d.slice(1),16),RGB[0]=d>>16&255,RGB[1]=d>>8&255,RGB[2]=d&255,RGB[3]=l==9||l==5?r(((d>>24&255)/255)*10000)/10000:-1;
}
return RGB;
}
var i=parseInt,r=Math.round,h=from.length>9,h=typeof(to)=="string"?to.length>9?true:to=="c"?!h:false:h,b=p<0,p=b?p*-1:p,to=to&&to!="c"?to:b?"#000000":"#FFFFFF",f=sbcRip(from),t=sbcRip(to);
if(!f||!t)return null;
if(h)return "rgb"+rgba+"("+r((t[0]-f[0])*p+f[0])+","+r((t[1]-f[1])*p+f[1])+","+r((t[2]-f[2])*p+f[2])+(f[3]<0&&t[3]<0?")":","+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*10000)/10000:t[3]<0?f[3]:t[3])+")");
else return "#"+(0x100000000+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*255):t[3]>-1?r(t[3]*255):f[3]>-1?r(f[3]*255):255)*0x1000000+r((t[0]-f[0])*p+f[0])*0x10000+r((t[1]-f[1])*p+f[1])*0x100+r((t[2]-f[2])*p+f[2])).toString(16).slice(f[3]>-1||t[3]>-1?1:3);
}
// ##### clone a javascript object
function cloneJSObject( obj ) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
var temp = obj.constructor(); // give temp the original obj's constructor
for (var key in obj) {
temp[key] = cloneJSObject(obj[key]);
}
return temp;
}
// get viewport coordinates and size
function getViewport() {
var $win = jQuery(window);
return {
l: $win.scrollLeft(),
t: $win.scrollTop(),
w: $win.width(),
h: $win.height()
}
}
// Check if element is in viewport
// avoid if possible (performance issue)
/*
function inViewport( $elt, threshold ) {
var wp = getViewport(),
eltOS = $elt.offset(),
th = $elt.outerHeight(true),
tw = $elt.outerWidth(true);
if( eltOS.top >= (wp.t - threshold)
&& (eltOS.top + th) <= (wp.t + wp.h + threshold)
&& eltOS.left >= (wp.l - threshold)
&& (eltOS.left + tw) <= (wp.l + wp.w + threshold) ) {
return true;
}
else {
return false;
}
}
*/
// Check if whole element is in ViewPort
// avoid if possible (performance issue)
function inViewportVert( $elt, threshold ) {
var wp = getViewport(),
eltOS = $elt.offset(),
th = $elt.outerHeight(true);
//var tw=$elt.outerWidth(true);
if( wp.t == 0 && (eltOS.top) <= (wp.t + wp.h ) ) { return true; }
if( eltOS.top >= wp.t && (eltOS.top + th) <= (wp.t + wp.h - threshold) ) {
return true;
}
else {
return false;
}
}
// Check if top of the element is in ViewPort
function topInViewportVert( $elt, threshold ) {
var wp = getViewport(),
eltOS = $elt.offset();
if( eltOS.top >= wp.t && eltOS.top <= (wp.t + wp.h - threshold) ) {
return true;
}
else {
return false;
}
}
// set z-index to display 2 elements on top of all others
// function set2ElementsOnTop( start, elt1, elt2 ) {
// var highest_index = 0;
// if( start=='' ) { start= '*'; }
// jQuery(start).each(function() {
// var cur = parseInt(jQuery(this).css('z-index'));
// highest_index = cur > highest_index ? cur : highest_index;
// });
// highest_index++;
// jQuery(elt2).css('z-index',highest_index+1);
// jQuery(elt1).css('z-index',highest_index);
// }
// set z-index to display element on top of all others
function setElementOnTop( start, elt ) {
var highest_index = 0;
if( start == '' ) { start = '*'; }
jQuery(start).each(function() {
var cur = parseInt(jQuery(this).css('z-index'));
highest_index = cur > highest_index ? cur : highest_index;
});
highest_index++;
jQuery(elt).css('z-index',highest_index);
}
// return the real type of the object
var toType = function( obj ) {
// by Angus Croll - http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
};
$.nanogallery2 = function (elt, options) {
// To avoid scope issues, use '_this' instead of 'this'
// to reference this class from internal events and functions.
var _this = this;
// Access to jQuery and DOM versions of element
_this.$e = jQuery(elt);
_this.e = elt;
// Add a reverse reference to the DOM object
_this.$e.data('nanogallery2data', _this);
_this.init = function () {
// define these global objects only once per HTML page
if (typeof window.NGY2Item === 'undefined') {
window.NGY2Tools = (function () {
function NGY2Tools() {
var nextId = 1; // private static --> all instances
}
// check album name - albumList/blockList/allowList
NGY2Tools.FilterAlbumName = function( title, ID ) {
var s = title.toUpperCase();
if( this.albumList.length > 0 ) {
for( var j=0; j < this.albumList.length; j++) {
if( s === this.albumList[j].toUpperCase() || ID === this.albumList[j] ) {
return true;
}
}
}
else {
var found = false;
if( this.allowList !== null ) {
//allowList : authorize only album cointaining one of the specified keyword in the title
for( var j = 0; j < this.allowList.length; j++) {
if( s.indexOf(this.allowList[j]) !== -1 ) {
found = true;
}
}
if( !found ) { return false; }
}
if( this.blockList !== null ) {
//blockList : ignore album cointaining one of the specified keyword in the title
for( var j = 0; j < this.blockList.length; j++) {
if( s.indexOf(this.blockList[j]) !== -1 ) {
return false;
}
}
}
return true;
}
};
/** @function nanoAlert */
/* Display an alert message in a specific element */
NGY2Tools.NanoAlert = function(context, msg, verbose) {
NGY2Tools.NanoConsoleLog.call(context, msg);
if( context.$E.conConsole != null ) {
context.$E.conConsole.css({visibility: 'visible', minHeight: '100px'});
if( verbose == false ) {
context.$E.conConsole.append('<p>' + msg + '</p>');
}
else {
context.$E.conConsole.append('<p>nanogallery2: '+ msg + ' [' + context.baseEltID + ']</p>');
}
}
};
/** @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 = '<img class="nGY2ViewerMedia" src="' + url + '" alt=" " itemprop="contentURL" draggable="false">';
}
};
//--- 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;
// }