diff --git a/files/chambrew20151126_3.resized.jpg b/files/chambre1/chambrew20151126_3.resized.jpg similarity index 100% rename from files/chambrew20151126_3.resized.jpg rename to files/chambre1/chambrew20151126_3.resized.jpg diff --git a/files/chambrew20151126_4.resized.jpg b/files/chambre1/chambrew20151126_4.resized.jpg similarity index 100% rename from files/chambrew20151126_4.resized.jpg rename to files/chambre1/chambrew20151126_4.resized.jpg diff --git a/files/dsc03930.resized.jpg b/files/chambre1/dsc03930.resized.jpg similarity index 100% rename from files/dsc03930.resized.jpg rename to files/chambre1/dsc03930.resized.jpg diff --git a/files/dsc03931.resized.jpg b/files/chambre1/dsc03931.resized.jpg similarity index 100% rename from files/dsc03931.resized.jpg rename to files/chambre1/dsc03931.resized.jpg diff --git a/files/chambree20151101_2.resized.jpg b/files/chambre2/chambree20151101_2.resized.jpg similarity index 100% rename from files/chambree20151101_2.resized.jpg rename to files/chambre2/chambree20151101_2.resized.jpg diff --git a/files/chambree20151126_2.resized.jpg b/files/chambre2/chambree20151126_2.resized.jpg similarity index 100% rename from files/chambree20151126_2.resized.jpg rename to files/chambre2/chambree20151126_2.resized.jpg diff --git a/files/chambree20151126_3.resized.jpg b/files/chambre2/chambree20151126_3.resized.jpg similarity index 100% rename from files/chambree20151126_3.resized.jpg rename to files/chambre2/chambree20151126_3.resized.jpg diff --git a/files/chambree20151126_5.resized.jpg b/files/chambre2/chambree20151126_5.resized.jpg similarity index 100% rename from files/chambree20151126_5.resized.jpg rename to files/chambre2/chambree20151126_5.resized.jpg diff --git a/files/chambres20160118_1.resized.jpg b/files/chambre3/chambres20160118_1.resized.jpg similarity index 100% rename from files/chambres20160118_1.resized.jpg rename to files/chambre3/chambres20160118_1.resized.jpg diff --git a/files/chambres20160118_4.resized.jpg b/files/chambre3/chambres20160118_4.resized.jpg similarity index 100% rename from files/chambres20160118_4.resized.jpg rename to files/chambre3/chambres20160118_4.resized.jpg diff --git a/files/chambres20160118_5.resized.jpg b/files/chambre3/chambres20160118_5.resized.jpg similarity index 100% rename from files/chambres20160118_5.resized.jpg rename to files/chambre3/chambres20160118_5.resized.jpg diff --git a/files/cuisine20160118_2.resized.jpg b/files/salon_cuisine/cuisine20160118_2.resized.jpg similarity index 100% rename from files/cuisine20160118_2.resized.jpg rename to files/salon_cuisine/cuisine20160118_2.resized.jpg diff --git a/files/cuisine20160118_3.resized.jpg b/files/salon_cuisine/cuisine20160118_3.resized.jpg similarity index 100% rename from files/cuisine20160118_3.resized.jpg rename to files/salon_cuisine/cuisine20160118_3.resized.jpg diff --git a/files/sjour20151102_1.resized.jpg b/files/salon_cuisine/sjour20151102_1.resized.jpg similarity index 100% rename from files/sjour20151102_1.resized.jpg rename to files/salon_cuisine/sjour20151102_1.resized.jpg diff --git a/files/sjour20151102_2.resized.jpg b/files/salon_cuisine/sjour20151102_2.resized.jpg similarity index 100% rename from files/sjour20151102_2.resized.jpg rename to files/salon_cuisine/sjour20151102_2.resized.jpg diff --git a/files/thumb_img_3740_1024.jpeg b/files/salon_cuisine/thumb_img_3740_1024.jpeg similarity index 100% rename from files/thumb_img_3740_1024.jpeg rename to files/salon_cuisine/thumb_img_3740_1024.jpeg diff --git a/files/dsc03926.resized.jpg b/files/sdb/dsc03926.resized.jpg similarity index 100% rename from files/dsc03926.resized.jpg rename to files/sdb/dsc03926.resized.jpg diff --git a/files/sdbe20151126_2.resized.jpg b/files/sdb/sdbe20151126_2.resized.jpg similarity index 100% rename from files/sdbe20151126_2.resized.jpg rename to files/sdb/sdbe20151126_2.resized.jpg diff --git a/files/sdbe20151126_3.resized.jpg b/files/sdb/sdbe20151126_3.resized.jpg similarity index 100% rename from files/sdbe20151126_3.resized.jpg rename to files/sdb/sdbe20151126_3.resized.jpg diff --git a/files/sdbe20151126_4.resized.jpg b/files/sdb/sdbe20151126_4.resized.jpg similarity index 100% rename from files/sdbe20151126_4.resized.jpg rename to files/sdb/sdbe20151126_4.resized.jpg diff --git a/files/sdbe20151126_5.resized.jpg b/files/sdb/sdbe20151126_5.resized.jpg similarity index 100% rename from files/sdbe20151126_5.resized.jpg rename to files/sdb/sdbe20151126_5.resized.jpg diff --git a/files/sdbw20151125_1.resized.jpg b/files/sdb/sdbw20151125_1.resized.jpg similarity index 100% rename from files/sdbw20151125_1.resized.jpg rename to files/sdb/sdbw20151125_1.resized.jpg diff --git a/files/sdbw20151126_2.resized.jpg b/files/sdb/sdbw20151126_2.resized.jpg similarity index 100% rename from files/sdbw20151126_2.resized.jpg rename to files/sdb/sdbw20151126_2.resized.jpg diff --git a/files/GPS-AgenceChauvin.png b/files/src/GPS-AgenceChauvin.png similarity index 100% rename from files/GPS-AgenceChauvin.png rename to files/src/GPS-AgenceChauvin.png diff --git a/files/GPS-LesTerrassesDesChoseaux.png b/files/src/GPS-LesTerrassesDesChoseaux.png similarity index 100% rename from files/GPS-LesTerrassesDesChoseaux.png rename to files/src/GPS-LesTerrassesDesChoseaux.png diff --git a/files/chauvin-redimensionné.jpg b/files/src/chauvin-redimensionné.jpg similarity index 100% rename from files/chauvin-redimensionné.jpg rename to files/src/chauvin-redimensionné.jpg diff --git a/files/chauvin.eps b/files/src/chauvin.eps similarity index 100% rename from files/chauvin.eps rename to files/src/chauvin.eps diff --git a/files/chauvin.png b/files/src/chauvin.png similarity index 100% rename from files/chauvin.png rename to files/src/chauvin.png diff --git a/files/chauvin.svg b/files/src/chauvin.svg similarity index 100% rename from files/chauvin.svg rename to files/src/chauvin.svg diff --git a/files/gps.svg b/files/src/gps.svg similarity index 100% rename from files/gps.svg rename to files/src/gps.svg diff --git a/files/location.svg b/files/src/location.svg similarity index 100% rename from files/location.svg rename to files/src/location.svg diff --git a/galleria-1.4.2.zip b/galleria-1.4.2.zip deleted file mode 100644 index 8fdd00b..0000000 Binary files a/galleria-1.4.2.zip and /dev/null differ diff --git a/galleria/LICENSE b/galleria/LICENSE deleted file mode 100644 index beac466..0000000 --- a/galleria/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2016 worse is better UG http://wib.io - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/galleria/galleria-1.4.7.js b/galleria/galleria-1.4.7.js deleted file mode 100644 index 4fccedd..0000000 --- a/galleria/galleria-1.4.7.js +++ /dev/null @@ -1,6919 +0,0 @@ -/** - * Galleria v1.4.7 2016-09-17 - * http://galleria.io - * - * Copyright (c) 2010 - 2016 worse is better UG - * Licensed under the MIT license - * https://raw.github.com/worseisbetter/galleria/master/LICENSE - * - */ - -(function( $, window, Galleria, undef ) { - -/*global jQuery, navigator, Image, module, define */ - -// some references -var doc = window.document, - $doc = $( doc ), - $win = $( window ), - -// native prototypes - protoArray = Array.prototype, - -// internal constants - VERSION = 1.47, - DEBUG = true, - TIMEOUT = 30000, - DUMMY = false, - NAV = navigator.userAgent.toLowerCase(), - HASH = window.location.hash.replace(/#\//, ''), - PROT = window.location.protocol == "file:" ? "http:" : window.location.protocol, - M = Math, - F = function(){}, - FALSE = function() { return false; }, - IE = (function() { - - var v = 3, - div = doc.createElement( 'div' ), - all = div.getElementsByTagName( 'i' ); - - do { - div.innerHTML = ''; - } while ( all[0] ); - - return v > 4 ? v : doc.documentMode || undef; - - }() ), - DOM = function() { - return { - html: doc.documentElement, - body: doc.body, - head: doc.getElementsByTagName('head')[0], - title: doc.title - }; - }, - IFRAME = window.parent !== window.self, - - // list of Galleria events - _eventlist = 'data ready thumbnail loadstart loadfinish image play pause progress ' + - 'fullscreen_enter fullscreen_exit idle_enter idle_exit rescale ' + - 'lightbox_open lightbox_close lightbox_image', - - _events = (function() { - - var evs = []; - - $.each( _eventlist.split(' '), function( i, ev ) { - evs.push( ev ); - - // legacy events - if ( /_/.test( ev ) ) { - evs.push( ev.replace( /_/g, '' ) ); - } - }); - - return evs; - - }()), - - // legacy options - // allows the old my_setting syntax and converts it to camel case - - _legacyOptions = function( options ) { - - var n; - - if ( typeof options !== 'object' ) { - - // return whatever it was... - return options; - } - - $.each( options, function( key, value ) { - if ( /^[a-z]+_/.test( key ) ) { - n = ''; - $.each( key.split('_'), function( i, k ) { - n += i > 0 ? k.substr( 0, 1 ).toUpperCase() + k.substr( 1 ) : k; - }); - options[ n ] = value; - delete options[ key ]; - } - }); - - return options; - }, - - _patchEvent = function( type ) { - - // allow 'image' instead of Galleria.IMAGE - if ( $.inArray( type, _events ) > -1 ) { - return Galleria[ type.toUpperCase() ]; - } - - return type; - }, - - // video providers - _video = { - youtube: { - reg: /https?:\/\/(?:[a-zA_Z]{2,3}.)?(?:youtube\.com\/watch\?)((?:[\w\d\-\_\=]+&(?:amp;)?)*v(?:<[A-Z]+>)?=([0-9a-zA-Z\-\_]+))/i, - embed: function() { - return PROT + '//www.youtube.com/embed/' + this.id; - }, - get_thumb: function( data ) { - return PROT + '//img.youtube.com/vi/'+this.id+'/default.jpg'; - }, - get_image: function( data ) { - return PROT + '//img.youtube.com/vi/'+this.id+'/hqdefault.jpg'; } - }, - vimeo: { - reg: /https?:\/\/(?:www\.)?(vimeo\.com)\/(?:hd#)?([0-9]+)/i, - embed: function() { - return PROT + '//player.vimeo.com/video/' + this.id; - }, - getUrl: function() { - return PROT + '//vimeo.com/api/v2/video/' + this.id + '.json?callback=?'; - }, - get_thumb: function( data ) { - return data[0].thumbnail_medium; - }, - get_image: function( data ) { - return data[0].thumbnail_large; - } - }, - dailymotion: { - reg: /https?:\/\/(?:www\.)?(dailymotion\.com)\/video\/([^_]+)/, - embed: function() { - return PROT + '//www.dailymotion.com/embed/video/' + this.id; - }, - getUrl: function() { - return 'https://api.dailymotion.com/video/' + this.id + '?fields=thumbnail_240_url,thumbnail_720_url&callback=?'; - }, - get_thumb: function( data ) { - return data.thumbnail_240_url; - }, - get_image: function( data ) { - return data.thumbnail_720_url; - } - }, - _inst: [] - }, - Video = function( type, id ) { - - for( var i=0; i<_video._inst.length; i++ ) { - if ( _video._inst[i].id === id && _video._inst[i].type == type ) { - return _video._inst[i]; - } - } - - this.type = type; - this.id = id; - this.readys = []; - - _video._inst.push(this); - - var self = this; - - $.extend( this, _video[type] ); - - _videoThumbs = function(data) { - self.data = data; - $.each( self.readys, function( i, fn ) { - fn( self.data ); - }); - self.readys = []; - }; - - if ( this.hasOwnProperty('getUrl') ) { - $.getJSON( this.getUrl(), _videoThumbs); - } else { - window.setTimeout(_videoThumbs, 400); - } - - this.getMedia = function( type, callback, fail ) { - fail = fail || F; - var self = this; - var success = function( data ) { - callback( self['get_'+type]( data ) ); - }; - try { - if ( self.data ) { - success( self.data ); - } else { - self.readys.push( success ); - } - } catch(e) { - fail(); - } - }; - }, - - // utility for testing the video URL and getting the video ID - _videoTest = function( url ) { - var match; - for ( var v in _video ) { - match = url && _video[v].reg && url.match( _video[v].reg ); - if( match && match.length ) { - return { - id: match[2], - provider: v - }; - } - } - return false; - }, - - // native fullscreen handler - _nativeFullscreen = { - - support: (function() { - var html = DOM().html; - return !IFRAME && ( html.requestFullscreen || html.msRequestFullscreen || html.mozRequestFullScreen || html.webkitRequestFullScreen ); - }()), - - callback: F, - - enter: function( instance, callback, elem ) { - - this.instance = instance; - - this.callback = callback || F; - - elem = elem || DOM().html; - if ( elem.requestFullscreen ) { - elem.requestFullscreen(); - } - else if ( elem.msRequestFullscreen ) { - elem.msRequestFullscreen(); - } - else if ( elem.mozRequestFullScreen ) { - elem.mozRequestFullScreen(); - } - else if ( elem.webkitRequestFullScreen ) { - elem.webkitRequestFullScreen(); - } - }, - - exit: function( callback ) { - - this.callback = callback || F; - - if ( doc.exitFullscreen ) { - doc.exitFullscreen(); - } - else if ( doc.msExitFullscreen ) { - doc.msExitFullscreen(); - } - else if ( doc.mozCancelFullScreen ) { - doc.mozCancelFullScreen(); - } - else if ( doc.webkitCancelFullScreen ) { - doc.webkitCancelFullScreen(); - } - }, - - instance: null, - - listen: function() { - - if ( !this.support ) { - return; - } - - var handler = function() { - - if ( !_nativeFullscreen.instance ) { - return; - } - var fs = _nativeFullscreen.instance._fullscreen; - - if ( doc.fullscreen || doc.mozFullScreen || doc.webkitIsFullScreen || ( doc.msFullscreenElement && doc.msFullscreenElement !== null ) ) { - fs._enter( _nativeFullscreen.callback ); - } else { - fs._exit( _nativeFullscreen.callback ); - } - }; - doc.addEventListener( 'fullscreenchange', handler, false ); - doc.addEventListener( 'MSFullscreenChange', handler, false ); - doc.addEventListener( 'mozfullscreenchange', handler, false ); - doc.addEventListener( 'webkitfullscreenchange', handler, false ); - } - }, - - // the internal gallery holder - _galleries = [], - - // the internal instance holder - _instances = [], - - // flag for errors - _hasError = false, - - // canvas holder - _canvas = false, - - // instance pool, holds the galleries until themeLoad is triggered - _pool = [], - - // Run galleries from theme trigger - _loadedThemes = [], - _themeLoad = function( theme ) { - - _loadedThemes.push(theme); - - // run the instances we have in the pool - // and apply the last theme if not specified - $.each( _pool, function( i, instance ) { - if ( instance._options.theme == theme.name || (!instance._initialized && !instance._options.theme) ) { - instance.theme = theme; - instance._init.call( instance ); - } - }); - }, - - // the Utils singleton - Utils = (function() { - - return { - - // legacy support for clearTimer - clearTimer: function( id ) { - $.each( Galleria.get(), function() { - this.clearTimer( id ); - }); - }, - - // legacy support for addTimer - addTimer: function( id ) { - $.each( Galleria.get(), function() { - this.addTimer( id ); - }); - }, - - array : function( obj ) { - return protoArray.slice.call(obj, 0); - }, - - create : function( className, nodeName ) { - nodeName = nodeName || 'div'; - var elem = doc.createElement( nodeName ); - elem.className = className; - return elem; - }, - - removeFromArray : function( arr, elem ) { - $.each(arr, function(i, el) { - if ( el == elem ) { - arr.splice(i, 1); - return false; - } - }); - return arr; - }, - - getScriptPath : function( src ) { - - // the currently executing script is always the last - src = src || $('script:last').attr('src'); - var slices = src.split('/'); - - if (slices.length == 1) { - return ''; - } - - slices.pop(); - - return slices.join('/') + '/'; - }, - - // CSS3 transitions, added in 1.2.4 - animate : (function() { - - // detect transition - var transition = (function( style ) { - var props = 'transition WebkitTransition MozTransition OTransition'.split(' '), - i; - - // disable css3 animations in opera until stable - if ( window.opera ) { - return false; - } - - for ( i = 0; props[i]; i++ ) { - if ( typeof style[ props[ i ] ] !== 'undefined' ) { - return props[ i ]; - } - } - return false; - }(( doc.body || doc.documentElement).style )); - - // map transitionend event - var endEvent = { - MozTransition: 'transitionend', - OTransition: 'oTransitionEnd', - WebkitTransition: 'webkitTransitionEnd', - transition: 'transitionend' - }[ transition ]; - - // map bezier easing conversions - var easings = { - _default: [0.25, 0.1, 0.25, 1], - galleria: [0.645, 0.045, 0.355, 1], - galleriaIn: [0.55, 0.085, 0.68, 0.53], - galleriaOut: [0.25, 0.46, 0.45, 0.94], - ease: [0.25, 0, 0.25, 1], - linear: [0.25, 0.25, 0.75, 0.75], - 'ease-in': [0.42, 0, 1, 1], - 'ease-out': [0, 0, 0.58, 1], - 'ease-in-out': [0.42, 0, 0.58, 1] - }; - - // function for setting transition css for all browsers - var setStyle = function( elem, value, suffix ) { - var css = {}; - suffix = suffix || 'transition'; - $.each( 'webkit moz ms o'.split(' '), function() { - css[ '-' + this + '-' + suffix ] = value; - }); - elem.css( css ); - }; - - // clear styles - var clearStyle = function( elem ) { - setStyle( elem, 'none', 'transition' ); - if ( Galleria.WEBKIT && Galleria.TOUCH ) { - setStyle( elem, 'translate3d(0,0,0)', 'transform' ); - if ( elem.data('revert') ) { - elem.css( elem.data('revert') ); - elem.data('revert', null); - } - } - }; - - // various variables - var change, strings, easing, syntax, revert, form, css; - - // the actual animation method - return function( elem, to, options ) { - - // extend defaults - options = $.extend({ - duration: 400, - complete: F, - stop: false - }, options); - - // cache jQuery instance - elem = $( elem ); - - if ( !options.duration ) { - elem.css( to ); - options.complete.call( elem[0] ); - return; - } - - // fallback to jQuery's animate if transition is not supported - if ( !transition ) { - elem.animate(to, options); - return; - } - - // stop - if ( options.stop ) { - // clear the animation - elem.off( endEvent ); - clearStyle( elem ); - } - - // see if there is a change - change = false; - $.each( to, function( key, val ) { - css = elem.css( key ); - if ( Utils.parseValue( css ) != Utils.parseValue( val ) ) { - change = true; - } - // also add computed styles for FF - elem.css( key, css ); - }); - if ( !change ) { - window.setTimeout( function() { - options.complete.call( elem[0] ); - }, options.duration ); - return; - } - - // the css strings to be applied - strings = []; - - // the easing bezier - easing = options.easing in easings ? easings[ options.easing ] : easings._default; - - // the syntax - syntax = ' ' + options.duration + 'ms' + ' cubic-bezier(' + easing.join(',') + ')'; - - // add a tiny timeout so that the browsers catches any css changes before animating - window.setTimeout( (function(elem, endEvent, to, syntax) { - return function() { - - // attach the end event - elem.one(endEvent, (function( elem ) { - return function() { - - // clear the animation - clearStyle(elem); - - // run the complete method - options.complete.call(elem[0]); - }; - }( elem ))); - - // do the webkit translate3d for better performance on iOS - if( Galleria.WEBKIT && Galleria.TOUCH ) { - - revert = {}; - form = [0,0,0]; - - $.each( ['left', 'top'], function(i, m) { - if ( m in to ) { - form[ i ] = ( Utils.parseValue( to[ m ] ) - Utils.parseValue(elem.css( m )) ) + 'px'; - revert[ m ] = to[ m ]; - delete to[ m ]; - } - }); - - if ( form[0] || form[1]) { - - elem.data('revert', revert); - - strings.push('-webkit-transform' + syntax); - - // 3d animate - setStyle( elem, 'translate3d(' + form.join(',') + ')', 'transform'); - } - } - - // push the animation props - $.each(to, function( p, val ) { - strings.push(p + syntax); - }); - - // set the animation styles - setStyle( elem, strings.join(',') ); - - // animate - elem.css( to ); - - }; - }(elem, endEvent, to, syntax)), 2); - }; - }()), - - removeAlpha : function( elem ) { - if ( elem instanceof jQuery ) { - elem = elem[0]; - } - if ( IE < 9 && elem ) { - - var style = elem.style, - currentStyle = elem.currentStyle, - filter = currentStyle && currentStyle.filter || style.filter || ""; - - if ( /alpha/.test( filter ) ) { - style.filter = filter.replace( /alpha\([^)]*\)/i, '' ); - } - } - }, - - forceStyles : function( elem, styles ) { - elem = $(elem); - if ( elem.attr( 'style' ) ) { - elem.data( 'styles', elem.attr( 'style' ) ).removeAttr( 'style' ); - } - elem.css( styles ); - }, - - revertStyles : function() { - $.each( Utils.array( arguments ), function( i, elem ) { - - elem = $( elem ); - elem.removeAttr( 'style' ); - - elem.attr('style',''); // "fixes" webkit bug - - if ( elem.data( 'styles' ) ) { - elem.attr( 'style', elem.data('styles') ).data( 'styles', null ); - } - }); - }, - - moveOut : function( elem ) { - Utils.forceStyles( elem, { - position: 'absolute', - left: -10000 - }); - }, - - moveIn : function() { - Utils.revertStyles.apply( Utils, Utils.array( arguments ) ); - }, - - hide : function( elem, speed, callback ) { - - callback = callback || F; - - var $elem = $(elem); - elem = $elem[0]; - - // save the value if not exist - if (! $elem.data('opacity') ) { - $elem.data('opacity', $elem.css('opacity') ); - } - - // always hide - var style = { opacity: 0 }; - - if (speed) { - - var complete = IE < 9 && elem ? function() { - Utils.removeAlpha( elem ); - elem.style.visibility = 'hidden'; - callback.call( elem ); - } : callback; - - Utils.animate( elem, style, { - duration: speed, - complete: complete, - stop: true - }); - } else { - if ( IE < 9 && elem ) { - Utils.removeAlpha( elem ); - elem.style.visibility = 'hidden'; - } else { - $elem.css( style ); - } - } - }, - - show : function( elem, speed, callback ) { - - callback = callback || F; - - var $elem = $(elem); - elem = $elem[0]; - - // bring back saved opacity - var saved = parseFloat( $elem.data('opacity') ) || 1, - style = { opacity: saved }; - - // animate or toggle - if (speed) { - - if ( IE < 9 ) { - $elem.css('opacity', 0); - elem.style.visibility = 'visible'; - } - - var complete = IE < 9 && elem ? function() { - if ( style.opacity == 1 ) { - Utils.removeAlpha( elem ); - } - callback.call( elem ); - } : callback; - - Utils.animate( elem, style, { - duration: speed, - complete: complete, - stop: true - }); - } else { - if ( IE < 9 && style.opacity == 1 && elem ) { - Utils.removeAlpha( elem ); - elem.style.visibility = 'visible'; - } else { - $elem.css( style ); - } - } - }, - - wait : function(options) { - - Galleria._waiters = Galleria._waiters || []; - - options = $.extend({ - until : FALSE, - success : F, - error : function() { Galleria.raise('Could not complete wait function.'); }, - timeout: 3000 - }, options); - - var start = Utils.timestamp(), - elapsed, - now, - tid, - fn = function() { - now = Utils.timestamp(); - elapsed = now - start; - Utils.removeFromArray( Galleria._waiters, tid ); - if ( options.until( elapsed ) ) { - options.success(); - return false; - } - if (typeof options.timeout == 'number' && now >= start + options.timeout) { - options.error(); - return false; - } - Galleria._waiters.push( tid = window.setTimeout(fn, 10) ); - }; - Galleria._waiters.push( tid = window.setTimeout(fn, 10) ); - }, - - toggleQuality : function( img, force ) { - - if ( ( IE !== 7 && IE !== 8 ) || !img || img.nodeName.toUpperCase() != 'IMG' ) { - return; - } - - if ( typeof force === 'undefined' ) { - force = img.style.msInterpolationMode === 'nearest-neighbor'; - } - - img.style.msInterpolationMode = force ? 'bicubic' : 'nearest-neighbor'; - }, - - insertStyleTag : function( styles, id ) { - - if ( id && $( '#'+id ).length ) { - return; - } - - var style = doc.createElement( 'style' ); - if ( id ) { - style.id = id; - } - - DOM().head.appendChild( style ); - - if ( style.styleSheet ) { // IE - style.styleSheet.cssText = styles; - } else { - var cssText = doc.createTextNode( styles ); - style.appendChild( cssText ); - } - }, - - // a loadscript method that works for local scripts - loadScript: function( url, callback ) { - - var done = false, - script = $('').attr({ - src: url, - async: true - }).get(0); - - // Attach handlers for all browsers - script.onload = script.onreadystatechange = function() { - if ( !done && (!this.readyState || - this.readyState === 'loaded' || this.readyState === 'complete') ) { - - done = true; - - // Handle memory leak in IE - script.onload = script.onreadystatechange = null; - - if (typeof callback === 'function') { - callback.call( this, this ); - } - } - }; - - DOM().head.appendChild( script ); - }, - - // parse anything into a number - parseValue: function( val ) { - if (typeof val === 'number') { - return val; - } else if (typeof val === 'string') { - var arr = val.match(/\-?\d|\./g); - return arr && arr.constructor === Array ? arr.join('')*1 : 0; - } else { - return 0; - } - }, - - // timestamp abstraction - timestamp: function() { - return new Date().getTime(); - }, - - loadCSS : function( href, id, callback ) { - - var link, - length; - - // look for manual css - $('link[rel=stylesheet]').each(function() { - if ( new RegExp( href ).test( this.href ) ) { - link = this; - return false; - } - }); - - if ( typeof id === 'function' ) { - callback = id; - id = undef; - } - - callback = callback || F; // dirty - - // if already present, return - if ( link ) { - callback.call( link, link ); - return link; - } - - // save the length of stylesheets to check against - length = doc.styleSheets.length; - - // check for existing id - if( $( '#' + id ).length ) { - - $( '#' + id ).attr( 'href', href ); - length--; - - } else { - link = $( '' ).attr({ - rel: 'stylesheet', - href: href, - id: id - }).get(0); - - var styles = $('link[rel="stylesheet"], style'); - if ( styles.length ) { - styles.get(0).parentNode.insertBefore( link, styles[0] ); - } else { - DOM().head.appendChild( link ); - } - - if ( IE && length >= 31 ) { - Galleria.raise( 'You have reached the browser stylesheet limit (31)', true ); - return; - } - } - - if ( typeof callback === 'function' ) { - - // First check for dummy element (new in 1.2.8) - var $loader = $('').attr( 'id', 'galleria-loader' ).hide().appendTo( DOM().body ); - - Utils.wait({ - until: function() { - return $loader.height() > 0; - }, - success: function() { - $loader.remove(); - callback.call( link, link ); - }, - error: function() { - $loader.remove(); - - // If failed, tell the dev to download the latest theme - Galleria.raise( 'Theme CSS could not load after 20 sec. ' + ( Galleria.QUIRK ? - 'Your browser is in Quirks Mode, please add a correct doctype.' : - 'Please download the latest theme at http://galleria.io/customer/.' ), true ); - }, - timeout: 5000 - }); - } - return link; - } - }; - }()), - - // play icon - _playIcon = function( container ) { - - var css = '.galleria-videoicon{width:60px;height:60px;position:absolute;top:50%;left:50%;z-index:1;' + - 'margin:-30px 0 0 -30px;cursor:pointer;background:#000;background:rgba(0,0,0,.8);border-radius:3px;-webkit-transition:all 150ms}' + - '.galleria-videoicon i{width:0px;height:0px;border-style:solid;border-width:10px 0 10px 16px;display:block;' + - 'border-color:transparent transparent transparent #ffffff;margin:20px 0 0 22px}.galleria-image:hover .galleria-videoicon{background:#000}'; - - Utils.insertStyleTag( css, 'galleria-videoicon' ); - - return $( Utils.create( 'galleria-videoicon' ) ).html( '' ).appendTo( container ) - .click( function() { $( this ).siblings( 'img' ).mouseup(); }); - }, - - // the transitions holder - _transitions = (function() { - - var _slide = function(params, complete, fade, door) { - - var easing = this.getOptions('easing'), - distance = this.getStageWidth(), - from = { left: distance * ( params.rewind ? -1 : 1 ) }, - to = { left: 0 }; - - if ( fade ) { - from.opacity = 0; - to.opacity = 1; - } else { - from.opacity = 1; - } - - $(params.next).css(from); - - Utils.animate(params.next, to, { - duration: params.speed, - complete: (function( elems ) { - return function() { - complete(); - elems.css({ - left: 0 - }); - }; - }( $( params.next ).add( params.prev ) )), - queue: false, - easing: easing - }); - - if (door) { - params.rewind = !params.rewind; - } - - if (params.prev) { - - from = { left: 0 }; - to = { left: distance * ( params.rewind ? 1 : -1 ) }; - - if ( fade ) { - from.opacity = 1; - to.opacity = 0; - } - - $(params.prev).css(from); - Utils.animate(params.prev, to, { - duration: params.speed, - queue: false, - easing: easing, - complete: function() { - $(this).css('opacity', 0); - } - }); - } - }; - - return { - - active: false, - - init: function( effect, params, complete ) { - if ( _transitions.effects.hasOwnProperty( effect ) ) { - _transitions.effects[ effect ].call( this, params, complete ); - } - }, - - effects: { - - fade: function(params, complete) { - $(params.next).css({ - opacity: 0, - left: 0 - }); - Utils.animate(params.next, { - opacity: 1 - },{ - duration: params.speed, - complete: complete - }); - if (params.prev) { - $(params.prev).css('opacity',1).show(); - Utils.animate(params.prev, { - opacity: 0 - },{ - duration: params.speed - }); - } - }, - - flash: function(params, complete) { - $(params.next).css({ - opacity: 0, - left: 0 - }); - if (params.prev) { - Utils.animate( params.prev, { - opacity: 0 - },{ - duration: params.speed/2, - complete: function() { - Utils.animate( params.next, { - opacity:1 - },{ - duration: params.speed, - complete: complete - }); - } - }); - } else { - Utils.animate( params.next, { - opacity: 1 - },{ - duration: params.speed, - complete: complete - }); - } - }, - - pulse: function(params, complete) { - if (params.prev) { - $(params.prev).hide(); - } - $(params.next).css({ - opacity: 0, - left: 0 - }).show(); - Utils.animate(params.next, { - opacity:1 - },{ - duration: params.speed, - complete: complete - }); - }, - - slide: function(params, complete) { - _slide.apply( this, Utils.array( arguments ) ); - }, - - fadeslide: function(params, complete) { - _slide.apply( this, Utils.array( arguments ).concat( [true] ) ); - }, - - doorslide: function(params, complete) { - _slide.apply( this, Utils.array( arguments ).concat( [false, true] ) ); - } - } - }; - }()); - -// listen to fullscreen -_nativeFullscreen.listen(); - -// create special click:fast event for fast touch interaction -$.event.special['click:fast'] = { - propagate: true, - add: function(handleObj) { - - var getCoords = function(e) { - if ( e.touches && e.touches.length ) { - var touch = e.touches[0]; - return { - x: touch.pageX, - y: touch.pageY - }; - } - }; - - var def = { - touched: false, - touchdown: false, - coords: { x:0, y:0 }, - evObj: {} - }; - - $(this).data({ - clickstate: def, - timer: 0 - }).on('touchstart.fast', function(e) { - window.clearTimeout($(this).data('timer')); - $(this).data('clickstate', { - touched: true, - touchdown: true, - coords: getCoords(e.originalEvent), - evObj: e - }); - }).on('touchmove.fast', function(e) { - var coords = getCoords(e.originalEvent), - state = $(this).data('clickstate'), - distance = Math.max( - Math.abs(state.coords.x - coords.x), - Math.abs(state.coords.y - coords.y) - ); - if ( distance > 6 ) { - $(this).data('clickstate', $.extend(state, { - touchdown: false - })); - } - }).on('touchend.fast', function(e) { - var $this = $(this), - state = $this.data('clickstate'); - if(state.touchdown) { - handleObj.handler.call(this, e); - } - $this.data('timer', window.setTimeout(function() { - $this.data('clickstate', def); - }, 400)); - }).on('click.fast', function(e) { - var state = $(this).data('clickstate'); - if ( state.touched ) { - return false; - } - $(this).data('clickstate', def); - handleObj.handler.call(this, e); - }); - }, - remove: function() { - $(this).off('touchstart.fast touchmove.fast touchend.fast click.fast'); - } -}; - -// trigger resize on orientationchange (IOS7) -$win.on( 'orientationchange', function() { - $(this).resize(); -}); - -/** - The main Galleria class - - @class - @constructor - - @example var gallery = new Galleria(); - - @author http://wib.io - - @requires jQuery - -*/ - -Galleria = function() { - - var self = this; - - // internal options - this._options = {}; - - // flag for controlling play/pause - this._playing = false; - - // internal interval for slideshow - this._playtime = 5000; - - // internal variable for the currently active image - this._active = null; - - // the internal queue, arrayified - this._queue = { length: 0 }; - - // the internal data array - this._data = []; - - // the internal dom collection - this._dom = {}; - - // the internal thumbnails array - this._thumbnails = []; - - // the internal layers array - this._layers = []; - - // internal init flag - this._initialized = false; - - // internal firstrun flag - this._firstrun = false; - - // global stagewidth/height - this._stageWidth = 0; - this._stageHeight = 0; - - // target holder - this._target = undef; - - // bind hashes - this._binds = []; - - // instance id - this._id = parseInt(M.random()*10000, 10); - - // add some elements - var divs = 'container stage images image-nav image-nav-left image-nav-right ' + - 'info info-text info-title info-description ' + - 'thumbnails thumbnails-list thumbnails-container thumb-nav-left thumb-nav-right ' + - 'loader counter tooltip', - spans = 'current total'; - - $.each( divs.split(' '), function( i, elemId ) { - self._dom[ elemId ] = Utils.create( 'galleria-' + elemId ); - }); - - $.each( spans.split(' '), function( i, elemId ) { - self._dom[ elemId ] = Utils.create( 'galleria-' + elemId, 'span' ); - }); - - // the internal keyboard object - // keeps reference of the keybinds and provides helper methods for binding keys - var keyboard = this._keyboard = { - - keys : { - 'UP': 38, - 'DOWN': 40, - 'LEFT': 37, - 'RIGHT': 39, - 'RETURN': 13, - 'ESCAPE': 27, - 'BACKSPACE': 8, - 'SPACE': 32 - }, - - map : {}, - - bound: false, - - press: function(e) { - var key = e.keyCode || e.which; - if ( key in keyboard.map && typeof keyboard.map[key] === 'function' ) { - keyboard.map[key].call(self, e); - } - }, - - attach: function(map) { - - var key, up; - - for( key in map ) { - if ( map.hasOwnProperty( key ) ) { - up = key.toUpperCase(); - if ( up in keyboard.keys ) { - keyboard.map[ keyboard.keys[up] ] = map[key]; - } else { - keyboard.map[ up ] = map[key]; - } - } - } - if ( !keyboard.bound ) { - keyboard.bound = true; - $doc.on('keydown', keyboard.press); - } - }, - - detach: function() { - keyboard.bound = false; - keyboard.map = {}; - $doc.off('keydown', keyboard.press); - } - }; - - // internal controls for keeping track of active / inactive images - var controls = this._controls = { - - 0: undef, - - 1: undef, - - active : 0, - - swap : function() { - controls.active = controls.active ? 0 : 1; - }, - - getActive : function() { - return self._options.swipe ? controls.slides[ self._active ] : controls[ controls.active ]; - }, - - getNext : function() { - return self._options.swipe ? controls.slides[ self.getNext( self._active ) ] : controls[ 1 - controls.active ]; - }, - - slides : [], - - frames: [], - - layers: [] - }; - - // internal carousel object - var carousel = this._carousel = { - - // shortcuts - next: self.$('thumb-nav-right'), - prev: self.$('thumb-nav-left'), - - // cache the width - width: 0, - - // track the current position - current: 0, - - // cache max value - max: 0, - - // save all hooks for each width in an array - hooks: [], - - // update the carousel - // you can run this method anytime, f.ex on window.resize - update: function() { - var w = 0, - h = 0, - hooks = [0]; - - $.each( self._thumbnails, function( i, thumb ) { - if ( thumb.ready ) { - w += thumb.outerWidth || $( thumb.container ).outerWidth( true ); - // Due to a bug in jquery, outerwidth() returns the floor of the actual outerwidth, - // if the browser is zoom to a value other than 100%. height() returns the floating point value. - var containerWidth = $( thumb.container).width(); - w += containerWidth - M.floor(containerWidth); - - hooks[ i+1 ] = w; - h = M.max( h, thumb.outerHeight || $( thumb.container).outerHeight( true ) ); - } - }); - - self.$( 'thumbnails' ).css({ - width: w, - height: h - }); - - carousel.max = w; - carousel.hooks = hooks; - carousel.width = self.$( 'thumbnails-list' ).width(); - carousel.setClasses(); - - self.$( 'thumbnails-container' ).toggleClass( 'galleria-carousel', w > carousel.width ); - - // one extra calculation - carousel.width = self.$( 'thumbnails-list' ).width(); - - // todo: fix so the carousel moves to the left - }, - - bindControls: function() { - - var i; - - carousel.next.on( 'click:fast', function(e) { - e.preventDefault(); - - if ( self._options.carouselSteps === 'auto' ) { - - for ( i = carousel.current; i < carousel.hooks.length; i++ ) { - if ( carousel.hooks[i] - carousel.hooks[ carousel.current ] > carousel.width ) { - carousel.set(i - 2); - break; - } - } - - } else { - carousel.set( carousel.current + self._options.carouselSteps); - } - }); - - carousel.prev.on( 'click:fast', function(e) { - e.preventDefault(); - - if ( self._options.carouselSteps === 'auto' ) { - - for ( i = carousel.current; i >= 0; i-- ) { - if ( carousel.hooks[ carousel.current ] - carousel.hooks[i] > carousel.width ) { - carousel.set( i + 2 ); - break; - } else if ( i === 0 ) { - carousel.set( 0 ); - break; - } - } - } else { - carousel.set( carousel.current - self._options.carouselSteps ); - } - }); - }, - - // calculate and set positions - set: function( i ) { - i = M.max( i, 0 ); - while ( carousel.hooks[i - 1] + carousel.width >= carousel.max && i >= 0 ) { - i--; - } - carousel.current = i; - carousel.animate(); - }, - - // get the last position - getLast: function(i) { - return ( i || carousel.current ) - 1; - }, - - // follow the active image - follow: function(i) { - - //don't follow if position fits - if ( i === 0 || i === carousel.hooks.length - 2 ) { - carousel.set( i ); - return; - } - - // calculate last position - var last = carousel.current; - while( carousel.hooks[last] - carousel.hooks[ carousel.current ] < - carousel.width && last <= carousel.hooks.length ) { - last ++; - } - - // set position - if ( i - 1 < carousel.current ) { - carousel.set( i - 1 ); - } else if ( i + 2 > last) { - carousel.set( i - last + carousel.current + 2 ); - } - }, - - // helper for setting disabled classes - setClasses: function() { - carousel.prev.toggleClass( 'disabled', !carousel.current ); - carousel.next.toggleClass( 'disabled', carousel.hooks[ carousel.current ] + carousel.width >= carousel.max ); - }, - - // the animation method - animate: function(to) { - carousel.setClasses(); - var num = carousel.hooks[ carousel.current ] * -1; - - if ( isNaN( num ) ) { - return; - } - - // FF 24 bug - self.$( 'thumbnails' ).css('left', function() { - return $(this).css('left'); - }); - - Utils.animate(self.get( 'thumbnails' ), { - left: num - },{ - duration: self._options.carouselSpeed, - easing: self._options.easing, - queue: false - }); - } - }; - - // tooltip control - // added in 1.2 - var tooltip = this._tooltip = { - - initialized : false, - - open: false, - - timer: 'tooltip' + self._id, - - swapTimer: 'swap' + self._id, - - init: function() { - - tooltip.initialized = true; - - var css = '.galleria-tooltip{padding:3px 8px;max-width:50%;background:#ffe;color:#000;z-index:3;position:absolute;font-size:11px;line-height:1.3;' + - 'opacity:0;box-shadow:0 0 2px rgba(0,0,0,.4);-moz-box-shadow:0 0 2px rgba(0,0,0,.4);-webkit-box-shadow:0 0 2px rgba(0,0,0,.4);}'; - - Utils.insertStyleTag( css, 'galleria-tooltip' ); - - self.$( 'tooltip' ).css({ - opacity: 0.8, - visibility: 'visible', - display: 'none' - }); - - }, - - // move handler - move: function( e ) { - var mouseX = self.getMousePosition(e).x, - mouseY = self.getMousePosition(e).y, - $elem = self.$( 'tooltip' ), - x = mouseX, - y = mouseY, - height = $elem.outerHeight( true ) + 1, - width = $elem.outerWidth( true ), - limitY = height + 15; - - var maxX = self.$( 'container' ).width() - width - 2, - maxY = self.$( 'container' ).height() - height - 2; - - if ( !isNaN(x) && !isNaN(y) ) { - - x += 10; - y -= ( height+8 ); - - x = M.max( 0, M.min( maxX, x ) ); - y = M.max( 0, M.min( maxY, y ) ); - - if( mouseY < limitY ) { - y = limitY; - } - - $elem.css({ left: x, top: y }); - } - }, - - // bind elements to the tooltip - // you can bind multiple elementIDs using { elemID : function } or { elemID : string } - // you can also bind single DOM elements using bind(elem, string) - bind: function( elem, value ) { - - // todo: revise if alternative tooltip is needed for mobile devices - if (Galleria.TOUCH) { - return; - } - - if (! tooltip.initialized ) { - tooltip.init(); - } - - var mouseout = function() { - self.$( 'container' ).off( 'mousemove', tooltip.move ); - self.clearTimer( tooltip.timer ); - - self.$( 'tooltip' ).stop().animate({ - opacity: 0 - }, 200, function() { - - self.$( 'tooltip' ).hide(); - - self.addTimer( tooltip.swapTimer, function() { - tooltip.open = false; - }, 1000); - }); - }; - - var hover = function( elem, value) { - - tooltip.define( elem, value ); - - $( elem ).hover(function() { - - self.clearTimer( tooltip.swapTimer ); - self.$('container').off( 'mousemove', tooltip.move ).on( 'mousemove', tooltip.move ).trigger( 'mousemove' ); - tooltip.show( elem ); - - self.addTimer( tooltip.timer, function() { - self.$( 'tooltip' ).stop().show().animate({ - opacity: 1 - }); - tooltip.open = true; - - }, tooltip.open ? 0 : 500); - - }, mouseout).click(mouseout); - }; - - if ( typeof value === 'string' ) { - hover( ( elem in self._dom ? self.get( elem ) : elem ), value ); - } else { - // asume elemID here - $.each( elem, function( elemID, val ) { - hover( self.get(elemID), val ); - }); - } - }, - - show: function( elem ) { - - elem = $( elem in self._dom ? self.get(elem) : elem ); - - var text = elem.data( 'tt' ), - mouseup = function( e ) { - - // attach a tiny settimeout to make sure the new tooltip is filled - window.setTimeout( (function( ev ) { - return function() { - tooltip.move( ev ); - }; - }( e )), 10); - - elem.off( 'mouseup', mouseup ); - - }; - - text = typeof text === 'function' ? text() : text; - - if ( ! text ) { - return; - } - - self.$( 'tooltip' ).html( text.replace(/\s/, ' ') ); - - // trigger mousemove on mouseup in case of click - elem.on( 'mouseup', mouseup ); - }, - - define: function( elem, value ) { - - // we store functions, not strings - if (typeof value !== 'function') { - var s = value; - value = function() { - return s; - }; - } - - elem = $( elem in self._dom ? self.get(elem) : elem ).data('tt', value); - - tooltip.show( elem ); - - } - }; - - // internal fullscreen control - var fullscreen = this._fullscreen = { - - scrolled: 0, - - crop: undef, - - active: false, - - prev: $(), - - beforeEnter: function(fn){ fn(); }, - beforeExit: function(fn){ fn(); }, - - keymap: self._keyboard.map, - - parseCallback: function( callback, enter ) { - - return _transitions.active ? function() { - if ( typeof callback == 'function' ) { - callback.call(self); - } - var active = self._controls.getActive(), - next = self._controls.getNext(); - - self._scaleImage( next ); - self._scaleImage( active ); - - if ( enter && self._options.trueFullscreen ) { - // Firefox bug, revise later - $( active.container ).add( next.container ).trigger( 'transitionend' ); - } - - } : callback; - - }, - - enter: function( callback ) { - - fullscreen.beforeEnter(function() { - - callback = fullscreen.parseCallback( callback, true ); - - if ( self._options.trueFullscreen && _nativeFullscreen.support ) { - - // do some stuff prior animation for wmoother transitions - - fullscreen.active = true; - - Utils.forceStyles( self.get('container'), { - width: '100%', - height: '100%' - }); - - self.rescale(); - - if ( Galleria.MAC ) { - if ( !( Galleria.SAFARI && /version\/[1-5]/.test(NAV)) ) { - self.$('container').css('opacity', 0).addClass('fullscreen'); - window.setTimeout(function() { - fullscreen.scale(); - self.$('container').css('opacity', 1); - }, 50); - } else { - self.$('stage').css('opacity', 0); - window.setTimeout(function() { - fullscreen.scale(); - self.$('stage').css('opacity', 1); - },4); - } - } else { - self.$('container').addClass('fullscreen'); - } - - $win.resize( fullscreen.scale ); - - _nativeFullscreen.enter( self, callback, self.get('container') ); - - } else { - - fullscreen.scrolled = $win.scrollTop(); - if( !Galleria.TOUCH ) { - window.scrollTo(0, 0); - } - - fullscreen._enter( callback ); - } - }); - - }, - - _enter: function( callback ) { - - fullscreen.active = true; - - if ( IFRAME ) { - - fullscreen.iframe = (function() { - - var elem, - refer = doc.referrer, - test = doc.createElement('a'), - loc = window.location; - - test.href = refer; - - if( test.protocol != loc.protocol || - test.hostname != loc.hostname || - test.port != loc.port ) { - Galleria.raise('Parent fullscreen not available. Iframe protocol, domains and ports must match.'); - return false; - } - - fullscreen.pd = window.parent.document; - - $( fullscreen.pd ).find('iframe').each(function() { - var idoc = this.contentDocument || this.contentWindow.document; - if ( idoc === doc ) { - elem = this; - return false; - } - }); - - return elem; - }()); - - } - - // hide the image until rescale is complete - Utils.hide( self.getActiveImage() ); - - if ( IFRAME && fullscreen.iframe ) { - fullscreen.iframe.scrolled = $( window.parent ).scrollTop(); - window.parent.scrollTo(0, 0); - } - - var data = self.getData(), - options = self._options, - inBrowser = !self._options.trueFullscreen || !_nativeFullscreen.support, - htmlbody = { - height: '100%', - overflow: 'hidden', - margin:0, - padding:0 - }; - - if (inBrowser) { - - self.$('container').addClass('fullscreen'); - fullscreen.prev = self.$('container').prev(); - - if ( !fullscreen.prev.length ) { - fullscreen.parent = self.$( 'container' ).parent(); - } - - // move - self.$( 'container' ).appendTo( 'body' ); - - // begin styleforce - - Utils.forceStyles(self.get('container'), { - position: Galleria.TOUCH ? 'absolute' : 'fixed', - top: 0, - left: 0, - width: '100%', - height: '100%', - zIndex: 10000 - }); - Utils.forceStyles( DOM().html, htmlbody ); - Utils.forceStyles( DOM().body, htmlbody ); - } - - if ( IFRAME && fullscreen.iframe ) { - Utils.forceStyles( fullscreen.pd.documentElement, htmlbody ); - Utils.forceStyles( fullscreen.pd.body, htmlbody ); - Utils.forceStyles( fullscreen.iframe, $.extend( htmlbody, { - width: '100%', - height: '100%', - top: 0, - left: 0, - position: 'fixed', - zIndex: 10000, - border: 'none' - })); - } - - // temporarily attach some keys - // save the old ones first in a cloned object - fullscreen.keymap = $.extend({}, self._keyboard.map); - - self.attachKeyboard({ - escape: self.exitFullscreen, - right: self.next, - left: self.prev - }); - - // temporarily save the crop - fullscreen.crop = options.imageCrop; - - // set fullscreen options - if ( options.fullscreenCrop != undef ) { - options.imageCrop = options.fullscreenCrop; - } - - // swap to big image if it's different from the display image - if ( data && data.big && data.image !== data.big ) { - var big = new Galleria.Picture(), - cached = big.isCached( data.big ), - index = self.getIndex(), - thumb = self._thumbnails[ index ]; - - self.trigger( { - type: Galleria.LOADSTART, - cached: cached, - rewind: false, - index: index, - imageTarget: self.getActiveImage(), - thumbTarget: thumb, - galleriaData: data - }); - - big.load( data.big, function( big ) { - self._scaleImage( big, { - complete: function( big ) { - self.trigger({ - type: Galleria.LOADFINISH, - cached: cached, - index: index, - rewind: false, - imageTarget: big.image, - thumbTarget: thumb - }); - var image = self._controls.getActive().image; - if ( image ) { - $( image ).width( big.image.width ).height( big.image.height ) - .attr( 'style', $( big.image ).attr('style') ) - .attr( 'src', big.image.src ); - } - } - }); - }); - - var n = self.getNext(index), - p = new Galleria.Picture(), - ndata = self.getData( n ); - p.preload( self.isFullscreen() && ndata.big ? ndata.big : ndata.image ); - } - - // init the first rescale and attach callbacks - - self.rescale(function() { - - self.addTimer(false, function() { - // show the image after 50 ms - if ( inBrowser ) { - Utils.show( self.getActiveImage() ); - } - - if (typeof callback === 'function') { - callback.call( self ); - } - self.rescale(); - - }, 100); - - self.trigger( Galleria.FULLSCREEN_ENTER ); - }); - - if ( !inBrowser ) { - Utils.show( self.getActiveImage() ); - } else { - $win.resize( fullscreen.scale ); - } - - }, - - scale : function() { - self.rescale(); - }, - - exit: function( callback ) { - - fullscreen.beforeExit(function() { - - callback = fullscreen.parseCallback( callback ); - - if ( self._options.trueFullscreen && _nativeFullscreen.support ) { - _nativeFullscreen.exit( callback ); - } else { - fullscreen._exit( callback ); - } - }); - }, - - _exit: function( callback ) { - - fullscreen.active = false; - - var inBrowser = !self._options.trueFullscreen || !_nativeFullscreen.support, - $container = self.$( 'container' ).removeClass( 'fullscreen' ); - - // move back - if ( fullscreen.parent ) { - fullscreen.parent.prepend( $container ); - } else { - $container.insertAfter( fullscreen.prev ); - } - - if ( inBrowser ) { - Utils.hide( self.getActiveImage() ); - - // revert all styles - Utils.revertStyles( self.get('container'), DOM().html, DOM().body ); - - // scroll back - if( !Galleria.TOUCH ) { - window.scrollTo(0, fullscreen.scrolled); - } - - // reload iframe src manually - var frame = self._controls.frames[ self._controls.active ]; - if ( frame && frame.image ) { - frame.image.src = frame.image.src; - } - } - - if ( IFRAME && fullscreen.iframe ) { - Utils.revertStyles( fullscreen.pd.documentElement, fullscreen.pd.body, fullscreen.iframe ); - if ( fullscreen.iframe.scrolled ) { - window.parent.scrollTo(0, fullscreen.iframe.scrolled ); - } - } - - // detach all keyboard events and apply the old keymap - self.detachKeyboard(); - self.attachKeyboard( fullscreen.keymap ); - - // bring back cached options - self._options.imageCrop = fullscreen.crop; - - // return to original image - var big = self.getData().big, - image = self._controls.getActive().image; - - if ( !self.getData().iframe && image && big && big == image.src ) { - - window.setTimeout(function(src) { - return function() { - image.src = src; - }; - }( self.getData().image ), 1 ); - - } - - self.rescale(function() { - self.addTimer(false, function() { - - // show the image after 50 ms - if ( inBrowser ) { - Utils.show( self.getActiveImage() ); - } - - if ( typeof callback === 'function' ) { - callback.call( self ); - } - - $win.trigger( 'resize' ); - - }, 50); - self.trigger( Galleria.FULLSCREEN_EXIT ); - }); - - $win.off('resize', fullscreen.scale); - } - }; - - // the internal idle object for controlling idle states - var idle = this._idle = { - - trunk: [], - - bound: false, - - active: false, - - add: function(elem, to, from, hide) { - if ( !elem || Galleria.TOUCH ) { - return; - } - if (!idle.bound) { - idle.addEvent(); - } - elem = $(elem); - - if ( typeof from == 'boolean' ) { - hide = from; - from = {}; - } - - from = from || {}; - - var extract = {}, - style; - - for ( style in to ) { - if ( to.hasOwnProperty( style ) ) { - extract[ style ] = elem.css( style ); - } - } - - elem.data('idle', { - from: $.extend( extract, from ), - to: to, - complete: true, - busy: false - }); - - if ( !hide ) { - idle.addTimer(); - } else { - elem.css( to ); - } - idle.trunk.push(elem); - }, - - remove: function(elem) { - - elem = $(elem); - - $.each(idle.trunk, function(i, el) { - if ( el && el.length && !el.not(elem).length ) { - elem.css( elem.data( 'idle' ).from ); - idle.trunk.splice(i, 1); - } - }); - - if (!idle.trunk.length) { - idle.removeEvent(); - self.clearTimer( idle.timer ); - } - }, - - addEvent : function() { - idle.bound = true; - self.$('container').on( 'mousemove click', idle.showAll ); - if ( self._options.idleMode == 'hover' ) { - self.$('container').on( 'mouseleave', idle.hide ); - } - }, - - removeEvent : function() { - idle.bound = false; - self.$('container').on( 'mousemove click', idle.showAll ); - if ( self._options.idleMode == 'hover' ) { - self.$('container').off( 'mouseleave', idle.hide ); - } - }, - - addTimer : function() { - if( self._options.idleMode == 'hover' ) { - return; - } - self.addTimer( 'idle', function() { - idle.hide(); - }, self._options.idleTime ); - }, - - hide : function() { - - if ( !self._options.idleMode || self.getIndex() === false ) { - return; - } - - self.trigger( Galleria.IDLE_ENTER ); - - var len = idle.trunk.length; - - $.each( idle.trunk, function(i, elem) { - - var data = elem.data('idle'); - - if (! data) { - return; - } - - elem.data('idle').complete = false; - - Utils.animate( elem, data.to, { - duration: self._options.idleSpeed, - complete: function() { - if ( i == len-1 ) { - idle.active = false; - } - } - }); - }); - }, - - showAll : function() { - - self.clearTimer( 'idle' ); - - $.each( idle.trunk, function( i, elem ) { - idle.show( elem ); - }); - }, - - show: function(elem) { - - var data = elem.data('idle'); - - if ( !idle.active || ( !data.busy && !data.complete ) ) { - - data.busy = true; - - self.trigger( Galleria.IDLE_EXIT ); - - self.clearTimer( 'idle' ); - - Utils.animate( elem, data.from, { - duration: self._options.idleSpeed/2, - complete: function() { - idle.active = true; - $(elem).data('idle').busy = false; - $(elem).data('idle').complete = true; - } - }); - - } - idle.addTimer(); - } - }; - - // internal lightbox object - // creates a predesigned lightbox for simple popups of images in galleria - var lightbox = this._lightbox = { - - width : 0, - - height : 0, - - initialized : false, - - active : null, - - image : null, - - elems : {}, - - keymap: false, - - init : function() { - - if ( lightbox.initialized ) { - return; - } - lightbox.initialized = true; - - // create some elements to work with - var elems = 'overlay box content shadow title info close prevholder prev nextholder next counter image', - el = {}, - op = self._options, - css = '', - abs = 'position:absolute;', - prefix = 'lightbox-', - cssMap = { - overlay: 'position:fixed;display:none;opacity:'+op.overlayOpacity+';filter:alpha(opacity='+(op.overlayOpacity*100)+ - ');top:0;left:0;width:100%;height:100%;background:'+op.overlayBackground+';z-index:99990', - box: 'position:fixed;display:none;width:400px;height:400px;top:50%;left:50%;margin-top:-200px;margin-left:-200px;z-index:99991', - shadow: abs+'background:#000;width:100%;height:100%;', - content: abs+'background-color:#fff;top:10px;left:10px;right:10px;bottom:10px;overflow:hidden', - info: abs+'bottom:10px;left:10px;right:10px;color:#444;font:11px/13px arial,sans-serif;height:13px', - close: abs+'top:10px;right:10px;height:20px;width:20px;background:#fff;text-align:center;cursor:pointer;color:#444;font:16px/22px arial,sans-serif;z-index:99999', - image: abs+'top:10px;left:10px;right:10px;bottom:30px;overflow:hidden;display:block;', - prevholder: abs+'width:50%;top:0;bottom:40px;cursor:pointer;', - nextholder: abs+'width:50%;top:0;bottom:40px;right:-1px;cursor:pointer;', - prev: abs+'top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;left:20px;display:none;text-align:center;color:#000;font:bold 16px/36px arial,sans-serif', - next: abs+'top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;right:20px;left:auto;display:none;font:bold 16px/36px arial,sans-serif;text-align:center;color:#000', - title: 'float:left', - counter: 'float:right;margin-left:8px;' - }, - hover = function(elem) { - return elem.hover( - function() { $(this).css( 'color', '#bbb' ); }, - function() { $(this).css( 'color', '#444' ); } - ); - }, - appends = {}; - - // fix for navigation hovers transparent background event "feature" - var exs = ''; - if ( IE > 7 ) { - exs = IE < 9 ? 'background:#000;filter:alpha(opacity=0);' : 'background:rgba(0,0,0,0);'; - } else { - exs = 'z-index:99999'; - } - - cssMap.nextholder += exs; - cssMap.prevholder += exs; - - // create and insert CSS - $.each(cssMap, function( key, value ) { - css += '.galleria-'+prefix+key+'{'+value+'}'; - }); - - css += '.galleria-'+prefix+'box.iframe .galleria-'+prefix+'prevholder,'+ - '.galleria-'+prefix+'box.iframe .galleria-'+prefix+'nextholder{'+ - 'width:100px;height:100px;top:50%;margin-top:-70px}'; - - Utils.insertStyleTag( css, 'galleria-lightbox' ); - - // create the elements - $.each(elems.split(' '), function( i, elemId ) { - self.addElement( 'lightbox-' + elemId ); - el[ elemId ] = lightbox.elems[ elemId ] = self.get( 'lightbox-' + elemId ); - }); - - // initiate the image - lightbox.image = new Galleria.Picture(); - - // append the elements - $.each({ - box: 'shadow content close prevholder nextholder', - info: 'title counter', - content: 'info image', - prevholder: 'prev', - nextholder: 'next' - }, function( key, val ) { - var arr = []; - $.each( val.split(' '), function( i, prop ) { - arr.push( prefix + prop ); - }); - appends[ prefix+key ] = arr; - }); - - self.append( appends ); - - $( el.image ).append( lightbox.image.container ); - - $( DOM().body ).append( el.overlay, el.box ); - - // add the prev/next nav and bind some controls - - hover( $( el.close ).on( 'click:fast', lightbox.hide ).html('×') ); - - $.each( ['Prev','Next'], function(i, dir) { - - var $d = $( el[ dir.toLowerCase() ] ).html( /v/.test( dir ) ? '‹ ' : ' ›' ), - $e = $( el[ dir.toLowerCase()+'holder'] ); - - $e.on( 'click:fast', function() { - lightbox[ 'show' + dir ](); - }); - - // IE7 and touch devices will simply show the nav - if ( IE < 8 || Galleria.TOUCH ) { - $d.show(); - return; - } - - $e.hover( function() { - $d.show(); - }, function(e) { - $d.stop().fadeOut( 200 ); - }); - - }); - $( el.overlay ).on( 'click:fast', lightbox.hide ); - - // the lightbox animation is slow on ipad - if ( Galleria.IPAD ) { - self._options.lightboxTransitionSpeed = 0; - } - - }, - - rescale: function(event) { - - // calculate - var width = M.min( $win.width()-40, lightbox.width ), - height = M.min( $win.height()-60, lightbox.height ), - ratio = M.min( width / lightbox.width, height / lightbox.height ), - destWidth = M.round( lightbox.width * ratio ) + 40, - destHeight = M.round( lightbox.height * ratio ) + 60, - to = { - width: destWidth, - height: destHeight, - 'margin-top': M.ceil( destHeight / 2 ) *- 1, - 'margin-left': M.ceil( destWidth / 2 ) *- 1 - }; - - // if rescale event, don't animate - if ( event ) { - $( lightbox.elems.box ).css( to ); - } else { - $( lightbox.elems.box ).animate( to, { - duration: self._options.lightboxTransitionSpeed, - easing: self._options.easing, - complete: function() { - var image = lightbox.image, - speed = self._options.lightboxFadeSpeed; - - self.trigger({ - type: Galleria.LIGHTBOX_IMAGE, - imageTarget: image.image - }); - - $( image.container ).show(); - - $( image.image ).animate({ opacity: 1 }, speed); - Utils.show( lightbox.elems.info, speed ); - } - }); - } - }, - - hide: function() { - - // remove the image - lightbox.image.image = null; - - $win.off('resize', lightbox.rescale); - - $( lightbox.elems.box ).hide().find( 'iframe' ).remove(); - - Utils.hide( lightbox.elems.info ); - - self.detachKeyboard(); - self.attachKeyboard( lightbox.keymap ); - - lightbox.keymap = false; - - Utils.hide( lightbox.elems.overlay, 200, function() { - $( this ).hide().css( 'opacity', self._options.overlayOpacity ); - self.trigger( Galleria.LIGHTBOX_CLOSE ); - }); - }, - - showNext: function() { - lightbox.show( self.getNext( lightbox.active ) ); - }, - - showPrev: function() { - lightbox.show( self.getPrev( lightbox.active ) ); - }, - - show: function(index) { - - lightbox.active = index = typeof index === 'number' ? index : self.getIndex() || 0; - - if ( !lightbox.initialized ) { - lightbox.init(); - } - - // trigger the event - self.trigger( Galleria.LIGHTBOX_OPEN ); - - // temporarily attach some keys - // save the old ones first in a cloned object - if ( !lightbox.keymap ) { - - lightbox.keymap = $.extend({}, self._keyboard.map); - - self.attachKeyboard({ - escape: lightbox.hide, - right: lightbox.showNext, - left: lightbox.showPrev - }); - } - - $win.off('resize', lightbox.rescale ); - - var data = self.getData(index), - total = self.getDataLength(), - n = self.getNext( index ), - ndata, p, i; - - Utils.hide( lightbox.elems.info ); - - try { - for ( i = self._options.preload; i > 0; i-- ) { - p = new Galleria.Picture(); - ndata = self.getData( n ); - p.preload( ndata.big ? ndata.big : ndata.image ); - n = self.getNext( n ); - } - } catch(e) {} - - lightbox.image.isIframe = ( data.iframe && !data.image ); - - $( lightbox.elems.box ).toggleClass( 'iframe', lightbox.image.isIframe ); - - $( lightbox.image.container ).find( '.galleria-videoicon' ).remove(); - - lightbox.image.load( data.big || data.image || data.iframe, function( image ) { - - if ( image.isIframe ) { - - var cw = $(window).width(), - ch = $(window).height(); - - if ( image.video && self._options.maxVideoSize ) { - var r = M.min( self._options.maxVideoSize/cw, self._options.maxVideoSize/ch ); - if ( r < 1 ) { - cw *= r; - ch *= r; - } - } - lightbox.width = cw; - lightbox.height = ch; - - } else { - lightbox.width = image.original.width; - lightbox.height = image.original.height; - } - - $( image.image ).css({ - width: image.isIframe ? '100%' : '100.1%', - height: image.isIframe ? '100%' : '100.1%', - top: 0, - bottom: 0, - zIndex: 99998, - opacity: 0, - visibility: 'visible' - }).parent().height('100%'); - - lightbox.elems.title.innerHTML = data.title || ''; - lightbox.elems.counter.innerHTML = (index + 1) + ' / ' + total; - $win.resize( lightbox.rescale ); - lightbox.rescale(); - - if( data.image && data.iframe ) { - - $( lightbox.elems.box ).addClass('iframe'); - - if ( data.video ) { - var $icon = _playIcon( image.container ).hide(); - window.setTimeout(function() { - $icon.fadeIn(200); - }, 200); - } - - $( image.image ).css( 'cursor', 'pointer' ).mouseup((function(data, image) { - return function(e) { - $( lightbox.image.container ).find( '.galleria-videoicon' ).remove(); - e.preventDefault(); - image.isIframe = true; - image.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { - width: '100%', - height: IE < 8 ? $( lightbox.image.container ).height() : '100%' - }); - }; - }(data, image))); - } - }); - - $( lightbox.elems.overlay ).show().css( 'visibility', 'visible' ); - $( lightbox.elems.box ).show(); - } - }; - - // the internal timeouts object - // provides helper methods for controlling timeouts - - var _timer = this._timer = { - - trunk: {}, - - add: function( id, fn, delay, loop ) { - id = id || new Date().getTime(); - loop = loop || false; - this.clear( id ); - if ( loop ) { - var old = fn; - fn = function() { - old(); - _timer.add( id, fn, delay ); - }; - } - this.trunk[ id ] = window.setTimeout( fn, delay ); - }, - - clear: function( id ) { - - var del = function( i ) { - window.clearTimeout( this.trunk[ i ] ); - delete this.trunk[ i ]; - }, i; - - if ( !!id && id in this.trunk ) { - del.call( this, id ); - - } else if ( typeof id === 'undefined' ) { - for ( i in this.trunk ) { - if ( this.trunk.hasOwnProperty( i ) ) { - del.call( this, i ); - } - } - } - } - }; - - return this; -}; - -// end Galleria constructor - -Galleria.prototype = { - - // bring back the constructor reference - - constructor: Galleria, - - /** - Use this function to initialize the gallery and start loading. - Should only be called once per instance. - - @param {HTMLElement} target The target element - @param {Object} options The gallery options - - @returns Instance - */ - - init: function( target, options ) { - - options = _legacyOptions( options ); - - // save the original ingredients - this._original = { - target: target, - options: options, - data: null - }; - - // save the target here - this._target = this._dom.target = target.nodeName ? target : $( target ).get(0); - - // save the original content for destruction - this._original.html = this._target.innerHTML; - - // push the instance - _instances.push( this ); - - // raise error if no target is detected - if ( !this._target ) { - Galleria.raise('Target not found', true); - return; - } - - // apply options - this._options = { - autoplay: false, - carousel: true, - carouselFollow: true, // legacy, deprecate at 1.3 - carouselSpeed: 400, - carouselSteps: 'auto', - clicknext: false, - dailymotion: { - foreground: '%23EEEEEE', - highlight: '%235BCEC5', - background: '%23222222', - logo: 0, - hideInfos: 1 - }, - dataConfig : function( elem ) { return {}; }, - dataSelector: 'img', - dataSort: false, - dataSource: this._target, - debug: undef, - dummy: undef, // 1.2.5 - easing: 'galleria', - extend: function(options) {}, - fullscreenCrop: undef, // 1.2.5 - fullscreenDoubleTap: true, // 1.2.4 toggles fullscreen on double-tap for touch devices - fullscreenTransition: undef, // 1.2.6 - height: 0, - idleMode: true, // 1.2.4 toggles idleMode - idleTime: 3000, - idleSpeed: 200, - imageCrop: false, - imageMargin: 0, - imagePan: false, - imagePanSmoothness: 12, - imagePosition: '50%', - imageTimeout: undef, // 1.2.5 - initialTransition: undef, // 1.2.4, replaces transitionInitial - keepSource: false, - layerFollow: true, // 1.2.5 - lightbox: false, // 1.2.3 - lightboxFadeSpeed: 200, - lightboxTransitionSpeed: 200, - linkSourceImages: true, - maxScaleRatio: undef, - maxVideoSize: undef, // 1.2.9 - minScaleRatio: undef, // deprecated in 1.2.9 - overlayOpacity: 0.85, - overlayBackground: '#0b0b0b', - pauseOnInteraction: true, - popupLinks: false, - preload: 2, - queue: true, - responsive: true, - show: 0, - showInfo: true, - showCounter: true, - showImagenav: true, - swipe: 'auto', // 1.2.4 -> revised in 1.3 -> changed type in 1.3.5 - theme: null, - thumbCrop: true, - thumbEventType: 'click:fast', - thumbMargin: 0, - thumbQuality: 'auto', - thumbDisplayOrder: true, // 1.2.8 - thumbPosition: '50%', // 1.3 - thumbnails: true, - touchTransition: undef, // 1.2.6 - transition: 'fade', - transitionInitial: undef, // legacy, deprecate in 1.3. Use initialTransition instead. - transitionSpeed: 400, - trueFullscreen: true, // 1.2.7 - useCanvas: false, // 1.2.4 - variation: '', // 1.3.2 - videoPoster: true, // 1.3 - vimeo: { - title: 0, - byline: 0, - portrait: 0, - color: 'aaaaaa' - }, - wait: 5000, // 1.2.7 - width: 'auto', - youtube: { - modestbranding: 1, - autohide: 1, - color: 'white', - hd: 1, - rel: 0, - showinfo: 0 - } - }; - - // legacy support for transitionInitial - this._options.initialTransition = this._options.initialTransition || this._options.transitionInitial; - - if ( options ) { - - // turn off debug - if ( options.debug === false ) { - DEBUG = false; - } - - // set timeout - if ( typeof options.imageTimeout === 'number' ) { - TIMEOUT = options.imageTimeout; - } - - // set dummy - if ( typeof options.dummy === 'string' ) { - DUMMY = options.dummy; - } - - // set theme - if ( typeof options.theme == 'string' ) { - this._options.theme = options.theme; - } - } - - // hide all content - $( this._target ).children().hide(); - - // Warn for quirks mode - if ( Galleria.QUIRK ) { - Galleria.raise('Your page is in Quirks mode, Galleria may not render correctly. Please validate your HTML and add a correct doctype.'); - } - - // now we just have to wait for the theme... - // first check if it has already loaded - if ( _loadedThemes.length ) { - if ( this._options.theme ) { - for ( var i=0; i<_loadedThemes.length; i++ ) { - if( this._options.theme === _loadedThemes[i].name ) { - this.theme = _loadedThemes[i]; - break; - } - } - } else { - // if no theme sepcified, apply the first loaded theme - this.theme = _loadedThemes[0]; - } - } - - if ( typeof this.theme == 'object' ) { - this._init(); - } else { - // if no theme is loaded yet, push the instance into a pool and run it when the theme is ready - _pool.push( this ); - } - - return this; - }, - - // this method should only be called once per instance - // for manipulation of data, use the .load method - - _init: function() { - - var self = this, - options = this._options; - - if ( this._initialized ) { - Galleria.raise( 'Init failed: Gallery instance already initialized.' ); - return this; - } - - this._initialized = true; - - if ( !this.theme ) { - Galleria.raise( 'Init failed: No theme found.', true ); - return this; - } - - // merge the theme & caller options - $.extend( true, options, this.theme.defaults, this._original.options, Galleria.configure.options ); - - // internally we use boolean for swipe - options.swipe = (function(s) { - - if ( s == 'enforced' ) { return true; } - - // legacy patch - if( s === false || s == 'disabled' ) { return false; } - - return !!Galleria.TOUCH; - - }( options.swipe )); - - // disable options that arent compatible with swipe - if ( options.swipe ) { - options.clicknext = false; - options.imagePan = false; - } - - // check for canvas support - (function( can ) { - if ( !( 'getContext' in can ) ) { - can = null; - return; - } - _canvas = _canvas || { - elem: can, - context: can.getContext( '2d' ), - cache: {}, - length: 0 - }; - }( doc.createElement( 'canvas' ) ) ); - - // bind the gallery to run when data is ready - this.bind( Galleria.DATA, function() { - - // remove big if total pixels are less than 1024 (most phones) - if ( window.screen && window.screen.width && Array.prototype.forEach ) { - - this._data.forEach(function(data) { - - var density = 'devicePixelRatio' in window ? window.devicePixelRatio : 1, - m = M.max( window.screen.width, window.screen.height ); - - if ( m*density < 1024 ) { - data.big = data.image; - } - }); - } - - // save the new data - this._original.data = this._data; - - // lets show the counter here - this.get('total').innerHTML = this.getDataLength(); - - // cache the container - var $container = this.$( 'container' ); - - // set ratio if height is < 2 - if ( self._options.height < 2 ) { - self._userRatio = self._ratio = self._options.height; - } - - // the gallery is ready, let's just wait for the css - var num = { width: 0, height: 0 }; - var testHeight = function() { - return self.$( 'stage' ).height(); - }; - - // check container and thumbnail height - Utils.wait({ - until: function() { - - // keep trying to get the value - num = self._getWH(); - $container.width( num.width ).height( num.height ); - return testHeight() && num.width && num.height > 50; - - }, - success: function() { - - self._width = num.width; - self._height = num.height; - self._ratio = self._ratio || num.height/num.width; - - // for some strange reason, webkit needs a single setTimeout to play ball - if ( Galleria.WEBKIT ) { - window.setTimeout( function() { - self._run(); - }, 1); - } else { - self._run(); - } - }, - error: function() { - - // Height was probably not set, raise hard errors - - if ( testHeight() ) { - Galleria.raise('Could not extract sufficient width/height of the gallery container. Traced measures: width:' + num.width + 'px, height: ' + num.height + 'px.', true); - } else { - Galleria.raise('Could not extract a stage height from the CSS. Traced height: ' + testHeight() + 'px.', true); - } - }, - timeout: typeof this._options.wait == 'number' ? this._options.wait : false - }); - }); - - // build the gallery frame - this.append({ - 'info-text' : - ['info-title', 'info-description'], - 'info' : - ['info-text'], - 'image-nav' : - ['image-nav-right', 'image-nav-left'], - 'stage' : - ['images', 'loader', 'counter', 'image-nav'], - 'thumbnails-list' : - ['thumbnails'], - 'thumbnails-container' : - ['thumb-nav-left', 'thumbnails-list', 'thumb-nav-right'], - 'container' : - ['stage', 'thumbnails-container', 'info', 'tooltip'] - }); - - Utils.hide( this.$( 'counter' ).append( - this.get( 'current' ), - doc.createTextNode(' / '), - this.get( 'total' ) - ) ); - - this.setCounter('–'); - - Utils.hide( self.get('tooltip') ); - - // add a notouch class on the container to prevent unwanted :hovers on touch devices - this.$( 'container' ).addClass([ - ( Galleria.TOUCH ? 'touch' : 'notouch' ), - this._options.variation, - 'galleria-theme-'+this.theme.name - ].join(' ')); - - // add images to the controls - if ( !this._options.swipe ) { - $.each( new Array(2), function( i ) { - - // create a new Picture instance - var image = new Galleria.Picture(); - - // apply some styles, create & prepend overlay - $( image.container ).css({ - position: 'absolute', - top: 0, - left: 0 - }).prepend( self._layers[i] = $( Utils.create('galleria-layer') ).css({ - position: 'absolute', - top:0, left:0, right:0, bottom:0, - zIndex:2 - })[0] ); - - // append the image - self.$( 'images' ).append( image.container ); - - // reload the controls - self._controls[i] = image; - - // build a frame - var frame = new Galleria.Picture(); - frame.isIframe = true; - - $( frame.container ).attr('class', 'galleria-frame').css({ - position: 'absolute', - top: 0, - left: 0, - zIndex: 4, - background: '#000', - display: 'none' - }).appendTo( image.container ); - - self._controls.frames[i] = frame; - - }); - } - - // some forced generic styling - this.$( 'images' ).css({ - position: 'relative', - top: 0, - left: 0, - width: '100%', - height: '100%' - }); - - if ( options.swipe ) { - this.$( 'images' ).css({ - position: 'absolute', - top: 0, - left: 0, - width: 0, - height: '100%' - }); - this.finger = new Galleria.Finger(this.get('stage'), { - onchange: function(page) { - self.pause().show(page); - }, - oncomplete: function(page) { - - var index = M.max( 0, M.min( parseInt( page, 10 ), self.getDataLength() - 1 ) ), - data = self.getData(index); - - $( self._thumbnails[ index ].container ) - .addClass( 'active' ) - .siblings( '.active' ) - .removeClass( 'active' ); - - if ( !data ) { - return; - } - - // remove video iframes - self.$( 'images' ).find( '.galleria-frame' ).css('opacity', 0).hide().find( 'iframe' ).remove(); - - if ( self._options.carousel && self._options.carouselFollow ) { - self._carousel.follow( index ); - } - } - }); - this.bind( Galleria.RESCALE, function() { - this.finger.setup(); - }); - this.$('stage').on('click', function(e) { - var data = self.getData(); - if ( !data ) { - return; - } - if ( data.iframe ) { - - if ( self.isPlaying() ) { - self.pause(); - } - var frame = self._controls.frames[ self._active ], - w = self._stageWidth, - h = self._stageHeight; - - if ( $( frame.container ).find( 'iframe' ).length ) { - return; - } - - $( frame.container ).css({ - width: w, - height: h, - opacity: 0 - }).show().animate({ - opacity: 1 - }, 200); - - window.setTimeout(function() { - frame.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { - width: w, - height: h - }, function( frame ) { - self.$( 'container' ).addClass( 'videoplay' ); - frame.scale({ - width: self._stageWidth, - height: self._stageHeight, - iframelimit: data.video ? self._options.maxVideoSize : undef - }); - }); - }, 100); - - return; - } - - if ( data.link ) { - if ( self._options.popupLinks ) { - var win = window.open( data.link, '_blank' ); - } else { - window.location.href = data.link; - } - return; - } - }); - this.bind( Galleria.IMAGE, function(e) { - - self.setCounter( e.index ); - self.setInfo( e.index ); - - var next = this.getNext(), - prev = this.getPrev(); - - var preloads = [prev,next]; - preloads.push(this.getNext(next), this.getPrev(prev), self._controls.slides.length-1); - - var filtered = []; - - $.each(preloads, function(i, val) { - if ( $.inArray(val, filtered) == -1 ) { - filtered.push(val); - } - }); - - $.each(filtered, function(i, loadme) { - var d = self.getData(loadme), - img = self._controls.slides[loadme], - src = self.isFullscreen() && d.big ? d.big : ( d.image || d.iframe ); - - if ( d.iframe && !d.image ) { - img.isIframe = true; - } - - if ( !img.ready ) { - self._controls.slides[loadme].load(src, function(img) { - if ( !img.isIframe ) { - $(img.image).css('visibility', 'hidden'); - } - self._scaleImage(img, { - complete: function(img) { - if ( !img.isIframe ) { - $(img.image).css({ - opacity: 0, - visibility: 'visible' - }).animate({ - opacity: 1 - }, 200); - } - } - }); - }); - } - }); - }); - } - - this.$( 'thumbnails, thumbnails-list' ).css({ - overflow: 'hidden', - position: 'relative' - }); - - // bind image navigation arrows - this.$( 'image-nav-right, image-nav-left' ).on( 'click:fast', function(e) { - - // pause if options is set - if ( options.pauseOnInteraction ) { - self.pause(); - } - - // navigate - var fn = /right/.test( this.className ) ? 'next' : 'prev'; - self[ fn ](); - - }).on('click', function(e) { - - e.preventDefault(); - - // tune the clicknext option - if ( options.clicknext || options.swipe ) { - e.stopPropagation(); - } - }); - - // hide controls if chosen to - $.each( ['info','counter','image-nav'], function( i, el ) { - if ( options[ 'show' + el.substr(0,1).toUpperCase() + el.substr(1).replace(/-/,'') ] === false ) { - Utils.moveOut( self.get( el.toLowerCase() ) ); - } - }); - - // load up target content - this.load(); - - // now it's usually safe to remove the content - // IE will never stop loading if we remove it, so let's keep it hidden for IE (it's usually fast enough anyway) - if ( !options.keepSource && !IE ) { - this._target.innerHTML = ''; - } - - // re-append the errors, if they happened before clearing - if ( this.get( 'errors' ) ) { - this.appendChild( 'target', 'errors' ); - } - - // append the gallery frame - this.appendChild( 'target', 'container' ); - - // parse the carousel on each thumb load - if ( options.carousel ) { - var count = 0, - show = options.show; - this.bind( Galleria.THUMBNAIL, function() { - this.updateCarousel(); - if ( ++count == this.getDataLength() && typeof show == 'number' && show > 0 ) { - this._carousel.follow( show ); - } - }); - } - - // bind window resize for responsiveness - if ( options.responsive ) { - $win.on( 'resize', function() { - if ( !self.isFullscreen() ) { - self.resize(); - } - }); - } - - // double-tap/click fullscreen toggle - - if ( options.fullscreenDoubleTap ) { - - this.$( 'stage' ).on( 'touchstart', (function() { - var last, cx, cy, lx, ly, now, - getData = function(e) { - return e.originalEvent.touches ? e.originalEvent.touches[0] : e; - }; - self.$( 'stage' ).on('touchmove', function() { - last = 0; - }); - return function(e) { - if( /(-left|-right)/.test(e.target.className) ) { - return; - } - now = Utils.timestamp(); - cx = getData(e).pageX; - cy = getData(e).pageY; - if ( e.originalEvent.touches.length < 2 && ( now - last < 300 ) && ( cx - lx < 20) && ( cy - ly < 20) ) { - self.toggleFullscreen(); - e.preventDefault(); - return; - } - last = now; - lx = cx; - ly = cy; - }; - }())); - } - - // bind the ons - $.each( Galleria.on.binds, function(i, bind) { - // check if already bound - if ( $.inArray( bind.hash, self._binds ) == -1 ) { - self.bind( bind.type, bind.callback ); - } - }); - - return this; - }, - - addTimer : function() { - this._timer.add.apply( this._timer, Utils.array( arguments ) ); - return this; - }, - - clearTimer : function() { - this._timer.clear.apply( this._timer, Utils.array( arguments ) ); - return this; - }, - - // parse width & height from CSS or options - - _getWH : function() { - - var $container = this.$( 'container' ), - $target = this.$( 'target' ), - self = this, - num = {}, - arr; - - $.each(['width', 'height'], function( i, m ) { - - // first check if options is set - if ( self._options[ m ] && typeof self._options[ m ] === 'number') { - num[ m ] = self._options[ m ]; - } else { - - arr = [ - Utils.parseValue( $container.css( m ) ), // the container css height - Utils.parseValue( $target.css( m ) ), // the target css height - $container[ m ](), // the container jQuery method - $target[ m ]() // the target jQuery method - ]; - - // if first time, include the min-width & min-height - if ( !self[ '_'+m ] ) { - arr.splice(arr.length, - Utils.parseValue( $container.css( 'min-'+m ) ), - Utils.parseValue( $target.css( 'min-'+m ) ) - ); - } - - // else extract the measures from different sources and grab the highest value - num[ m ] = M.max.apply( M, arr ); - } - }); - - // allow setting a height ratio instead of exact value - // useful when doing responsive galleries - - if ( self._userRatio ) { - num.height = num.width * self._userRatio; - } - - return num; - }, - - // Creates the thumbnails and carousel - // can be used at any time, f.ex when the data object is manipulated - // push is an optional argument with pushed images - - _createThumbnails : function( push ) { - - this.get( 'total' ).innerHTML = this.getDataLength(); - - var src, - thumb, - data, - - $container, - - self = this, - o = this._options, - - i = push ? this._data.length - push.length : 0, - chunk = i, - - thumbchunk = [], - loadindex = 0, - - gif = IE < 8 ? 'http://upload.wikimedia.org/wikipedia/commons/c/c0/Blank.gif' : - 'data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D', - - // get previously active thumbnail, if exists - active = (function() { - var a = self.$('thumbnails').find('.active'); - if ( !a.length ) { - return false; - } - return a.find('img').attr('src'); - }()), - - // cache the thumbnail option - optval = typeof o.thumbnails === 'string' ? o.thumbnails.toLowerCase() : null, - - // move some data into the instance - // for some reason, jQuery cant handle css(property) when zooming in FF, breaking the gallery - // so we resort to getComputedStyle for browsers who support it - getStyle = function( prop ) { - return doc.defaultView && doc.defaultView.getComputedStyle ? - doc.defaultView.getComputedStyle( thumb.container, null )[ prop ] : - $container.css( prop ); - }, - - fake = function(image, index, container) { - return function() { - $( container ).append( image ); - self.trigger({ - type: Galleria.THUMBNAIL, - thumbTarget: image, - index: index, - galleriaData: self.getData( index ) - }); - }; - }, - - onThumbEvent = function( e ) { - - // pause if option is set - if ( o.pauseOnInteraction ) { - self.pause(); - } - - // extract the index from the data - var index = $( e.currentTarget ).data( 'index' ); - if ( self.getIndex() !== index ) { - self.show( index ); - } - - e.preventDefault(); - }, - - thumbComplete = function( thumb, callback ) { - - $( thumb.container ).css( 'visibility', 'visible' ); - self.trigger({ - type: Galleria.THUMBNAIL, - thumbTarget: thumb.image, - index: thumb.data.order, - galleriaData: self.getData( thumb.data.order ) - }); - - if ( typeof callback == 'function' ) { - callback.call( self, thumb ); - } - }, - - onThumbLoad = function( thumb, callback ) { - - // scale when ready - thumb.scale({ - width: thumb.data.width, - height: thumb.data.height, - crop: o.thumbCrop, - margin: o.thumbMargin, - canvas: o.useCanvas, - position: o.thumbPosition, - complete: function( thumb ) { - - // shrink thumbnails to fit - var top = ['left', 'top'], - arr = ['Width', 'Height'], - m, - css, - data = self.getData( thumb.index ); - - // calculate shrinked positions - $.each(arr, function( i, measure ) { - m = measure.toLowerCase(); - if ( (o.thumbCrop !== true || o.thumbCrop === m ) ) { - css = {}; - css[ m ] = thumb[ m ]; - $( thumb.container ).css( css ); - css = {}; - css[ top[ i ] ] = 0; - $( thumb.image ).css( css ); - } - - // cache outer measures - thumb[ 'outer' + measure ] = $( thumb.container )[ 'outer' + measure ]( true ); - }); - - // set high quality if downscale is moderate - Utils.toggleQuality( thumb.image, - o.thumbQuality === true || - ( o.thumbQuality === 'auto' && thumb.original.width < thumb.width * 3 ) - ); - - if ( o.thumbDisplayOrder && !thumb.lazy ) { - - $.each( thumbchunk, function( i, th ) { - if ( i === loadindex && th.ready && !th.displayed ) { - - loadindex++; - th.displayed = true; - - thumbComplete( th, callback ); - - return; - } - }); - } else { - thumbComplete( thumb, callback ); - } - } - }); - }; - - if ( !push ) { - this._thumbnails = []; - this.$( 'thumbnails' ).empty(); - } - - // loop through data and create thumbnails - for( ; this._data[ i ]; i++ ) { - - data = this._data[ i ]; - - // get source from thumb or image - src = data.thumb || data.image; - - if ( ( o.thumbnails === true || optval == 'lazy' ) && ( data.thumb || data.image ) ) { - - // add a new Picture instance - thumb = new Galleria.Picture(i); - - // save the index - thumb.index = i; - - // flag displayed - thumb.displayed = false; - - // flag lazy - thumb.lazy = false; - - // flag video - thumb.video = false; - - // append the thumbnail - this.$( 'thumbnails' ).append( thumb.container ); - - // cache the container - $container = $( thumb.container ); - - // hide it - $container.css( 'visibility', 'hidden' ); - - thumb.data = { - width : Utils.parseValue( getStyle( 'width' ) ), - height : Utils.parseValue( getStyle( 'height' ) ), - order : i, - src : src - }; - - // grab & reset size for smoother thumbnail loads - if ( o.thumbCrop !== true ) { - $container.css( { width: 'auto', height: 'auto' } ); - } else { - $container.css( { width: thumb.data.width, height: thumb.data.height } ); - } - - // load the thumbnail - if ( optval == 'lazy' ) { - - $container.addClass( 'lazy' ); - - thumb.lazy = true; - - thumb.load( gif, { - height: thumb.data.height, - width: thumb.data.width - }); - - } else { - thumb.load( src, onThumbLoad ); - } - - // preload all images here - if ( o.preload === 'all' ) { - thumb.preload( data.image ); - } - - // create empty spans if thumbnails is set to 'empty' - } else if ( ( data.iframe && optval !== null ) || optval === 'empty' || optval === 'numbers' ) { - thumb = { - container: Utils.create( 'galleria-image' ), - image: Utils.create( 'img', 'span' ), - ready: true, - data: { - order: i - } - }; - - // create numbered thumbnails - if ( optval === 'numbers' ) { - $( thumb.image ).text( i + 1 ); - } - - if ( data.iframe ) { - $( thumb.image ).addClass( 'iframe' ); - } - - this.$( 'thumbnails' ).append( thumb.container ); - - // we need to "fake" a loading delay before we append and trigger - // 50+ should be enough - - window.setTimeout( ( fake )( thumb.image, i, thumb.container ), 50 + ( i*20 ) ); - - // create null object to silent errors - } else { - thumb = { - container: null, - image: null - }; - } - - // add events for thumbnails - // you can control the event type using thumb_event_type - // we'll add the same event to the source if it's kept - - $( thumb.container ).add( o.keepSource && o.linkSourceImages ? data.original : null ) - .data('index', i).on( o.thumbEventType, onThumbEvent ) - .data('thumbload', onThumbLoad); - - if (active === src) { - $( thumb.container ).addClass( 'active' ); - } - - this._thumbnails.push( thumb ); - } - - thumbchunk = this._thumbnails.slice( chunk ); - - return this; - }, - - /** - Lazy-loads thumbnails. - You can call this method to load lazy thumbnails at run time - - @param {Array|Number} index Index or array of indexes of thumbnails to be loaded - @param {Function} complete Callback that is called when all lazy thumbnails have been loaded - - @returns Instance - */ - - lazyLoad: function( index, complete ) { - - var arr = index.constructor == Array ? index : [ index ], - self = this, - loaded = 0; - - $.each( arr, function(i, ind) { - - if ( ind > self._thumbnails.length - 1 ) { - return; - } - - var thumb = self._thumbnails[ ind ], - data = thumb.data, - callback = function() { - if ( ++loaded == arr.length && typeof complete == 'function' ) { - complete.call( self ); - } - }, - thumbload = $( thumb.container ).data( 'thumbload' ); - if ( thumb.video ) { - thumbload.call( self, thumb, callback ); - } else { - thumb.load( data.src , function( thumb ) { - thumbload.call( self, thumb, callback ); - }); - } - }); - - return this; - - }, - - /** - Lazy-loads thumbnails in chunks. - This method automatcally chops up the loading process of many thumbnails into chunks - - @param {Number} size Size of each chunk to be loaded - @param {Number} [delay] Delay between each loads - - @returns Instance - */ - - lazyLoadChunks: function( size, delay ) { - - var len = this.getDataLength(), - i = 0, - n = 0, - arr = [], - temp = [], - self = this; - - delay = delay || 0; - - for( ; i 50 ); // what is an acceptable height? - }, - - success: function() { - - // save the instance - _galleries.push( self ); - - // postrun some stuff after the gallery is ready - - // create the touch slider - if ( self._options.swipe ) { - - var $images = self.$( 'images' ).width( self.getDataLength() * self._stageWidth ); - $.each( new Array( self.getDataLength() ), function(i) { - - var image = new Galleria.Picture(), - data = self.getData(i); - - $( image.container ).css({ - position: 'absolute', - top: 0, - left: self._stageWidth*i - }).prepend( self._layers[i] = $( Utils.create('galleria-layer') ).css({ - position: 'absolute', - top:0, left:0, right:0, bottom:0, - zIndex:2 - })[0] ).appendTo( $images ); - - if( data.video ) { - _playIcon( image.container ); - } - - self._controls.slides.push(image); - - var frame = new Galleria.Picture(); - frame.isIframe = true; - - $( frame.container ).attr('class', 'galleria-frame').css({ - position: 'absolute', - top: 0, - left: 0, - zIndex: 4, - background: '#000', - display: 'none' - }).appendTo( image.container ); - - self._controls.frames.push(frame); - }); - - self.finger.setup(); - } - - // show counter - Utils.show( self.get('counter') ); - - // bind carousel nav - if ( self._options.carousel ) { - self._carousel.bindControls(); - } - - // start autoplay - if ( self._options.autoplay ) { - - self.pause(); - - if ( typeof self._options.autoplay === 'number' ) { - self._playtime = self._options.autoplay; - } - - self._playing = true; - } - // if second load, just do the show and return - if ( self._firstrun ) { - - if ( self._options.autoplay ) { - self.trigger( Galleria.PLAY ); - } - - if ( typeof self._options.show === 'number' ) { - self.show( self._options.show ); - } - return; - } - - self._firstrun = true; - - // initialize the History plugin - if ( Galleria.History ) { - - // bind the show method - Galleria.History.change(function( value ) { - - // if ID is NaN, the user pressed back from the first image - // return to previous address - if ( isNaN( value ) ) { - window.history.go(-1); - - // else show the image - } else { - self.show( value, undef, true ); - } - }); - } - - self.trigger( Galleria.READY ); - - // call the theme init method - self.theme.init.call( self, self._options ); - - // Trigger Galleria.ready - $.each( Galleria.ready.callbacks, function(i ,fn) { - if ( typeof fn == 'function' ) { - fn.call( self, self._options ); - } - }); - - // call the extend option - self._options.extend.call( self, self._options ); - - // show the initial image - // first test for permalinks in history - if ( /^[0-9]{1,4}$/.test( HASH ) && Galleria.History ) { - self.show( HASH, undef, true ); - - } else if( self._data[ self._options.show ] ) { - self.show( self._options.show ); - } - - // play trigger - if ( self._options.autoplay ) { - self.trigger( Galleria.PLAY ); - } - }, - - error: function() { - Galleria.raise('Stage width or height is too small to show the gallery. Traced measures: width:' + self._stageWidth + 'px, height: ' + self._stageHeight + 'px.', true); - } - - }); - }, - - /** - Loads data into the gallery. - You can call this method on an existing gallery to reload the gallery with new data. - - @param {Array|string} [source] Optional JSON array of data or selector of where to find data in the document. - Defaults to the Galleria target or dataSource option. - - @param {string} [selector] Optional element selector of what elements to parse. - Defaults to 'img'. - - @param {Function} [config] Optional function to modify the data extraction proceedure from the selector. - See the dataConfig option for more information. - - @returns Instance - */ - - load : function( source, selector, config ) { - - var self = this, - o = this._options; - - // empty the data array - this._data = []; - - // empty the thumbnails - this._thumbnails = []; - this.$('thumbnails').empty(); - - // shorten the arguments - if ( typeof selector === 'function' ) { - config = selector; - selector = null; - } - - // use the source set by target - source = source || o.dataSource; - - // use selector set by option - selector = selector || o.dataSelector; - - // use the dataConfig set by option - config = config || o.dataConfig; - - // if source is a true object, make it into an array - if( $.isPlainObject( source ) ) { - source = [source]; - } - - // check if the data is an array already - if ( $.isArray( source ) ) { - if ( this.validate( source ) ) { - this._data = source; - } else { - Galleria.raise( 'Load failed: JSON Array not valid.' ); - } - } else { - - // add .video and .iframe to the selector (1.2.7) - selector += ',.video,.iframe'; - - // loop through images and set data - $( source ).find( selector ).each( function( i, elem ) { - - elem = $( elem ); - var data = {}, - parent = elem.parent(), - href = parent.attr( 'href' ), - rel = parent.attr( 'rel' ); - - if( href && ( elem[0].nodeName == 'IMG' || elem.hasClass('video') ) && _videoTest( href ) ) { - data.video = href; - } else if( href && elem.hasClass('iframe') ) { - data.iframe = href; - } else { - data.image = data.big = href; - } - - if ( rel ) { - data.big = rel; - } - - // alternative extraction from HTML5 data attribute, added in 1.2.7 - $.each( 'big title description link layer image'.split(' '), function( i, val ) { - if ( elem.data(val) ) { - data[ val ] = elem.data(val).toString(); - } - }); - - if ( !data.big ) { - data.big = data.image; - } - - // mix default extractions with the hrefs and config - // and push it into the data array - self._data.push( $.extend({ - - title: elem.attr('title') || '', - thumb: elem.attr('src'), - image: elem.attr('src'), - big: elem.attr('src'), - description: elem.attr('alt') || '', - link: elem.attr('longdesc'), - original: elem.get(0) // saved as a reference - - }, data, config( elem ) ) ); - - }); - } - - if ( typeof o.dataSort == 'function' ) { - protoArray.sort.call( this._data, o.dataSort ); - } else if ( o.dataSort == 'random' ) { - this._data.sort( function() { - return M.round(M.random())-0.5; - }); - } - - // trigger the DATA event and return - if ( this.getDataLength() ) { - this._parseData( function() { - this.trigger( Galleria.DATA ); - } ); - } - return this; - - }, - - // make sure the data works properly - _parseData : function( callback ) { - - var self = this, - current, - ready = false, - onload = function() { - var complete = true; - $.each( self._data, function( i, data ) { - if ( data.loading ) { - complete = false; - return false; - } - }); - if ( complete && !ready ) { - ready = true; - callback.call( self ); - } - }; - - $.each( this._data, function( i, data ) { - - current = self._data[ i ]; - - // copy image as thumb if no thumb exists - if ( 'thumb' in data === false ) { - current.thumb = data.image; - } - // copy image as big image if no biggie exists - if ( !data.big ) { - current.big = data.image; - } - // parse video - if ( 'video' in data ) { - var result = _videoTest( data.video ); - - if ( result ) { - current.iframe = new Video(result.provider, result.id ).embed() + (function() { - - // add options - if ( typeof self._options[ result.provider ] == 'object' ) { - var str = '?', arr = []; - $.each( self._options[ result.provider ], function( key, val ) { - arr.push( key + '=' + val ); - }); - - // small youtube specifics, perhaps move to _video later - if ( result.provider == 'youtube' ) { - arr = ['wmode=opaque'].concat(arr); - } - return str + arr.join('&'); - } - return ''; - }()); - - // pre-fetch video providers media - - if( !current.thumb || !current.image ) { - $.each( ['thumb', 'image'], function( i, type ) { - if ( type == 'image' && !self._options.videoPoster ) { - current.image = undef; - return; - } - var video = new Video( result.provider, result.id ); - if ( !current[ type ] ) { - current.loading = true; - video.getMedia( type, (function(current, type) { - return function(src) { - current[ type ] = src; - if ( type == 'image' && !current.big ) { - current.big = current.image; - } - delete current.loading; - onload(); - }; - }( current, type ))); - } - }); - } - } - } - }); - - onload(); - - return this; - }, - - /** - Destroy the Galleria instance and recover the original content - - @example this.destroy(); - - @returns Instance - */ - - destroy : function() { - this.$( 'target' ).data( 'galleria', null ); - this.$( 'container' ).off( 'galleria' ); - this.get( 'target' ).innerHTML = this._original.html; - this.clearTimer(); - Utils.removeFromArray( _instances, this ); - Utils.removeFromArray( _galleries, this ); - if ( Galleria._waiters.length ) { - $.each( Galleria._waiters, function( i, w ) { - if ( w ) window.clearTimeout( w ); - }); - } - return this; - }, - - /** - Adds and/or removes images from the gallery - Works just like Array.splice - https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice - - @example this.splice( 2, 4 ); // removes 4 images after the second image - - @returns Instance - */ - - splice : function() { - var self = this, - args = Utils.array( arguments ); - window.setTimeout(function() { - protoArray.splice.apply( self._data, args ); - self._parseData( function() { - self._createThumbnails(); - }); - },2); - return self; - }, - - /** - Append images to the gallery - Works just like Array.push - https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push - - @example this.push({ image: 'image1.jpg' }); // appends the image to the gallery - - @returns Instance - */ - - push : function() { - var self = this, - args = Utils.array( arguments ); - - if ( args.length == 1 && args[0].constructor == Array ) { - args = args[0]; - } - - window.setTimeout(function() { - protoArray.push.apply( self._data, args ); - self._parseData( function() { - self._createThumbnails( args ); - }); - }, 2); - return self; - }, - - _getActive : function() { - return this._controls.getActive(); - }, - - validate : function( data ) { - // todo: validate a custom data array - return true; - }, - - /** - Bind any event to Galleria - - @param {string} type The Event type to listen for - @param {Function} fn The function to execute when the event is triggered - - @example this.bind( 'image', function() { Galleria.log('image shown') }); - - @returns Instance - */ - - bind : function(type, fn) { - - // allow 'image' instead of Galleria.IMAGE - type = _patchEvent( type ); - - this.$( 'container' ).on( type, this.proxy(fn) ); - return this; - }, - - /** - Unbind any event to Galleria - - @param {string} type The Event type to forget - - @returns Instance - */ - - unbind : function(type) { - - type = _patchEvent( type ); - - this.$( 'container' ).off( type ); - return this; - }, - - /** - Manually trigger a Galleria event - - @param {string} type The Event to trigger - - @returns Instance - */ - - trigger : function( type ) { - - type = typeof type === 'object' ? - $.extend( type, { scope: this } ) : - { type: _patchEvent( type ), scope: this }; - - this.$( 'container' ).trigger( type ); - - return this; - }, - - /** - Assign an "idle state" to any element. - The idle state will be applied after a certain amount of idle time - Useful to hide f.ex navigation when the gallery is inactive - - @param {HTMLElement|string} elem The Dom node or selector to apply the idle state to - @param {Object} styles the CSS styles to apply when in idle mode - @param {Object} [from] the CSS styles to apply when in normal - @param {Boolean} [hide] set to true if you want to hide it first - - @example addIdleState( this.get('image-nav'), { opacity: 0 }); - @example addIdleState( '.galleria-image-nav', { top: -200 }, true); - - @returns Instance - */ - - addIdleState: function( elem, styles, from, hide ) { - this._idle.add.apply( this._idle, Utils.array( arguments ) ); - return this; - }, - - /** - Removes any idle state previously set using addIdleState() - - @param {HTMLElement|string} elem The Dom node or selector to remove the idle state from. - - @returns Instance - */ - - removeIdleState: function( elem ) { - this._idle.remove.apply( this._idle, Utils.array( arguments ) ); - return this; - }, - - /** - Force Galleria to enter idle mode. - - @returns Instance - */ - - enterIdleMode: function() { - this._idle.hide(); - return this; - }, - - /** - Force Galleria to exit idle mode. - - @returns Instance - */ - - exitIdleMode: function() { - this._idle.showAll(); - return this; - }, - - /** - Enter FullScreen mode - - @param {Function} callback the function to be executed when the fullscreen mode is fully applied. - - @returns Instance - */ - - enterFullscreen: function( callback ) { - this._fullscreen.enter.apply( this, Utils.array( arguments ) ); - return this; - }, - - /** - Exits FullScreen mode - - @param {Function} callback the function to be executed when the fullscreen mode is fully applied. - - @returns Instance - */ - - exitFullscreen: function( callback ) { - this._fullscreen.exit.apply( this, Utils.array( arguments ) ); - return this; - }, - - /** - Toggle FullScreen mode - - @param {Function} callback the function to be executed when the fullscreen mode is fully applied or removed. - - @returns Instance - */ - - toggleFullscreen: function( callback ) { - this._fullscreen[ this.isFullscreen() ? 'exit' : 'enter'].apply( this, Utils.array( arguments ) ); - return this; - }, - - /** - Adds a tooltip to any element. - You can also call this method with an object as argument with elemID:value pairs to apply tooltips to (see examples) - - @param {HTMLElement} elem The DOM Node to attach the event to - @param {string|Function} value The tooltip message. Can also be a function that returns a string. - - @example this.bindTooltip( this.get('thumbnails'), 'My thumbnails'); - @example this.bindTooltip( this.get('thumbnails'), function() { return 'My thumbs' }); - @example this.bindTooltip( { image_nav: 'Navigation' }); - - @returns Instance - */ - - bindTooltip: function( elem, value ) { - this._tooltip.bind.apply( this._tooltip, Utils.array(arguments) ); - return this; - }, - - /** - Note: this method is deprecated. Use refreshTooltip() instead. - - Redefine a tooltip. - Use this if you want to re-apply a tooltip value to an already bound tooltip element. - - @param {HTMLElement} elem The DOM Node to attach the event to - @param {string|Function} value The tooltip message. Can also be a function that returns a string. - - @returns Instance - */ - - defineTooltip: function( elem, value ) { - this._tooltip.define.apply( this._tooltip, Utils.array(arguments) ); - return this; - }, - - /** - Refresh a tooltip value. - Use this if you want to change the tooltip value at runtime, f.ex if you have a play/pause toggle. - - @param {HTMLElement} elem The DOM Node that has a tooltip that should be refreshed - - @returns Instance - */ - - refreshTooltip: function( elem ) { - this._tooltip.show.apply( this._tooltip, Utils.array(arguments) ); - return this; - }, - - /** - Open a pre-designed lightbox with the currently active image. - You can control some visuals using gallery options. - - @returns Instance - */ - - openLightbox: function() { - this._lightbox.show.apply( this._lightbox, Utils.array( arguments ) ); - return this; - }, - - /** - Close the lightbox. - - @returns Instance - */ - - closeLightbox: function() { - this._lightbox.hide.apply( this._lightbox, Utils.array( arguments ) ); - return this; - }, - - /** - Check if a variation exists - - @returns {Boolean} If the variation has been applied - */ - - hasVariation: function( variation ) { - return $.inArray( variation, this._options.variation.split(/\s+/) ) > -1; - }, - - /** - Get the currently active image element. - - @returns {HTMLElement} The image element - */ - - getActiveImage: function() { - var active = this._getActive(); - return active ? active.image : undef; - }, - - /** - Get the currently active thumbnail element. - - @returns {HTMLElement} The thumbnail element - */ - - getActiveThumb: function() { - return this._thumbnails[ this._active ].image || undef; - }, - - /** - Get the mouse position relative to the gallery container - - @param e The mouse event - - @example - -var gallery = this; -$(document).mousemove(function(e) { - console.log( gallery.getMousePosition(e).x ); -}); - - @returns {Object} Object with x & y of the relative mouse postion - */ - - getMousePosition : function(e) { - return { - x: e.pageX - this.$( 'container' ).offset().left, - y: e.pageY - this.$( 'container' ).offset().top - }; - }, - - /** - Adds a panning effect to the image - - @param [img] The optional image element. If not specified it takes the currently active image - - @returns Instance - */ - - addPan : function( img ) { - - if ( this._options.imageCrop === false ) { - return; - } - - img = $( img || this.getActiveImage() ); - - // define some variables and methods - var self = this, - x = img.width() / 2, - y = img.height() / 2, - destX = parseInt( img.css( 'left' ), 10 ), - destY = parseInt( img.css( 'top' ), 10 ), - curX = destX || 0, - curY = destY || 0, - distX = 0, - distY = 0, - active = false, - ts = Utils.timestamp(), - cache = 0, - move = 0, - - // positions the image - position = function( dist, cur, pos ) { - if ( dist > 0 ) { - move = M.round( M.max( dist * -1, M.min( 0, cur ) ) ); - if ( cache !== move ) { - - cache = move; - - if ( IE === 8 ) { // scroll is faster for IE - img.parent()[ 'scroll' + pos ]( move * -1 ); - } else { - var css = {}; - css[ pos.toLowerCase() ] = move; - img.css(css); - } - } - } - }, - - // calculates mouse position after 50ms - calculate = function(e) { - if (Utils.timestamp() - ts < 50) { - return; - } - active = true; - x = self.getMousePosition(e).x; - y = self.getMousePosition(e).y; - }, - - // the main loop to check - loop = function(e) { - - if (!active) { - return; - } - - distX = img.width() - self._stageWidth; - distY = img.height() - self._stageHeight; - destX = x / self._stageWidth * distX * -1; - destY = y / self._stageHeight * distY * -1; - curX += ( destX - curX ) / self._options.imagePanSmoothness; - curY += ( destY - curY ) / self._options.imagePanSmoothness; - - position( distY, curY, 'Top' ); - position( distX, curX, 'Left' ); - - }; - - // we need to use scroll in IE8 to speed things up - if ( IE === 8 ) { - - img.parent().scrollTop( curY * -1 ).scrollLeft( curX * -1 ); - img.css({ - top: 0, - left: 0 - }); - - } - - // unbind and bind event - this.$( 'stage' ).off( 'mousemove', calculate ).on( 'mousemove', calculate ); - - // loop the loop - this.addTimer( 'pan' + self._id, loop, 50, true); - - return this; - }, - - /** - Brings the scope into any callback - - @param fn The callback to bring the scope into - @param [scope] Optional scope to bring - - @example $('#fullscreen').click( this.proxy(function() { this.enterFullscreen(); }) ) - - @returns {Function} Return the callback with the gallery scope - */ - - proxy : function( fn, scope ) { - if ( typeof fn !== 'function' ) { - return F; - } - scope = scope || this; - return function() { - return fn.apply( scope, Utils.array( arguments ) ); - }; - }, - - /** - Tells you the theme name of the gallery - - @returns {String} theme name - */ - - getThemeName : function() { - return this.theme.name; - }, - - /** - Removes the panning effect set by addPan() - - @returns Instance - */ - - removePan: function() { - - // todo: doublecheck IE8 - - this.$( 'stage' ).off( 'mousemove' ); - - this.clearTimer( 'pan' + this._id ); - - return this; - }, - - /** - Adds an element to the Galleria DOM array. - When you add an element here, you can access it using element ID in many API calls - - @param {string} id The element ID you wish to use. You can add many elements by adding more arguments. - - @example addElement('mybutton'); - @example addElement('mybutton','mylink'); - - @returns Instance - */ - - addElement : function( id ) { - - var dom = this._dom; - - $.each( Utils.array(arguments), function( i, blueprint ) { - dom[ blueprint ] = Utils.create( 'galleria-' + blueprint ); - }); - - return this; - }, - - /** - Attach keyboard events to Galleria - - @param {Object} map The map object of events. - Possible keys are 'UP', 'DOWN', 'LEFT', 'RIGHT', 'RETURN', 'ESCAPE', 'BACKSPACE', and 'SPACE'. - - @example - -this.attachKeyboard({ - right: this.next, - left: this.prev, - up: function() { - console.log( 'up key pressed' ) - } -}); - - @returns Instance - */ - - attachKeyboard : function( map ) { - this._keyboard.attach.apply( this._keyboard, Utils.array( arguments ) ); - return this; - }, - - /** - Detach all keyboard events to Galleria - - @returns Instance - */ - - detachKeyboard : function() { - this._keyboard.detach.apply( this._keyboard, Utils.array( arguments ) ); - return this; - }, - - /** - Fast helper for appending galleria elements that you added using addElement() - - @param {string} parentID The parent element ID where the element will be appended - @param {string} childID the element ID that should be appended - - @example this.addElement('myElement'); - this.appendChild( 'info', 'myElement' ); - - @returns Instance - */ - - appendChild : function( parentID, childID ) { - this.$( parentID ).append( this.get( childID ) || childID ); - return this; - }, - - /** - Fast helper for prepending galleria elements that you added using addElement() - - @param {string} parentID The parent element ID where the element will be prepended - @param {string} childID the element ID that should be prepended - - @example - -this.addElement('myElement'); -this.prependChild( 'info', 'myElement' ); - - @returns Instance - */ - - prependChild : function( parentID, childID ) { - this.$( parentID ).prepend( this.get( childID ) || childID ); - return this; - }, - - /** - Remove an element by blueprint - - @param {string} elemID The element to be removed. - You can remove multiple elements by adding arguments. - - @returns Instance - */ - - remove : function( elemID ) { - this.$( Utils.array( arguments ).join(',') ).remove(); - return this; - }, - - // a fast helper for building dom structures - // leave this out of the API for now - - append : function( data ) { - var i, j; - for( i in data ) { - if ( data.hasOwnProperty( i ) ) { - if ( data[i].constructor === Array ) { - for( j = 0; data[i][j]; j++ ) { - this.appendChild( i, data[i][j] ); - } - } else { - this.appendChild( i, data[i] ); - } - } - } - return this; - }, - - // an internal helper for scaling according to options - _scaleImage : function( image, options ) { - - image = image || this._controls.getActive(); - - // janpub (JH) fix: - // image might be unselected yet - // e.g. when external logics rescales the gallery on window resize events - if( !image ) { - return; - } - - var complete, - - scaleLayer = function( img ) { - $( img.container ).children(':first').css({ - top: M.max(0, Utils.parseValue( img.image.style.top )), - left: M.max(0, Utils.parseValue( img.image.style.left )), - width: Utils.parseValue( img.image.width ), - height: Utils.parseValue( img.image.height ) - }); - }; - - options = $.extend({ - width: this._stageWidth, - height: this._stageHeight, - crop: this._options.imageCrop, - max: this._options.maxScaleRatio, - min: this._options.minScaleRatio, - margin: this._options.imageMargin, - position: this._options.imagePosition, - iframelimit: this._options.maxVideoSize - }, options ); - - if ( this._options.layerFollow && this._options.imageCrop !== true ) { - - if ( typeof options.complete == 'function' ) { - complete = options.complete; - options.complete = function() { - complete.call( image, image ); - scaleLayer( image ); - }; - } else { - options.complete = scaleLayer; - } - - } else { - $( image.container ).children(':first').css({ top: 0, left: 0 }); - } - - image.scale( options ); - return this; - }, - - /** - Updates the carousel, - useful if you resize the gallery and want to re-check if the carousel nav is needed. - - @returns Instance - */ - - updateCarousel : function() { - this._carousel.update(); - return this; - }, - - /** - Resize the entire gallery container - - @param {Object} [measures] Optional object with width/height specified - @param {Function} [complete] The callback to be called when the scaling is complete - - @returns Instance - */ - - resize : function( measures, complete ) { - - if ( typeof measures == 'function' ) { - complete = measures; - measures = undef; - } - - measures = $.extend( { width:0, height:0 }, measures ); - - var self = this, - $container = this.$( 'container' ); - - $.each( measures, function( m, val ) { - if ( !val ) { - $container[ m ]( 'auto' ); - measures[ m ] = self._getWH()[ m ]; - } - }); - - $.each( measures, function( m, val ) { - $container[ m ]( val ); - }); - - return this.rescale( complete ); - - }, - - /** - Rescales the gallery - - @param {number} width The target width - @param {number} height The target height - @param {Function} complete The callback to be called when the scaling is complete - - @returns Instance - */ - - rescale : function( width, height, complete ) { - - var self = this; - - // allow rescale(fn) - if ( typeof width === 'function' ) { - complete = width; - width = undef; - } - - var scale = function() { - - // set stagewidth - self._stageWidth = width || self.$( 'stage' ).width(); - self._stageHeight = height || self.$( 'stage' ).height(); - - if ( self._options.swipe ) { - $.each( self._controls.slides, function(i, img) { - self._scaleImage( img ); - $( img.container ).css('left', self._stageWidth * i); - }); - self.$('images').css('width', self._stageWidth * self.getDataLength()); - } else { - // scale the active image - self._scaleImage(); - } - - if ( self._options.carousel ) { - self.updateCarousel(); - } - - var frame = self._controls.frames[ self._controls.active ]; - - if (frame) { - self._controls.frames[ self._controls.active ].scale({ - width: self._stageWidth, - height: self._stageHeight, - iframelimit: self._options.maxVideoSize - }); - } - - self.trigger( Galleria.RESCALE ); - - if ( typeof complete === 'function' ) { - complete.call( self ); - } - }; - - scale.call( self ); - - return this; - }, - - /** - Refreshes the gallery. - Useful if you change image options at runtime and want to apply the changes to the active image. - - @returns Instance - */ - - refreshImage : function() { - this._scaleImage(); - if ( this._options.imagePan ) { - this.addPan(); - } - return this; - }, - - _preload: function() { - if ( this._options.preload ) { - var p, i, - n = this.getNext(), - ndata; - try { - for ( i = this._options.preload; i > 0; i-- ) { - p = new Galleria.Picture(); - ndata = this.getData( n ); - p.preload( this.isFullscreen() && ndata.big ? ndata.big : ndata.image ); - n = this.getNext( n ); - } - } catch(e) {} - } - }, - - /** - Shows an image by index - - @param {number|boolean} index The index to show - @param {Boolean} rewind A boolean that should be true if you want the transition to go back - - @returns Instance - */ - - show : function( index, rewind, _history ) { - - var swipe = this._options.swipe; - - // do nothing queue is long || index is false || queue is false and transition is in progress - if ( !swipe && - ( this._queue.length > 3 || index === false || ( !this._options.queue && this._queue.stalled ) ) ) { - return; - } - - index = M.max( 0, M.min( parseInt( index, 10 ), this.getDataLength() - 1 ) ); - - rewind = typeof rewind !== 'undefined' ? !!rewind : index < this.getIndex(); - - _history = _history || false; - - // do the history thing and return - if ( !_history && Galleria.History ) { - Galleria.History.set( index.toString() ); - return; - } - - if ( this.finger && index !== this._active ) { - this.finger.to = -( index*this.finger.width ); - this.finger.index = index; - } - this._active = index; - - // we do things a bit simpler in swipe: - if ( swipe ) { - - var data = this.getData(index), - self = this; - if ( !data ) { - return; - } - - var src = this.isFullscreen() && data.big ? data.big : ( data.image || data.iframe ), - image = this._controls.slides[index], - cached = image.isCached( src ), - thumb = this._thumbnails[ index ]; - - var evObj = { - cached: cached, - index: index, - rewind: rewind, - imageTarget: image.image, - thumbTarget: thumb.image, - galleriaData: data - }; - - this.trigger($.extend(evObj, { - type: Galleria.LOADSTART - })); - - self.$('container').removeClass( 'videoplay' ); - - var complete = function() { - - self._layers[index].innerHTML = self.getData().layer || ''; - - self.trigger($.extend(evObj, { - type: Galleria.LOADFINISH - })); - self._playCheck(); - }; - - self._preload(); - - window.setTimeout(function() { - - // load if not ready - if ( !image.ready || $(image.image).attr('src') != src ) { - if ( data.iframe && !data.image ) { - image.isIframe = true; - } - image.load(src, function(image) { - evObj.imageTarget = image.image; - self._scaleImage(image, complete).trigger($.extend(evObj, { - type: Galleria.IMAGE - })); - complete(); - }); - } else { - self.trigger($.extend(evObj, { - type: Galleria.IMAGE - })); - complete(); - } - }, 100); - - } else { - protoArray.push.call( this._queue, { - index : index, - rewind : rewind - }); - if ( !this._queue.stalled ) { - this._show(); - } - } - - return this; - }, - - // the internal _show method does the actual showing - _show : function() { - - // shortcuts - var self = this, - queue = this._queue[ 0 ], - data = this.getData( queue.index ); - - if ( !data ) { - return; - } - - var src = this.isFullscreen() && data.big ? data.big : ( data.image || data.iframe ), - active = this._controls.getActive(), - next = this._controls.getNext(), - cached = next.isCached( src ), - thumb = this._thumbnails[ queue.index ], - mousetrigger = function() { - $( next.image ).trigger( 'mouseup' ); - }; - - self.$('container').toggleClass('iframe', !!data.isIframe).removeClass( 'videoplay' ); - - // to be fired when loading & transition is complete: - var complete = (function( data, next, active, queue, thumb ) { - - return function() { - - var win; - - _transitions.active = false; - - // optimize quality - Utils.toggleQuality( next.image, self._options.imageQuality ); - - // remove old layer - self._layers[ self._controls.active ].innerHTML = ''; - - // swap - $( active.container ).css({ - zIndex: 0, - opacity: 0 - }).show(); - - $( active.container ).find( 'iframe, .galleria-videoicon' ).remove(); - $( self._controls.frames[ self._controls.active ].container ).hide(); - - $( next.container ).css({ - zIndex: 1, - left: 0, - top: 0 - }).show(); - - self._controls.swap(); - - // add pan according to option - if ( self._options.imagePan ) { - self.addPan( next.image ); - } - - // make the image clickable - // order of precedence: iframe, link, lightbox, clicknext - if ( ( data.iframe && data.image ) || data.link || self._options.lightbox || self._options.clicknext ) { - - $( next.image ).css({ - cursor: 'pointer' - }).on( 'mouseup', function( e ) { - - // non-left click - if ( typeof e.which == 'number' && e.which > 1 ) { - return; - } - - // iframe / video - if ( data.iframe ) { - - if ( self.isPlaying() ) { - self.pause(); - } - var frame = self._controls.frames[ self._controls.active ], - w = self._stageWidth, - h = self._stageHeight; - - $( frame.container ).css({ - width: w, - height: h, - opacity: 0 - }).show().animate({ - opacity: 1 - }, 200); - - window.setTimeout(function() { - frame.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { - width: w, - height: h - }, function( frame ) { - self.$( 'container' ).addClass( 'videoplay' ); - frame.scale({ - width: self._stageWidth, - height: self._stageHeight, - iframelimit: data.video ? self._options.maxVideoSize : undef - }); - }); - }, 100); - - return; - } - - // clicknext - if ( self._options.clicknext && !Galleria.TOUCH ) { - if ( self._options.pauseOnInteraction ) { - self.pause(); - } - self.next(); - return; - } - - // popup link - if ( data.link ) { - if ( self._options.popupLinks ) { - win = window.open( data.link, '_blank' ); - } else { - window.location.href = data.link; - } - return; - } - - if ( self._options.lightbox ) { - self.openLightbox(); - } - - }); - } - - // check if we are playing - self._playCheck(); - - // trigger IMAGE event - self.trigger({ - type: Galleria.IMAGE, - index: queue.index, - imageTarget: next.image, - thumbTarget: thumb.image, - galleriaData: data - }); - - // remove the queued image - protoArray.shift.call( self._queue ); - - // remove stalled - self._queue.stalled = false; - - // if we still have images in the queue, show it - if ( self._queue.length ) { - self._show(); - } - - }; - }( data, next, active, queue, thumb )); - - // let the carousel follow - if ( this._options.carousel && this._options.carouselFollow ) { - this._carousel.follow( queue.index ); - } - - // preload images - self._preload(); - - // show the next image, just in case - Utils.show( next.container ); - - next.isIframe = data.iframe && !data.image; - - // add active classes - $( self._thumbnails[ queue.index ].container ) - .addClass( 'active' ) - .siblings( '.active' ) - .removeClass( 'active' ); - - // trigger the LOADSTART event - self.trigger( { - type: Galleria.LOADSTART, - cached: cached, - index: queue.index, - rewind: queue.rewind, - imageTarget: next.image, - thumbTarget: thumb.image, - galleriaData: data - }); - - // stall the queue - self._queue.stalled = true; - - // begin loading the next image - next.load( src, function( next ) { - - // add layer HTML - var layer = $( self._layers[ 1-self._controls.active ] ).html( data.layer || '' ).hide(); - - self._scaleImage( next, { - - complete: function( next ) { - - // toggle low quality for IE - if ( 'image' in active ) { - Utils.toggleQuality( active.image, false ); - } - Utils.toggleQuality( next.image, false ); - - // remove the image panning, if applied - // TODO: rethink if this is necessary - self.removePan(); - - // set the captions and counter - self.setInfo( queue.index ); - self.setCounter( queue.index ); - - // show the layer now - if ( data.layer ) { - layer.show(); - // inherit click events set on image - if ( ( data.iframe && data.image ) || data.link || self._options.lightbox || self._options.clicknext ) { - layer.css( 'cursor', 'pointer' ).off( 'mouseup' ).mouseup( mousetrigger ); - } - } - - // add play icon - if( data.video && data.image ) { - _playIcon( next.container ); - } - - var transition = self._options.transition; - - // can JavaScript loop through objects in order? yes. - $.each({ - initial: active.image === null, - touch: Galleria.TOUCH, - fullscreen: self.isFullscreen() - }, function( type, arg ) { - if ( arg && self._options[ type + 'Transition' ] !== undef ) { - transition = self._options[ type + 'Transition' ]; - return false; - } - }); - - // validate the transition - if ( transition in _transitions.effects === false ) { - complete(); - } else { - var params = { - prev: active.container, - next: next.container, - rewind: queue.rewind, - speed: self._options.transitionSpeed || 400 - }; - - _transitions.active = true; - - // call the transition function and send some stuff - _transitions.init.call( self, transition, params, complete ); - - } - - // trigger the LOADFINISH event - self.trigger({ - type: Galleria.LOADFINISH, - cached: cached, - index: queue.index, - rewind: queue.rewind, - imageTarget: next.image, - thumbTarget: self._thumbnails[ queue.index ].image, - galleriaData: self.getData( queue.index ) - }); - } - }); - }); - }, - - /** - Gets the next index - - @param {number} [base] Optional starting point - - @returns {number} the next index, or the first if you are at the first (looping) - */ - - getNext : function( base ) { - base = typeof base === 'number' ? base : this.getIndex(); - return base === this.getDataLength() - 1 ? 0 : base + 1; - }, - - /** - Gets the previous index - - @param {number} [base] Optional starting point - - @returns {number} the previous index, or the last if you are at the first (looping) - */ - - getPrev : function( base ) { - base = typeof base === 'number' ? base : this.getIndex(); - return base === 0 ? this.getDataLength() - 1 : base - 1; - }, - - /** - Shows the next image in line - - @returns Instance - */ - - next : function() { - if ( this.getDataLength() > 1 ) { - this.show( this.getNext(), false ); - } - return this; - }, - - /** - Shows the previous image in line - - @returns Instance - */ - - prev : function() { - if ( this.getDataLength() > 1 ) { - this.show( this.getPrev(), true ); - } - return this; - }, - - /** - Retrieve a DOM element by element ID - - @param {string} elemId The delement ID to fetch - - @returns {HTMLElement} The elements DOM node or null if not found. - */ - - get : function( elemId ) { - return elemId in this._dom ? this._dom[ elemId ] : null; - }, - - /** - Retrieve a data object - - @param {number} index The data index to retrieve. - If no index specified it will take the currently active image - - @returns {Object} The data object - */ - - getData : function( index ) { - return index in this._data ? - this._data[ index ] : this._data[ this._active ]; - }, - - /** - Retrieve the number of data items - - @returns {number} The data length - */ - getDataLength : function() { - return this._data.length; - }, - - /** - Retrieve the currently active index - - @returns {number|boolean} The active index or false if none found - */ - - getIndex : function() { - return typeof this._active === 'number' ? this._active : false; - }, - - /** - Retrieve the stage height - - @returns {number} The stage height - */ - - getStageHeight : function() { - return this._stageHeight; - }, - - /** - Retrieve the stage width - - @returns {number} The stage width - */ - - getStageWidth : function() { - return this._stageWidth; - }, - - /** - Retrieve the option - - @param {string} key The option key to retrieve. If no key specified it will return all options in an object. - - @returns option or options - */ - - getOptions : function( key ) { - return typeof key === 'undefined' ? this._options : this._options[ key ]; - }, - - /** - Set options to the instance. - You can set options using a key & value argument or a single object argument (see examples) - - @param {string} key The option key - @param {string} value the the options value - - @example setOptions( 'autoplay', true ) - @example setOptions({ autoplay: true }); - - @returns Instance - */ - - setOptions : function( key, value ) { - if ( typeof key === 'object' ) { - $.extend( this._options, key ); - } else { - this._options[ key ] = value; - } - return this; - }, - - /** - Starts playing the slideshow - - @param {number} delay Sets the slideshow interval in milliseconds. - If you set it once, you can just call play() and get the same interval the next time. - - @returns Instance - */ - - play : function( delay ) { - - this._playing = true; - - this._playtime = delay || this._playtime; - - this._playCheck(); - - this.trigger( Galleria.PLAY ); - - return this; - }, - - /** - Stops the slideshow if currently playing - - @returns Instance - */ - - pause : function() { - - this._playing = false; - - this.trigger( Galleria.PAUSE ); - - return this; - }, - - /** - Toggle between play and pause events. - - @param {number} delay Sets the slideshow interval in milliseconds. - - @returns Instance - */ - - playToggle : function( delay ) { - return ( this._playing ) ? this.pause() : this.play( delay ); - }, - - /** - Checks if the gallery is currently playing - - @returns {Boolean} - */ - - isPlaying : function() { - return this._playing; - }, - - /** - Checks if the gallery is currently in fullscreen mode - - @returns {Boolean} - */ - - isFullscreen : function() { - return this._fullscreen.active; - }, - - _playCheck : function() { - var self = this, - played = 0, - interval = 20, - now = Utils.timestamp(), - timer_id = 'play' + this._id; - - if ( this._playing ) { - - this.clearTimer( timer_id ); - - var fn = function() { - - played = Utils.timestamp() - now; - if ( played >= self._playtime && self._playing ) { - self.clearTimer( timer_id ); - self.next(); - return; - } - if ( self._playing ) { - - // trigger the PROGRESS event - self.trigger({ - type: Galleria.PROGRESS, - percent: M.ceil( played / self._playtime * 100 ), - seconds: M.floor( played / 1000 ), - milliseconds: played - }); - - self.addTimer( timer_id, fn, interval ); - } - }; - self.addTimer( timer_id, fn, interval ); - } - }, - - /** - Modify the slideshow delay - - @param {number} delay the number of milliseconds between slides, - - @returns Instance - */ - - setPlaytime: function( delay ) { - this._playtime = delay; - return this; - }, - - setIndex: function( val ) { - this._active = val; - return this; - }, - - /** - Manually modify the counter - - @param {number} [index] Optional data index to fectch, - if no index found it assumes the currently active index - - @returns Instance - */ - - setCounter: function( index ) { - - if ( typeof index === 'number' ) { - index++; - } else if ( typeof index === 'undefined' ) { - index = this.getIndex()+1; - } - - this.get( 'current' ).innerHTML = index; - - if ( IE ) { // weird IE bug - - var count = this.$( 'counter' ), - opacity = count.css( 'opacity' ); - - if ( parseInt( opacity, 10 ) === 1) { - Utils.removeAlpha( count[0] ); - } else { - this.$( 'counter' ).css( 'opacity', opacity ); - } - - } - - return this; - }, - - /** - Manually set captions - - @param {number} [index] Optional data index to fectch and apply as caption, - if no index found it assumes the currently active index - - @returns Instance - */ - - setInfo : function( index ) { - - var self = this, - data = this.getData( index ); - - $.each( ['title','description'], function( i, type ) { - - var elem = self.$( 'info-' + type ); - - if ( !!data[type] ) { - elem[ data[ type ].length ? 'show' : 'hide' ]().html( data[ type ] ); - } else { - elem.empty().hide(); - } - }); - - return this; - }, - - /** - Checks if the data contains any captions - - @param {number} [index] Optional data index to fectch, - if no index found it assumes the currently active index. - - @returns {boolean} - */ - - hasInfo : function( index ) { - - var check = 'title description'.split(' '), - i; - - for ( i = 0; check[i]; i++ ) { - if ( !!this.getData( index )[ check[i] ] ) { - return true; - } - } - return false; - - }, - - jQuery : function( str ) { - - var self = this, - ret = []; - - $.each( str.split(','), function( i, elemId ) { - elemId = $.trim( elemId ); - - if ( self.get( elemId ) ) { - ret.push( elemId ); - } - }); - - var jQ = $( self.get( ret.shift() ) ); - - $.each( ret, function( i, elemId ) { - jQ = jQ.add( self.get( elemId ) ); - }); - - return jQ; - - }, - - /** - Converts element IDs into a jQuery collection - You can call for multiple IDs separated with commas. - - @param {string} str One or more element IDs (comma-separated) - - @returns jQuery - - @example this.$('info,container').hide(); - */ - - $ : function( str ) { - return this.jQuery.apply( this, Utils.array( arguments ) ); - } - -}; - -// End of Galleria prototype - -// Add events as static variables -$.each( _events, function( i, ev ) { - - // legacy events - var type = /_/.test( ev ) ? ev.replace( /_/g, '' ) : ev; - - Galleria[ ev.toUpperCase() ] = 'galleria.'+type; - -} ); - -$.extend( Galleria, { - - // Browser helpers - IE9: IE === 9, - IE8: IE === 8, - IE7: IE === 7, - IE6: IE === 6, - IE: IE, - WEBKIT: /webkit/.test( NAV ), - CHROME: /chrome/.test( NAV ), - SAFARI: /safari/.test( NAV ) && !(/chrome/.test( NAV )), - QUIRK: ( IE && doc.compatMode && doc.compatMode === "BackCompat" ), - MAC: /mac/.test( navigator.platform.toLowerCase() ), - OPERA: !!window.opera, - IPHONE: /iphone/.test( NAV ), - IPAD: /ipad/.test( NAV ), - ANDROID: /android/.test( NAV ), - TOUCH: ('ontouchstart' in doc) - -}); - -// Galleria static methods - -/** - Adds a theme that you can use for your Gallery - - @param {Object} theme Object that should contain all your theme settings. -
    -
  • name - name of the theme
  • -
  • author - name of the author
  • -
  • css - css file name (not path)
  • -
  • defaults - default options to apply, including theme-specific options
  • -
  • init - the init function
  • -
- - @returns {Object} theme -*/ - -Galleria.addTheme = function( theme ) { - - // make sure we have a name - if ( !theme.name ) { - Galleria.raise('No theme name specified'); - } - - if ( typeof theme.defaults !== 'object' ) { - theme.defaults = {}; - } else { - theme.defaults = _legacyOptions( theme.defaults ); - } - - var css = false, - reg, reg2; - - if ( typeof theme.css === 'string' ) { - - // look for manually added CSS - $('link').each(function( i, link ) { - reg = new RegExp( theme.css ); - if ( reg.test( link.href ) ) { - - // we found the css - css = true; - - // the themeload trigger - _themeLoad( theme ); - - return false; - } - }); - - // else look for the absolute path and load the CSS dynamic - if ( !css ) { - - - $(function() { - // Try to determine the css-path from the theme script. - // In IE8/9, the script-dom-element seems to be not present - // at once, if galleria itself is inserted into the dom - // dynamically. We therefore try multiple times before raising - // an error. - var retryCount = 0; - var tryLoadCss = function() { - $('script').each(function (i, script) { - // look for the theme script - reg = new RegExp('galleria\\.' + theme.name.toLowerCase() + '\\.'); - reg2 = new RegExp('galleria\\.io\\/theme\\/' + theme.name.toLowerCase() + '\\/(\\d*\\.*)?(\\d*\\.*)?(\\d*\\/)?js'); - if (reg.test(script.src) || reg2.test(script.src)) { - // we have a match - css = script.src.replace(/[^\/]*$/, '') + theme.css; - - window.setTimeout(function () { - Utils.loadCSS(css, 'galleria-theme-'+theme.name, function () { - - // run galleries with this theme - _themeLoad(theme); - - }); - }, 1); - } - }); - if (!css) { - if (retryCount++ > 5) { - Galleria.raise('No theme CSS loaded'); - } else { - window.setTimeout(tryLoadCss, 500); - } - } - }; - tryLoadCss(); - }); - } - - } else { - - // pass - _themeLoad( theme ); - } - return theme; -}; - -/** - loadTheme loads a theme js file and attaches a load event to Galleria - - @param {string} src The relative path to the theme source file - - @param {Object} [options] Optional options you want to apply - - @returns Galleria -*/ - -Galleria.loadTheme = function( src, options ) { - - // Don't load if theme is already loaded - if( $('script').filter(function() { return $(this).attr('src') == src; }).length ) { - return; - } - - var loaded = false, - err; - - // start listening for the timeout onload - $( window ).load( function() { - if ( !loaded ) { - // give it another 20 seconds - err = window.setTimeout(function() { - if ( !loaded ) { - Galleria.raise( "Galleria had problems loading theme at " + src + ". Please check theme path or load manually.", true ); - } - }, 20000); - } - }); - - // load the theme - Utils.loadScript( src, function() { - loaded = true; - window.clearTimeout( err ); - }); - - return Galleria; -}; - -/** - Retrieves a Galleria instance. - - @param {number} [index] Optional index to retrieve. - If no index is supplied, the method will return all instances in an array. - - @returns Instance or Array of instances -*/ - -Galleria.get = function( index ) { - if ( !!_instances[ index ] ) { - return _instances[ index ]; - } else if ( typeof index !== 'number' ) { - return _instances; - } else { - Galleria.raise('Gallery index ' + index + ' not found'); - } -}; - -/** - - Configure Galleria options via a static function. - The options will be applied to all instances - - @param {string|object} key The options to apply or a key - - @param [value] If key is a string, this is the value - - @returns Galleria - -*/ - -Galleria.configure = function( key, value ) { - - var opts = {}; - - if( typeof key == 'string' && value ) { - opts[key] = value; - key = opts; - } else { - $.extend( opts, key ); - } - - Galleria.configure.options = opts; - - $.each( Galleria.get(), function(i, instance) { - instance.setOptions( opts ); - }); - - return Galleria; -}; - -Galleria.configure.options = {}; - -/** - - Bind a Galleria event to the gallery - - @param {string} type A string representing the galleria event - - @param {function} callback The function that should run when the event is triggered - - @returns Galleria - -*/ - -Galleria.on = function( type, callback ) { - if ( !type ) { - return; - } - - callback = callback || F; - - // hash the bind - var hash = type + callback.toString().replace(/\s/g,'') + Utils.timestamp(); - - // for existing instances - $.each( Galleria.get(), function(i, instance) { - instance._binds.push( hash ); - instance.bind( type, callback ); - }); - - // for future instances - Galleria.on.binds.push({ - type: type, - callback: callback, - hash: hash - }); - - return Galleria; -}; - -Galleria.on.binds = []; - -/** - - Run Galleria - Alias for $(selector).galleria(options) - - @param {string} selector A selector of element(s) to intialize galleria to - - @param {object} options The options to apply - - @returns Galleria - -*/ - -Galleria.run = function( selector, options ) { - if ( $.isFunction( options ) ) { - options = { extend: options }; - } - $( selector || '#galleria' ).galleria( options ); - return Galleria; -}; - -/** - Creates a transition to be used in your gallery - - @param {string} name The name of the transition that you will use as an option - - @param {Function} fn The function to be executed in the transition. - The function contains two arguments, params and complete. - Use the params Object to integrate the transition, and then call complete when you are done. - - @returns Galleria - -*/ - -Galleria.addTransition = function( name, fn ) { - _transitions.effects[name] = fn; - return Galleria; -}; - -/** - The Galleria utilites -*/ - -Galleria.utils = Utils; - -/** - A helper metod for cross-browser logging. - It uses the console log if available otherwise it falls back to alert - - @example Galleria.log("hello", document.body, [1,2,3]); -*/ - -Galleria.log = function() { - var args = Utils.array( arguments ); - if( 'console' in window && 'log' in window.console ) { - try { - return window.console.log.apply( window.console, args ); - } catch( e ) { - $.each( args, function() { - window.console.log(this); - }); - } - } else { - return window.alert( args.join('
') ); - } -}; - -/** - A ready method for adding callbacks when a gallery is ready - Each method is call before the extend option for every instance - - @param {function} callback The function to call - - @returns Galleria -*/ - -Galleria.ready = function( fn ) { - if ( typeof fn != 'function' ) { - return Galleria; - } - $.each( _galleries, function( i, gallery ) { - fn.call( gallery, gallery._options ); - }); - Galleria.ready.callbacks.push( fn ); - return Galleria; -}; - -Galleria.ready.callbacks = []; - -/** - Method for raising errors - - @param {string} msg The message to throw - - @param {boolean} [fatal] Set this to true to override debug settings and display a fatal error -*/ - -Galleria.raise = function( msg, fatal ) { - - var type = fatal ? 'Fatal error' : 'Error', - - css = { - color: '#fff', - position: 'absolute', - top: 0, - left: 0, - zIndex: 100000 - }, - - echo = function( msg ) { - - var html = '
' + - ( fatal ? '' + type + ': ' : '' ) + - msg + '
'; - - $.each( _instances, function() { - - var cont = this.$( 'errors' ), - target = this.$( 'target' ); - - if ( !cont.length ) { - - target.css( 'position', 'relative' ); - - cont = this.addElement( 'errors' ).appendChild( 'target', 'errors' ).$( 'errors' ).css(css); - } - cont.append( html ); - - }); - - if ( !_instances.length ) { - $('
').css( $.extend( css, { position: 'fixed' } ) ).append( html ).appendTo( DOM().body ); - } - }; - - // if debug is on, display errors and throw exception if fatal - if ( DEBUG ) { - echo( msg ); - if ( fatal ) { - throw new Error(type + ': ' + msg); - } - - // else just echo a silent generic error if fatal - } else if ( fatal ) { - if ( _hasError ) { - return; - } - _hasError = true; - fatal = false; - echo( 'Gallery could not load.' ); - } -}; - -// Add the version -Galleria.version = VERSION; - -Galleria.getLoadedThemes = function() { - return $.map(_loadedThemes, function(theme) { - return theme.name; - }); -}; - -/** - A method for checking what version of Galleria the user has installed and throws a readable error if the user needs to upgrade. - Useful when building plugins that requires a certain version to function. - - @param {number} version The minimum version required - - @param {string} [msg] Optional message to display. If not specified, Galleria will throw a generic error. - - @returns Galleria -*/ - -Galleria.requires = function( version, msg ) { - msg = msg || 'You need to upgrade Galleria to version ' + version + ' to use one or more components.'; - if ( Galleria.version < version ) { - Galleria.raise(msg, true); - } - return Galleria; -}; - -/** - Adds preload, cache, scale and crop functionality - - @constructor - - @requires jQuery - - @param {number} [id] Optional id to keep track of instances -*/ - -Galleria.Picture = function( id ) { - - // save the id - this.id = id || null; - - // the image should be null until loaded - this.image = null; - - // Create a new container - this.container = Utils.create('galleria-image'); - - // add container styles - $( this.container ).css({ - overflow: 'hidden', - position: 'relative' // for IE Standards mode - }); - - // saves the original measurements - this.original = { - width: 0, - height: 0 - }; - - // flag when the image is ready - this.ready = false; - - // flag for iframe Picture - this.isIframe = false; - -}; - -Galleria.Picture.prototype = { - - // the inherited cache object - cache: {}, - - // show the image on stage - show: function() { - Utils.show( this.image ); - }, - - // hide the image - hide: function() { - Utils.moveOut( this.image ); - }, - - clear: function() { - this.image = null; - }, - - /** - Checks if an image is in cache - - @param {string} src The image source path, ex '/path/to/img.jpg' - - @returns {boolean} - */ - - isCached: function( src ) { - return !!this.cache[src]; - }, - - /** - Preloads an image into the cache - - @param {string} src The image source path, ex '/path/to/img.jpg' - - @returns Galleria.Picture - */ - - preload: function( src ) { - $( new Image() ).load((function(src, cache) { - return function() { - cache[ src ] = src; - }; - }( src, this.cache ))).attr( 'src', src ); - }, - - /** - Loads an image and call the callback when ready. - Will also add the image to cache. - - @param {string} src The image source path, ex '/path/to/img.jpg' - @param {Object} [size] The forced size of the image, defined as an object { width: xx, height:xx } - @param {Function} callback The function to be executed when the image is loaded & scaled - - @returns The image container (jQuery object) - */ - - load: function(src, size, callback) { - - if ( typeof size == 'function' ) { - callback = size; - size = null; - } - - if( this.isIframe ) { - var id = 'if'+new Date().getTime(); - - var iframe = this.image = $('