diff --git a/_config.yml b/_config.yml
index 839311000d4c23f867fae6fdeb12ca5669cd1b62..7688f0aaf6cb0edf2b1298b052e75bf934e2ca8f 100644
--- a/_config.yml
+++ b/_config.yml
@@ -65,6 +65,8 @@ collections:
     output: true
     feature_image: "/assets/projekte.jpg"
     permalink: project/:path/
+  imagemeta:
+    output: false
   press:
     output: false
 
@@ -119,6 +121,7 @@ sharing_links: # Appear at the bottom of single blog posts, uncomment and commen
 
 #Defining reusable html templates for the webste that are places in the _includes folder
 image: "image.html"
+galery: "galery.html"
 pressespiegel: "pressespiegel.html"
 default-feature: "/assets/logo.jpg"
 
@@ -130,3 +133,4 @@ vorsitz1: Lukas Ruge
 vorsitz2: Johannes Thorn
 finanzen: Matthias Schiffer
 kontakt: Matthias Schiffer
+postadresse: Chaotikum e.V. <br> Postfach 12 64 <br> 23502 Lübeck
diff --git a/_imagemeta/feinstaub1.markdown b/_imagemeta/feinstaub1.markdown
new file mode 100644
index 0000000000000000000000000000000000000000..70b148b44c148754f1e4e0f6a3479d4e60b07c3b
--- /dev/null
+++ b/_imagemeta/feinstaub1.markdown
@@ -0,0 +1,7 @@
+---
+title: Feinstaubsensor
+url: https://chaotikum.org/_media/undefined:20170910-img_4773.jpg
+description: Feinstaubssensor-Set mit NODE MCU, weiteren Sensoren und Kabeln
+tags:
+ - feinstaub
+---
diff --git a/_imagemeta/feinstaub2.markdown b/_imagemeta/feinstaub2.markdown
new file mode 100644
index 0000000000000000000000000000000000000000..7e7d15fb64f7fc91f4d8837f4c20e35167c83a6b
--- /dev/null
+++ b/_imagemeta/feinstaub2.markdown
@@ -0,0 +1,7 @@
+---
+title: Feinstaubsensor
+url: https://chaotikum.org/_media/undefined:20170910-img_4773.jpg
+description: Blablabla
+tags:
+ - feinstaub
+---
diff --git a/_imagemeta/testfile1.markdown b/_imagemeta/testfile1.markdown
new file mode 100644
index 0000000000000000000000000000000000000000..9d16be1e12ad54b5e8b8e08053d583a8063253b8
--- /dev/null
+++ b/_imagemeta/testfile1.markdown
@@ -0,0 +1,5 @@
+---
+title: Testfile
+tags:
+ - fu
+---
diff --git a/_includes/galery.html b/_includes/galery.html
new file mode 100644
index 0000000000000000000000000000000000000000..ca8c146a3e778a73a3c4bd4b3143511de61a22d5
--- /dev/null
+++ b/_includes/galery.html
@@ -0,0 +1,14 @@
+<div class="galleria">
+{% for image in site.imagemeta %}
+  {% if image.tags contains {{include.topic}} %}
+    <p>bla</p>
+    <img src="{{include.url}}" data-title="My title" data-description="My description">
+  {% endif %}
+{% endfor %}
+</div>
+<script>
+  (function() {
+    Galleria.loadTheme('{{site.baseurl}}/assets/scripts/galleria/themes/classic/galleria.classic.min.js');
+    Galleria.run('.galleria');
+  }());
+</script>
diff --git a/_includes/nav-header.html b/_includes/nav-header.html
index ffe608d99927867319f56a4c7da9b4fe98f39b4c..32818a09646727e494cbd20be4bc327f428d167c 100644
--- a/_includes/nav-header.html
+++ b/_includes/nav-header.html
@@ -42,3 +42,6 @@ const applyToggle = (list, button, breakpoint) => {
 
 applyToggle('.list--nav', '.button', 640)
 </script>
+
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.7/galleria.min.js"></script>
diff --git a/_includes/space-status.html b/_includes/space-status.html
index 1819816e3e9ab3fa2b6cf862eaf736a6ea0f70b7..fa44cb5cef13007bcf7603f454283eb1c13c0a9a 100644
--- a/_includes/space-status.html
+++ b/_includes/space-status.html
@@ -12,7 +12,7 @@ function spaceopen() {
     if(data.open) {
       console.log("OPEN");
       //$("#spaceopen").css( "border", "3px solid green" );
-      $("#spaceopen").html("<div style='float:left'><img src='{{ site.baseurl }}/assets/open.png' width='35'></div>Der nbsp ist offen!<a href='http://status.nobreakspace.org/' target='_blank'>Status</a>");
+      $("#spaceopen").html("<div style='float:left'><img src='{{ site.baseurl }}/assets/open.png' width='35'></div>Der nbsp ist offen!<br><div style='text-align: right;'><a href='http://status.nobreakspace.org/' target='_blank' style='color: #EAEAEA;'>Status</a></div>");
     } else {
       console.log("CLOSED");
       //$("#spaceopen").css( "border", "3px solid red" );
diff --git a/_includes/vereinnavigation.html b/_includes/vereinnavigation.html
index 5849b809dcfa449f356794379d71873338964b55..f788e21f57897ab57a3492257bfa48b286de71eb 100644
--- a/_includes/vereinnavigation.html
+++ b/_includes/vereinnavigation.html
@@ -1,5 +1,10 @@
 <ul>
   <li><a href="{{site.baseurl}}/verein">Verein</a></li>
+  <li><a href="{{site.baseurl}}/verein/membership">Mitglied werden</a></li>
   <li><a href="{{site.baseurl}}/verein/press">Presse</a></li>
-  <li><a href="{{site.baseurl}}/verein/satzung">Satzung</a></li>
+  <li><a href="{{site.baseurl}}/verein/satzung">Satzung</a>
+    <ul>
+      <li><a href="{{site.baseurl}}/verein/beitrag">Beitragsordnung</a></li>
+    </ul>
+  </li>
 </ul>
diff --git a/_layouts/verein.html b/_layouts/verein.html
index 9cdb19606b471f80b250a01d9ce663a2c0c45e36..ff5a67665e270f9c5121a006c8bb7cfc15ea20cf 100644
--- a/_layouts/verein.html
+++ b/_layouts/verein.html
@@ -17,7 +17,7 @@ layout: default
   </div>
 
   {% include site-aside.html %}
-	
+
 </main>
 
 {% include site-footer.html %}
diff --git a/_posts/blog/2017-09-27-102-osm-stammtisch-und-mappingparty.markdown b/_posts/blog/2017-09-27-102-osm-stammtisch-und-mappingparty.markdown
new file mode 100644
index 0000000000000000000000000000000000000000..5203d5162d83761590e90be0c0ae877fcd829bef
--- /dev/null
+++ b/_posts/blog/2017-09-27-102-osm-stammtisch-und-mappingparty.markdown
@@ -0,0 +1,17 @@
+---
+layout: post
+title:  "102. OSM-Stammtisch und Mappingparty"
+date:   2017-09-27 10:00:00 +0200
+image: osm.png
+comments: true
+categories:
+- blog
+tags:
+- osm
+frontpage: true
+---
+Am 28.09 trifft sich die [Lübecker Open Street Map Community](http://www.osm-luebeck.de/) um 19:00 Uhr zum [Lübecker Mappertreffen](https://wiki.openstreetmap.org/wiki/L%C3%BCbecker_Mappertreffen) im [Nobreakspace](http://chaotikum.org/hackerspace:nbsp).
+
+Jeder, der sich für [Open Street Map](https://www.openstreetmap.org/) interessiert ist eingeladen.
+
+Noch viel spannender wird es zwei Tage später, am 30. September findet eine [Mappingparty](https://wiki.openstreetmap.org/wiki/L%C3%BCbecker_Mappertreffen) statt. Schwerpunkt soll die Lübecker Altstadt sein, der Treffpunkt is der [Nobreakspace](http://chaotikum.org/hackerspace:nbsp), es geht um 14:00 Uhr los.
diff --git a/_projects/feinstaubsensoren.md b/_projects/feinstaubsensoren.md
index af38119880e7ef663c2288ce2aaced478fce2fcc..625f96ac8812942f4ad1647a6a3bbb29af8085af 100644
--- a/_projects/feinstaubsensoren.md
+++ b/_projects/feinstaubsensoren.md
@@ -19,4 +19,6 @@ Mit dem Konzept von [luftdaten.info](http://luftdaten.info/) werden Feinstaubsen
 
 Jeder Teilnehmer hat die Option seine Daten auf der von [luftdaten.info](http://luftdaten.info/) breit gestellten [Karte](http://deutschland.maps.luftdaten.info/) darstellen zu lassen.
 
+{% include {{site.galery}} topic="feinstaub" %}
+
 Zudem sollen auf dem Nbsp-Dashboard die erfassten Lübecker Werte sichtbar mit den [Werten des Bundesumwelatmes](http://www.umweltbundesamt.de/themen/luft/luftschadstoffe/feinstaub) verglichen werden.
diff --git a/_sass/_normalize.scss b/_sass/_normalize.scss
index bf25c949ad66d7efbc27b1e6aec688cdb2e466f6..7a738a7bb362d0846017ed08982d8ac67a77d315 100644
--- a/_sass/_normalize.scss
+++ b/_sass/_normalize.scss
@@ -82,6 +82,10 @@ summary { /* 1 */
   text-align: left;
 }
 
+#galleria {
+  height:467px;
+}
+
 .share {
   margin-top: 20px;
 }
diff --git a/assets/.DS_Store b/assets/.DS_Store
index 0294fc26dd69b95e229fee7b1a8d2081ffdbb6e2..f57ac2d18b404f682f0b69e9f7a4dde73da361ae 100644
Binary files a/assets/.DS_Store and b/assets/.DS_Store differ
diff --git a/assets/scripts/galleria/.DS_Store b/assets/scripts/galleria/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..205a45f17ae7720b643f07bc5b0f62a9b3d3fb38
Binary files /dev/null and b/assets/scripts/galleria/.DS_Store differ
diff --git a/assets/scripts/galleria/galleria-1.5.7.js b/assets/scripts/galleria/galleria-1.5.7.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e3a27f46b90f5f8f3f84a8c6aa0ba930d5995a0
--- /dev/null
+++ b/assets/scripts/galleria/galleria-1.5.7.js
@@ -0,0 +1,6930 @@
+/**
+ * Galleria v1.5.7 2017-05-10
+ * 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.57,
+    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; },
+    MOBILE = !(
+        ( window.screen.width > 1279 && window.devicePixelRatio == 1 ) || // there are not so many mobile devices with more than 1280px and pixelRatio equal to 1 (i.e. retina displays are equal to 2...)
+        ( window.screen.width > 1000 && window.innerWidth < (window.screen.width * .9) ) // this checks in the end if a user is using a resized browser window which is not common on mobile devices
+    ),
+    IE = (function() {
+
+        var v = 3,
+            div = doc.createElement( 'div' ),
+            all = div.getElementsByTagName( 'i' );
+
+        do {
+            div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->';
+        } 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;(?:amp;)?)*v(?:&lt;[A-Z]+&gt;)?=([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 = $('<scr'+'ipt>').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 = $( '<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 = $('<s>').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( '<i></i>' ).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/, '&#160;') );
+
+            // 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('&#215;') );
+
+            $.each( ['Prev','Next'], function(i, dir) {
+
+                var $d = $( el[ dir.toLowerCase() ] ).html( /v/.test( dir ) ? '&#8249;&#160;' : '&#160;&#8250;' ),
+                    $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('&#8211;');
+
+        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 (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<len; i++ ) {
+            temp.push(i);
+            if ( ++n == size || i == len-1 ) {
+                arr.push( temp );
+                n = 0;
+                temp = [];
+            }
+        }
+
+        var init = function( wait ) {
+            var a = arr.shift();
+            if ( a ) {
+                window.setTimeout(function() {
+                    self.lazyLoad(a, function() {
+                        init( true );
+                    });
+                }, ( delay && wait ) ? delay : 0 );
+            }
+        };
+
+        init( false );
+
+        return this;
+
+    },
+
+    // the internal _run method should be called after loading data into galleria
+    // makes sure the gallery has proper measurements before postrun & ready
+    _run : function() {
+
+        var self = this;
+
+        self._createThumbnails();
+
+        // make sure we have a stageHeight && stageWidth
+
+        Utils.wait({
+
+            timeout: 10000,
+
+            until: function() {
+
+                // Opera crap
+                if ( Galleria.OPERA ) {
+                    self.$( 'stage' ).css( 'display', 'inline-block' );
+                }
+
+                self._stageWidth  = self.$( 'stage' ).width();
+                self._stageHeight = self.$( 'stage' ).height();
+
+                return( self._stageWidth &&
+                        self._stageHeight > 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 !== undefined && 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 ) && MOBILE // rule out false positives on Win10
+
+});
+
+// Galleria static methods
+
+/**
+    Adds a theme that you can use for your Gallery
+
+    @param {Object} theme Object that should contain all your theme settings.
+    <ul>
+        <li>name - name of the theme</li>
+        <li>author - name of the author</li>
+        <li>css - css file name (not path)</li>
+        <li>defaults - default options to apply, including theme-specific options</li>
+        <li>init - the init function</li>
+    </ul>
+
+    @returns {Object} theme
+*/
+
+Galleria.addTheme = function( theme ) {
+
+    // make sure we have a name
+    if ( !theme.name ) {
+        Galleria.raise('No theme name specified');
+    }
+
+    // make sure it's compatible
+    if ( !theme.version || parseInt(Galleria.version*10) > parseInt(theme.version*10) ) {
+        Galleria.raise('This version of Galleria requires '+theme.name+' theme version '+parseInt(Galleria.version*10)/10+' or later', true);
+    }
+
+    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 ).on('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('<br>') );
+    }
+};
+
+/**
+    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 = '<div style="padding:4px;margin:0 0 2px;background:#' +
+                ( fatal ? '811' : '222' ) + ';">' +
+                ( fatal ? '<strong>' + type + ': </strong>' : '' ) +
+                msg + '</div>';
+
+            $.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 ) {
+                $('<div>').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() ).on( '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 = $('<iframe>', {
+                src: src,
+                frameborder: 0,
+                id: id,
+                allowfullscreen: true,
+                css: { visibility: 'hidden' }
+            })[0];
+
+            if ( size ) {
+                $( iframe ).css( size );
+            }
+
+            $( this.container ).find( 'iframe,img' ).remove();
+
+            this.container.appendChild( this.image );
+
+            $('#'+id).on( 'load', (function( self, callback ) {
+                return function() {
+                    window.setTimeout(function() {
+                        $( self.image ).css( 'visibility', 'visible' );
+                        if( typeof callback == 'function' ) {
+                            callback.call( self, self );
+                        }
+                    }, 10);
+                };
+            }( this, callback )));
+
+            return this.container;
+        }
+
+        this.image = new Image();
+
+        // IE8 opacity inherit bug
+        if ( Galleria.IE8 ) {
+            $( this.image ).css( 'filter', 'inherit' );
+        }
+
+        // FF shaking images bug:
+        // http://support.galleria.io/discussions/problems/12245-shaking-photos
+        if ( !Galleria.IE && !Galleria.CHROME && !Galleria.SAFARI ) {
+            $( this.image ).css( 'image-rendering', 'optimizequality' );
+        }
+
+        var reload = false,
+            resort = false,
+
+            // some jquery cache
+            $container = $( this.container ),
+            $image = $( this.image ),
+
+            onerror = function() {
+                if ( !reload ) {
+                    reload = true;
+                    // reload the image with a timestamp
+                    window.setTimeout((function(image, src) {
+                        return function() {
+                            image.attr('src', src + (src.indexOf('?') > -1 ? '&' : '?') + Utils.timestamp() );
+                        };
+                    }( $(this), src )), 50);
+                } else {
+                    // apply the dummy image if it exists
+                    if ( DUMMY ) {
+                        $( this ).attr( 'src', DUMMY );
+                    } else {
+                        Galleria.raise('Image not found: ' + src);
+                    }
+                }
+            },
+
+            // the onload method
+            onload = (function( self, callback, src ) {
+
+                return function() {
+
+                    var complete = function() {
+
+                        $( this ).off( 'load' );
+
+                        // save the original size
+                        self.original = size || {
+                            height: this.height,
+                            width: this.width
+                        };
+
+                        // translate3d if needed
+                        if ( Galleria.HAS3D ) {
+                            this.style.MozTransform = this.style.webkitTransform = 'translate3d(0,0,0)';
+                        }
+
+                        $container.append( this );
+
+                        self.cache[ src ] = src; // will override old cache
+
+                        if (typeof callback == 'function' ) {
+                            window.setTimeout(function() {
+                                callback.call( self, self );
+                            },1);
+                        }
+                    };
+
+                    // Delay the callback to "fix" the Adblock Bug
+                    // http://code.google.com/p/adblockforchrome/issues/detail?id=3701
+                    if ( ( !this.width || !this.height ) ) {
+                        (function( img ) {
+                            Utils.wait({
+                                until: function() {
+                                    return img.width && img.height;
+                                },
+                                success: function() {
+                                    complete.call( img );
+                                },
+                                error: function() {
+                                    if ( !resort ) {
+                                        $(new Image()).on( 'load', onload ).attr( 'src', img.src );
+                                        resort = true;
+                                    } else {
+                                        Galleria.raise('Could not extract width/height from image: ' + img.src +
+                                            '. Traced measures: width:' + img.width + 'px, height: ' + img.height + 'px.');
+                                    }
+                                },
+                                timeout: 100
+                            });
+                        }( this ));
+                    } else {
+                        complete.call( this );
+                    }
+                };
+            }( this, callback, src ));
+
+        // remove any previous images
+        $container.find( 'iframe,img' ).remove();
+
+        // append the image
+        $image.css( 'display', 'block');
+
+        // hide it for now
+        Utils.hide( this.image );
+
+        // remove any max/min scaling
+        $.each('minWidth minHeight maxWidth maxHeight'.split(' '), function(i, prop) {
+            $image.css(prop, (/min/.test(prop) ? '0' : 'none'));
+        });
+
+        // begin load and insert in cache when done
+        $image.on( 'load', onload ).on( 'error', onerror ).attr( 'src', src );
+
+        // return the container
+        return this.container;
+    },
+
+    /**
+        Scales and crops the image
+
+        @param {Object} options The method takes an object with a number of options:
+
+        <ul>
+            <li>width - width of the container</li>
+            <li>height - height of the container</li>
+            <li>min - minimum scale ratio</li>
+            <li>max - maximum scale ratio</li>
+            <li>margin - distance in pixels from the image border to the container</li>
+            <li>complete - a callback that fires when scaling is complete</li>
+            <li>position - positions the image, works like the css background-image property.</li>
+            <li>crop - defines how to crop. Can be true, false, 'width' or 'height'</li>
+            <li>canvas - set to true to try a canvas-based rescale</li>
+        </ul>
+
+        @returns The image container object (jQuery)
+    */
+
+    scale: function( options ) {
+
+        var self = this;
+
+        // extend some defaults
+        options = $.extend({
+            width: 0,
+            height: 0,
+            min: undef,
+            max: undef,
+            margin: 0,
+            complete: F,
+            position: 'center',
+            crop: false,
+            canvas: false,
+            iframelimit: undef
+        }, options);
+
+        if( this.isIframe ) {
+
+            var cw = options.width,
+                ch = options.height,
+                nw, nh;
+            if ( options.iframelimit ) {
+                var r = M.min( options.iframelimit/cw, options.iframelimit/ch );
+                if ( r < 1 ) {
+                    nw = cw * r;
+                    nh = ch * r;
+
+                    $( this.image ).css({
+                        top: ch/2-nh/2,
+                        left: cw/2-nw/2,
+                        position: 'absolute'
+                    });
+                } else {
+                    $( this.image ).css({
+                        top: 0,
+                        left: 0
+                    });
+                }
+            }
+            $( this.image ).width( nw || cw ).height( nh || ch ).removeAttr( 'width' ).removeAttr( 'height' );
+            $( this.container ).width( cw ).height( ch );
+            options.complete.call(self, self);
+            try {
+                if( this.image.contentWindow ) {
+                    $( this.image.contentWindow ).trigger('resize');
+                }
+            } catch(e) {}
+            return this.container;
+
+        }
+
+        // return the element if no image found
+        if (!this.image) {
+            return this.container;
+        }
+
+        // store locale variables
+        var width,
+            height,
+            $container = $( self.container ),
+            data;
+
+        // wait for the width/height
+        Utils.wait({
+            until: function() {
+                width  = options.width ||
+                         $container.width() ||
+                         Utils.parseValue( $container.css('width') );
+
+                height = options.height ||
+                         $container.height() ||
+                         Utils.parseValue( $container.css('height') );
+
+                return width && height;
+            },
+            success: function() {
+
+                // calculate some cropping
+                var newWidth = ( width - options.margin * 2 ) / self.original.width,
+                    newHeight = ( height - options.margin * 2 ) / self.original.height,
+                    min = M.min( newWidth, newHeight ),
+                    max = M.max( newWidth, newHeight ),
+                    cropMap = {
+                        'true'  : max,
+                        'width' : newWidth,
+                        'height': newHeight,
+                        'false' : min,
+                        'landscape': self.original.width > self.original.height ? max : min,
+                        'portrait': self.original.width < self.original.height ? max : min
+                    },
+                    ratio = cropMap[ options.crop.toString() ],
+                    canvasKey = '';
+
+                // allow maxScaleRatio
+                if ( options.max ) {
+                    ratio = M.min( options.max, ratio );
+                }
+
+                // allow minScaleRatio
+                if ( options.min ) {
+                    ratio = M.max( options.min, ratio );
+                }
+
+                $.each( ['width','height'], function( i, m ) {
+                    $( self.image )[ m ]( self[ m ] = self.image[ m ] = M.round( self.original[ m ] * ratio ) );
+                });
+
+                $( self.container ).width( width ).height( height );
+
+                if ( options.canvas && _canvas ) {
+
+                    _canvas.elem.width = self.width;
+                    _canvas.elem.height = self.height;
+
+                    canvasKey = self.image.src + ':' + self.width + 'x' + self.height;
+
+                    self.image.src = _canvas.cache[ canvasKey ] || (function( key ) {
+
+                        _canvas.context.drawImage(self.image, 0, 0, self.original.width*ratio, self.original.height*ratio);
+
+                        try {
+
+                            data = _canvas.elem.toDataURL();
+                            _canvas.length += data.length;
+                            _canvas.cache[ key ] = data;
+                            return data;
+
+                        } catch( e ) {
+                            return self.image.src;
+                        }
+
+                    }( canvasKey ) );
+
+                }
+
+                // calculate image_position
+                var pos = {},
+                    mix = {},
+                    getPosition = function(value, measure, margin) {
+                        var result = 0;
+                        if (/\%/.test(value)) {
+                            var flt = parseInt( value, 10 ) / 100,
+                                m = self.image[ measure ] || $( self.image )[ measure ]();
+
+                            result = M.ceil( m * -1 * flt + margin * flt );
+                        } else {
+                            result = Utils.parseValue( value );
+                        }
+                        return result;
+                    },
+                    positionMap = {
+                        'top': { top: 0 },
+                        'left': { left: 0 },
+                        'right': { left: '100%' },
+                        'bottom': { top: '100%' }
+                    };
+
+                $.each( options.position.toLowerCase().split(' '), function( i, value ) {
+                    if ( value === 'center' ) {
+                        value = '50%';
+                    }
+                    pos[i ? 'top' : 'left'] = value;
+                });
+
+                $.each( pos, function( i, value ) {
+                    if ( positionMap.hasOwnProperty( value ) ) {
+                        $.extend( mix, positionMap[ value ] );
+                    }
+                });
+
+                pos = pos.top ? $.extend( pos, mix ) : mix;
+
+                pos = $.extend({
+                    top: '50%',
+                    left: '50%'
+                }, pos);
+
+                // apply position
+                $( self.image ).css({
+                    position : 'absolute',
+                    top :  getPosition(pos.top, 'height', height),
+                    left : getPosition(pos.left, 'width', width)
+                });
+
+                // show the image
+                self.show();
+
+                // flag ready and call the callback
+                self.ready = true;
+                options.complete.call( self, self );
+
+            },
+            error: function() {
+                Galleria.raise('Could not scale image: '+self.image.src);
+            },
+            timeout: 1000
+        });
+        return this;
+    }
+};
+
+// our own easings
+$.extend( $.easing, {
+
+    galleria: function (_, t, b, c, d) {
+        if ((t/=d/2) < 1) {
+            return c/2*t*t*t + b;
+        }
+        return c/2*((t-=2)*t*t + 2) + b;
+    },
+
+    galleriaIn: function (_, t, b, c, d) {
+        return c*(t/=d)*t + b;
+    },
+
+    galleriaOut: function (_, t, b, c, d) {
+        return -c *(t/=d)*(t-2) + b;
+    }
+
+});
+
+
+// Forked version of Ainos Finger.js for native-style touch
+
+Galleria.Finger = (function() {
+
+    var abs = M.abs;
+
+    // test for translate3d support
+    var has3d = Galleria.HAS3D = (function() {
+
+        var el = doc.createElement('p'),
+            has3d,
+            t = ['webkit','O','ms','Moz',''],
+            s,
+            i=0,
+            a = 'transform';
+
+        DOM().html.insertBefore(el, null);
+
+        for (; t[i]; i++) {
+            s = t[i] ? t[i]+'Transform' : a;
+            if (el.style[s] !== undefined) {
+                el.style[s] = "translate3d(1px,1px,1px)";
+                has3d = $(el).css(t[i] ? '-'+t[i].toLowerCase()+'-'+a : a);
+            }
+        }
+
+        DOM().html.removeChild(el);
+        return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
+    }());
+
+    // request animation shim
+    var requestFrame = (function(){
+        var r = 'RequestAnimationFrame';
+        return window.requestAnimationFrame ||
+               window['webkit'+r] ||
+               window['moz'+r] ||
+               window['o'+r] ||
+               window['ms'+r] ||
+               function( callback ) {
+                   window.setTimeout(callback, 1000 / 60);
+               };
+    }());
+
+    var Finger = function(elem, options) {
+
+        // default options
+        this.config = {
+            start: 0,
+            duration: 500,
+            onchange: function() {},
+            oncomplete: function() {},
+            easing: function(x,t,b,c,d) {
+                return -c * ((t=t/d-1)*t*t*t - 1) + b; // easeOutQuart
+            }
+        };
+
+        this.easeout = function (x, t, b, c, d) {
+            return c*((t=t/d-1)*t*t*t*t + 1) + b;
+        };
+
+        if ( !elem.children.length ) {
+            return;
+        }
+
+        var self = this;
+
+        // extend options
+        $.extend(this.config, options);
+
+        this.elem = elem;
+        this.child = elem.children[0];
+        this.to = this.pos = 0;
+        this.touching = false;
+        this.start = {};
+        this.index = this.config.start;
+        this.anim = 0;
+        this.easing = this.config.easing;
+
+        if ( !has3d ) {
+          this.child.style.position = 'absolute';
+          this.elem.style.position = 'relative';
+        }
+
+        // Bind event handlers to context
+        $.each(['ontouchstart','ontouchmove','ontouchend','setup'], function(i, fn) {
+            self[fn] = (function(caller) {
+                return function() {
+                    caller.apply( self, arguments );
+                };
+            }(self[fn]));
+        });
+
+        // the physical animator
+        this.setX = function() {
+
+            var style = self.child.style;
+
+            if (!has3d) {
+                // this is actually faster than CSS3 translate
+                style.left = self.pos+'px';
+                return;
+            }
+            style.MozTransform = style.webkitTransform = style.transform = 'translate3d(' + self.pos + 'px,0,0)';
+            return;
+        };
+
+        // bind events
+        $(elem).on('touchstart', this.ontouchstart);
+        $(window).on('resize', this.setup);
+        $(window).on('orientationchange', this.setup);
+
+        // set up width
+        this.setup();
+
+        // start the animations
+        (function animloop(){
+          requestFrame(animloop);
+          self.loop.call( self );
+        }());
+
+    };
+
+    Finger.prototype = {
+
+        constructor: Finger,
+
+        setup: function() {
+            this.width = $( this.elem ).width();
+            this.length = M.ceil( $(this.child).width() / this.width );
+            if ( this.index !== 0 ) {
+                this.index = M.max(0, M.min( this.index, this.length-1 ) );
+                this.pos = this.to = -this.width*this.index;
+            }
+        },
+
+        setPosition: function(pos) {
+            this.pos = pos;
+            this.to = pos;
+        },
+
+        ontouchstart: function(e) {
+
+            var touch = e.originalEvent.touches;
+
+            this.start = {
+                pageX: touch[0].pageX,
+                pageY: touch[0].pageY,
+                time:  +new Date()
+            };
+
+            this.isScrolling = null;
+            this.touching = true;
+            this.deltaX = 0;
+
+            $doc.on('touchmove', this.ontouchmove);
+            $doc.on('touchend', this.ontouchend);
+        },
+
+        ontouchmove: function(e) {
+
+            var touch = e.originalEvent.touches;
+
+            // ensure swiping with one touch and not pinching
+            if( touch && touch.length > 1 || e.scale && e.scale !== 1 ) {
+                return;
+            }
+
+            this.deltaX = touch[0].pageX - this.start.pageX;
+
+            // determine if scrolling test has run - one time test
+            if ( this.isScrolling === null ) {
+                this.isScrolling = !!(
+                    this.isScrolling ||
+                    M.abs(this.deltaX) < M.abs(touch[0].pageY - this.start.pageY)
+                );
+            }
+
+            // if user is not trying to scroll vertically
+            if (!this.isScrolling) {
+
+                // prevent native scrolling
+                e.preventDefault();
+
+                // increase resistance if first or last slide
+                this.deltaX /= ( (!this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0 ) ?
+                    ( M.abs(this.deltaX) / this.width + 1.8 )  : 1 );
+                this.to = this.deltaX - this.index * this.width;
+            }
+            e.stopPropagation();
+        },
+
+        ontouchend: function(e) {
+
+            this.touching = false;
+
+            // determine if slide attempt triggers next/prev slide
+            var isValidSlide = +new Date() - this.start.time < 250 &&
+                M.abs(this.deltaX) > 40 ||
+                M.abs(this.deltaX) > this.width/2,
+
+                isPastBounds = !this.index && this.deltaX > 0 ||
+                    this.index == this.length - 1 && this.deltaX < 0;
+
+            // if not scrolling vertically
+            if ( !this.isScrolling ) {
+                this.show( this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ) );
+            }
+
+            $doc.off('touchmove', this.ontouchmove);
+            $doc.off('touchend', this.ontouchend);
+        },
+
+        show: function( index ) {
+            if ( index != this.index ) {
+                this.config.onchange.call(this, index);
+            } else {
+                this.to = -( index*this.width );
+            }
+        },
+
+        moveTo: function( index ) {
+            if ( index != this.index ) {
+                this.pos = this.to = -( index*this.width );
+                this.index = index;
+            }
+        },
+
+        loop: function() {
+
+            var distance = this.to - this.pos,
+                factor = 1;
+
+            if ( this.width && distance ) {
+                factor = M.max(0.5, M.min(1.5, M.abs(distance / this.width) ) );
+            }
+
+            // if distance is short or the user is touching, do a 1-1 animation
+            if ( this.touching || M.abs(distance) <= 1 ) {
+                this.pos = this.to;
+                distance = 0;
+                if ( this.anim && !this.touching ) {
+                    this.config.oncomplete( this.index );
+                }
+                this.anim = 0;
+                this.easing = this.config.easing;
+            } else {
+                if ( !this.anim ) {
+                    // save animation parameters
+                    this.anim = { start: this.pos, time: +new Date(), distance: distance, factor: factor, destination: this.to };
+                }
+                // check if to has changed or time has run out
+                var elapsed = +new Date() - this.anim.time;
+                var duration = this.config.duration*this.anim.factor;
+
+                if ( elapsed > duration || this.anim.destination != this.to ) {
+                    this.anim = 0;
+                    this.easing = this.easeout;
+                    return;
+                }
+                // apply easing
+                this.pos = this.easing(
+                    null,
+                    elapsed,
+                    this.anim.start,
+                    this.anim.distance,
+                    duration
+                );
+            }
+            this.setX();
+        }
+    };
+
+    return Finger;
+
+}());
+
+// the plugin initializer
+$.fn.galleria = function( options ) {
+
+    var selector = this.selector;
+
+    // try domReady if element not found
+    if ( !$(this).length ) {
+
+        $(function() {
+            if ( $( selector ).length ) {
+
+                // if found on domReady, go ahead
+                $( selector ).galleria( options );
+
+            } else {
+
+                // if not, try fetching the element for 5 secs, then raise a warning.
+                Galleria.utils.wait({
+                    until: function() {
+                        return $( selector ).length;
+                    },
+                    success: function() {
+                        $( selector ).galleria( options );
+                    },
+                    error: function() {
+                        Galleria.raise('Init failed: Galleria could not find the element "'+selector+'".');
+                    },
+                    timeout: 5000
+                });
+
+            }
+        });
+        return this;
+    }
+
+    return this.each(function() {
+
+        // destroy previous instance and prepare for new load
+        if ( $.data(this, 'galleria') ) {
+            $.data( this, 'galleria' ).destroy();
+            $( this ).find( '*' ).hide();
+        }
+
+        // load the new gallery
+        $.data( this, 'galleria', new Galleria().init( this, options ) );
+    });
+
+};
+
+// export as AMD or CommonJS
+if ( typeof module === "object" && module && typeof module.exports === "object" ) {
+    module.exports = Galleria;
+} else {
+    window.Galleria = Galleria;
+    if ( typeof define === "function" && define.amd ) {
+        define( "galleria", ['jquery'], function() { return Galleria; } );
+    }
+}
+
+// phew
+
+}( jQuery, this ) );
diff --git a/assets/scripts/galleria/galleria-1.5.7.min.js b/assets/scripts/galleria/galleria-1.5.7.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..cfda735ce8078b51893384e05078257ca329e7ea
--- /dev/null
+++ b/assets/scripts/galleria/galleria-1.5.7.min.js
@@ -0,0 +1,13 @@
+/**
+ * Galleria - v1.5.7 2017-05-10
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a,b,c,d){var e=b.document,f=a(e),g=a(b),h=Array.prototype,i=1.57,j=!0,k=3e4,l=!1,m=navigator.userAgent.toLowerCase(),n=b.location.hash.replace(/#\//,""),o="file:"==b.location.protocol?"http:":b.location.protocol,p=Math,q=function(){},r=function(){return!1},s=!(b.screen.width>1279&&1==b.devicePixelRatio||b.screen.width>1e3&&b.innerWidth<.9*b.screen.width),t=function(){var a=3,b=e.createElement("div"),c=b.getElementsByTagName("i");do b.innerHTML="<!--[if gt IE "+ ++a+"]><i></i><![endif]-->";while(c[0]);return a>4?a:e.documentMode||d}(),u=function(){return{html:e.documentElement,body:e.body,head:e.getElementsByTagName("head")[0],title:e.title}},v=b.parent!==b.self,w="data ready thumbnail loadstart loadfinish image play pause progress fullscreen_enter fullscreen_exit idle_enter idle_exit rescale lightbox_open lightbox_close lightbox_image",x=function(){var b=[];return a.each(w.split(" "),function(a,c){b.push(c),/_/.test(c)&&b.push(c.replace(/_/g,""))}),b}(),y=function(b){var c;return"object"!=typeof b?b:(a.each(b,function(d,e){/^[a-z]+_/.test(d)&&(c="",a.each(d.split("_"),function(a,b){c+=a>0?b.substr(0,1).toUpperCase()+b.substr(1):b}),b[c]=e,delete b[d])}),b)},z=function(b){return a.inArray(b,x)>-1?c[b.toUpperCase()]:b},A={youtube:{reg:/https?:\/\/(?:[a-zA_Z]{2,3}.)?(?:youtube\.com\/watch\?)((?:[\w\d\-\_\=]+&amp;(?:amp;)?)*v(?:&lt;[A-Z]+&gt;)?=([0-9a-zA-Z\-\_]+))/i,embed:function(){return o+"//www.youtube.com/embed/"+this.id},get_thumb:function(a){return o+"//img.youtube.com/vi/"+this.id+"/default.jpg"},get_image:function(a){return o+"//img.youtube.com/vi/"+this.id+"/hqdefault.jpg"}},vimeo:{reg:/https?:\/\/(?:www\.)?(vimeo\.com)\/(?:hd#)?([0-9]+)/i,embed:function(){return o+"//player.vimeo.com/video/"+this.id},getUrl:function(){return o+"//vimeo.com/api/v2/video/"+this.id+".json?callback=?"},get_thumb:function(a){return a[0].thumbnail_medium},get_image:function(a){return a[0].thumbnail_large}},dailymotion:{reg:/https?:\/\/(?:www\.)?(dailymotion\.com)\/video\/([^_]+)/,embed:function(){return o+"//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(a){return a.thumbnail_240_url},get_image:function(a){return a.thumbnail_720_url}},_inst:[]},B=function(c,d){for(var e=0;e<A._inst.length;e++)if(A._inst[e].id===d&&A._inst[e].type==c)return A._inst[e];this.type=c,this.id=d,this.readys=[],A._inst.push(this);var f=this;a.extend(this,A[c]),_videoThumbs=function(b){f.data=b,a.each(f.readys,function(a,b){b(f.data)}),f.readys=[]},this.hasOwnProperty("getUrl")?a.getJSON(this.getUrl(),_videoThumbs):b.setTimeout(_videoThumbs,400),this.getMedia=function(a,b,c){c=c||q;var d=this,e=function(c){b(d["get_"+a](c))};try{d.data?e(d.data):d.readys.push(e)}catch(a){c()}}},C=function(a){var b;for(var c in A)if(b=a&&A[c].reg&&a.match(A[c].reg),b&&b.length)return{id:b[2],provider:c};return!1},D={support:function(){var a=u().html;return!v&&(a.requestFullscreen||a.msRequestFullscreen||a.mozRequestFullScreen||a.webkitRequestFullScreen)}(),callback:q,enter:function(a,b,c){this.instance=a,this.callback=b||q,c=c||u().html,c.requestFullscreen?c.requestFullscreen():c.msRequestFullscreen?c.msRequestFullscreen():c.mozRequestFullScreen?c.mozRequestFullScreen():c.webkitRequestFullScreen&&c.webkitRequestFullScreen()},exit:function(a){this.callback=a||q,e.exitFullscreen?e.exitFullscreen():e.msExitFullscreen?e.msExitFullscreen():e.mozCancelFullScreen?e.mozCancelFullScreen():e.webkitCancelFullScreen&&e.webkitCancelFullScreen()},instance:null,listen:function(){if(this.support){var a=function(){if(D.instance){var a=D.instance._fullscreen;e.fullscreen||e.mozFullScreen||e.webkitIsFullScreen||e.msFullscreenElement&&null!==e.msFullscreenElement?a._enter(D.callback):a._exit(D.callback)}};e.addEventListener("fullscreenchange",a,!1),e.addEventListener("MSFullscreenChange",a,!1),e.addEventListener("mozfullscreenchange",a,!1),e.addEventListener("webkitfullscreenchange",a,!1)}}},E=[],F=[],G=!1,H=!1,I=[],J=[],K=function(b){J.push(b),a.each(I,function(a,c){c._options.theme!=b.name&&(c._initialized||c._options.theme)||(c.theme=b,c._init.call(c))})},L=function(){return{clearTimer:function(b){a.each(c.get(),function(){this.clearTimer(b)})},addTimer:function(b){a.each(c.get(),function(){this.addTimer(b)})},array:function(a){return h.slice.call(a,0)},create:function(a,b){b=b||"div";var c=e.createElement(b);return c.className=a,c},removeFromArray:function(b,c){return a.each(b,function(a,d){if(d==c)return b.splice(a,1),!1}),b},getScriptPath:function(b){b=b||a("script:last").attr("src");var c=b.split("/");return 1==c.length?"":(c.pop(),c.join("/")+"/")},animate:function(){var d,f,g,h,i,j,k,l=function(a){var c,d="transition WebkitTransition MozTransition OTransition".split(" ");if(b.opera)return!1;for(c=0;d[c];c++)if("undefined"!=typeof a[d[c]])return d[c];return!1}((e.body||e.documentElement).style),m={MozTransition:"transitionend",OTransition:"oTransitionEnd",WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[l],n={_default:[.25,.1,.25,1],galleria:[.645,.045,.355,1],galleriaIn:[.55,.085,.68,.53],galleriaOut:[.25,.46,.45,.94],ease:[.25,0,.25,1],linear:[.25,.25,.75,.75],"ease-in":[.42,0,1,1],"ease-out":[0,0,.58,1],"ease-in-out":[.42,0,.58,1]},o=function(b,c,d){var e={};d=d||"transition",a.each("webkit moz ms o".split(" "),function(){e["-"+this+"-"+d]=c}),b.css(e)},p=function(a){o(a,"none","transition"),c.WEBKIT&&c.TOUCH&&(o(a,"translate3d(0,0,0)","transform"),a.data("revert")&&(a.css(a.data("revert")),a.data("revert",null)))};return function(e,r,s){return s=a.extend({duration:400,complete:q,stop:!1},s),e=a(e),s.duration?l?(s.stop&&(e.off(m),p(e)),d=!1,a.each(r,function(a,b){k=e.css(a),L.parseValue(k)!=L.parseValue(b)&&(d=!0),e.css(a,k)}),d?(f=[],g=s.easing in n?n[s.easing]:n._default,h=" "+s.duration+"ms cubic-bezier("+g.join(",")+")",void b.setTimeout(function(b,d,e,g){return function(){b.one(d,function(a){return function(){p(a),s.complete.call(a[0])}}(b)),c.WEBKIT&&c.TOUCH&&(i={},j=[0,0,0],a.each(["left","top"],function(a,c){c in e&&(j[a]=L.parseValue(e[c])-L.parseValue(b.css(c))+"px",i[c]=e[c],delete e[c])}),(j[0]||j[1])&&(b.data("revert",i),f.push("-webkit-transform"+g),o(b,"translate3d("+j.join(",")+")","transform"))),a.each(e,function(a,b){f.push(a+g)}),o(b,f.join(",")),b.css(e)}}(e,m,r,h),2)):void b.setTimeout(function(){s.complete.call(e[0])},s.duration)):void e.animate(r,s):(e.css(r),void s.complete.call(e[0]))}}(),removeAlpha:function(a){if(a instanceof jQuery&&(a=a[0]),t<9&&a){var b=a.style,c=a.currentStyle,d=c&&c.filter||b.filter||"";/alpha/.test(d)&&(b.filter=d.replace(/alpha\([^)]*\)/i,""))}},forceStyles:function(b,c){b=a(b),b.attr("style")&&b.data("styles",b.attr("style")).removeAttr("style"),b.css(c)},revertStyles:function(){a.each(L.array(arguments),function(b,c){c=a(c),c.removeAttr("style"),c.attr("style",""),c.data("styles")&&c.attr("style",c.data("styles")).data("styles",null)})},moveOut:function(a){L.forceStyles(a,{position:"absolute",left:-1e4})},moveIn:function(){L.revertStyles.apply(L,L.array(arguments))},hide:function(b,c,d){d=d||q;var e=a(b);b=e[0],e.data("opacity")||e.data("opacity",e.css("opacity"));var f={opacity:0};if(c){var g=t<9&&b?function(){L.removeAlpha(b),b.style.visibility="hidden",d.call(b)}:d;L.animate(b,f,{duration:c,complete:g,stop:!0})}else t<9&&b?(L.removeAlpha(b),b.style.visibility="hidden"):e.css(f)},show:function(b,c,d){d=d||q;var e=a(b);b=e[0];var f=parseFloat(e.data("opacity"))||1,g={opacity:f};if(c){t<9&&(e.css("opacity",0),b.style.visibility="visible");var h=t<9&&b?function(){1==g.opacity&&L.removeAlpha(b),d.call(b)}:d;L.animate(b,g,{duration:c,complete:h,stop:!0})}else t<9&&1==g.opacity&&b?(L.removeAlpha(b),b.style.visibility="visible"):e.css(g)},wait:function(d){c._waiters=c._waiters||[],d=a.extend({until:r,success:q,error:function(){c.raise("Could not complete wait function.")},timeout:3e3},d);var e,f,g,h=L.timestamp(),i=function(){return f=L.timestamp(),e=f-h,L.removeFromArray(c._waiters,g),d.until(e)?(d.success(),!1):"number"==typeof d.timeout&&f>=h+d.timeout?(d.error(),!1):void c._waiters.push(g=b.setTimeout(i,10))};c._waiters.push(g=b.setTimeout(i,10))},toggleQuality:function(a,b){7!==t&&8!==t||!a||"IMG"!=a.nodeName.toUpperCase()||("undefined"==typeof b&&(b="nearest-neighbor"===a.style.msInterpolationMode),a.style.msInterpolationMode=b?"bicubic":"nearest-neighbor")},insertStyleTag:function(b,c){if(!c||!a("#"+c).length){var d=e.createElement("style");if(c&&(d.id=c),u().head.appendChild(d),d.styleSheet)d.styleSheet.cssText=b;else{var f=e.createTextNode(b);d.appendChild(f)}}},loadScript:function(b,c){var d=!1,e=a("<script>").attr({src:b,async:!0}).get(0);e.onload=e.onreadystatechange=function(){d||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState||(d=!0,e.onload=e.onreadystatechange=null,"function"==typeof c&&c.call(this,this))},u().head.appendChild(e)},parseValue:function(a){if("number"==typeof a)return a;if("string"==typeof a){var b=a.match(/\-?\d|\./g);return b&&b.constructor===Array?1*b.join(""):0}return 0},timestamp:function(){return(new Date).getTime()},loadCSS:function(b,f,g){var h,i;if(a("link[rel=stylesheet]").each(function(){if(new RegExp(b).test(this.href))return h=this,!1}),"function"==typeof f&&(g=f,f=d),g=g||q,h)return g.call(h,h),h;if(i=e.styleSheets.length,a("#"+f).length)a("#"+f).attr("href",b),i--;else{h=a("<link>").attr({rel:"stylesheet",href:b,id:f}).get(0);var j=a('link[rel="stylesheet"], style');if(j.length?j.get(0).parentNode.insertBefore(h,j[0]):u().head.appendChild(h),t&&i>=31)return void c.raise("You have reached the browser stylesheet limit (31)",!0)}if("function"==typeof g){var k=a("<s>").attr("id","galleria-loader").hide().appendTo(u().body);L.wait({until:function(){return k.height()>0},success:function(){k.remove(),g.call(h,h)},error:function(){k.remove(),c.raise("Theme CSS could not load after 20 sec. "+(c.QUIRK?"Your browser is in Quirks Mode, please add a correct doctype.":"Please download the latest theme at http://galleria.io/customer/."),!0)},timeout:5e3})}return h}}}(),M=function(b){var c=".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}";return L.insertStyleTag(c,"galleria-videoicon"),a(L.create("galleria-videoicon")).html("<i></i>").appendTo(b).click(function(){a(this).siblings("img").mouseup()})},N=function(){var b=function(b,c,d,e){var f=this.getOptions("easing"),g=this.getStageWidth(),h={left:g*(b.rewind?-1:1)},i={left:0};d?(h.opacity=0,i.opacity=1):h.opacity=1,a(b.next).css(h),L.animate(b.next,i,{duration:b.speed,complete:function(a){return function(){c(),a.css({left:0})}}(a(b.next).add(b.prev)),queue:!1,easing:f}),e&&(b.rewind=!b.rewind),b.prev&&(h={left:0},i={left:g*(b.rewind?1:-1)},d&&(h.opacity=1,i.opacity=0),a(b.prev).css(h),L.animate(b.prev,i,{duration:b.speed,queue:!1,easing:f,complete:function(){a(this).css("opacity",0)}}))};return{active:!1,init:function(a,b,c){N.effects.hasOwnProperty(a)&&N.effects[a].call(this,b,c)},effects:{fade:function(b,c){a(b.next).css({opacity:0,left:0}),L.animate(b.next,{opacity:1},{duration:b.speed,complete:c}),b.prev&&(a(b.prev).css("opacity",1).show(),L.animate(b.prev,{opacity:0},{duration:b.speed}))},flash:function(b,c){a(b.next).css({opacity:0,left:0}),b.prev?L.animate(b.prev,{opacity:0},{duration:b.speed/2,complete:function(){L.animate(b.next,{opacity:1},{duration:b.speed,complete:c})}}):L.animate(b.next,{opacity:1},{duration:b.speed,complete:c})},pulse:function(b,c){b.prev&&a(b.prev).hide(),a(b.next).css({opacity:0,left:0}).show(),L.animate(b.next,{opacity:1},{duration:b.speed,complete:c})},slide:function(a,c){b.apply(this,L.array(arguments))},fadeslide:function(a,c){b.apply(this,L.array(arguments).concat([!0]))},doorslide:function(a,c){b.apply(this,L.array(arguments).concat([!1,!0]))}}}}();D.listen(),a.event.special["click:fast"]={propagate:!0,add:function(c){var d=function(a){if(a.touches&&a.touches.length){var b=a.touches[0];return{x:b.pageX,y:b.pageY}}},e={touched:!1,touchdown:!1,coords:{x:0,y:0},evObj:{}};a(this).data({clickstate:e,timer:0}).on("touchstart.fast",function(c){b.clearTimeout(a(this).data("timer")),a(this).data("clickstate",{touched:!0,touchdown:!0,coords:d(c.originalEvent),evObj:c})}).on("touchmove.fast",function(b){var c=d(b.originalEvent),e=a(this).data("clickstate"),f=Math.max(Math.abs(e.coords.x-c.x),Math.abs(e.coords.y-c.y));f>6&&a(this).data("clickstate",a.extend(e,{touchdown:!1}))}).on("touchend.fast",function(d){var f=a(this),g=f.data("clickstate");g.touchdown&&c.handler.call(this,d),f.data("timer",b.setTimeout(function(){f.data("clickstate",e)},400))}).on("click.fast",function(b){var d=a(this).data("clickstate");return!d.touched&&(a(this).data("clickstate",e),void c.handler.call(this,b))})},remove:function(){a(this).off("touchstart.fast touchmove.fast touchend.fast click.fast")}},g.on("orientationchange",function(){a(this).resize()}),c=function(){var h=this;this._options={},this._playing=!1,this._playtime=5e3,this._active=null,this._queue={length:0},this._data=[],this._dom={},this._thumbnails=[],this._layers=[],this._initialized=!1,this._firstrun=!1,this._stageWidth=0,this._stageHeight=0,this._target=d,this._binds=[],this._id=parseInt(1e4*p.random(),10);var i="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",j="current total";a.each(i.split(" "),function(a,b){h._dom[b]=L.create("galleria-"+b)}),a.each(j.split(" "),function(a,b){h._dom[b]=L.create("galleria-"+b,"span")});var k=this._keyboard={keys:{UP:38,DOWN:40,LEFT:37,RIGHT:39,RETURN:13,ESCAPE:27,BACKSPACE:8,SPACE:32},map:{},bound:!1,press:function(a){var b=a.keyCode||a.which;b in k.map&&"function"==typeof k.map[b]&&k.map[b].call(h,a)},attach:function(a){var b,c;for(b in a)a.hasOwnProperty(b)&&(c=b.toUpperCase(),c in k.keys?k.map[k.keys[c]]=a[b]:k.map[c]=a[b]);k.bound||(k.bound=!0,f.on("keydown",k.press))},detach:function(){k.bound=!1,k.map={},f.off("keydown",k.press)}},l=this._controls={0:d,1:d,active:0,swap:function(){l.active=l.active?0:1},getActive:function(){return h._options.swipe?l.slides[h._active]:l[l.active]},getNext:function(){return h._options.swipe?l.slides[h.getNext(h._active)]:l[1-l.active]},slides:[],frames:[],layers:[]},n=this._carousel={next:h.$("thumb-nav-right"),prev:h.$("thumb-nav-left"),width:0,current:0,max:0,hooks:[],update:function(){var b=0,c=0,d=[0];a.each(h._thumbnails,function(e,f){if(f.ready){b+=f.outerWidth||a(f.container).outerWidth(!0);var g=a(f.container).width();b+=g-p.floor(g),d[e+1]=b,c=p.max(c,f.outerHeight||a(f.container).outerHeight(!0))}}),h.$("thumbnails").css({width:b,height:c}),n.max=b,n.hooks=d,n.width=h.$("thumbnails-list").width(),n.setClasses(),h.$("thumbnails-container").toggleClass("galleria-carousel",b>n.width),n.width=h.$("thumbnails-list").width()},bindControls:function(){var a;n.next.on("click:fast",function(b){if(b.preventDefault(),"auto"===h._options.carouselSteps){for(a=n.current;a<n.hooks.length;a++)if(n.hooks[a]-n.hooks[n.current]>n.width){n.set(a-2);break}}else n.set(n.current+h._options.carouselSteps)}),n.prev.on("click:fast",function(b){if(b.preventDefault(),"auto"===h._options.carouselSteps)for(a=n.current;a>=0;a--){if(n.hooks[n.current]-n.hooks[a]>n.width){n.set(a+2);break}if(0===a){n.set(0);break}}else n.set(n.current-h._options.carouselSteps)})},set:function(a){for(a=p.max(a,0);n.hooks[a-1]+n.width>=n.max&&a>=0;)a--;n.current=a,n.animate()},getLast:function(a){return(a||n.current)-1},follow:function(a){if(0===a||a===n.hooks.length-2)return void n.set(a);for(var b=n.current;n.hooks[b]-n.hooks[n.current]<n.width&&b<=n.hooks.length;)b++;a-1<n.current?n.set(a-1):a+2>b&&n.set(a-b+n.current+2)},setClasses:function(){n.prev.toggleClass("disabled",!n.current),n.next.toggleClass("disabled",n.hooks[n.current]+n.width>=n.max)},animate:function(b){n.setClasses();var c=n.hooks[n.current]*-1;isNaN(c)||(h.$("thumbnails").css("left",function(){return a(this).css("left")}),L.animate(h.get("thumbnails"),{left:c},{duration:h._options.carouselSpeed,easing:h._options.easing,queue:!1}))}},o=this._tooltip={initialized:!1,open:!1,timer:"tooltip"+h._id,swapTimer:"swap"+h._id,init:function(){o.initialized=!0;var a=".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);}";L.insertStyleTag(a,"galleria-tooltip"),h.$("tooltip").css({opacity:.8,visibility:"visible",display:"none"})},move:function(a){var b=h.getMousePosition(a).x,c=h.getMousePosition(a).y,d=h.$("tooltip"),e=b,f=c,g=d.outerHeight(!0)+1,i=d.outerWidth(!0),j=g+15,k=h.$("container").width()-i-2,l=h.$("container").height()-g-2;isNaN(e)||isNaN(f)||(e+=10,f-=g+8,e=p.max(0,p.min(k,e)),f=p.max(0,p.min(l,f)),c<j&&(f=j),d.css({left:e,top:f}))},bind:function(b,d){if(!c.TOUCH){o.initialized||o.init();var e=function(){h.$("container").off("mousemove",o.move),h.clearTimer(o.timer),h.$("tooltip").stop().animate({opacity:0},200,function(){h.$("tooltip").hide(),h.addTimer(o.swapTimer,function(){o.open=!1},1e3)})},f=function(b,c){o.define(b,c),a(b).hover(function(){h.clearTimer(o.swapTimer),h.$("container").off("mousemove",o.move).on("mousemove",o.move).trigger("mousemove"),o.show(b),h.addTimer(o.timer,function(){h.$("tooltip").stop().show().animate({opacity:1}),o.open=!0},o.open?0:500)},e).click(e)};"string"==typeof d?f(b in h._dom?h.get(b):b,d):a.each(b,function(a,b){f(h.get(a),b)})}},show:function(c){c=a(c in h._dom?h.get(c):c);var d=c.data("tt"),e=function(a){b.setTimeout(function(a){return function(){o.move(a)}}(a),10),c.off("mouseup",e)};d="function"==typeof d?d():d,d&&(h.$("tooltip").html(d.replace(/\s/,"&#160;")),c.on("mouseup",e))},define:function(b,c){if("function"!=typeof c){var d=c;c=function(){return d}}b=a(b in h._dom?h.get(b):b).data("tt",c),o.show(b)}},q=this._fullscreen={scrolled:0,crop:d,active:!1,prev:a(),beforeEnter:function(a){a()},beforeExit:function(a){a()},keymap:h._keyboard.map,parseCallback:function(b,c){return N.active?function(){"function"==typeof b&&b.call(h);var d=h._controls.getActive(),e=h._controls.getNext();h._scaleImage(e),h._scaleImage(d),c&&h._options.trueFullscreen&&a(d.container).add(e.container).trigger("transitionend")}:b},enter:function(a){q.beforeEnter(function(){a=q.parseCallback(a,!0),h._options.trueFullscreen&&D.support?(q.active=!0,L.forceStyles(h.get("container"),{width:"100%",height:"100%"}),h.rescale(),c.MAC?c.SAFARI&&/version\/[1-5]/.test(m)?(h.$("stage").css("opacity",0),b.setTimeout(function(){q.scale(),h.$("stage").css("opacity",1)},4)):(h.$("container").css("opacity",0).addClass("fullscreen"),b.setTimeout(function(){q.scale(),h.$("container").css("opacity",1)},50)):h.$("container").addClass("fullscreen"),g.resize(q.scale),D.enter(h,a,h.get("container"))):(q.scrolled=g.scrollTop(),c.TOUCH||b.scrollTo(0,0),q._enter(a))})},_enter:function(f){q.active=!0,v&&(q.iframe=function(){var d,f=e.referrer,g=e.createElement("a"),h=b.location;return g.href=f,g.protocol!=h.protocol||g.hostname!=h.hostname||g.port!=h.port?(c.raise("Parent fullscreen not available. Iframe protocol, domains and ports must match."),!1):(q.pd=b.parent.document,a(q.pd).find("iframe").each(function(){var a=this.contentDocument||this.contentWindow.document;if(a===e)return d=this,!1}),d)}()),L.hide(h.getActiveImage()),v&&q.iframe&&(q.iframe.scrolled=a(b.parent).scrollTop(),b.parent.scrollTo(0,0));var i=h.getData(),j=h._options,k=!h._options.trueFullscreen||!D.support,l={height:"100%",overflow:"hidden",margin:0,padding:0};if(k&&(h.$("container").addClass("fullscreen"),q.prev=h.$("container").prev(),q.prev.length||(q.parent=h.$("container").parent()),h.$("container").appendTo("body"),L.forceStyles(h.get("container"),{position:c.TOUCH?"absolute":"fixed",top:0,left:0,width:"100%",height:"100%",zIndex:1e4}),L.forceStyles(u().html,l),L.forceStyles(u().body,l)),v&&q.iframe&&(L.forceStyles(q.pd.documentElement,l),L.forceStyles(q.pd.body,l),L.forceStyles(q.iframe,a.extend(l,{width:"100%",height:"100%",top:0,left:0,position:"fixed",zIndex:1e4,border:"none"}))),q.keymap=a.extend({},h._keyboard.map),h.attachKeyboard({escape:h.exitFullscreen,right:h.next,left:h.prev}),q.crop=j.imageCrop,j.fullscreenCrop!=d&&(j.imageCrop=j.fullscreenCrop),i&&i.big&&i.image!==i.big){var m=new c.Picture,n=m.isCached(i.big),o=h.getIndex(),p=h._thumbnails[o];h.trigger({type:c.LOADSTART,cached:n,rewind:!1,index:o,imageTarget:h.getActiveImage(),thumbTarget:p,galleriaData:i}),m.load(i.big,function(b){h._scaleImage(b,{complete:function(b){h.trigger({type:c.LOADFINISH,cached:n,index:o,rewind:!1,imageTarget:b.image,thumbTarget:p});var d=h._controls.getActive().image;d&&a(d).width(b.image.width).height(b.image.height).attr("style",a(b.image).attr("style")).attr("src",b.image.src)}})});var r=h.getNext(o),s=new c.Picture,t=h.getData(r);s.preload(h.isFullscreen()&&t.big?t.big:t.image)}h.rescale(function(){h.addTimer(!1,function(){k&&L.show(h.getActiveImage()),"function"==typeof f&&f.call(h),h.rescale()},100),h.trigger(c.FULLSCREEN_ENTER)}),k?g.resize(q.scale):L.show(h.getActiveImage())},scale:function(){h.rescale()},exit:function(a){q.beforeExit(function(){a=q.parseCallback(a),h._options.trueFullscreen&&D.support?D.exit(a):q._exit(a)})},_exit:function(a){q.active=!1;var d=!h._options.trueFullscreen||!D.support,e=h.$("container").removeClass("fullscreen");if(q.parent?q.parent.prepend(e):e.insertAfter(q.prev),d){L.hide(h.getActiveImage()),L.revertStyles(h.get("container"),u().html,u().body),c.TOUCH||b.scrollTo(0,q.scrolled);var f=h._controls.frames[h._controls.active];f&&f.image&&(f.image.src=f.image.src)}v&&q.iframe&&(L.revertStyles(q.pd.documentElement,q.pd.body,q.iframe),q.iframe.scrolled&&b.parent.scrollTo(0,q.iframe.scrolled)),h.detachKeyboard(),h.attachKeyboard(q.keymap),h._options.imageCrop=q.crop;var i=h.getData().big,j=h._controls.getActive().image;!h.getData().iframe&&j&&i&&i==j.src&&b.setTimeout(function(a){return function(){j.src=a}}(h.getData().image),1),h.rescale(function(){h.addTimer(!1,function(){d&&L.show(h.getActiveImage()),"function"==typeof a&&a.call(h),g.trigger("resize")},50),h.trigger(c.FULLSCREEN_EXIT)}),g.off("resize",q.scale)}},r=this._idle={trunk:[],bound:!1,active:!1,add:function(b,d,e,f){if(b&&!c.TOUCH){r.bound||r.addEvent(),b=a(b),"boolean"==typeof e&&(f=e,e={}),e=e||{};var g,h={};for(g in d)d.hasOwnProperty(g)&&(h[g]=b.css(g));b.data("idle",{from:a.extend(h,e),to:d,complete:!0,busy:!1}),f?b.css(d):r.addTimer(),r.trunk.push(b)}},remove:function(b){b=a(b),a.each(r.trunk,function(a,c){c&&c.length&&!c.not(b).length&&(b.css(b.data("idle").from),r.trunk.splice(a,1))}),r.trunk.length||(r.removeEvent(),h.clearTimer(r.timer))},addEvent:function(){r.bound=!0,h.$("container").on("mousemove click",r.showAll),"hover"==h._options.idleMode&&h.$("container").on("mouseleave",r.hide)},removeEvent:function(){r.bound=!1,h.$("container").on("mousemove click",r.showAll),"hover"==h._options.idleMode&&h.$("container").off("mouseleave",r.hide)},addTimer:function(){"hover"!=h._options.idleMode&&h.addTimer("idle",function(){r.hide()},h._options.idleTime)},hide:function(){if(h._options.idleMode&&h.getIndex()!==!1){h.trigger(c.IDLE_ENTER);var b=r.trunk.length;a.each(r.trunk,function(a,c){var d=c.data("idle");d&&(c.data("idle").complete=!1,L.animate(c,d.to,{duration:h._options.idleSpeed,complete:function(){a==b-1&&(r.active=!1)}}))})}},showAll:function(){h.clearTimer("idle"),a.each(r.trunk,function(a,b){r.show(b)})},show:function(b){var d=b.data("idle");r.active&&(d.busy||d.complete)||(d.busy=!0,h.trigger(c.IDLE_EXIT),h.clearTimer("idle"),L.animate(b,d.from,{duration:h._options.idleSpeed/2,complete:function(){r.active=!0,a(b).data("idle").busy=!1,a(b).data("idle").complete=!0}})),r.addTimer()}},s=this._lightbox={width:0,height:0,initialized:!1,active:null,image:null,elems:{},keymap:!1,init:function(){if(!s.initialized){s.initialized=!0;var b="overlay box content shadow title info close prevholder prev nextholder next counter image",d={},e=h._options,f="",g="position:absolute;",i="lightbox-",j={overlay:"position:fixed;display:none;opacity:"+e.overlayOpacity+";filter:alpha(opacity="+100*e.overlayOpacity+");top:0;left:0;width:100%;height:100%;background:"+e.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:g+"background:#000;width:100%;height:100%;",content:g+"background-color:#fff;top:10px;left:10px;right:10px;bottom:10px;overflow:hidden",info:g+"bottom:10px;left:10px;right:10px;color:#444;font:11px/13px arial,sans-serif;height:13px",close:g+"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:g+"top:10px;left:10px;right:10px;bottom:30px;overflow:hidden;display:block;",prevholder:g+"width:50%;top:0;bottom:40px;cursor:pointer;",nextholder:g+"width:50%;top:0;bottom:40px;right:-1px;cursor:pointer;",prev:g+"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:g+"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;"},k=function(b){return b.hover(function(){a(this).css("color","#bbb")},function(){a(this).css("color","#444")})},l={},m="";m=t>7?t<9?"background:#000;filter:alpha(opacity=0);":"background:rgba(0,0,0,0);":"z-index:99999",j.nextholder+=m,j.prevholder+=m,a.each(j,function(a,b){f+=".galleria-"+i+a+"{"+b+"}"}),f+=".galleria-"+i+"box.iframe .galleria-"+i+"prevholder,.galleria-"+i+"box.iframe .galleria-"+i+"nextholder{width:100px;height:100px;top:50%;margin-top:-70px}",L.insertStyleTag(f,"galleria-lightbox"),a.each(b.split(" "),function(a,b){h.addElement("lightbox-"+b),d[b]=s.elems[b]=h.get("lightbox-"+b)}),s.image=new c.Picture,a.each({box:"shadow content close prevholder nextholder",info:"title counter",content:"info image",prevholder:"prev",nextholder:"next"},function(b,c){var d=[];a.each(c.split(" "),function(a,b){d.push(i+b)}),l[i+b]=d}),h.append(l),a(d.image).append(s.image.container),a(u().body).append(d.overlay,d.box),k(a(d.close).on("click:fast",s.hide).html("&#215;")),a.each(["Prev","Next"],function(b,e){var f=a(d[e.toLowerCase()]).html(/v/.test(e)?"&#8249;&#160;":"&#160;&#8250;"),g=a(d[e.toLowerCase()+"holder"]);return g.on("click:fast",function(){s["show"+e]()}),t<8||c.TOUCH?void f.show():void g.hover(function(){f.show()},function(a){f.stop().fadeOut(200)})}),a(d.overlay).on("click:fast",s.hide),c.IPAD&&(h._options.lightboxTransitionSpeed=0)}},rescale:function(b){var d=p.min(g.width()-40,s.width),e=p.min(g.height()-60,s.height),f=p.min(d/s.width,e/s.height),i=p.round(s.width*f)+40,j=p.round(s.height*f)+60,k={width:i,height:j,"margin-top":p.ceil(j/2)*-1,"margin-left":p.ceil(i/2)*-1};b?a(s.elems.box).css(k):a(s.elems.box).animate(k,{duration:h._options.lightboxTransitionSpeed,easing:h._options.easing,complete:function(){var b=s.image,d=h._options.lightboxFadeSpeed;h.trigger({type:c.LIGHTBOX_IMAGE,imageTarget:b.image}),a(b.container).show(),a(b.image).animate({opacity:1},d),L.show(s.elems.info,d)}})},hide:function(){s.image.image=null,g.off("resize",s.rescale),a(s.elems.box).hide().find("iframe").remove(),L.hide(s.elems.info),h.detachKeyboard(),h.attachKeyboard(s.keymap),s.keymap=!1,L.hide(s.elems.overlay,200,function(){a(this).hide().css("opacity",h._options.overlayOpacity),h.trigger(c.LIGHTBOX_CLOSE)})},showNext:function(){s.show(h.getNext(s.active))},showPrev:function(){s.show(h.getPrev(s.active))},show:function(d){s.active=d="number"==typeof d?d:h.getIndex()||0,s.initialized||s.init(),h.trigger(c.LIGHTBOX_OPEN),s.keymap||(s.keymap=a.extend({},h._keyboard.map),h.attachKeyboard({escape:s.hide,right:s.showNext,left:s.showPrev})),g.off("resize",s.rescale);var e,f,i,j=h.getData(d),k=h.getDataLength(),l=h.getNext(d);L.hide(s.elems.info);try{for(i=h._options.preload;i>0;i--)f=new c.Picture,e=h.getData(l),f.preload(e.big?e.big:e.image),l=h.getNext(l)}catch(a){}s.image.isIframe=j.iframe&&!j.image,a(s.elems.box).toggleClass("iframe",s.image.isIframe),a(s.image.container).find(".galleria-videoicon").remove(),s.image.load(j.big||j.image||j.iframe,function(c){if(c.isIframe){var e=a(b).width(),f=a(b).height();if(c.video&&h._options.maxVideoSize){var i=p.min(h._options.maxVideoSize/e,h._options.maxVideoSize/f);i<1&&(e*=i,f*=i)}s.width=e,s.height=f}else s.width=c.original.width,s.height=c.original.height;if(a(c.image).css({width:c.isIframe?"100%":"100.1%",height:c.isIframe?"100%":"100.1%",top:0,bottom:0,zIndex:99998,opacity:0,visibility:"visible"}).parent().height("100%"),s.elems.title.innerHTML=j.title||"",s.elems.counter.innerHTML=d+1+" / "+k,g.resize(s.rescale),s.rescale(),j.image&&j.iframe){if(a(s.elems.box).addClass("iframe"),j.video){var l=M(c.container).hide();b.setTimeout(function(){l.fadeIn(200)},200)}a(c.image).css("cursor","pointer").mouseup(function(b,c){return function(d){a(s.image.container).find(".galleria-videoicon").remove(),d.preventDefault(),c.isIframe=!0,c.load(b.iframe+(b.video?"&autoplay=1":""),{width:"100%",height:t<8?a(s.image.container).height():"100%"})}}(j,c))}}),a(s.elems.overlay).show().css("visibility","visible"),a(s.elems.box).show()}},w=this._timer={trunk:{},add:function(a,c,d,e){if(a=a||(new Date).getTime(),e=e||!1,this.clear(a),e){var f=c;c=function(){f(),w.add(a,c,d)}}this.trunk[a]=b.setTimeout(c,d)},clear:function(a){var c,d=function(a){b.clearTimeout(this.trunk[a]),delete this.trunk[a]};if(a&&a in this.trunk)d.call(this,a);else if("undefined"==typeof a)for(c in this.trunk)this.trunk.hasOwnProperty(c)&&d.call(this,c)}};return this},c.prototype={constructor:c,init:function(b,e){if(e=y(e),this._original={target:b,options:e,data:null},this._target=this._dom.target=b.nodeName?b:a(b).get(0),this._original.html=this._target.innerHTML,F.push(this),!this._target)return void c.raise("Target not found",!0);if(this._options={autoplay:!1,carousel:!0,carouselFollow:!0,carouselSpeed:400,carouselSteps:"auto",clicknext:!1,dailymotion:{foreground:"%23EEEEEE",highlight:"%235BCEC5",background:"%23222222",logo:0,hideInfos:1},dataConfig:function(a){return{}},dataSelector:"img",dataSort:!1,dataSource:this._target,debug:d,dummy:d,easing:"galleria",extend:function(a){},fullscreenCrop:d,fullscreenDoubleTap:!0,fullscreenTransition:d,height:0,idleMode:!0,idleTime:3e3,idleSpeed:200,imageCrop:!1,imageMargin:0,imagePan:!1,imagePanSmoothness:12,imagePosition:"50%",imageTimeout:d,initialTransition:d,keepSource:!1,layerFollow:!0,lightbox:!1,lightboxFadeSpeed:200,lightboxTransitionSpeed:200,linkSourceImages:!0,maxScaleRatio:d,maxVideoSize:d,minScaleRatio:d,overlayOpacity:.85,overlayBackground:"#0b0b0b",pauseOnInteraction:!0,popupLinks:!1,preload:2,queue:!0,responsive:!0,show:0,showInfo:!0,showCounter:!0,showImagenav:!0,swipe:"auto",theme:null,thumbCrop:!0,thumbEventType:"click:fast",thumbMargin:0,thumbQuality:"auto",thumbDisplayOrder:!0,thumbPosition:"50%",thumbnails:!0,touchTransition:d,transition:"fade",transitionInitial:d,transitionSpeed:400,trueFullscreen:!0,useCanvas:!1,variation:"",videoPoster:!0,vimeo:{title:0,byline:0,portrait:0,color:"aaaaaa"},wait:5e3,
+width:"auto",youtube:{modestbranding:1,autohide:1,color:"white",hd:1,rel:0,showinfo:0}},this._options.initialTransition=this._options.initialTransition||this._options.transitionInitial,e&&(e.debug===!1&&(j=!1),"number"==typeof e.imageTimeout&&(k=e.imageTimeout),"string"==typeof e.dummy&&(l=e.dummy),"string"==typeof e.theme&&(this._options.theme=e.theme)),a(this._target).children().hide(),c.QUIRK&&c.raise("Your page is in Quirks mode, Galleria may not render correctly. Please validate your HTML and add a correct doctype."),J.length)if(this._options.theme){for(var f=0;f<J.length;f++)if(this._options.theme===J[f].name){this.theme=J[f];break}}else this.theme=J[0];return"object"==typeof this.theme?this._init():I.push(this),this},_init:function(){var f=this,h=this._options;if(this._initialized)return c.raise("Init failed: Gallery instance already initialized."),this;if(this._initialized=!0,!this.theme)return c.raise("Init failed: No theme found.",!0),this;if(a.extend(!0,h,this.theme.defaults,this._original.options,c.configure.options),h.swipe=function(a){return"enforced"==a||a!==!1&&"disabled"!=a&&!!c.TOUCH}(h.swipe),h.swipe&&(h.clicknext=!1,h.imagePan=!1),function(a){return"getContext"in a?void(H=H||{elem:a,context:a.getContext("2d"),cache:{},length:0}):void(a=null)}(e.createElement("canvas")),this.bind(c.DATA,function(){b.screen&&b.screen.width&&Array.prototype.forEach&&this._data.forEach(function(a){var c="devicePixelRatio"in b?b.devicePixelRatio:1,d=p.max(b.screen.width,b.screen.height);d*c<1024&&(a.big=a.image)}),this._original.data=this._data,this.get("total").innerHTML=this.getDataLength();var a=this.$("container");f._options.height<2&&(f._userRatio=f._ratio=f._options.height);var d={width:0,height:0},e=function(){return f.$("stage").height()};L.wait({until:function(){return d=f._getWH(),a.width(d.width).height(d.height),e()&&d.width&&d.height>50},success:function(){f._width=d.width,f._height=d.height,f._ratio=f._ratio||d.height/d.width,c.WEBKIT?b.setTimeout(function(){f._run()},1):f._run()},error:function(){e()?c.raise("Could not extract sufficient width/height of the gallery container. Traced measures: width:"+d.width+"px, height: "+d.height+"px.",!0):c.raise("Could not extract a stage height from the CSS. Traced height: "+e()+"px.",!0)},timeout:"number"==typeof this._options.wait&&this._options.wait})}),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"]}),L.hide(this.$("counter").append(this.get("current"),e.createTextNode(" / "),this.get("total"))),this.setCounter("&#8211;"),L.hide(f.get("tooltip")),this.$("container").addClass([c.TOUCH?"touch":"notouch",this._options.variation,"galleria-theme-"+this.theme.name].join(" ")),this._options.swipe||a.each(new Array(2),function(b){var d=new c.Picture;a(d.container).css({position:"absolute",top:0,left:0}).prepend(f._layers[b]=a(L.create("galleria-layer")).css({position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:2})[0]),f.$("images").append(d.container),f._controls[b]=d;var e=new c.Picture;e.isIframe=!0,a(e.container).attr("class","galleria-frame").css({position:"absolute",top:0,left:0,zIndex:4,background:"#000",display:"none"}).appendTo(d.container),f._controls.frames[b]=e}),this.$("images").css({position:"relative",top:0,left:0,width:"100%",height:"100%"}),h.swipe&&(this.$("images").css({position:"absolute",top:0,left:0,width:0,height:"100%"}),this.finger=new c.Finger(this.get("stage"),{onchange:function(a){f.pause().show(a)},oncomplete:function(b){var c=p.max(0,p.min(parseInt(b,10),f.getDataLength()-1)),d=f.getData(c);a(f._thumbnails[c].container).addClass("active").siblings(".active").removeClass("active"),d&&(f.$("images").find(".galleria-frame").css("opacity",0).hide().find("iframe").remove(),f._options.carousel&&f._options.carouselFollow&&f._carousel.follow(c))}}),this.bind(c.RESCALE,function(){this.finger.setup()}),this.$("stage").on("click",function(c){var e=f.getData();if(e){if(e.iframe){f.isPlaying()&&f.pause();var g=f._controls.frames[f._active],h=f._stageWidth,i=f._stageHeight;if(a(g.container).find("iframe").length)return;return a(g.container).css({width:h,height:i,opacity:0}).show().animate({opacity:1},200),void b.setTimeout(function(){g.load(e.iframe+(e.video?"&autoplay=1":""),{width:h,height:i},function(a){f.$("container").addClass("videoplay"),a.scale({width:f._stageWidth,height:f._stageHeight,iframelimit:e.video?f._options.maxVideoSize:d})})},100)}if(e.link)if(f._options.popupLinks){b.open(e.link,"_blank")}else b.location.href=e.link;else;}}),this.bind(c.IMAGE,function(b){f.setCounter(b.index),f.setInfo(b.index);var c=this.getNext(),d=this.getPrev(),e=[d,c];e.push(this.getNext(c),this.getPrev(d),f._controls.slides.length-1);var g=[];a.each(e,function(b,c){a.inArray(c,g)==-1&&g.push(c)}),a.each(g,function(b,c){var d=f.getData(c),e=f._controls.slides[c],g=f.isFullscreen()&&d.big?d.big:d.image||d.iframe;d.iframe&&!d.image&&(e.isIframe=!0),e.ready||f._controls.slides[c].load(g,function(b){b.isIframe||a(b.image).css("visibility","hidden"),f._scaleImage(b,{complete:function(b){b.isIframe||a(b.image).css({opacity:0,visibility:"visible"}).animate({opacity:1},200)}})})})})),this.$("thumbnails, thumbnails-list").css({overflow:"hidden",position:"relative"}),this.$("image-nav-right, image-nav-left").on("click:fast",function(a){h.pauseOnInteraction&&f.pause();var b=/right/.test(this.className)?"next":"prev";f[b]()}).on("click",function(a){a.preventDefault(),(h.clicknext||h.swipe)&&a.stopPropagation()}),a.each(["info","counter","image-nav"],function(a,b){h["show"+b.substr(0,1).toUpperCase()+b.substr(1).replace(/-/,"")]===!1&&L.moveOut(f.get(b.toLowerCase()))}),this.load(),h.keepSource||t||(this._target.innerHTML=""),this.get("errors")&&this.appendChild("target","errors"),this.appendChild("target","container"),h.carousel){var i=0,j=h.show;this.bind(c.THUMBNAIL,function(){this.updateCarousel(),++i==this.getDataLength()&&"number"==typeof j&&j>0&&this._carousel.follow(j)})}return h.responsive&&g.on("resize",function(){f.isFullscreen()||f.resize()}),h.fullscreenDoubleTap&&this.$("stage").on("touchstart",function(){var a,b,c,d,e,g,h=function(a){return a.originalEvent.touches?a.originalEvent.touches[0]:a};return f.$("stage").on("touchmove",function(){a=0}),function(i){if(!/(-left|-right)/.test(i.target.className)){if(g=L.timestamp(),b=h(i).pageX,c=h(i).pageY,i.originalEvent.touches.length<2&&g-a<300&&b-d<20&&c-e<20)return f.toggleFullscreen(),void i.preventDefault();a=g,d=b,e=c}}}()),a.each(c.on.binds,function(b,c){a.inArray(c.hash,f._binds)==-1&&f.bind(c.type,c.callback)}),this},addTimer:function(){return this._timer.add.apply(this._timer,L.array(arguments)),this},clearTimer:function(){return this._timer.clear.apply(this._timer,L.array(arguments)),this},_getWH:function(){var b,c=this.$("container"),d=this.$("target"),e=this,f={};return a.each(["width","height"],function(a,g){e._options[g]&&"number"==typeof e._options[g]?f[g]=e._options[g]:(b=[L.parseValue(c.css(g)),L.parseValue(d.css(g)),c[g](),d[g]()],e["_"+g]||b.splice(b.length,L.parseValue(c.css("min-"+g)),L.parseValue(d.css("min-"+g))),f[g]=p.max.apply(p,b))}),e._userRatio&&(f.height=f.width*e._userRatio),f},_createThumbnails:function(d){this.get("total").innerHTML=this.getDataLength();var f,g,h,i,j=this,k=this._options,l=d?this._data.length-d.length:0,m=l,n=[],o=0,p=t<8?"http://upload.wikimedia.org/wikipedia/commons/c/c0/Blank.gif":"data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D",q=function(){var a=j.$("thumbnails").find(".active");return!!a.length&&a.find("img").attr("src")}(),r="string"==typeof k.thumbnails?k.thumbnails.toLowerCase():null,s=function(a){return e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g.container,null)[a]:i.css(a)},u=function(b,d,e){return function(){a(e).append(b),j.trigger({type:c.THUMBNAIL,thumbTarget:b,index:d,galleriaData:j.getData(d)})}},v=function(b){k.pauseOnInteraction&&j.pause();var c=a(b.currentTarget).data("index");j.getIndex()!==c&&j.show(c),b.preventDefault()},w=function(b,d){a(b.container).css("visibility","visible"),j.trigger({type:c.THUMBNAIL,thumbTarget:b.image,index:b.data.order,galleriaData:j.getData(b.data.order)}),"function"==typeof d&&d.call(j,b)},x=function(b,c){b.scale({width:b.data.width,height:b.data.height,crop:k.thumbCrop,margin:k.thumbMargin,canvas:k.useCanvas,position:k.thumbPosition,complete:function(b){var d,e,f=["left","top"],g=["Width","Height"];j.getData(b.index);a.each(g,function(c,g){d=g.toLowerCase(),k.thumbCrop===!0&&k.thumbCrop!==d||(e={},e[d]=b[d],a(b.container).css(e),e={},e[f[c]]=0,a(b.image).css(e)),b["outer"+g]=a(b.container)["outer"+g](!0)}),L.toggleQuality(b.image,k.thumbQuality===!0||"auto"===k.thumbQuality&&b.original.width<3*b.width),k.thumbDisplayOrder&&!b.lazy?a.each(n,function(a,b){if(a===o&&b.ready&&!b.displayed)return o++,b.displayed=!0,void w(b,c)}):w(b,c)}})};for(d||(this._thumbnails=[],this.$("thumbnails").empty());this._data[l];l++)h=this._data[l],f=h.thumb||h.image,k.thumbnails!==!0&&"lazy"!=r||!h.thumb&&!h.image?h.iframe&&null!==r||"empty"===r||"numbers"===r?(g={container:L.create("galleria-image"),image:L.create("img","span"),ready:!0,data:{order:l}},"numbers"===r&&a(g.image).text(l+1),h.iframe&&a(g.image).addClass("iframe"),this.$("thumbnails").append(g.container),b.setTimeout(u(g.image,l,g.container),50+20*l)):g={container:null,image:null}:(g=new c.Picture(l),g.index=l,g.displayed=!1,g.lazy=!1,g.video=!1,this.$("thumbnails").append(g.container),i=a(g.container),i.css("visibility","hidden"),g.data={width:L.parseValue(s("width")),height:L.parseValue(s("height")),order:l,src:f},k.thumbCrop!==!0?i.css({width:"auto",height:"auto"}):i.css({width:g.data.width,height:g.data.height}),"lazy"==r?(i.addClass("lazy"),g.lazy=!0,g.load(p,{height:g.data.height,width:g.data.width})):g.load(f,x),"all"===k.preload&&g.preload(h.image)),a(g.container).add(k.keepSource&&k.linkSourceImages?h.original:null).data("index",l).on(k.thumbEventType,v).data("thumbload",x),q===f&&a(g.container).addClass("active"),this._thumbnails.push(g);return n=this._thumbnails.slice(m),this},lazyLoad:function(b,c){var d=b.constructor==Array?b:[b],e=this,f=0;return a.each(d,function(b,g){if(!(g>e._thumbnails.length-1)){var h=e._thumbnails[g],i=h.data,j=function(){++f==d.length&&"function"==typeof c&&c.call(e)},k=a(h.container).data("thumbload");k&&(h.video?k.call(e,h,j):h.load(i.src,function(a){k.call(e,a,j)}))}}),this},lazyLoadChunks:function(a,c){var d=this.getDataLength(),e=0,f=0,g=[],h=[],i=this;for(c=c||0;e<d;e++)h.push(e),++f!=a&&e!=d-1||(g.push(h),f=0,h=[]);var j=function(a){var d=g.shift();d&&b.setTimeout(function(){i.lazyLoad(d,function(){j(!0)})},c&&a?c:0)};return j(!1),this},_run:function(){var e=this;e._createThumbnails(),L.wait({timeout:1e4,until:function(){return c.OPERA&&e.$("stage").css("display","inline-block"),e._stageWidth=e.$("stage").width(),e._stageHeight=e.$("stage").height(),e._stageWidth&&e._stageHeight>50},success:function(){if(E.push(e),e._options.swipe){var f=e.$("images").width(e.getDataLength()*e._stageWidth);a.each(new Array(e.getDataLength()),function(b){var d=new c.Picture,g=e.getData(b);a(d.container).css({position:"absolute",top:0,left:e._stageWidth*b}).prepend(e._layers[b]=a(L.create("galleria-layer")).css({position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:2})[0]).appendTo(f),g.video&&M(d.container),e._controls.slides.push(d);var h=new c.Picture;h.isIframe=!0,a(h.container).attr("class","galleria-frame").css({position:"absolute",top:0,left:0,zIndex:4,background:"#000",display:"none"}).appendTo(d.container),e._controls.frames.push(h)}),e.finger.setup()}return L.show(e.get("counter")),e._options.carousel&&e._carousel.bindControls(),e._options.autoplay&&(e.pause(),"number"==typeof e._options.autoplay&&(e._playtime=e._options.autoplay),e._playing=!0),e._firstrun?(e._options.autoplay&&e.trigger(c.PLAY),void("number"==typeof e._options.show&&e.show(e._options.show))):(e._firstrun=!0,c.History&&c.History.change(function(a){isNaN(a)?b.history.go(-1):e.show(a,d,!0)}),e.trigger(c.READY),e.theme.init.call(e,e._options),a.each(c.ready.callbacks,function(a,b){"function"==typeof b&&b.call(e,e._options)}),e._options.extend.call(e,e._options),/^[0-9]{1,4}$/.test(n)&&c.History?e.show(n,d,!0):e._data[e._options.show]&&e.show(e._options.show),void(e._options.autoplay&&e.trigger(c.PLAY)))},error:function(){c.raise("Stage width or height is too small to show the gallery. Traced measures: width:"+e._stageWidth+"px, height: "+e._stageHeight+"px.",!0)}})},load:function(b,d,e){var f=this,g=this._options;return this._data=[],this._thumbnails=[],this.$("thumbnails").empty(),"function"==typeof d&&(e=d,d=null),b=b||g.dataSource,d=d||g.dataSelector,e=e||g.dataConfig,a.isPlainObject(b)&&(b=[b]),a.isArray(b)?this.validate(b)?this._data=b:c.raise("Load failed: JSON Array not valid."):(d+=",.video,.iframe",a(b).find(d).each(function(b,c){c=a(c);var d={},g=c.parent(),h=g.attr("href"),i=g.attr("rel");h&&("IMG"==c[0].nodeName||c.hasClass("video"))&&C(h)?d.video=h:h&&c.hasClass("iframe")?d.iframe=h:d.image=d.big=h,i&&(d.big=i),a.each("big title description link layer image".split(" "),function(a,b){c.data(b)&&(d[b]=c.data(b).toString())}),d.big||(d.big=d.image),f._data.push(a.extend({title:c.attr("title")||"",thumb:c.attr("src"),image:c.attr("src"),big:c.attr("src"),description:c.attr("alt")||"",link:c.attr("longdesc"),original:c.get(0)},d,e(c)))})),"function"==typeof g.dataSort?h.sort.call(this._data,g.dataSort):"random"==g.dataSort&&this._data.sort(function(){return p.round(p.random())-.5}),this.getDataLength()&&this._parseData(function(){this.trigger(c.DATA)}),this},_parseData:function(b){var c,e=this,f=!1,g=function(){var c=!0;a.each(e._data,function(a,b){if(b.loading)return c=!1,!1}),c&&!f&&(f=!0,b.call(e))};return a.each(this._data,function(b,f){if(c=e._data[b],"thumb"in f==!1&&(c.thumb=f.image),f.big||(c.big=f.image),"video"in f){var h=C(f.video);h&&(c.iframe=new B(h.provider,h.id).embed()+function(){if("object"==typeof e._options[h.provider]){var b="?",c=[];return a.each(e._options[h.provider],function(a,b){c.push(a+"="+b)}),"youtube"==h.provider&&(c=["wmode=opaque"].concat(c)),b+c.join("&")}return""}(),c.thumb&&c.image||a.each(["thumb","image"],function(a,b){if("image"==b&&!e._options.videoPoster)return void(c.image=d);var f=new B(h.provider,h.id);c[b]||(c.loading=!0,f.getMedia(b,function(a,b){return function(c){a[b]=c,"image"!=b||a.big||(a.big=a.image),delete a.loading,g()}}(c,b)))}))}}),g(),this},destroy:function(){return this.$("target").data("galleria",null),this.$("container").off("galleria"),this.get("target").innerHTML=this._original.html,this.clearTimer(),L.removeFromArray(F,this),L.removeFromArray(E,this),void 0!==c._waiters&&c._waiters.length&&a.each(c._waiters,function(a,c){c&&b.clearTimeout(c)}),this},splice:function(){var a=this,c=L.array(arguments);return b.setTimeout(function(){h.splice.apply(a._data,c),a._parseData(function(){a._createThumbnails()})},2),a},push:function(){var a=this,c=L.array(arguments);return 1==c.length&&c[0].constructor==Array&&(c=c[0]),b.setTimeout(function(){h.push.apply(a._data,c),a._parseData(function(){a._createThumbnails(c)})},2),a},_getActive:function(){return this._controls.getActive()},validate:function(a){return!0},bind:function(a,b){return a=z(a),this.$("container").on(a,this.proxy(b)),this},unbind:function(a){return a=z(a),this.$("container").off(a),this},trigger:function(b){return b="object"==typeof b?a.extend(b,{scope:this}):{type:z(b),scope:this},this.$("container").trigger(b),this},addIdleState:function(a,b,c,d){return this._idle.add.apply(this._idle,L.array(arguments)),this},removeIdleState:function(a){return this._idle.remove.apply(this._idle,L.array(arguments)),this},enterIdleMode:function(){return this._idle.hide(),this},exitIdleMode:function(){return this._idle.showAll(),this},enterFullscreen:function(a){return this._fullscreen.enter.apply(this,L.array(arguments)),this},exitFullscreen:function(a){return this._fullscreen.exit.apply(this,L.array(arguments)),this},toggleFullscreen:function(a){return this._fullscreen[this.isFullscreen()?"exit":"enter"].apply(this,L.array(arguments)),this},bindTooltip:function(a,b){return this._tooltip.bind.apply(this._tooltip,L.array(arguments)),this},defineTooltip:function(a,b){return this._tooltip.define.apply(this._tooltip,L.array(arguments)),this},refreshTooltip:function(a){return this._tooltip.show.apply(this._tooltip,L.array(arguments)),this},openLightbox:function(){return this._lightbox.show.apply(this._lightbox,L.array(arguments)),this},closeLightbox:function(){return this._lightbox.hide.apply(this._lightbox,L.array(arguments)),this},hasVariation:function(b){return a.inArray(b,this._options.variation.split(/\s+/))>-1},getActiveImage:function(){var a=this._getActive();return a?a.image:d},getActiveThumb:function(){return this._thumbnails[this._active].image||d},getMousePosition:function(a){return{x:a.pageX-this.$("container").offset().left,y:a.pageY-this.$("container").offset().top}},addPan:function(b){if(this._options.imageCrop!==!1){b=a(b||this.getActiveImage());var c=this,d=b.width()/2,e=b.height()/2,f=parseInt(b.css("left"),10),g=parseInt(b.css("top"),10),h=f||0,i=g||0,j=0,k=0,l=!1,m=L.timestamp(),n=0,o=0,q=function(a,c,d){if(a>0&&(o=p.round(p.max(a*-1,p.min(0,c))),n!==o))if(n=o,8===t)b.parent()["scroll"+d](o*-1);else{var e={};e[d.toLowerCase()]=o,b.css(e)}},r=function(a){L.timestamp()-m<50||(l=!0,d=c.getMousePosition(a).x,e=c.getMousePosition(a).y)},s=function(a){l&&(j=b.width()-c._stageWidth,k=b.height()-c._stageHeight,f=d/c._stageWidth*j*-1,g=e/c._stageHeight*k*-1,h+=(f-h)/c._options.imagePanSmoothness,i+=(g-i)/c._options.imagePanSmoothness,q(k,i,"Top"),q(j,h,"Left"))};return 8===t&&(b.parent().scrollTop(i*-1).scrollLeft(h*-1),b.css({top:0,left:0})),this.$("stage").off("mousemove",r).on("mousemove",r),this.addTimer("pan"+c._id,s,50,!0),this}},proxy:function(a,b){return"function"!=typeof a?q:(b=b||this,function(){return a.apply(b,L.array(arguments))})},getThemeName:function(){return this.theme.name},removePan:function(){return this.$("stage").off("mousemove"),this.clearTimer("pan"+this._id),this},addElement:function(b){var c=this._dom;return a.each(L.array(arguments),function(a,b){c[b]=L.create("galleria-"+b)}),this},attachKeyboard:function(a){return this._keyboard.attach.apply(this._keyboard,L.array(arguments)),this},detachKeyboard:function(){return this._keyboard.detach.apply(this._keyboard,L.array(arguments)),this},appendChild:function(a,b){return this.$(a).append(this.get(b)||b),this},prependChild:function(a,b){return this.$(a).prepend(this.get(b)||b),this},remove:function(a){return this.$(L.array(arguments).join(",")).remove(),this},append:function(a){var b,c;for(b in a)if(a.hasOwnProperty(b))if(a[b].constructor===Array)for(c=0;a[b][c];c++)this.appendChild(b,a[b][c]);else this.appendChild(b,a[b]);return this},_scaleImage:function(b,c){if(b=b||this._controls.getActive()){var d,e=function(b){a(b.container).children(":first").css({top:p.max(0,L.parseValue(b.image.style.top)),left:p.max(0,L.parseValue(b.image.style.left)),width:L.parseValue(b.image.width),height:L.parseValue(b.image.height)})};return c=a.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},c),this._options.layerFollow&&this._options.imageCrop!==!0?"function"==typeof c.complete?(d=c.complete,c.complete=function(){d.call(b,b),e(b)}):c.complete=e:a(b.container).children(":first").css({top:0,left:0}),b.scale(c),this}},updateCarousel:function(){return this._carousel.update(),this},resize:function(b,c){"function"==typeof b&&(c=b,b=d),b=a.extend({width:0,height:0},b);var e=this,f=this.$("container");return a.each(b,function(a,c){c||(f[a]("auto"),b[a]=e._getWH()[a])}),a.each(b,function(a,b){f[a](b)}),this.rescale(c)},rescale:function(b,e,f){var g=this;"function"==typeof b&&(f=b,b=d);var h=function(){g._stageWidth=b||g.$("stage").width(),g._stageHeight=e||g.$("stage").height(),g._options.swipe?(a.each(g._controls.slides,function(b,c){g._scaleImage(c),a(c.container).css("left",g._stageWidth*b)}),g.$("images").css("width",g._stageWidth*g.getDataLength())):g._scaleImage(),g._options.carousel&&g.updateCarousel();var d=g._controls.frames[g._controls.active];d&&g._controls.frames[g._controls.active].scale({width:g._stageWidth,height:g._stageHeight,iframelimit:g._options.maxVideoSize}),g.trigger(c.RESCALE),"function"==typeof f&&f.call(g)};return h.call(g),this},refreshImage:function(){return this._scaleImage(),this._options.imagePan&&this.addPan(),this},_preload:function(){if(this._options.preload){var a,b,d,e=this.getNext();try{for(b=this._options.preload;b>0;b--)a=new c.Picture,d=this.getData(e),a.preload(this.isFullscreen()&&d.big?d.big:d.image),e=this.getNext(e)}catch(a){}}},show:function(d,e,f){var g=this._options.swipe;if(g||!(this._queue.length>3||d===!1||!this._options.queue&&this._queue.stalled)){if(d=p.max(0,p.min(parseInt(d,10),this.getDataLength()-1)),e="undefined"!=typeof e?!!e:d<this.getIndex(),f=f||!1,!f&&c.History)return void c.History.set(d.toString());if(this.finger&&d!==this._active&&(this.finger.to=-(d*this.finger.width),this.finger.index=d),this._active=d,g){var i=this.getData(d),j=this;if(!i)return;var k=this.isFullscreen()&&i.big?i.big:i.image||i.iframe,l=this._controls.slides[d],m=l.isCached(k),n=this._thumbnails[d],o={cached:m,index:d,rewind:e,imageTarget:l.image,thumbTarget:n.image,galleriaData:i};this.trigger(a.extend(o,{type:c.LOADSTART})),j.$("container").removeClass("videoplay");var q=function(){j._layers[d].innerHTML=j.getData().layer||"",j.trigger(a.extend(o,{type:c.LOADFINISH})),j._playCheck()};j._preload(),b.setTimeout(function(){l.ready&&a(l.image).attr("src")==k?(j.trigger(a.extend(o,{type:c.IMAGE})),q()):(i.iframe&&!i.image&&(l.isIframe=!0),l.load(k,function(b){o.imageTarget=b.image,j._scaleImage(b,q).trigger(a.extend(o,{type:c.IMAGE})),q()}))},100)}else h.push.call(this._queue,{index:d,rewind:e}),this._queue.stalled||this._show();return this}},_show:function(){var e=this,f=this._queue[0],g=this.getData(f.index);if(g){var i=this.isFullscreen()&&g.big?g.big:g.image||g.iframe,j=this._controls.getActive(),k=this._controls.getNext(),l=k.isCached(i),m=this._thumbnails[f.index],n=function(){a(k.image).trigger("mouseup")};e.$("container").toggleClass("iframe",!!g.isIframe).removeClass("videoplay");var o=function(f,g,i,j,k){return function(){var l;N.active=!1,L.toggleQuality(g.image,e._options.imageQuality),e._layers[e._controls.active].innerHTML="",a(i.container).css({zIndex:0,opacity:0}).show(),a(i.container).find("iframe, .galleria-videoicon").remove(),a(e._controls.frames[e._controls.active].container).hide(),a(g.container).css({zIndex:1,left:0,top:0}).show(),e._controls.swap(),e._options.imagePan&&e.addPan(g.image),(f.iframe&&f.image||f.link||e._options.lightbox||e._options.clicknext)&&a(g.image).css({cursor:"pointer"}).on("mouseup",function(g){if(!("number"==typeof g.which&&g.which>1)){if(f.iframe){e.isPlaying()&&e.pause();var h=e._controls.frames[e._controls.active],i=e._stageWidth,j=e._stageHeight;return a(h.container).css({width:i,height:j,opacity:0}).show().animate({opacity:1},200),void b.setTimeout(function(){h.load(f.iframe+(f.video?"&autoplay=1":""),{width:i,height:j},function(a){e.$("container").addClass("videoplay"),a.scale({width:e._stageWidth,height:e._stageHeight,iframelimit:f.video?e._options.maxVideoSize:d})})},100)}return e._options.clicknext&&!c.TOUCH?(e._options.pauseOnInteraction&&e.pause(),void e.next()):f.link?void(e._options.popupLinks?l=b.open(f.link,"_blank"):b.location.href=f.link):void(e._options.lightbox&&e.openLightbox())}}),e._playCheck(),e.trigger({type:c.IMAGE,index:j.index,imageTarget:g.image,thumbTarget:k.image,galleriaData:f}),h.shift.call(e._queue),e._queue.stalled=!1,e._queue.length&&e._show()}}(g,k,j,f,m);this._options.carousel&&this._options.carouselFollow&&this._carousel.follow(f.index),e._preload(),L.show(k.container),k.isIframe=g.iframe&&!g.image,a(e._thumbnails[f.index].container).addClass("active").siblings(".active").removeClass("active"),e.trigger({type:c.LOADSTART,cached:l,index:f.index,rewind:f.rewind,imageTarget:k.image,thumbTarget:m.image,galleriaData:g}),e._queue.stalled=!0,k.load(i,function(b){var h=a(e._layers[1-e._controls.active]).html(g.layer||"").hide();e._scaleImage(b,{complete:function(b){"image"in j&&L.toggleQuality(j.image,!1),L.toggleQuality(b.image,!1),e.removePan(),e.setInfo(f.index),e.setCounter(f.index),g.layer&&(h.show(),(g.iframe&&g.image||g.link||e._options.lightbox||e._options.clicknext)&&h.css("cursor","pointer").off("mouseup").mouseup(n)),g.video&&g.image&&M(b.container);var i=e._options.transition;if(a.each({initial:null===j.image,touch:c.TOUCH,fullscreen:e.isFullscreen()},function(a,b){if(b&&e._options[a+"Transition"]!==d)return i=e._options[a+"Transition"],!1}),i in N.effects==!1)o();else{var k={prev:j.container,next:b.container,rewind:f.rewind,speed:e._options.transitionSpeed||400};N.active=!0,N.init.call(e,i,k,o)}e.trigger({type:c.LOADFINISH,cached:l,index:f.index,rewind:f.rewind,imageTarget:b.image,thumbTarget:e._thumbnails[f.index].image,galleriaData:e.getData(f.index)})}})})}},getNext:function(a){return a="number"==typeof a?a:this.getIndex(),a===this.getDataLength()-1?0:a+1},getPrev:function(a){return a="number"==typeof a?a:this.getIndex(),0===a?this.getDataLength()-1:a-1},next:function(){return this.getDataLength()>1&&this.show(this.getNext(),!1),this},prev:function(){return this.getDataLength()>1&&this.show(this.getPrev(),!0),this},get:function(a){return a in this._dom?this._dom[a]:null},getData:function(a){return a in this._data?this._data[a]:this._data[this._active]},getDataLength:function(){return this._data.length},getIndex:function(){return"number"==typeof this._active&&this._active},getStageHeight:function(){return this._stageHeight},getStageWidth:function(){return this._stageWidth},getOptions:function(a){return"undefined"==typeof a?this._options:this._options[a]},setOptions:function(b,c){return"object"==typeof b?a.extend(this._options,b):this._options[b]=c,this},play:function(a){return this._playing=!0,this._playtime=a||this._playtime,this._playCheck(),this.trigger(c.PLAY),this},pause:function(){return this._playing=!1,this.trigger(c.PAUSE),this},playToggle:function(a){return this._playing?this.pause():this.play(a)},isPlaying:function(){return this._playing},isFullscreen:function(){return this._fullscreen.active},_playCheck:function(){var a=this,b=0,d=20,e=L.timestamp(),f="play"+this._id;if(this._playing){this.clearTimer(f);var g=function(){return b=L.timestamp()-e,b>=a._playtime&&a._playing?(a.clearTimer(f),void a.next()):void(a._playing&&(a.trigger({type:c.PROGRESS,percent:p.ceil(b/a._playtime*100),seconds:p.floor(b/1e3),milliseconds:b}),a.addTimer(f,g,d)))};a.addTimer(f,g,d)}},setPlaytime:function(a){return this._playtime=a,this},setIndex:function(a){return this._active=a,this},setCounter:function(a){if("number"==typeof a?a++:"undefined"==typeof a&&(a=this.getIndex()+1),this.get("current").innerHTML=a,t){var b=this.$("counter"),c=b.css("opacity");1===parseInt(c,10)?L.removeAlpha(b[0]):this.$("counter").css("opacity",c)}return this},setInfo:function(b){var c=this,d=this.getData(b);return a.each(["title","description"],function(a,b){var e=c.$("info-"+b);d[b]?e[d[b].length?"show":"hide"]().html(d[b]):e.empty().hide()}),this},hasInfo:function(a){var b,c="title description".split(" ");for(b=0;c[b];b++)if(this.getData(a)[c[b]])return!0;return!1},jQuery:function(b){var c=this,d=[];a.each(b.split(","),function(b,e){e=a.trim(e),c.get(e)&&d.push(e)});var e=a(c.get(d.shift()));return a.each(d,function(a,b){e=e.add(c.get(b))}),e},$:function(a){return this.jQuery.apply(this,L.array(arguments))}},a.each(x,function(a,b){var d=/_/.test(b)?b.replace(/_/g,""):b;c[b.toUpperCase()]="galleria."+d}),a.extend(c,{IE9:9===t,IE8:8===t,IE7:7===t,IE6:6===t,IE:t,WEBKIT:/webkit/.test(m),CHROME:/chrome/.test(m),SAFARI:/safari/.test(m)&&!/chrome/.test(m),QUIRK:t&&e.compatMode&&"BackCompat"===e.compatMode,MAC:/mac/.test(navigator.platform.toLowerCase()),OPERA:!!b.opera,IPHONE:/iphone/.test(m),IPAD:/ipad/.test(m),ANDROID:/android/.test(m),TOUCH:"ontouchstart"in e&&s}),c.addTheme=function(d){d.name||c.raise("No theme name specified"),(!d.version||parseInt(10*c.version)>parseInt(10*d.version))&&c.raise("This version of Galleria requires "+d.name+" theme version "+parseInt(10*c.version)/10+" or later",!0),"object"!=typeof d.defaults?d.defaults={}:d.defaults=y(d.defaults);var e,f,g=!1;return"string"==typeof d.css?(a("link").each(function(a,b){if(e=new RegExp(d.css),e.test(b.href))return g=!0,K(d),!1}),g||a(function(){var h=0,i=function(){a("script").each(function(a,c){e=new RegExp("galleria\\."+d.name.toLowerCase()+"\\."),f=new RegExp("galleria\\.io\\/theme\\/"+d.name.toLowerCase()+"\\/(\\d*\\.*)?(\\d*\\.*)?(\\d*\\/)?js"),(e.test(c.src)||f.test(c.src))&&(g=c.src.replace(/[^\/]*$/,"")+d.css,b.setTimeout(function(){L.loadCSS(g,"galleria-theme-"+d.name,function(){K(d)})},1))}),g||(h++>5?c.raise("No theme CSS loaded"):b.setTimeout(i,500))};i()})):K(d),d},c.loadTheme=function(d,e){if(!a("script").filter(function(){return a(this).attr("src")==d}).length){var f,g=!1;return a(b).on("load",function(){g||(f=b.setTimeout(function(){g||c.raise("Galleria had problems loading theme at "+d+". Please check theme path or load manually.",!0)},2e4))}),L.loadScript(d,function(){g=!0,b.clearTimeout(f)}),c}},c.get=function(a){return F[a]?F[a]:"number"!=typeof a?F:void c.raise("Gallery index "+a+" not found")},c.configure=function(b,d){var e={};return"string"==typeof b&&d?(e[b]=d,b=e):a.extend(e,b),c.configure.options=e,a.each(c.get(),function(a,b){b.setOptions(e)}),c},c.configure.options={},c.on=function(b,d){if(b){d=d||q;var e=b+d.toString().replace(/\s/g,"")+L.timestamp();return a.each(c.get(),function(a,c){c._binds.push(e),c.bind(b,d)}),c.on.binds.push({type:b,callback:d,hash:e}),c}},c.on.binds=[],c.run=function(b,d){return a.isFunction(d)&&(d={extend:d}),a(b||"#galleria").galleria(d),c},c.addTransition=function(a,b){return N.effects[a]=b,c},c.utils=L,c.log=function(){var c=L.array(arguments);if(!("console"in b&&"log"in b.console))return b.alert(c.join("<br>"));try{return b.console.log.apply(b.console,c)}catch(d){a.each(c,function(){b.console.log(this)})}},c.ready=function(b){return"function"!=typeof b?c:(a.each(E,function(a,c){b.call(c,c._options)}),c.ready.callbacks.push(b),c)},c.ready.callbacks=[],c.raise=function(b,c){var d=c?"Fatal error":"Error",e={color:"#fff",position:"absolute",top:0,left:0,zIndex:1e5},f=function(b){var f='<div style="padding:4px;margin:0 0 2px;background:#'+(c?"811":"222")+';">'+(c?"<strong>"+d+": </strong>":"")+b+"</div>";a.each(F,function(){var a=this.$("errors"),b=this.$("target");a.length||(b.css("position","relative"),a=this.addElement("errors").appendChild("target","errors").$("errors").css(e)),a.append(f)}),F.length||a("<div>").css(a.extend(e,{position:"fixed"})).append(f).appendTo(u().body)};if(j){if(f(b),c)throw new Error(d+": "+b)}else if(c){if(G)return;G=!0,c=!1,f("Gallery could not load.")}},c.version=i,c.getLoadedThemes=function(){return a.map(J,function(a){return a.name})},c.requires=function(a,b){return b=b||"You need to upgrade Galleria to version "+a+" to use one or more components.",c.version<a&&c.raise(b,!0),c},c.Picture=function(b){this.id=b||null,this.image=null,this.container=L.create("galleria-image"),a(this.container).css({overflow:"hidden",position:"relative"}),this.original={width:0,height:0
+},this.ready=!1,this.isIframe=!1},c.Picture.prototype={cache:{},show:function(){L.show(this.image)},hide:function(){L.moveOut(this.image)},clear:function(){this.image=null},isCached:function(a){return!!this.cache[a]},preload:function(b){a(new Image).on("load",function(a,b){return function(){b[a]=a}}(b,this.cache)).attr("src",b)},load:function(d,e,f){if("function"==typeof e&&(f=e,e=null),this.isIframe){var g="if"+(new Date).getTime(),h=this.image=a("<iframe>",{src:d,frameborder:0,id:g,allowfullscreen:!0,css:{visibility:"hidden"}})[0];return e&&a(h).css(e),a(this.container).find("iframe,img").remove(),this.container.appendChild(this.image),a("#"+g).on("load",function(c,d){return function(){b.setTimeout(function(){a(c.image).css("visibility","visible"),"function"==typeof d&&d.call(c,c)},10)}}(this,f)),this.container}this.image=new Image,c.IE8&&a(this.image).css("filter","inherit"),c.IE||c.CHROME||c.SAFARI||a(this.image).css("image-rendering","optimizequality");var i=!1,j=!1,k=a(this.container),m=a(this.image),n=function(){i?l?a(this).attr("src",l):c.raise("Image not found: "+d):(i=!0,b.setTimeout(function(a,b){return function(){a.attr("src",b+(b.indexOf("?")>-1?"&":"?")+L.timestamp())}}(a(this),d),50))},o=function(d,f,g){return function(){var h=function(){a(this).off("load"),d.original=e||{height:this.height,width:this.width},c.HAS3D&&(this.style.MozTransform=this.style.webkitTransform="translate3d(0,0,0)"),k.append(this),d.cache[g]=g,"function"==typeof f&&b.setTimeout(function(){f.call(d,d)},1)};this.width&&this.height?h.call(this):!function(b){L.wait({until:function(){return b.width&&b.height},success:function(){h.call(b)},error:function(){j?c.raise("Could not extract width/height from image: "+b.src+". Traced measures: width:"+b.width+"px, height: "+b.height+"px."):(a(new Image).on("load",o).attr("src",b.src),j=!0)},timeout:100})}(this)}}(this,f,d);return k.find("iframe,img").remove(),m.css("display","block"),L.hide(this.image),a.each("minWidth minHeight maxWidth maxHeight".split(" "),function(a,b){m.css(b,/min/.test(b)?"0":"none")}),m.on("load",o).on("error",n).attr("src",d),this.container},scale:function(b){var e=this;if(b=a.extend({width:0,height:0,min:d,max:d,margin:0,complete:q,position:"center",crop:!1,canvas:!1,iframelimit:d},b),this.isIframe){var f,g,h=b.width,i=b.height;if(b.iframelimit){var j=p.min(b.iframelimit/h,b.iframelimit/i);j<1?(f=h*j,g=i*j,a(this.image).css({top:i/2-g/2,left:h/2-f/2,position:"absolute"})):a(this.image).css({top:0,left:0})}a(this.image).width(f||h).height(g||i).removeAttr("width").removeAttr("height"),a(this.container).width(h).height(i),b.complete.call(e,e);try{this.image.contentWindow&&a(this.image.contentWindow).trigger("resize")}catch(a){}return this.container}if(!this.image)return this.container;var k,l,m,n=a(e.container);return L.wait({until:function(){return k=b.width||n.width()||L.parseValue(n.css("width")),l=b.height||n.height()||L.parseValue(n.css("height")),k&&l},success:function(){var c=(k-2*b.margin)/e.original.width,d=(l-2*b.margin)/e.original.height,f=p.min(c,d),g=p.max(c,d),h={true:g,width:c,height:d,false:f,landscape:e.original.width>e.original.height?g:f,portrait:e.original.width<e.original.height?g:f},i=h[b.crop.toString()],j="";b.max&&(i=p.min(b.max,i)),b.min&&(i=p.max(b.min,i)),a.each(["width","height"],function(b,c){a(e.image)[c](e[c]=e.image[c]=p.round(e.original[c]*i))}),a(e.container).width(k).height(l),b.canvas&&H&&(H.elem.width=e.width,H.elem.height=e.height,j=e.image.src+":"+e.width+"x"+e.height,e.image.src=H.cache[j]||function(a){H.context.drawImage(e.image,0,0,e.original.width*i,e.original.height*i);try{return m=H.elem.toDataURL(),H.length+=m.length,H.cache[a]=m,m}catch(a){return e.image.src}}(j));var n={},o={},q=function(b,c,d){var f=0;if(/\%/.test(b)){var g=parseInt(b,10)/100,h=e.image[c]||a(e.image)[c]();f=p.ceil(h*-1*g+d*g)}else f=L.parseValue(b);return f},r={top:{top:0},left:{left:0},right:{left:"100%"},bottom:{top:"100%"}};a.each(b.position.toLowerCase().split(" "),function(a,b){"center"===b&&(b="50%"),n[a?"top":"left"]=b}),a.each(n,function(b,c){r.hasOwnProperty(c)&&a.extend(o,r[c])}),n=n.top?a.extend(n,o):o,n=a.extend({top:"50%",left:"50%"},n),a(e.image).css({position:"absolute",top:q(n.top,"height",l),left:q(n.left,"width",k)}),e.show(),e.ready=!0,b.complete.call(e,e)},error:function(){c.raise("Could not scale image: "+e.image.src)},timeout:1e3}),this}},a.extend(a.easing,{galleria:function(a,b,c,d,e){return(b/=e/2)<1?d/2*b*b*b+c:d/2*((b-=2)*b*b+2)+c},galleriaIn:function(a,b,c,d,e){return d*(b/=e)*b+c},galleriaOut:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}}),c.Finger=function(){var d=(p.abs,c.HAS3D=function(){var b,c,d=e.createElement("p"),f=["webkit","O","ms","Moz",""],g=0,h="transform";for(u().html.insertBefore(d,null);f[g];g++)c=f[g]?f[g]+"Transform":h,void 0!==d.style[c]&&(d.style[c]="translate3d(1px,1px,1px)",b=a(d).css(f[g]?"-"+f[g].toLowerCase()+"-"+h:h));return u().html.removeChild(d),void 0!==b&&b.length>0&&"none"!==b}()),g=function(){var a="RequestAnimationFrame";return b.requestAnimationFrame||b["webkit"+a]||b["moz"+a]||b["o"+a]||b["ms"+a]||function(a){b.setTimeout(a,1e3/60)}}(),h=function(c,e){if(this.config={start:0,duration:500,onchange:function(){},oncomplete:function(){},easing:function(a,b,c,d,e){return-d*((b=b/e-1)*b*b*b-1)+c}},this.easeout=function(a,b,c,d,e){return d*((b=b/e-1)*b*b*b*b+1)+c},c.children.length){var f=this;a.extend(this.config,e),this.elem=c,this.child=c.children[0],this.to=this.pos=0,this.touching=!1,this.start={},this.index=this.config.start,this.anim=0,this.easing=this.config.easing,d||(this.child.style.position="absolute",this.elem.style.position="relative"),a.each(["ontouchstart","ontouchmove","ontouchend","setup"],function(a,b){f[b]=function(a){return function(){a.apply(f,arguments)}}(f[b])}),this.setX=function(){var a=f.child.style;return d?void(a.MozTransform=a.webkitTransform=a.transform="translate3d("+f.pos+"px,0,0)"):void(a.left=f.pos+"px")},a(c).on("touchstart",this.ontouchstart),a(b).on("resize",this.setup),a(b).on("orientationchange",this.setup),this.setup(),function a(){g(a),f.loop.call(f)}()}};return h.prototype={constructor:h,setup:function(){this.width=a(this.elem).width(),this.length=p.ceil(a(this.child).width()/this.width),0!==this.index&&(this.index=p.max(0,p.min(this.index,this.length-1)),this.pos=this.to=-this.width*this.index)},setPosition:function(a){this.pos=a,this.to=a},ontouchstart:function(a){var b=a.originalEvent.touches;this.start={pageX:b[0].pageX,pageY:b[0].pageY,time:+new Date},this.isScrolling=null,this.touching=!0,this.deltaX=0,f.on("touchmove",this.ontouchmove),f.on("touchend",this.ontouchend)},ontouchmove:function(a){var b=a.originalEvent.touches;b&&b.length>1||a.scale&&1!==a.scale||(this.deltaX=b[0].pageX-this.start.pageX,null===this.isScrolling&&(this.isScrolling=!!(this.isScrolling||p.abs(this.deltaX)<p.abs(b[0].pageY-this.start.pageY))),this.isScrolling||(a.preventDefault(),this.deltaX/=!this.index&&this.deltaX>0||this.index==this.length-1&&this.deltaX<0?p.abs(this.deltaX)/this.width+1.8:1,this.to=this.deltaX-this.index*this.width),a.stopPropagation())},ontouchend:function(a){this.touching=!1;var b=+new Date-this.start.time<250&&p.abs(this.deltaX)>40||p.abs(this.deltaX)>this.width/2,c=!this.index&&this.deltaX>0||this.index==this.length-1&&this.deltaX<0;this.isScrolling||this.show(this.index+(b&&!c?this.deltaX<0?1:-1:0)),f.off("touchmove",this.ontouchmove),f.off("touchend",this.ontouchend)},show:function(a){a!=this.index?this.config.onchange.call(this,a):this.to=-(a*this.width)},moveTo:function(a){a!=this.index&&(this.pos=this.to=-(a*this.width),this.index=a)},loop:function(){var a=this.to-this.pos,b=1;if(this.width&&a&&(b=p.max(.5,p.min(1.5,p.abs(a/this.width)))),this.touching||p.abs(a)<=1)this.pos=this.to,a=0,this.anim&&!this.touching&&this.config.oncomplete(this.index),this.anim=0,this.easing=this.config.easing;else{this.anim||(this.anim={start:this.pos,time:+new Date,distance:a,factor:b,destination:this.to});var c=+new Date-this.anim.time,d=this.config.duration*this.anim.factor;if(c>d||this.anim.destination!=this.to)return this.anim=0,void(this.easing=this.easeout);this.pos=this.easing(null,c,this.anim.start,this.anim.distance,d)}this.setX()}},h}(),a.fn.galleria=function(b){var d=this.selector;return a(this).length?this.each(function(){a.data(this,"galleria")&&(a.data(this,"galleria").destroy(),a(this).find("*").hide()),a.data(this,"galleria",(new c).init(this,b))}):(a(function(){a(d).length?a(d).galleria(b):c.utils.wait({until:function(){return a(d).length},success:function(){a(d).galleria(b)},error:function(){c.raise('Init failed: Galleria could not find the element "'+d+'".')},timeout:5e3})}),this)},"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=c:(b.Galleria=c,"function"==typeof define&&define.amd&&define("galleria",["jquery"],function(){return c}))}(jQuery,this);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/flickr/flickr-demo.html b/assets/scripts/galleria/plugins/flickr/flickr-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..1b3ccb200f26302496ea60f56f74d28b96259298
--- /dev/null
+++ b/assets/scripts/galleria/plugins/flickr/flickr-demo.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Flickr Plugin</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px;}
+
+        </style>
+
+        <!-- load jQuery -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <!-- load flickr plugin -->
+        <script src="galleria.flickr.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Flickr Plugin Demo</h1>
+        <p>Demonstrating a basic gallery example with a Flickr search.</p>
+
+        <!-- Adding gallery images. This is just a container for the dynamic flickr images -->
+
+        <div id="galleria"></div>
+
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+        <a href="#" id="close">cloase</a>
+    </div>
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('../../themes/classic/galleria.classic.min.js');
+
+        // Initialize Galleria
+        Galleria.run('#galleria', {
+
+            // search flickr for "galleria"
+            flickr: 'search:galleria',
+
+            flickrOptions: {
+                // sort by interestingness
+                sort: 'interestingness-desc'
+            }
+        });
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/flickr/flickr-loader.gif b/assets/scripts/galleria/plugins/flickr/flickr-loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..beaacacc93292a68ac6f21016d8affad0f9cca16
Binary files /dev/null and b/assets/scripts/galleria/plugins/flickr/flickr-loader.gif differ
diff --git a/assets/scripts/galleria/plugins/flickr/galleria.flickr.js b/assets/scripts/galleria/plugins/flickr/galleria.flickr.js
new file mode 100644
index 0000000000000000000000000000000000000000..9487b738a7e3231ee38334c07e79c09ff8059b90
--- /dev/null
+++ b/assets/scripts/galleria/plugins/flickr/galleria.flickr.js
@@ -0,0 +1,384 @@
+/**
+ * Galleria Flickr Plugin 2016-09-03
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.requires(1.25, 'The Flickr Plugin requires Galleria version 1.2.5 or later.');
+
+// The script path
+var PATH = Galleria.utils.getScriptPath();
+
+/**
+
+    @class
+    @constructor
+
+    @example var flickr = new Galleria.Flickr();
+
+    @author http://galleria.io
+
+    @requires jQuery
+    @requires Galleria
+
+    @param {String} [api_key] Flickr API key to be used, defaults to the Galleria key
+
+    @returns Instance
+*/
+
+Galleria.Flickr = function( api_key ) {
+
+    this.api_key = api_key || '2a2ce06c15780ebeb0b706650fc890b2';
+
+    this.options = {
+        max: 30,                       // photos to return
+        imageSize: 'medium',           // photo size ( thumb,small,medium,big,original )
+        thumbSize: 'thumb',            // thumbnail size ( thumb,small,medium,big,original )
+        sort: 'interestingness-desc',  // sort option ( date-posted-asc, date-posted-desc, date-taken-asc, date-taken-desc, interestingness-desc, interestingness-asc, relevance )
+        description: false,            // set this to true to get description as caption
+        complete: function(){},        // callback to be called inside the Galleria.prototype.load
+        backlink: false                // set this to true if you want to pass a link back to the original image
+    };
+};
+
+Galleria.Flickr.prototype = {
+
+    // bring back the constructor reference
+
+    constructor: Galleria.Flickr,
+
+    /**
+        Search for anything at Flickr
+
+        @param {String} phrase The string to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    search: function( phrase, callback ) {
+        return this._find({
+            text: phrase
+        }, callback );
+    },
+
+    /**
+        Search for anything at Flickr by tag
+
+        @param {String} tag The tag(s) to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    tags: function( tag, callback ) {
+        return this._find({
+            tags: tag
+        }, callback);
+    },
+
+    /**
+        Get a user's public photos
+
+        @param {String} username The username as shown in the URL to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    user: function( username, callback ) {
+        return this._call({
+            method: 'flickr.urls.lookupUser',
+            url: 'flickr.com/photos/' + username
+        }, function( data ) {
+            this._find({
+                user_id: data.user.id,
+                method: 'flickr.people.getPublicPhotos'
+            }, callback);
+        });
+    },
+
+    /**
+        Get photos from a photoset by ID
+
+        @param {String|Number} photoset_id The photoset id to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    set: function( photoset_id, callback ) {
+        return this._find({
+            photoset_id: photoset_id,
+            method: 'flickr.photosets.getPhotos'
+        }, callback);
+    },
+
+    /**
+        Get photos from a gallery by ID
+
+        @param {String|Number} gallery_id The gallery id to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    gallery: function( gallery_id, callback ) {
+        return this._find({
+            gallery_id: gallery_id,
+            method: 'flickr.galleries.getPhotos'
+        }, callback);
+    },
+
+    /**
+        Search groups and fetch photos from the first group found
+        Useful if you know the exact name of a group and want to show the groups photos.
+
+        @param {String} group The group name to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    groupsearch: function( group, callback ) {
+        return this._call({
+            text: group,
+            method: 'flickr.groups.search'
+        }, function( data ) {
+            this.group( data.groups.group[0].nsid, callback );
+        });
+    },
+
+    /**
+        Get photos from a group by ID
+
+        @param {String} group_id The group id to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    group: function ( group_id, callback ) {
+        return this._find({
+            group_id: group_id,
+            method: 'flickr.groups.pools.getPhotos'
+        }, callback );
+    },
+
+    /**
+        Set flickr options
+
+        @param {Object} options The options object to blend
+
+        @returns Instance
+    */
+
+    setOptions: function( options ) {
+        $.extend(this.options, options);
+        return this;
+    },
+
+
+    // call Flickr and raise errors
+
+    _call: function( params, callback ) {
+
+        var url = 'https://api.flickr.com/services/rest/?';
+
+        var scope = this;
+
+        params = $.extend({
+            format : 'json',
+            jsoncallback : '?',
+            api_key: this.api_key
+        }, params );
+
+        $.each(params, function( key, value ) {
+            url += '&' + key + '=' + value;
+        });
+
+        $.getJSON(url, function(data) {
+            if ( data.stat === 'ok' ) {
+                callback.call(scope, data);
+            } else {
+                Galleria.raise( data.code.toString() + ' ' + data.stat + ': ' + data.message, true );
+            }
+        });
+        return scope;
+    },
+
+
+    // "hidden" way of getting a big image (~1024) from flickr
+
+    _getBig: function( photo ) {
+
+        if ( photo.url_l ) {
+            return photo.url_l;
+        } else if ( parseInt( photo.width_o, 10 ) > 1280 ) {
+
+            return 'https://farm'+photo.farm + '.static.flickr.com/'+photo.server +
+                '/' + photo.id + '_' + photo.secret + '_b.jpg';
+        }
+
+        return photo.url_o || photo.url_z || photo.url_m;
+
+    },
+
+
+    // get image size by option name
+
+    _getSize: function( photo, size ) {
+
+        var img;
+
+        switch(size) {
+
+            case 'thumb':
+                img = photo.url_t;
+                break;
+
+            case 'small':
+                img = photo.url_s;
+                break;
+
+            case 'big':
+                img = this._getBig( photo );
+                break;
+
+            case 'original':
+                img = photo.url_o ? photo.url_o : this._getBig( photo );
+                break;
+
+            default:
+                img = photo.url_z || photo.url_m;
+                break;
+        }
+        return img;
+    },
+
+
+    // ask flickr for photos, parse the result and call the callback with the galleria-ready data array
+
+    _find: function( params, callback ) {
+
+        params = $.extend({
+            method: 'flickr.photos.search',
+            extras: 'url_t,url_m,url_o,url_s,url_l,url_z,description',
+            sort: this.options.sort,
+            per_page: Math.min( this.options.max, 500 )
+        }, params );
+
+        return this._call( params, function(data) {
+
+            var gallery = [],
+                photos = data.photos ? data.photos.photo : data.photoset.photo,
+                len = photos.length,
+                photo,
+                i;
+
+            for ( i=0; i<len; i++ ) {
+
+                photo = photos[i];
+
+                gallery.push({
+                    thumb: this._getSize( photo, this.options.thumbSize ),
+                    image: this._getSize( photo, this.options.imageSize ),
+                    big: this._getBig( photo ),
+                    title: photos[i].title,
+                    description: this.options.description && photos[i].description ? photos[i].description._content : '',
+                    link: this.options.backlink ? 'https://flickr.com/photos/' + photo.owner + '/' + photo.id : ''
+                });
+            }
+            callback.call( this, gallery );
+        });
+    }
+};
+
+
+/**
+    Galleria modifications
+    We fake-extend the load prototype to make Flickr integration as simple as possible
+*/
+
+
+// save the old prototype in a local variable
+
+var load = Galleria.prototype.load;
+
+
+// fake-extend the load prototype using the flickr data
+
+Galleria.prototype.load = function() {
+
+    // pass if no data is provided or flickr option not found
+    if ( arguments.length || typeof this._options.flickr !== 'string' ) {
+        load.apply( this, Galleria.utils.array( arguments ) );
+        return;
+    }
+
+    // define some local vars
+    var self = this,
+        args = Galleria.utils.array( arguments ),
+        flickr = this._options.flickr.split(':'),
+        f,
+        opts = $.extend({}, self._options.flickrOptions),
+        loader = typeof opts.loader !== 'undefined' ?
+            opts.loader : $('<div>').css({
+                width: 48,
+                height: 48,
+                opacity: 0.7,
+                background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%'
+            });
+
+    if ( flickr.length ) {
+
+        // validate the method
+        if ( typeof Galleria.Flickr.prototype[ flickr[0] ] !== 'function' ) {
+            Galleria.raise( flickr[0] + ' method not found in Flickr plugin' );
+            return load.apply( this, args );
+        }
+
+        // validate the argument
+        if ( !flickr[1] ) {
+            Galleria.raise( 'No flickr argument found' );
+            return load.apply( this, args );
+        }
+
+        // apply the preloader
+        window.setTimeout(function() {
+            self.$( 'target' ).append( loader );
+        },100);
+
+        // create the instance
+        f = new Galleria.Flickr();
+
+        // apply Flickr options
+        if ( typeof self._options.flickrOptions === 'object' ) {
+            f.setOptions( self._options.flickrOptions );
+        }
+
+        // call the flickr method and trigger the DATA event
+        f[ flickr[0] ]( flickr[1], function( data ) {
+
+            self._data = data;
+            loader.remove();
+            self.trigger( Galleria.DATA );
+            f.options.complete.call(f, data);
+
+        });
+    } else {
+
+        // if flickr array not found, pass
+        load.apply( this, args );
+    }
+};
+
+}( jQuery ) );
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/assets/scripts/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..2eb9b36366cc1cf1fb1759cdc0b46736e7c5582e
--- /dev/null
+++ b/assets/scripts/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a){Galleria.requires(1.25,"The Flickr Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Flickr=function(a){this.api_key=a||"2a2ce06c15780ebeb0b706650fc890b2",this.options={max:30,imageSize:"medium",thumbSize:"thumb",sort:"interestingness-desc",description:!1,complete:function(){},backlink:!1}},Galleria.Flickr.prototype={constructor:Galleria.Flickr,search:function(a,b){return this._find({text:a},b)},tags:function(a,b){return this._find({tags:a},b)},user:function(a,b){return this._call({method:"flickr.urls.lookupUser",url:"flickr.com/photos/"+a},function(a){this._find({user_id:a.user.id,method:"flickr.people.getPublicPhotos"},b)})},set:function(a,b){return this._find({photoset_id:a,method:"flickr.photosets.getPhotos"},b)},gallery:function(a,b){return this._find({gallery_id:a,method:"flickr.galleries.getPhotos"},b)},groupsearch:function(a,b){return this._call({text:a,method:"flickr.groups.search"},function(a){this.group(a.groups.group[0].nsid,b)})},group:function(a,b){return this._find({group_id:a,method:"flickr.groups.pools.getPhotos"},b)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c){var d="https://api.flickr.com/services/rest/?",e=this;return b=a.extend({format:"json",jsoncallback:"?",api_key:this.api_key},b),a.each(b,function(a,b){d+="&"+a+"="+b}),a.getJSON(d,function(a){"ok"===a.stat?c.call(e,a):Galleria.raise(a.code.toString()+" "+a.stat+": "+a.message,!0)}),e},_getBig:function(a){return a.url_l?a.url_l:parseInt(a.width_o,10)>1280?"https://farm"+a.farm+".static.flickr.com/"+a.server+"/"+a.id+"_"+a.secret+"_b.jpg":a.url_o||a.url_z||a.url_m},_getSize:function(a,b){var c;switch(b){case"thumb":c=a.url_t;break;case"small":c=a.url_s;break;case"big":c=this._getBig(a);break;case"original":c=a.url_o?a.url_o:this._getBig(a);break;default:c=a.url_z||a.url_m}return c},_find:function(b,c){return b=a.extend({method:"flickr.photos.search",extras:"url_t,url_m,url_o,url_s,url_l,url_z,description",sort:this.options.sort,per_page:Math.min(this.options.max,500)},b),this._call(b,function(a){var b,d,e=[],f=a.photos?a.photos.photo:a.photoset.photo,g=f.length;for(d=0;d<g;d++)b=f[d],e.push({thumb:this._getSize(b,this.options.thumbSize),image:this._getSize(b,this.options.imageSize),big:this._getBig(b),title:f[d].title,description:this.options.description&&f[d].description?f[d].description._content:"",link:this.options.backlink?"https://flickr.com/photos/"+b.owner+"/"+b.id:""});c.call(this,e)})}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.flickr)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.flickr.split(":"),h=a.extend({},e._options.flickrOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Flickr.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Flickr plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No flickr argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Flickr,"object"==typeof e._options.flickrOptions&&d.setOptions(e._options.flickrOptions),d[g[0]](g[1],function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)})}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/assets/scripts/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..2413313da9d3c55f3afdf3e68e2441cc8bab7fe8
--- /dev/null
+++ b/assets/scripts/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a){Galleria.requires(1.25,"The Flickr Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Flickr=function(a){this.api_key=a||"2a2ce06c15780ebeb0b706650fc890b2",this.options={max:30,imageSize:"medium",thumbSize:"thumb",sort:"interestingness-desc",description:!1,complete:function(){},backlink:!1}},Galleria.Flickr.prototype={constructor:Galleria.Flickr,search:function(a,b){return this._find({text:a},b)},tags:function(a,b){return this._find({tags:a},b)},user:function(a,b){return this._call({method:"flickr.urls.lookupUser",url:"flickr.com/photos/"+a},function(a){this._find({user_id:a.user.id,method:"flickr.people.getPublicPhotos"},b)})},set:function(a,b){return this._find({photoset_id:a,method:"flickr.photosets.getPhotos"},b)},gallery:function(a,b){return this._find({gallery_id:a,method:"flickr.galleries.getPhotos"},b)},groupsearch:function(a,b){return this._call({text:a,method:"flickr.groups.search"},function(a){this.group(a.groups.group[0].nsid,b)})},group:function(a,b){return this._find({group_id:a,method:"flickr.groups.pools.getPhotos"},b)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c){var d="https://api.flickr.com/services/rest/?",e=this;return b=a.extend({format:"json",jsoncallback:"?",api_key:this.api_key},b),a.each(b,function(a,b){d+="&"+a+"="+b}),a.getJSON(d,function(a){"ok"===a.stat?c.call(e,a):Galleria.raise(a.code.toString()+" "+a.stat+": "+a.message,!0)}),e},_getBig:function(a){return a.url_l?a.url_l:parseInt(a.width_o,10)>1280?"https://farm"+a.farm+".static.flickr.com/"+a.server+"/"+a.id+"_"+a.secret+"_b.jpg":a.url_o||a.url_z||a.url_m},_getSize:function(a,b){var c;switch(b){case"thumb":c=a.url_t;break;case"small":c=a.url_s;break;case"big":c=this._getBig(a);break;case"original":c=a.url_o?a.url_o:this._getBig(a);break;default:c=a.url_z||a.url_m}return c},_find:function(b,c){return b=a.extend({method:"flickr.photos.search",extras:"url_t,url_m,url_o,url_s,url_l,url_z,description",sort:this.options.sort,per_page:Math.min(this.options.max,500)},b),this._call(b,function(a){var b,d,e=[],f=a.photos?a.photos.photo:a.photoset.photo,g=f.length;for(d=0;d<g;d++)b=f[d],e.push({thumb:this._getSize(b,this.options.thumbSize),image:this._getSize(b,this.options.imageSize),big:this._getBig(b),title:f[d].title,description:this.options.description&&f[d].description?f[d].description._content:"",link:this.options.backlink?"https://flickr.com/photos/"+b.owner+"/"+b.id:""});c.call(this,e)})}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.flickr)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.flickr.split(":"),h=a.extend({},e._options.flickrOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Flickr.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Flickr plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No flickr argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Flickr,"object"==typeof e._options.flickrOptions&&d.setOptions(e._options.flickrOptions),d[g[0]](g[1],function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)})}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/flickr/galleria.flickr.min.js b/assets/scripts/galleria/plugins/flickr/galleria.flickr.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..4b79ca35be47830b88aa9b0b77ae8de76a33a8ed
--- /dev/null
+++ b/assets/scripts/galleria/plugins/flickr/galleria.flickr.min.js
@@ -0,0 +1 @@
+(function($){Galleria.requires(1.25,"The Flickr Plugin requires Galleria version 1.2.5 or later.");var PATH=Galleria.utils.getScriptPath();Galleria.Flickr=function(api_key){this.api_key=api_key||"2a2ce06c15780ebeb0b706650fc890b2";this.options={max:30,imageSize:"medium",thumbSize:"thumb",sort:"interestingness-desc",description:false,complete:function(){},backlink:false}};Galleria.Flickr.prototype={constructor:Galleria.Flickr,search:function(phrase,callback){return this._find({text:phrase},callback)},tags:function(tag,callback){return this._find({tags:tag},callback)},user:function(username,callback){return this._call({method:"flickr.urls.lookupUser",url:"flickr.com/photos/"+username},function(data){this._find({user_id:data.user.id,method:"flickr.people.getPublicPhotos"},callback)})},set:function(photoset_id,callback){return this._find({photoset_id:photoset_id,method:"flickr.photosets.getPhotos"},callback)},gallery:function(gallery_id,callback){return this._find({gallery_id:gallery_id,method:"flickr.galleries.getPhotos"},callback)},groupsearch:function(group,callback){return this._call({text:group,method:"flickr.groups.search"},function(data){this.group(data.groups.group[0].nsid,callback)})},group:function(group_id,callback){return this._find({group_id:group_id,method:"flickr.groups.pools.getPhotos"},callback)},setOptions:function(options){$.extend(this.options,options);return this},_call:function(params,callback){var url="https://api.flickr.com/services/rest/?";var scope=this;params=$.extend({format:"json",jsoncallback:"?",api_key:this.api_key},params);$.each(params,function(key,value){url+="&"+key+"="+value});$.getJSON(url,function(data){if(data.stat==="ok"){callback.call(scope,data)}else{Galleria.raise(data.code.toString()+" "+data.stat+": "+data.message,true)}});return scope},_getBig:function(photo){if(photo.url_l){return photo.url_l}else if(parseInt(photo.width_o,10)>1280){return"https://farm"+photo.farm+".static.flickr.com/"+photo.server+"/"+photo.id+"_"+photo.secret+"_b.jpg"}return photo.url_o||photo.url_z||photo.url_m},_getSize:function(photo,size){var img;switch(size){case"thumb":img=photo.url_t;break;case"small":img=photo.url_s;break;case"big":img=this._getBig(photo);break;case"original":img=photo.url_o?photo.url_o:this._getBig(photo);break;default:img=photo.url_z||photo.url_m;break}return img},_find:function(params,callback){params=$.extend({method:"flickr.photos.search",extras:"url_t,url_m,url_o,url_s,url_l,url_z,description",sort:this.options.sort,per_page:Math.min(this.options.max,500)},params);return this._call(params,function(data){var gallery=[],photos=data.photos?data.photos.photo:data.photoset.photo,len=photos.length,photo,i;for(i=0;i<len;i++){photo=photos[i];gallery.push({thumb:this._getSize(photo,this.options.thumbSize),image:this._getSize(photo,this.options.imageSize),big:this._getBig(photo),title:photos[i].title,description:this.options.description&&photos[i].description?photos[i].description._content:"",link:this.options.backlink?"https://flickr.com/photos/"+photo.owner+"/"+photo.id:""})}callback.call(this,gallery)})}};var load=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||typeof this._options.flickr!=="string"){load.apply(this,Galleria.utils.array(arguments));return}var self=this,args=Galleria.utils.array(arguments),flickr=this._options.flickr.split(":"),f,opts=$.extend({},self._options.flickrOptions),loader=typeof opts.loader!=="undefined"?opts.loader:$("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+PATH+"loader.gif) no-repeat 50% 50%"});if(flickr.length){if(typeof Galleria.Flickr.prototype[flickr[0]]!=="function"){Galleria.raise(flickr[0]+" method not found in Flickr plugin");return load.apply(this,args)}if(!flickr[1]){Galleria.raise("No flickr argument found");return load.apply(this,args)}window.setTimeout(function(){self.$("target").append(loader)},100);f=new Galleria.Flickr;if(typeof self._options.flickrOptions==="object"){f.setOptions(self._options.flickrOptions)}f[flickr[0]](flickr[1],function(data){self._data=data;loader.remove();self.trigger(Galleria.DATA);f.options.complete.call(f,data)})}else{load.apply(this,args)}}})(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/flickr/loader.gif b/assets/scripts/galleria/plugins/flickr/loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750
Binary files /dev/null and b/assets/scripts/galleria/plugins/flickr/loader.gif differ
diff --git a/assets/scripts/galleria/plugins/history/galleria.history.js b/assets/scripts/galleria/plugins/history/galleria.history.js
new file mode 100644
index 0000000000000000000000000000000000000000..45688c8216c719b739616f8d0b6b3bb54325f262
--- /dev/null
+++ b/assets/scripts/galleria/plugins/history/galleria.history.js
@@ -0,0 +1,147 @@
+/**
+ * Galleria History Plugin 2016-09-03
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function( $, window ) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.requires(1.25, 'The History Plugin requires Galleria version 1.2.5 or later.');
+
+Galleria.History = (function() {
+
+    var onloads = [],
+
+        init = false,
+
+        loc = window.location,
+
+        doc = window.document,
+
+        ie = Galleria.IE,
+
+        support = 'onhashchange' in window && ( doc.mode === undefined || doc.mode > 7 ),
+
+        iframe,
+
+        get = function( winloc ) {
+            if( iframe && !support && Galleria.IE ) {
+                winloc = winloc || iframe.location;
+            }  else {
+                winloc = loc;
+            }
+            return parseInt( winloc.hash.substr(2), 10 );
+        },
+
+        saved = get( loc ),
+
+        callbacks = [],
+
+        onchange = function() {
+            $.each( callbacks, function( i, fn ) {
+                fn.call( window, get() );
+            });
+        },
+
+        ready = function() {
+            $.each( onloads, function(i, fn) {
+                fn();
+            });
+
+            init = true;
+        },
+
+        setHash = function( val ) {
+            return '/' + val;
+        };
+
+    // always remove support if IE < 8
+    if ( support && ie < 8 ) {
+        support = false;
+    }
+
+    if ( !support ) {
+
+        $(function() {
+
+            var interval = window.setInterval(function() {
+
+                var hash = get();
+
+                if ( !isNaN( hash ) && hash != saved ) {
+                    saved = hash;
+                    loc.hash = setHash( hash );
+                    onchange();
+                }
+
+            }, 50);
+
+            if ( ie ) {
+
+                $('<iframe tabindex="-1" title="empty">').hide().attr( 'src', 'about:blank' ).one('load', function() {
+
+                    iframe = this.contentWindow;
+
+                    ready();
+
+                }).insertAfter(doc.body);
+
+            } else {
+                ready();
+            }
+        });
+    } else {
+        ready();
+    }
+
+    return {
+
+        change: function( fn ) {
+
+            callbacks.push( fn );
+
+            if( support ) {
+                window.onhashchange = onchange;
+            }
+        },
+
+        set: function( val ) {
+
+            if ( isNaN( val ) ) {
+                return;
+            }
+
+            if ( !support && ie ) {
+
+                this.ready(function() {
+
+                    var idoc = iframe.document;
+                    idoc.open();
+                    idoc.close();
+
+                    iframe.location.hash = setHash( val );
+
+                });
+            }
+
+            loc.hash = setHash( val );
+        },
+
+        ready: function(fn) {
+            if (!init) {
+                onloads.push(fn);
+            } else {
+                fn();
+            }
+        }
+    };
+}());
+
+}( jQuery, this ));
+
diff --git a/assets/scripts/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/assets/scripts/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..58c5ac07b3f408dd22f4ff250d70ba3e6e0c4176
--- /dev/null
+++ b/assets/scripts/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a,b){Galleria.requires(1.25,"The History Plugin requires Galleria version 1.2.5 or later."),Galleria.History=function(){var c,d=[],e=!1,f=b.location,g=b.document,h=Galleria.IE,i="onhashchange"in b&&(void 0===g.mode||g.mode>7),j=function(a){return a=c&&!i&&Galleria.IE?a||c.location:f,parseInt(a.hash.substr(2),10)},k=j(f),l=[],m=function(){a.each(l,function(a,c){c.call(b,j())})},n=function(){a.each(d,function(a,b){b()}),e=!0},o=function(a){return"/"+a};return i&&h<8&&(i=!1),i?n():a(function(){b.setInterval(function(){var a=j();isNaN(a)||a==k||(k=a,f.hash=o(a),m())},50);h?a('<iframe tabindex="-1" title="empty">').hide().attr("src","about:blank").one("load",function(){c=this.contentWindow,n()}).insertAfter(g.body):n()}),{change:function(a){l.push(a),i&&(b.onhashchange=m)},set:function(a){isNaN(a)||(!i&&h&&this.ready(function(){var b=c.document;b.open(),b.close(),c.location.hash=o(a)}),f.hash=o(a))},ready:function(a){e?a():d.push(a)}}}()}(jQuery,this);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/assets/scripts/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..e727328b6edd5264ac1759f41da8cbb1ce8ce80a
--- /dev/null
+++ b/assets/scripts/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a,b){Galleria.requires(1.25,"The History Plugin requires Galleria version 1.2.5 or later."),Galleria.History=function(){var c,d=[],e=!1,f=b.location,g=b.document,h=Galleria.IE,i="onhashchange"in b&&(void 0===g.mode||g.mode>7),j=function(a){return a=c&&!i&&Galleria.IE?a||c.location:f,parseInt(a.hash.substr(2),10)},k=j(f),l=[],m=function(){a.each(l,function(a,c){c.call(b,j())})},n=function(){a.each(d,function(a,b){b()}),e=!0},o=function(a){return"/"+a};return i&&h<8&&(i=!1),i?n():a(function(){b.setInterval(function(){var a=j();isNaN(a)||a==k||(k=a,f.hash=o(a),m())},50);h?a('<iframe tabindex="-1" title="empty">').hide().attr("src","about:blank").one("load",function(){c=this.contentWindow,n()}).insertAfter(g.body):n()}),{change:function(a){l.push(a),i&&(b.onhashchange=m)},set:function(a){isNaN(a)||(!i&&h&&this.ready(function(){var b=c.document;b.open(),b.close(),c.location.hash=o(a)}),f.hash=o(a))},ready:function(a){e?a():d.push(a)}}}()}(jQuery,this);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/history/galleria.history.min.js b/assets/scripts/galleria/plugins/history/galleria.history.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..13e87be547eee86f6acca3ca6c8e469d18b35d8b
--- /dev/null
+++ b/assets/scripts/galleria/plugins/history/galleria.history.min.js
@@ -0,0 +1 @@
+(function($,window){Galleria.requires(1.25,"The History Plugin requires Galleria version 1.2.5 or later.");Galleria.History=function(){var onloads=[],init=false,loc=window.location,doc=window.document,ie=Galleria.IE,support="onhashchange"in window&&(doc.mode===undefined||doc.mode>7),iframe,get=function(winloc){if(iframe&&!support&&Galleria.IE){winloc=winloc||iframe.location}else{winloc=loc}return parseInt(winloc.hash.substr(2),10)},saved=get(loc),callbacks=[],onchange=function(){$.each(callbacks,function(i,fn){fn.call(window,get())})},ready=function(){$.each(onloads,function(i,fn){fn()});init=true},setHash=function(val){return"/"+val};if(support&&ie<8){support=false}if(!support){$(function(){var interval=window.setInterval(function(){var hash=get();if(!isNaN(hash)&&hash!=saved){saved=hash;loc.hash=setHash(hash);onchange()}},50);if(ie){$('<iframe tabindex="-1" title="empty">').hide().attr("src","about:blank").one("load",function(){iframe=this.contentWindow;ready()}).insertAfter(doc.body)}else{ready()}})}else{ready()}return{change:function(fn){callbacks.push(fn);if(support){window.onhashchange=onchange}},set:function(val){if(isNaN(val)){return}if(!support&&ie){this.ready(function(){var idoc=iframe.document;idoc.open();idoc.close();iframe.location.hash=setHash(val)})}loc.hash=setHash(val)},ready:function(fn){if(!init){onloads.push(fn)}else{fn()}}}}()})(jQuery,this);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/history/history-demo.html b/assets/scripts/galleria/plugins/history/history-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..5819b8e7b7c3fbf8702b5e6c2896312288187140
--- /dev/null
+++ b/assets/scripts/galleria/plugins/history/history-demo.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria History Plugin</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+
+        <!-- load jQuery -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <!-- load the History plugin, no need for further scripting -->
+        <script src="galleria.history.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria History Plugin</h1>
+        <p>Demonstrating a basic history example. Supports most browsers, including FF 3.0+ and IE 7+</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Locomotives-Roundhouse2.jpg/800px-Locomotives-Roundhouse2.jpg">
+                <img title="Locomotives Roundhouse"
+                     alt="Steam locomotives of the Chicago &amp; North Western Railway."
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Locomotives-Roundhouse2.jpg/100px-Locomotives-Roundhouse2.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Icebergs_in_the_High_Arctic_-_20050907.jpg/1000px-Icebergs_in_the_High_Arctic_-_20050907.jpg">
+                <img title="Icebergs in the High Arctic"
+                     alt="”The debris loading isn't particularly extensive, but the color is usual.”"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Icebergs_in_the_High_Arctic_-_20050907.jpg/100px-Icebergs_in_the_High_Arctic_-_20050907.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg/1000px-Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg">
+                <img title="Araña"
+                     alt="Xysticus cristatus, A Estrada, Galicia, Spain"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg/100px-Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg/1000px-9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg">
+                <img title="Museo storia naturale"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg/100px-9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg/1000px-Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg">
+                <img title="Grjótagjá caves in summer 2009"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg/100px-Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/9/90/20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg/1000px-20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg">
+                <img title="Thermes"
+                     alt="Xanthi hot-spa springs, Xanthi Prefecture, Greece"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/90/20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg/100px-20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Polish_Army_Ko%C5%82obrzeg_077.JPG/1024px-Polish_Army_Ko%C5%82obrzeg_077.JPG">
+                <img title="Polish Army Kołobrzeg"
+                     alt="A display of the Polish Army. Both the soldier, and the vehicle belong to the 7th Pomeranian Coastal Defence Brigade, a part of the Szczecin-based 12th Mechanized Division ”Bolesław Krzywousty”"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Polish_Army_Ko%C5%82obrzeg_077.JPG/100px-Polish_Army_Ko%C5%82obrzeg_077.JPG">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/20100213_Zlatograd_Bulgaria_3.jpg/1024px-20100213_Zlatograd_Bulgaria_3.jpg">
+                <img title="Zlatograd Bulgaria"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/20100213_Zlatograd_Bulgaria_3.jpg/100px-20100213_Zlatograd_Bulgaria_3.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg/1024px-FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg">
+                <img title="09-28-2001 in New York City"
+                     alt="New York, NY, September 28, 2001 -- Debris on surrounding roofs at the site of the World Trade Center. Photo by Andrea Booher/ FEMA News Photo"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg/100px-FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Antennae%2C_Hubble_images.jpg/1024px-Antennae%2C_Hubble_images.jpg">
+                <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Antennae%2C_Hubble_images.jpg/100px-Antennae%2C_Hubble_images.jpg">
+            </a>
+        </div>
+
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('../../themes/classic/galleria.classic.min.js');
+
+        // Initialize Galleria
+        Galleria.run('#galleria');
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/picasa/galleria.picasa.js b/assets/scripts/galleria/plugins/picasa/galleria.picasa.js
new file mode 100644
index 0000000000000000000000000000000000000000..8cf1ead15abfe8e16a0efcb51cdd20a4654d28c0
--- /dev/null
+++ b/assets/scripts/galleria/plugins/picasa/galleria.picasa.js
@@ -0,0 +1,321 @@
+/**
+ * Galleria Picasa Plugin 2016-09-03
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.requires(1.25, 'The Picasa Plugin requires Galleria version 1.2.5 or later.');
+
+// The script path
+var PATH = Galleria.utils.getScriptPath();
+
+/**
+
+    @class
+    @constructor
+
+    @example var picasa = new Galleria.Picasa();
+
+    @author http://wib.io
+
+    @requires jQuery
+    @requires Galleria
+
+    @returns Instance
+*/
+
+Galleria.Picasa = function() {
+
+    this.options = {
+        max: 30,                       // photos to return
+        imageSize: 'medium',           // photo size ( thumb,small,medium,big,original ) or a number
+        thumbSize: 'thumb',            // thumbnail size ( thumb,small,medium,big,original ) or a number
+        complete: function(){}         // callback to be called inside the Galleria.prototype.load
+    };
+
+};
+
+Galleria.Picasa.prototype = {
+
+    // bring back the constructor reference
+
+    constructor: Galleria.Picasa,
+
+    /**
+        Search for anything at Picasa
+
+        @param {String} phrase The string to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    search: function( phrase, callback ) {
+        return this._call( 'search', 'all', {
+            q: phrase
+        }, callback );
+    },
+
+    /**
+        Get a user's public photos
+
+        @param {String} username The username to fetch photos from
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    user: function( username, callback ) {
+        return this._call( 'user', 'user/' + username, callback );
+    },
+
+    /**
+        Get photos from an album
+
+        @param {String} username The username that owns the album
+        @param {String} album The album ID
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    useralbum: function( username, album, callback ) {
+        return this._call( 'useralbum', 'user/' + username + '/album/' + album, callback );
+    },
+
+    /**
+        Set picasa options
+
+        @param {Object} options The options object to blend
+
+        @returns Instance
+    */
+
+    setOptions: function( options ) {
+        $.extend(this.options, options);
+        return this;
+    },
+
+
+    // call Picasa
+
+    _call: function( type, url, params, callback ) {
+
+        url = 'https://picasaweb.google.com/data/feed/api/' + url + '?';
+
+        if (typeof params == 'function') {
+            callback = params;
+            params = {};
+        }
+
+        var self = this;
+
+        params = $.extend({
+            'kind': 'photo',
+            'access': 'public',
+            'max-results': this.options.max,
+            'thumbsize': this._getSizes().join(','),
+            'alt': 'json-in-script',
+            'callback': '?'
+        }, params );
+
+        $.each(params, function( key, value ) {
+            url += '&' + key + '=' + value;
+        });
+
+        // since Picasa throws 404 when the call is malformed, we must set a timeout here:
+
+        var data = false;
+
+        Galleria.utils.wait({
+            until: function() {
+                return data;
+            },
+            success: function() {
+                self._parse.call( self, data.feed.entry, callback );
+            },
+            error: function() {
+                var msg = '';
+                if ( type == 'user' ) {
+                    msg = 'user not found.';
+                } else if ( type == 'useralbum' ) {
+                    msg = 'album or user not found.';
+                }
+                Galleria.raise('Picasa request failed' + (msg ? ': ' + msg : '.'));
+            },
+            timeout: 5000
+        });
+
+        $.getJSON( url, function( result ) {
+            data = result;
+        });
+
+        return self;
+    },
+
+
+    // parse image sizes and return an array of three
+
+    _getSizes: function() {
+
+        var self = this,
+            norm = {
+                small: '72c',
+                thumb: '104u',
+                medium: '640u',
+                big: '1024u',
+                original: '1600u'
+            },
+            op = self.options,
+            t = {},
+            n,
+            sz = [32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];
+
+        $(['thumbSize', 'imageSize']).each(function() {
+            if( op[this] in norm ) {
+                t[this] = norm[ op[this] ];
+            } else {
+                n = Galleria.utils.parseValue( op[this] );
+                if (n > 1600) {
+                    n = 1600;
+                } else {
+                    $.each( sz, function(i) {
+                        if ( n < this ) {
+                            n = sz[i-1];
+                            return false;
+                        }
+                    });
+                }
+                t[this] = n;
+            }
+        });
+
+        return [ t.thumbSize, t.imageSize, '1280u'];
+
+    },
+
+
+    // parse the result and call the callback with the galleria-ready data array
+
+    _parse: function( data, callback ) {
+
+        var self = this,
+            gallery = [],
+            img;
+
+        $.each( data, function() {
+
+            img = this.media$group.media$thumbnail;
+
+            gallery.push({
+                thumb: img[0].url,
+                image: img[1].url,
+                big: img[2].url,
+                title: this.summary.$t
+            });
+        });
+
+        callback.call( this, gallery );
+    }
+};
+
+
+/**
+    Galleria modifications
+    We fake-extend the load prototype to make Picasa integration as simple as possible
+*/
+
+
+// save the old prototype in a local variable
+
+var load = Galleria.prototype.load;
+
+
+// fake-extend the load prototype using the picasa data
+
+Galleria.prototype.load = function() {
+
+    // pass if no data is provided or picasa option not found
+    if ( arguments.length || typeof this._options.picasa !== 'string' ) {
+        load.apply( this, Galleria.utils.array( arguments ) );
+        return;
+    }
+
+    // define some local vars
+    var self = this,
+        args = Galleria.utils.array( arguments ),
+        picasa = this._options.picasa.split(':'),
+        p,
+        opts = $.extend({}, self._options.picasaOptions),
+        loader = typeof opts.loader !== 'undefined' ?
+            opts.loader : $('<div>').css({
+                width: 48,
+                height: 48,
+                opacity: 0.7,
+                background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%'
+            });
+
+    if ( picasa.length ) {
+
+        // validate the method
+        if ( typeof Galleria.Picasa.prototype[ picasa[0] ] !== 'function' ) {
+            Galleria.raise( picasa[0] + ' method not found in Picasa plugin' );
+            return load.apply( this, args );
+        }
+
+        // validate the argument
+        if ( !picasa[1] ) {
+            Galleria.raise( 'No picasa argument found' );
+            return load.apply( this, args );
+        }
+
+        // apply the preloader
+        window.setTimeout(function() {
+            self.$( 'target' ).append( loader );
+        },100);
+
+        // create the instance
+        p = new Galleria.Picasa();
+
+        // apply Flickr options
+        if ( typeof self._options.picasaOptions === 'object' ) {
+            p.setOptions( self._options.picasaOptions );
+        }
+
+        // call the picasa method and trigger the DATA event
+        var arg = [];
+        if ( picasa[0] == 'useralbum' ) {
+            arg = picasa[1].split('/');
+            if (arg.length != 2) {
+                Galleria.raise( 'Picasa useralbum not correctly formatted (should be [user]/[album])');
+                return;
+            }
+        } else {
+            arg.push( picasa[1] );
+        }
+
+        arg.push(function(data) {
+            self._data = data;
+            loader.remove();
+            self.trigger( Galleria.DATA );
+            p.options.complete.call(p, data);
+        });
+
+        p[ picasa[0] ].apply( p, arg );
+
+    } else {
+
+        // if flickr array not found, pass
+        load.apply( this, args );
+    }
+};
+
+}( jQuery ) );
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/assets/scripts/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..2480a0258acff955abeddf719646830e425a301f
--- /dev/null
+++ b/assets/scripts/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a){Galleria.requires(1.25,"The Picasa Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Picasa=function(){this.options={max:30,imageSize:"medium",thumbSize:"thumb",complete:function(){}}},Galleria.Picasa.prototype={constructor:Galleria.Picasa,search:function(a,b){return this._call("search","all",{q:a},b)},user:function(a,b){return this._call("user","user/"+a,b)},useralbum:function(a,b,c){return this._call("useralbum","user/"+a+"/album/"+b,c)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c,d,e){c="https://picasaweb.google.com/data/feed/api/"+c+"?","function"==typeof d&&(e=d,d={});var f=this;d=a.extend({kind:"photo",access:"public","max-results":this.options.max,thumbsize:this._getSizes().join(","),alt:"json-in-script",callback:"?"},d),a.each(d,function(a,b){c+="&"+a+"="+b});var g=!1;return Galleria.utils.wait({until:function(){return g},success:function(){f._parse.call(f,g.feed.entry,e)},error:function(){var a="";"user"==b?a="user not found.":"useralbum"==b&&(a="album or user not found."),Galleria.raise("Picasa request failed"+(a?": "+a:"."))},timeout:5e3}),a.getJSON(c,function(a){g=a}),f},_getSizes:function(){var b,c=this,d={small:"72c",thumb:"104u",medium:"640u",big:"1024u",original:"1600u"},e=c.options,f={},g=[32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];return a(["thumbSize","imageSize"]).each(function(){e[this]in d?f[this]=d[e[this]]:(b=Galleria.utils.parseValue(e[this]),b>1600?b=1600:a.each(g,function(a){if(b<this)return b=g[a-1],!1}),f[this]=b)}),[f.thumbSize,f.imageSize,"1280u"]},_parse:function(b,c){var d,e=[];a.each(b,function(){d=this.media$group.media$thumbnail,e.push({thumb:d[0].url,image:d[1].url,big:d[2].url,title:this.summary.$t})}),c.call(this,e)}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.picasa)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.picasa.split(":"),h=a.extend({},e._options.picasaOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Picasa.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Picasa plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No picasa argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Picasa,"object"==typeof e._options.picasaOptions&&d.setOptions(e._options.picasaOptions);var j=[];if("useralbum"==g[0]){if(j=g[1].split("/"),2!=j.length)return void Galleria.raise("Picasa useralbum not correctly formatted (should be [user]/[album])")}else j.push(g[1]);j.push(function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)}),d[g[0]].apply(d,j)}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/assets/scripts/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..991ac2444fbb15ce987b3a51892ed8b87b7c1498
--- /dev/null
+++ b/assets/scripts/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a){Galleria.requires(1.25,"The Picasa Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Picasa=function(){this.options={max:30,imageSize:"medium",thumbSize:"thumb",complete:function(){}}},Galleria.Picasa.prototype={constructor:Galleria.Picasa,search:function(a,b){return this._call("search","all",{q:a},b)},user:function(a,b){return this._call("user","user/"+a,b)},useralbum:function(a,b,c){return this._call("useralbum","user/"+a+"/album/"+b,c)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c,d,e){c="https://picasaweb.google.com/data/feed/api/"+c+"?","function"==typeof d&&(e=d,d={});var f=this;d=a.extend({kind:"photo",access:"public","max-results":this.options.max,thumbsize:this._getSizes().join(","),alt:"json-in-script",callback:"?"},d),a.each(d,function(a,b){c+="&"+a+"="+b});var g=!1;return Galleria.utils.wait({until:function(){return g},success:function(){f._parse.call(f,g.feed.entry,e)},error:function(){var a="";"user"==b?a="user not found.":"useralbum"==b&&(a="album or user not found."),Galleria.raise("Picasa request failed"+(a?": "+a:"."))},timeout:5e3}),a.getJSON(c,function(a){g=a}),f},_getSizes:function(){var b,c=this,d={small:"72c",thumb:"104u",medium:"640u",big:"1024u",original:"1600u"},e=c.options,f={},g=[32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];return a(["thumbSize","imageSize"]).each(function(){e[this]in d?f[this]=d[e[this]]:(b=Galleria.utils.parseValue(e[this]),b>1600?b=1600:a.each(g,function(a){if(b<this)return b=g[a-1],!1}),f[this]=b)}),[f.thumbSize,f.imageSize,"1280u"]},_parse:function(b,c){var d,e=[];a.each(b,function(){d=this.media$group.media$thumbnail,e.push({thumb:d[0].url,image:d[1].url,big:d[2].url,title:this.summary.$t})}),c.call(this,e)}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.picasa)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.picasa.split(":"),h=a.extend({},e._options.picasaOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Picasa.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Picasa plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No picasa argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Picasa,"object"==typeof e._options.picasaOptions&&d.setOptions(e._options.picasaOptions);var j=[];if("useralbum"==g[0]){if(j=g[1].split("/"),2!=j.length)return void Galleria.raise("Picasa useralbum not correctly formatted (should be [user]/[album])")}else j.push(g[1]);j.push(function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)}),d[g[0]].apply(d,j)}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/picasa/galleria.picasa.min.js b/assets/scripts/galleria/plugins/picasa/galleria.picasa.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb377ad124b510cec049612b91c0e916638818e0
--- /dev/null
+++ b/assets/scripts/galleria/plugins/picasa/galleria.picasa.min.js
@@ -0,0 +1 @@
+(function($){Galleria.requires(1.25,"The Picasa Plugin requires Galleria version 1.2.5 or later.");var PATH=Galleria.utils.getScriptPath();Galleria.Picasa=function(){this.options={max:30,imageSize:"medium",thumbSize:"thumb",complete:function(){}}};Galleria.Picasa.prototype={constructor:Galleria.Picasa,search:function(phrase,callback){return this._call("search","all",{q:phrase},callback)},user:function(username,callback){return this._call("user","user/"+username,callback)},useralbum:function(username,album,callback){return this._call("useralbum","user/"+username+"/album/"+album,callback)},setOptions:function(options){$.extend(this.options,options);return this},_call:function(type,url,params,callback){url="https://picasaweb.google.com/data/feed/api/"+url+"?";if(typeof params=="function"){callback=params;params={}}var self=this;params=$.extend({kind:"photo",access:"public","max-results":this.options.max,thumbsize:this._getSizes().join(","),alt:"json-in-script",callback:"?"},params);$.each(params,function(key,value){url+="&"+key+"="+value});var data=false;Galleria.utils.wait({until:function(){return data},success:function(){self._parse.call(self,data.feed.entry,callback)},error:function(){var msg="";if(type=="user"){msg="user not found."}else if(type=="useralbum"){msg="album or user not found."}Galleria.raise("Picasa request failed"+(msg?": "+msg:"."))},timeout:5e3});$.getJSON(url,function(result){data=result});return self},_getSizes:function(){var self=this,norm={small:"72c",thumb:"104u",medium:"640u",big:"1024u",original:"1600u"},op=self.options,t={},n,sz=[32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];$(["thumbSize","imageSize"]).each(function(){if(op[this]in norm){t[this]=norm[op[this]]}else{n=Galleria.utils.parseValue(op[this]);if(n>1600){n=1600}else{$.each(sz,function(i){if(n<this){n=sz[i-1];return false}})}t[this]=n}});return[t.thumbSize,t.imageSize,"1280u"]},_parse:function(data,callback){var self=this,gallery=[],img;$.each(data,function(){img=this.media$group.media$thumbnail;gallery.push({thumb:img[0].url,image:img[1].url,big:img[2].url,title:this.summary.$t})});callback.call(this,gallery)}};var load=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||typeof this._options.picasa!=="string"){load.apply(this,Galleria.utils.array(arguments));return}var self=this,args=Galleria.utils.array(arguments),picasa=this._options.picasa.split(":"),p,opts=$.extend({},self._options.picasaOptions),loader=typeof opts.loader!=="undefined"?opts.loader:$("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+PATH+"loader.gif) no-repeat 50% 50%"});if(picasa.length){if(typeof Galleria.Picasa.prototype[picasa[0]]!=="function"){Galleria.raise(picasa[0]+" method not found in Picasa plugin");return load.apply(this,args)}if(!picasa[1]){Galleria.raise("No picasa argument found");return load.apply(this,args)}window.setTimeout(function(){self.$("target").append(loader)},100);p=new Galleria.Picasa;if(typeof self._options.picasaOptions==="object"){p.setOptions(self._options.picasaOptions)}var arg=[];if(picasa[0]=="useralbum"){arg=picasa[1].split("/");if(arg.length!=2){Galleria.raise("Picasa useralbum not correctly formatted (should be [user]/[album])");return}}else{arg.push(picasa[1])}arg.push(function(data){self._data=data;loader.remove();self.trigger(Galleria.DATA);p.options.complete.call(p,data)});p[picasa[0]].apply(p,arg)}else{load.apply(this,args)}}})(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/plugins/picasa/loader.gif b/assets/scripts/galleria/plugins/picasa/loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750
Binary files /dev/null and b/assets/scripts/galleria/plugins/picasa/loader.gif differ
diff --git a/assets/scripts/galleria/plugins/picasa/picasa-demo.html b/assets/scripts/galleria/plugins/picasa/picasa-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..2e8ba253554cf67e47bcb0fb834d38653058a5b8
--- /dev/null
+++ b/assets/scripts/galleria/plugins/picasa/picasa-demo.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Picasa Plugin</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px;}
+
+        </style>
+
+        <!-- load jQuery -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <!-- load picasa plugin -->
+        <script src="galleria.picasa.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Picasa Plugin Demo</h1>
+        <p>Demonstrating a basic gallery example with photos from a Picasa album.</p>
+
+        <!-- Adding gallery images. This is just a container for the dynamic picasa images -->
+
+        <div id="galleria"></div>
+
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('../../themes/classic/galleria.classic.min.js');
+
+        Galleria.run('#galleria', {
+            // The user & album. This example fetches the album "Demo" from the user "galleriajs"
+            picasa: 'useralbum:galleriajs/Demo'
+        });
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/classic/classic-demo-cdn (SFConflict me@a1b0n.com 2017-02-12-23-35-56).html b/assets/scripts/galleria/themes/classic/classic-demo-cdn (SFConflict me@a1b0n.com 2017-02-12-23-35-56).html
new file mode 100644
index 0000000000000000000000000000000000000000..e7189e3f8888739c72c41036195b33b608c22cbf
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/classic-demo-cdn (SFConflict me@a1b0n.com 2017-02-12-23-35-56).html	
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Classic Theme</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Classic Theme</h1>
+        <p>Demonstrating a basic gallery example.</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                    data-title="Biandintz eta zaldiak"
+                    data-description="Horses on Bianditz mountain, in Navarre, Spain."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                    data-title="Athabasca Rail"
+                    data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                    data-title="Back-scattering crepuscular rays"
+                    data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                    data-title="Interior convento"
+                    data-description="Interior view of Yuriria Convent, founded in 1550."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                    data-title="Oxbow Bend outlook"
+                    data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                    data-title="Hazy blue hour"
+                    data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                    data-title="Haute Severaisse valley"
+                    data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                    data-title="Bohinj lake"
+                    data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                    data-title="Bowling Balls"
+                    data-description="Mendocino county, California, USA."
+                >
+            </a>
+            <a href="https://vimeo.com/25750735">
+                <span class="video">Works for vimeo too.</span>
+            </a>
+            <a href="https://www.youtube.com/watch?v=GOD-RyVB-3Q">
+                <span class="video">Works for youtube too.</span>
+            </a>
+
+        </div>
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <!-- load jQuery -->
+    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+    <!-- load Galleria -->
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.3/galleria.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.3/themes/classic/galleria.classic.min.js"></script>
+    <script>
+        $(function() {
+            Galleria.run('#galleria');
+        });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/classic/classic-demo-cdn.html b/assets/scripts/galleria/themes/classic/classic-demo-cdn.html
new file mode 100644
index 0000000000000000000000000000000000000000..a6df2c466654049bf98685a0509cb8d5f5ccab82
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/classic-demo-cdn.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Classic Theme</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Classic Theme</h1>
+        <p>Demonstrating a basic gallery example.</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                    data-title="Biandintz eta zaldiak"
+                    data-description="Horses on Bianditz mountain, in Navarre, Spain."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                    data-title="Athabasca Rail"
+                    data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                    data-title="Back-scattering crepuscular rays"
+                    data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                    data-title="Interior convento"
+                    data-description="Interior view of Yuriria Convent, founded in 1550."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                    data-title="Oxbow Bend outlook"
+                    data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                    data-title="Hazy blue hour"
+                    data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                    data-title="Haute Severaisse valley"
+                    data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                    data-title="Bohinj lake"
+                    data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                    data-title="Bowling Balls"
+                    data-description="Mendocino county, California, USA."
+                >
+            </a>
+            <a href="https://vimeo.com/25750735">
+                <span class="video">Works for vimeo too.</span>
+            </a>
+            <a href="https://www.youtube.com/watch?v=GOD-RyVB-3Q">
+                <span class="video">Works for youtube too.</span>
+            </a>
+
+        </div>
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <!-- load jQuery -->
+    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+    <!-- load Galleria -->
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.7/galleria.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.7/themes/classic/galleria.classic.min.js"></script>
+    <script>
+        $(function() {
+            Galleria.run('#galleria');
+        });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/classic/classic-demo.html b/assets/scripts/galleria/themes/classic/classic-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..b55c93cf2a871e541e217889649928cc6abc0549
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/classic-demo.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Classic Theme</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+
+        <!-- load jQuery -->
+        <!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Classic Theme</h1>
+        <p>Demonstrating a basic gallery example.</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                    data-title="Biandintz eta zaldiak"
+                    data-description="Horses on Bianditz mountain, in Navarre, Spain."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                    data-title="Athabasca Rail"
+                    data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                    data-title="Back-scattering crepuscular rays"
+                    data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                    data-title="Interior convento"
+                    data-description="Interior view of Yuriria Convent, founded in 1550."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                    data-title="Oxbow Bend outlook"
+                    data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                    data-title="Hazy blue hour"
+                    data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                    data-title="Haute Severaisse valley"
+                    data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                    data-title="Bohinj lake"
+                    data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                    data-title="Bowling Balls"
+                    data-description="Mendocino county, California, USA."
+                >
+            </a>
+            <a href="https://vimeo.com/25750735">
+                <span class="video">Works for vimeo too.</span>
+            </a>
+            <a href="https://www.youtube.com/watch?v=GOD-RyVB-3Q">
+                <span class="video">Works for youtube too.</span>
+            </a>
+
+        </div>
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('galleria.classic.min.js');
+
+        // Initialize Galleria
+        Galleria.run('#galleria');
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/classic/classic-loader.gif b/assets/scripts/galleria/themes/classic/classic-loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750
Binary files /dev/null and b/assets/scripts/galleria/themes/classic/classic-loader.gif differ
diff --git a/assets/scripts/galleria/themes/classic/classic-map.png b/assets/scripts/galleria/themes/classic/classic-map.png
new file mode 100644
index 0000000000000000000000000000000000000000..8d3c8c45cf3ccffe1df58634063d61bd6c009125
Binary files /dev/null and b/assets/scripts/galleria/themes/classic/classic-map.png differ
diff --git a/assets/scripts/galleria/themes/classic/galleria.classic.css b/assets/scripts/galleria/themes/classic/galleria.classic.css
new file mode 100644
index 0000000000000000000000000000000000000000..bf312d4ab6886ade841a84c231228236831ad047
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/galleria.classic.css
@@ -0,0 +1,227 @@
+/**
+ * Galleria Classic Theme 2017-02-13
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+#galleria-loader{height:1px!important}
+
+.galleria-theme-classic {
+    position: relative;
+    overflow: hidden;
+    background: #000;
+}
+.galleria-theme-classic img {
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -o-user-select: none;
+}
+.galleria-theme-classic .galleria-stage {
+    position: absolute;
+    top: 10px;
+    bottom: 60px;
+    left: 10px;
+    right: 10px;
+    overflow:hidden;
+}
+.galleria-theme-classic .galleria-thumbnails-container {
+    height: 50px;
+    bottom: 0;
+    position: absolute;
+    left: 10px;
+    right: 10px;
+    z-index: 2;
+}
+.galleria-theme-classic .galleria-carousel .galleria-thumbnails-list {
+    margin-left: 30px;
+    margin-right: 30px;
+}
+.galleria-theme-classic .galleria-thumbnails .galleria-image {
+    height: 40px;
+    width: 60px;
+    background: #000;
+    margin: 0 5px 0 0;
+    border: 1px solid #000;
+    float: left;
+    cursor: pointer;
+}
+.galleria-theme-classic .galleria-counter {
+    position: absolute;
+    bottom: 10px;
+    left: 10px;
+    text-align: right;
+    color: #fff;
+    font: normal 11px/1 arial,sans-serif;
+    z-index: 1;
+}
+.galleria-theme-classic .galleria-loader {
+    background: #000;
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    z-index: 2;
+    display: none;
+    background: url(classic-loader.gif) no-repeat 2px 2px;
+}
+.galleria-theme-classic .galleria-info {
+    width: 50%;
+    top: 15px;
+    left: 15px;
+    z-index: 2;
+    position: absolute;
+}
+.galleria-theme-classic .galleria-info-text {
+    background-color: #000;
+    padding: 12px;
+    display: none;
+    /* IE7 */ zoom:1;
+}
+.galleria-theme-classic .galleria-info-title {
+    font: bold 12px/1.1 arial,sans-serif;
+    margin: 0;
+    color: #fff;
+    margin-bottom: 7px;
+}
+.galleria-theme-classic .galleria-info-description {
+    font: italic 12px/1.4 georgia,serif;
+    margin: 0;
+    color: #bbb;
+}
+.galleria-theme-classic .galleria-info-close {
+    width: 9px;
+    height: 9px;
+    position: absolute;
+    top: 5px;
+    right: 5px;
+    background-position: -753px -11px;
+    opacity: .5;
+    filter: alpha(opacity=50);
+    cursor: pointer;
+    display: none;
+}
+.galleria-theme-classic .notouch .galleria-info-close:hover{
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .touch .galleria-info-close:active{
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .galleria-info-link {
+    background-position: -669px -5px;
+    opacity: .7;
+    filter: alpha(opacity=70);
+    position: absolute;
+    width: 20px;
+    height: 20px;
+    cursor: pointer;
+    background-color: #000;
+}
+.galleria-theme-classic.notouch .galleria-info-link:hover {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic.touch .galleria-info-link:active {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .galleria-image-nav {
+    position: absolute;
+    top: 50%;
+    margin-top: -62px;
+    width: 100%;
+    height: 62px;
+    left: 0;
+}
+.galleria-theme-classic .galleria-image-nav-left,
+.galleria-theme-classic .galleria-image-nav-right {
+    opacity: .3;
+    filter: alpha(opacity=30);
+    cursor: pointer;
+    width: 62px;
+    height: 124px;
+    position: absolute;
+    left: 10px;
+    z-index: 2;
+    background-position: 0 46px;
+}
+.galleria-theme-classic .galleria-image-nav-right {
+    left: auto;
+    right: 10px;
+    background-position: -254px 46px;
+    z-index: 2;
+}
+.galleria-theme-classic.notouch .galleria-image-nav-left:hover,
+.galleria-theme-classic.notouch .galleria-image-nav-right:hover {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic.touch .galleria-image-nav-left:active,
+.galleria-theme-classic.touch .galleria-image-nav-right:active {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .galleria-thumb-nav-left,
+.galleria-theme-classic .galleria-thumb-nav-right {
+    cursor: pointer;
+    display: none;
+    background-position: -495px 5px;
+    position: absolute;
+    left: 0;
+    top: 0;
+    height: 40px;
+    width: 23px;
+    z-index: 3;
+    opacity: .8;
+    filter: alpha(opacity=80);
+}
+.galleria-theme-classic .galleria-thumb-nav-right {
+    background-position: -578px 5px;
+    border-right: none;
+    right: 0;
+    left: auto;
+}
+.galleria-theme-classic .galleria-thumbnails-container .disabled {
+    opacity: .2;
+    filter: alpha(opacity=20);
+    cursor: default;
+}
+.galleria-theme-classic.notouch .galleria-thumb-nav-left:hover,
+.galleria-theme-classic.notouch .galleria-thumb-nav-right:hover {
+    opacity: 1;
+    filter: alpha(opacity=100);
+    background-color: #111;
+}
+.galleria-theme-classic.touch .galleria-thumb-nav-left:active,
+.galleria-theme-classic.touch .galleria-thumb-nav-right:active {
+    opacity: 1;
+    filter: alpha(opacity=100);
+    background-color: #111;
+}
+.galleria-theme-classic.notouch .galleria-thumbnails-container .disabled:hover {
+    opacity: .2;
+    filter: alpha(opacity=20);
+    background-color: transparent;
+}
+
+.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-left,
+.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-right {
+    display: block;
+}
+.galleria-theme-classic .galleria-thumb-nav-left,
+.galleria-theme-classic .galleria-thumb-nav-right,
+.galleria-theme-classic .galleria-info-link,
+.galleria-theme-classic .galleria-info-close,
+.galleria-theme-classic .galleria-image-nav-left,
+.galleria-theme-classic .galleria-image-nav-right {
+    background-image: url(classic-map.png);
+    background-repeat: no-repeat;
+}
+.galleria-theme-classic.galleria-container.videoplay .galleria-info,
+.galleria-theme-classic.galleria-container.videoplay .galleria-counter{ display:none!important; }
diff --git a/assets/scripts/galleria/themes/classic/galleria.classic.js b/assets/scripts/galleria/themes/classic/galleria.classic.js
new file mode 100644
index 0000000000000000000000000000000000000000..20560d87afe1ca9943f7b52145873729dafe3706
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/galleria.classic.js
@@ -0,0 +1,102 @@
+/**
+ * Galleria Classic Theme 2017-02-13
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global window, jQuery, Galleria */
+
+Galleria.addTheme({
+    name: 'classic',
+    version: 1.5,
+    author: 'Galleria',
+    css: 'galleria.classic.css',
+    defaults: {
+        transition: 'slide',
+        thumbCrop:  'height',
+
+        // set this to false if you want to show the caption all the time:
+        _toggleInfo: true
+    },
+    init: function(options) {
+
+        Galleria.requires(1.4, 'This version of Classic theme requires Galleria 1.4 or later');
+
+        // add some elements
+        this.addElement('info-link','info-close');
+        this.append({
+            'info' : ['info-link','info-close']
+        });
+
+        // cache some stuff
+        var info = this.$('info-link,info-close,info-text'),
+            touch = Galleria.TOUCH;
+
+        // show loader & counter with opacity
+        this.$('loader,counter').show().css('opacity', 0.4);
+
+        // some stuff for non-touch browsers
+        if (! touch ) {
+            this.addIdleState( this.get('image-nav-left'), { left:-50 });
+            this.addIdleState( this.get('image-nav-right'), { right:-50 });
+            this.addIdleState( this.get('counter'), { opacity:0 });
+        }
+
+        // toggle info
+        if ( options._toggleInfo === true ) {
+            info.bind( 'click:fast', function() {
+                info.toggle();
+            });
+        } else {
+            info.show();
+            this.$('info-link, info-close').hide();
+        }
+
+        // bind some stuff
+        this.bind('thumbnail', function(e) {
+
+            if (! touch ) {
+                // fade thumbnails
+                $(e.thumbTarget).css('opacity', 0.6).parent().hover(function() {
+                    $(this).not('.active').children().stop().fadeTo(100, 1);
+                }, function() {
+                    $(this).not('.active').children().stop().fadeTo(400, 0.6);
+                });
+
+                if ( e.index === this.getIndex() ) {
+                    $(e.thumbTarget).css('opacity',1);
+                }
+            } else {
+                $(e.thumbTarget).css('opacity', this.getIndex() ? 1 : 0.6).bind('click:fast', function() {
+                    $(this).css( 'opacity', 1 ).parent().siblings().children().css('opacity', 0.6);
+                });
+            }
+        });
+
+        var activate = function(e) {
+            $(e.thumbTarget).css('opacity',1).parent().siblings().children().css('opacity', 0.6);
+        };
+
+        this.bind('loadstart', function(e) {
+            if (!e.cached) {
+                this.$('loader').show().fadeTo(200, 0.4);
+            }
+            window.setTimeout(function() {
+                activate(e);
+            }, touch ? 300 : 0);
+            this.$('info').toggle( this.hasInfo() );
+        });
+
+        this.bind('loadfinish', function(e) {
+            this.$('loader').fadeOut(200);
+        });
+    }
+});
+
+}(jQuery));
diff --git a/assets/scripts/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/assets/scripts/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..37e5a3a0ac2250d0af98713c09af8452b8fa783a
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a){Galleria.addTheme({name:"classic",version:1.5,author:"Galleria",css:"galleria.classic.css",defaults:{transition:"slide",thumbCrop:"height",_toggleInfo:!0},init:function(b){Galleria.requires(1.4,"This version of Classic theme requires Galleria 1.4 or later"),this.addElement("info-link","info-close"),this.append({info:["info-link","info-close"]});var c=this.$("info-link,info-close,info-text"),d=Galleria.TOUCH;this.$("loader,counter").show().css("opacity",.4),d||(this.addIdleState(this.get("image-nav-left"),{left:-50}),this.addIdleState(this.get("image-nav-right"),{right:-50}),this.addIdleState(this.get("counter"),{opacity:0})),b._toggleInfo===!0?c.bind("click:fast",function(){c.toggle()}):(c.show(),this.$("info-link, info-close").hide()),this.bind("thumbnail",function(b){d?a(b.thumbTarget).css("opacity",this.getIndex()?1:.6).bind("click:fast",function(){a(this).css("opacity",1).parent().siblings().children().css("opacity",.6)}):(a(b.thumbTarget).css("opacity",.6).parent().hover(function(){a(this).not(".active").children().stop().fadeTo(100,1)},function(){a(this).not(".active").children().stop().fadeTo(400,.6)}),b.index===this.getIndex()&&a(b.thumbTarget).css("opacity",1))});var e=function(b){a(b.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)};this.bind("loadstart",function(a){a.cached||this.$("loader").show().fadeTo(200,.4),window.setTimeout(function(){e(a)},d?300:0),this.$("info").toggle(this.hasInfo())}),this.bind("loadfinish",function(a){this.$("loader").fadeOut(200)})}})}(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/assets/scripts/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..85352ccbdd6868823ceb7aa0029f1bbe7c716d6a
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a){Galleria.addTheme({name:"classic",version:1.5,author:"Galleria",css:"galleria.classic.css",defaults:{transition:"slide",thumbCrop:"height",_toggleInfo:!0},init:function(b){Galleria.requires(1.4,"This version of Classic theme requires Galleria 1.4 or later"),this.addElement("info-link","info-close"),this.append({info:["info-link","info-close"]});var c=this.$("info-link,info-close,info-text"),d=Galleria.TOUCH;this.$("loader,counter").show().css("opacity",.4),d||(this.addIdleState(this.get("image-nav-left"),{left:-50}),this.addIdleState(this.get("image-nav-right"),{right:-50}),this.addIdleState(this.get("counter"),{opacity:0})),b._toggleInfo===!0?c.bind("click:fast",function(){c.toggle()}):(c.show(),this.$("info-link, info-close").hide()),this.bind("thumbnail",function(b){d?a(b.thumbTarget).css("opacity",this.getIndex()?1:.6).bind("click:fast",function(){a(this).css("opacity",1).parent().siblings().children().css("opacity",.6)}):(a(b.thumbTarget).css("opacity",.6).parent().hover(function(){a(this).not(".active").children().stop().fadeTo(100,1)},function(){a(this).not(".active").children().stop().fadeTo(400,.6)}),b.index===this.getIndex()&&a(b.thumbTarget).css("opacity",1))});var e=function(b){a(b.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)};this.bind("loadstart",function(a){a.cached||this.$("loader").show().fadeTo(200,.4),window.setTimeout(function(){e(a)},d?300:0),this.$("info").toggle(this.hasInfo())}),this.bind("loadfinish",function(a){this.$("loader").fadeOut(200)})}})}(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/classic/galleria.classic.min.css b/assets/scripts/galleria/themes/classic/galleria.classic.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..0291f8278b9314e78fd8ae54c4bd83d52f480cbe
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/galleria.classic.min.css
@@ -0,0 +1 @@
+#galleria-loader{height:1px!important}.galleria-theme-classic{position:relative;overflow:hidden;background:#000}.galleria-theme-classic img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none}.galleria-theme-classic .galleria-stage{position:absolute;top:10px;bottom:60px;left:10px;right:10px;overflow:hidden}.galleria-theme-classic .galleria-thumbnails-container{height:50px;bottom:0;position:absolute;left:10px;right:10px;z-index:2}.galleria-theme-classic .galleria-carousel .galleria-thumbnails-list{margin-left:30px;margin-right:30px}.galleria-theme-classic .galleria-thumbnails .galleria-image{height:40px;width:60px;background:#000;margin:0 5px 0 0;border:1px solid #000;float:left;cursor:pointer}.galleria-theme-classic .galleria-counter{position:absolute;bottom:10px;left:10px;text-align:right;color:#fff;font:400 11px/1 arial,sans-serif;z-index:1}.galleria-theme-classic .galleria-loader{width:20px;height:20px;position:absolute;top:10px;right:10px;z-index:2;display:none;background:url(classic-loader.gif) 2px 2px no-repeat}.galleria-theme-classic .galleria-info{width:50%;top:15px;left:15px;z-index:2;position:absolute}.galleria-theme-classic .galleria-info-text{background-color:#000;padding:12px;display:none;zoom:1}.galleria-theme-classic .galleria-info-title{font:700 12px/1.1 arial,sans-serif;margin:0 0 7px;color:#fff}.galleria-theme-classic .galleria-info-description{font:italic 12px/1.4 georgia,serif;margin:0;color:#bbb}.galleria-theme-classic .galleria-info-close{width:9px;height:9px;position:absolute;top:5px;right:5px;background-position:-753px -11px;opacity:.5;filter:alpha(opacity=50);cursor:pointer;display:none}.galleria-theme-classic .notouch .galleria-info-close:hover,.galleria-theme-classic .touch .galleria-info-close:active{opacity:1;filter:alpha(opacity=100)}.galleria-theme-classic .galleria-info-link{background-position:-669px -5px;opacity:.7;filter:alpha(opacity=70);position:absolute;width:20px;height:20px;cursor:pointer;background-color:#000}.galleria-theme-classic.notouch .galleria-info-link:hover,.galleria-theme-classic.touch .galleria-info-link:active{opacity:1;filter:alpha(opacity=100)}.galleria-theme-classic .galleria-image-nav{position:absolute;top:50%;margin-top:-62px;width:100%;height:62px;left:0}.galleria-theme-classic .galleria-image-nav-left,.galleria-theme-classic .galleria-image-nav-right{opacity:.3;filter:alpha(opacity=30);cursor:pointer;width:62px;height:124px;position:absolute;left:10px;z-index:2;background-position:0 46px}.galleria-theme-classic .galleria-image-nav-right{left:auto;right:10px;background-position:-254px 46px;z-index:2}.galleria-theme-classic.notouch .galleria-image-nav-left:hover,.galleria-theme-classic.notouch .galleria-image-nav-right:hover,.galleria-theme-classic.touch .galleria-image-nav-left:active,.galleria-theme-classic.touch .galleria-image-nav-right:active{opacity:1;filter:alpha(opacity=100)}.galleria-theme-classic .galleria-thumb-nav-left,.galleria-theme-classic .galleria-thumb-nav-right{cursor:pointer;display:none;background-position:-495px 5px;position:absolute;left:0;top:0;height:40px;width:23px;z-index:3;opacity:.8;filter:alpha(opacity=80)}.galleria-theme-classic .galleria-thumb-nav-right{background-position:-578px 5px;border-right:none;right:0;left:auto}.galleria-theme-classic .galleria-thumbnails-container .disabled{opacity:.2;filter:alpha(opacity=20);cursor:default}.galleria-theme-classic.notouch .galleria-thumb-nav-left:hover,.galleria-theme-classic.notouch .galleria-thumb-nav-right:hover,.galleria-theme-classic.touch .galleria-thumb-nav-left:active,.galleria-theme-classic.touch .galleria-thumb-nav-right:active{opacity:1;filter:alpha(opacity=100);background-color:#111}.galleria-theme-classic.notouch .galleria-thumbnails-container .disabled:hover{opacity:.2;filter:alpha(opacity=20);background-color:transparent}.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-left,.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-right{display:block}.galleria-theme-classic .galleria-image-nav-left,.galleria-theme-classic .galleria-image-nav-right,.galleria-theme-classic .galleria-info-close,.galleria-theme-classic .galleria-info-link,.galleria-theme-classic .galleria-thumb-nav-left,.galleria-theme-classic .galleria-thumb-nav-right{background-image:url(classic-map.png);background-repeat:no-repeat}.galleria-theme-classic.galleria-container.videoplay .galleria-counter,.galleria-theme-classic.galleria-container.videoplay .galleria-info{display:none!important}
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/classic/galleria.classic.min.js b/assets/scripts/galleria/themes/classic/galleria.classic.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..4f9987c2ea1e01aea02f31259f807d56f7b47fe4
--- /dev/null
+++ b/assets/scripts/galleria/themes/classic/galleria.classic.min.js
@@ -0,0 +1 @@
+(function($){Galleria.addTheme({name:"classic",version:1.5,author:"Galleria",css:"galleria.classic.css",defaults:{transition:"slide",thumbCrop:"height",_toggleInfo:true},init:function(options){Galleria.requires(1.4,"This version of Classic theme requires Galleria 1.4 or later");this.addElement("info-link","info-close");this.append({info:["info-link","info-close"]});var info=this.$("info-link,info-close,info-text"),touch=Galleria.TOUCH;this.$("loader,counter").show().css("opacity",.4);if(!touch){this.addIdleState(this.get("image-nav-left"),{left:-50});this.addIdleState(this.get("image-nav-right"),{right:-50});this.addIdleState(this.get("counter"),{opacity:0})}if(options._toggleInfo===true){info.bind("click:fast",function(){info.toggle()})}else{info.show();this.$("info-link, info-close").hide()}this.bind("thumbnail",function(e){if(!touch){$(e.thumbTarget).css("opacity",.6).parent().hover(function(){$(this).not(".active").children().stop().fadeTo(100,1)},function(){$(this).not(".active").children().stop().fadeTo(400,.6)});if(e.index===this.getIndex()){$(e.thumbTarget).css("opacity",1)}}else{$(e.thumbTarget).css("opacity",this.getIndex()?1:.6).bind("click:fast",function(){$(this).css("opacity",1).parent().siblings().children().css("opacity",.6)})}});var activate=function(e){$(e.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)};this.bind("loadstart",function(e){if(!e.cached){this.$("loader").show().fadeTo(200,.4)}window.setTimeout(function(){activate(e)},touch?300:0);this.$("info").toggle(this.hasInfo())});this.bind("loadfinish",function(e){this.$("loader").fadeOut(200)})}})})(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/fullscreen/b.png b/assets/scripts/galleria/themes/fullscreen/b.png
new file mode 100644
index 0000000000000000000000000000000000000000..42ee9a0e6b8bb73a0742f74866ca31664dd59704
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/b.png differ
diff --git a/assets/scripts/galleria/themes/fullscreen/down-neg.gif b/assets/scripts/galleria/themes/fullscreen/down-neg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..629f78fbee79ec1d491faa7b5916155aebcd4d58
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/down-neg.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/down.gif b/assets/scripts/galleria/themes/fullscreen/down.gif
new file mode 100644
index 0000000000000000000000000000000000000000..006dcc254439119209fd9df8b05d61a86ff0956d
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/down.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/fix.gif b/assets/scripts/galleria/themes/fullscreen/fix.gif
new file mode 100644
index 0000000000000000000000000000000000000000..35d42e808f0a8017b8d52a06be2f8fec0b466a66
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/fix.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/fullscreen-demo-cdn.html b/assets/scripts/galleria/themes/fullscreen/fullscreen-demo-cdn.html
new file mode 100644
index 0000000000000000000000000000000000000000..094df19e6c1b017cf3d5f99e269cc259160ce351
--- /dev/null
+++ b/assets/scripts/galleria/themes/fullscreen/fullscreen-demo-cdn.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html lang="sv">
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no">
+        <title>Galleria Fullscreen Theme Demo</title>
+
+        <style>
+        body{background:#000;}
+        </style>
+
+    </head>
+<body>
+    <div class="galleria">
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                data-title="Biandintz eta zaldiak"
+                data-description="Horses on Bianditz mountain, in Navarre, Spain."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                data-title="Athabasca Rail"
+                data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                data-title="Back-scattering crepuscular rays"
+                data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                data-title="Interior convento"
+                data-description="Interior view of Yuriria Convent, founded in 1550."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                data-title="Oxbow Bend outlook"
+                data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                data-title="Hazy blue hour"
+                data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                data-title="Haute Severaisse valley"
+                data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                data-title="Bohinj lake"
+                data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                data-title="Bowling Balls"
+                data-description="Mendocino county, California, USA."
+            >
+        </a>
+    </div>
+
+    <!-- load jQuery -->
+    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+    <!-- load Galleria -->
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.4/galleria.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.4/themes/fullscreen/galleria.fullscreen.min.js"></script>
+    <script>
+        $(function() {
+            Galleria.run('.galleria');
+        });
+    </script>
+    </body>
+</html>
diff --git a/assets/scripts/galleria/themes/fullscreen/fullscreen-demo.html b/assets/scripts/galleria/themes/fullscreen/fullscreen-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..3c0bfef17686254f3bf2fe5b06ae9678e3bbd996
--- /dev/null
+++ b/assets/scripts/galleria/themes/fullscreen/fullscreen-demo.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="sv">
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no">
+        <title>Galleria Fullscreen Theme Demo</title>
+
+        <!-- load jQuery -->
+        <!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <style>
+        body{background:#000;}
+        </style>
+
+    </head>
+<body>
+    <div class="galleria">
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                data-title="Biandintz eta zaldiak"
+                data-description="Horses on Bianditz mountain, in Navarre, Spain."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                data-title="Athabasca Rail"
+                data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                data-title="Back-scattering crepuscular rays"
+                data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                data-title="Interior convento"
+                data-description="Interior view of Yuriria Convent, founded in 1550."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                data-title="Oxbow Bend outlook"
+                data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                data-title="Hazy blue hour"
+                data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                data-title="Haute Severaisse valley"
+                data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                data-title="Bohinj lake"
+                data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                data-title="Bowling Balls"
+                data-description="Mendocino county, California, USA."
+            >
+        </a>
+    </div>
+    <script>
+    $(function() {
+        // Load the Fullscreen theme
+        Galleria.loadTheme('galleria.fullscreen.min.js');
+
+        // Initialize Galleria
+        Galleria.run('.galleria');
+    });
+    </script>
+    </body>
+</html>
diff --git a/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.css b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.css
new file mode 100644
index 0000000000000000000000000000000000000000..205be2292ecaea68bd1145ec9472edaaa22e8bff
--- /dev/null
+++ b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.css
@@ -0,0 +1,217 @@
+/**
+ * Galleria Classic Theme 2017-02-27
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed 2017-02-27 under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+#galleria-loader{height:1px!important}
+
+html,
+body { background: #000 }
+.galleria-theme-fullscreen {
+    height: 100%;
+    overflow: hidden;
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    background: #000;
+    -webkit-font-smoothing: antialiased;
+}
+.galleria-theme-fullscreen img {
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -o-user-select: none;
+}
+.galleria-theme-fullscreen .galleria-stage {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+}
+.galleria-theme-fullscreen .galleria-thumbnails-container {
+    position: absolute;
+    bottom: 0;
+    z-index: 2;
+    padding-top: 16px;
+    width: 100%;
+}
+.galleria-theme-fullscreen.videoplay .galleria-thumbnails-container { display:none!important; }
+.galleria-theme-fullscreen.videoplay .galleria-image-nav { top:80px; bottom:80px; height:auto; }
+
+.galleria-theme-fullscreen .galleria-thumbnails-tab {
+    opacity: .7;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
+    filter: alpha(opacity=70);
+    position: absolute;
+    left: 50%;
+    margin-left: -50px;
+    top: 0;
+    height: 16px;
+    width: 100px;
+    background: #000 url(up.gif) no-repeat 50% 5px;
+    cursor: pointer;
+    -moz-border-radius-topleft: 4px;
+    -moz-border-radius-topright: 4px;
+    -webkit-border-top-right-radius: 4px;
+    -webkit-border-top-left-radius: 4px;
+}
+.galleria-theme-fullscreen.light .galleria-thumbnails-tab {
+    background:#fff url(up-neg.gif) no-repeat 50% 50%;
+    opacity: 1;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+    filter: alpha(opacity=100);
+}
+.galleria-theme-fullscreen .galleria-thumbnails-tab:hover {
+    opacity: 1;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+    filter: alpha(opacity=100);
+}
+.galleria-theme-fullscreen .galleria-thumbnails-tab.open,
+.galleria-theme-fullscreen .galleria-thumbnails-tab.open:hover {
+    background-image: url(down.gif);
+    opacity: 1;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+    filter: alpha(opacity=100);
+}
+.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open,
+.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open:hover {
+    background-image: url(down-neg.gif);
+}
+.galleria-theme-fullscreen .galleria-thumbnails {
+    background: #000;
+    overflow: hidden;
+}
+.galleria-theme-fullscreen .galleria-thumbnails-list {
+    background: #000;
+    padding-top: 5px;
+    padding-bottom: 5px;
+    overflow: hidden;
+}
+.galleria-theme-fullscreen.light .galleria-thumbnails,
+.galleria-theme-fullscreen.light .galleria-thumbnails-list {
+    background:#fff;
+}
+.galleria-theme-fullscreen .galleria-thumbnails .galleria-image {
+    width: 80px;
+    height: 50px;
+    float: left;
+    cursor: pointer;
+    margin-right: 5px;
+}
+.galleria-theme-fullscreen .galleria-thumbnails .galleria-image img { background: #000 }
+.galleria-theme-fullscreen .galleria-thumbnails .active { cursor: default }
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumbnails-list {
+    border-left: 30px solid #000;
+    border-right: 30px solid #000;
+}
+.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumbnails-list {
+    border-color: #fff;
+}
+.galleria-theme-fullscreen .galleria-image-nav {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+.galleria-theme-fullscreen .galleria-image-nav-right,
+.galleria-theme-fullscreen .galleria-image-nav-left {
+    width: 100px;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    background: url(r.gif) no-repeat 50% 50%;
+    position: absolute;
+    cursor: pointer;
+    z-index: 2;
+    display: none;
+}
+.galleria-theme-fullscreen.smallarrows .galleria-image-nav-right {
+    background-image: url(r-neg.png);
+}
+.galleria-theme-fullscreen .galleria-image-nav-left {
+    left: 0;
+    right: auto;
+    background-image: url(l.gif);
+}
+.galleria-theme-fullscreen.smallarrows .galleria-image-nav-left {
+    background-image: url(l-neg.png);
+}
+.galleria-theme-fullscreen .galleria-loader {
+    width: 30px;
+    height: 30px;
+    background: #fff url(loader.gif) no-repeat 50% 50%;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-top: -15px;
+    margin-left: -15px;
+    z-index: 3;
+}
+.galleria-theme-fullscreen .galleria-info {
+    z-index: 4;
+    font: 13px/1.4 helvetica,arial,sans-serif;
+    color: #fff;
+    position: absolute;
+    top: 0;
+    width: 100%;
+    border-top: 2px solid #000;
+    display: none;
+    text-align: center;
+    padding: 10px 0;
+    background: rgba(0,0,0,.5);
+    border-bottom:1px solid rgba(0,0,0,.1);
+}
+.galleria-theme-fullscreen.light .galleria-info{background:rgba(255,255,255,.5);color:#000;}
+.galleria-theme-fullscreen .galleria-info-text {
+    width: 50%;
+    margin: 0 auto;
+}
+.galleria-theme-fullscreen .galleria-info-title { font-weight: bold; display: inline-block; margin-right:10px; }
+.galleria-theme-fullscreen .galleria-info-description { display:inline-block; }
+.galleria-theme-fullscreen .galleria-thumb-nav-left,
+.galleria-theme-fullscreen .galleria-thumb-nav-right {
+    cursor: pointer;
+    display: none;
+    background: url(p.gif) no-repeat 50% 50%;
+    position: absolute;
+    left: 5px;
+    top: 21px;
+    bottom: 5px;
+    width: 20px;
+    z-index: 3;
+    opacity: .8;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
+    filter: alpha(opacity=80);
+}
+.galleria-theme-fullscreen.light .galleria-thumb-nav-left{
+    background-image: url(p-neg.png);
+}
+.galleria-theme-fullscreen .galleria-thumb-nav-right {
+    background-image: url(n.gif);
+    left: auto;
+    right: 5px;
+}
+.galleria-theme-fullscreen.light .galleria-thumb-nav-right{
+    background-image: url(n-neg.png);
+}
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left,
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right { display: block }
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left:hover,
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right:hover { background-color: #222 }
+.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled,
+.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled,
+.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled:hover,
+.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled:hover {
+    opacity: .2;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
+    filter: alpha(opacity=20);
+    cursor: default;
+}
+.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-left:hover,
+.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-right:hover { background-color: #ddd }
+
diff --git a/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.js b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.js
new file mode 100644
index 0000000000000000000000000000000000000000..4bb6608f4ae31cebe34a328920aefc4a7310a626
--- /dev/null
+++ b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.js
@@ -0,0 +1,182 @@
+/**
+ * Galleria Classic Theme 2017-02-27
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed 2017-02-27 under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.addTheme({
+    name: 'fullscreen',
+    version: '1.5.4',
+    author: 'Galleria',
+    css: 'galleria.fullscreen.css',
+    // begin site script
+    defaults: {
+        transition: 'none',
+        imageCrop: true,
+        thumbCrop: 'height',
+        easing: 'galleriaOut',
+        trueFullscreen: false,
+
+        // set this to false if you want to keep the thumbnails:
+        _hideDock: Galleria.TOUCH ? false : true,
+
+        // set this to true if you want to shrink the carousel when clicking a thumbnail:
+        _closeOnClick: false
+    },
+    init: function(options) {
+
+        Galleria.requires( 1.5, 'This version of Fullscreen theme requires Galleria version 1.5 or later');
+
+        this.addElement('thumbnails-tab');
+        this.appendChild('thumbnails-container', 'thumbnails-tab');
+
+        var tab      = this.$('thumbnails-tab'),
+            loader   = this.$('loader'),
+            thumbs   = this.$('thumbnails-container'),
+            list     = this.$('thumbnails-list'),
+            infotext = this.$('info-text'),
+            info     = this.$('info'),
+            OPEN     = !options._hideDock,
+            POS      = 0;
+            
+        if (Galleria.IE) {
+            this.addElement('iefix');
+            this.appendChild('container', 'iefix');
+            this.$('iefix').css({
+                zIndex: 3,
+                position: 'absolute',
+                backgroundColor: this.hasVariation('light') ? '#fff' : '#000',
+                opacity: 0.4,
+                top: 0
+            });
+        }
+
+        if ( options.thumbnails === false ) {
+            thumbs.hide();
+        }
+
+        var fixCaption = this.proxy(function(img) {
+
+            var w = img.width || $(img).width();
+
+            if (!(img || w)) {
+                return;
+            }
+            w = Math.min(w, $(window).width());
+            infotext.width(w - 40);
+            if (Galleria.IE && this.getOptions('showInfo')) {
+                this.$('iefix').width(info.outerWidth()).height(info.outerHeight());
+            }
+        });
+
+        this.bind('rescale', function() {
+            POS = this.getStageHeight() - tab.height() - 2;
+            thumbs.css('top', OPEN ? POS - list.outerHeight() + 2 : POS);
+            var img = this.getActiveImage();
+            if (img) {
+                fixCaption(img);
+            }
+        });
+
+        this.bind('loadstart', function(e) {
+            if (!e.cached) {
+                loader.show().fadeTo(100, 1);
+            }
+            $(e.thumbTarget).css('opacity', 1).parent().siblings().children().css('opacity', 0.6);
+        });
+
+        this.bind('loadfinish', function(e) {
+            loader.fadeOut(300);
+            this.$('info, iefix').toggle(this.hasInfo());
+        });
+
+        this.bind('image', function(e) {
+            e.imageTarget && fixCaption(e.imageTarget);
+        });
+
+        this.bind('thumbnail', function(e) {
+            $(e.thumbTarget).parent(':not(.active)').children().css('opacity', 0.6);
+            $(e.thumbTarget).on('click:fast', function() {
+                if (OPEN && options._closeOnClick) {
+                    tab.trigger('click:fast');
+                }
+            });
+        });
+
+        this.trigger('rescale');
+
+        if ( !Galleria.TOUCH ) {
+
+            this.addIdleState(thumbs, { opacity: 0 });
+            this.addIdleState(this.get('info'), { opacity: 0 });
+
+            this.$('image-nav-left, image-nav-right').css('opacity', 0.01).hover(function() {
+                $(this).animate({opacity: 1}, 100);
+            }, function() {
+                $(this).animate({opacity: 0});
+            }).show();
+
+        }
+
+        if (Galleria.IE) {
+            this.addIdleState(this.get('iefix'), { opacity: 0 });
+        }
+
+        if (options._hideDock) {
+            tab.on('click:fast', this.proxy(function() {
+                tab.toggleClass('open', !OPEN);
+                if (!OPEN) {
+                    thumbs.animate({
+                        top: POS - list.outerHeight() + 2
+                    }, 400, options.easing);
+                } else {
+                    thumbs.animate({
+                        top: POS
+                    }, 400, options.easing);
+                }
+                OPEN = !OPEN;
+            }));
+        } else {
+            this.bind('thumbnail', function() {
+                thumbs.css('top', POS - list.outerHeight() + 2);
+            });
+            tab.css('visibility', 'hidden');
+        }
+
+        this.$('thumbnails').children().hover(function() {
+            $(this).not('.active').children().stop().fadeTo(100, 1);
+        }, function() {
+            $(this).not('.active').children().stop().fadeTo(400, 0.6);
+        });
+
+        this.enterFullscreen();
+        this.attachKeyboard({
+            escape: function(e) {
+                return false;
+            },
+            up: function(e) {
+                if (!OPEN) {
+                    tab.trigger('click:fast');
+                }
+                e.preventDefault();
+            },
+            down: function(e) {
+                if (OPEN) {
+                    tab.trigger('click:fast');
+                }
+                e.preventDefault();
+            }
+        });
+    }
+    // end site script
+});
+
+}(jQuery));
diff --git a/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.min.css b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..6e5e1606f2fcd4dd5ae73855222157436f715451
--- /dev/null
+++ b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.min.css
@@ -0,0 +1 @@
+#galleria-loader{height:1px!important}body,html{background:#000}.galleria-theme-fullscreen{height:100%;overflow:hidden;position:fixed;top:0;left:0;width:100%;background:#000;-webkit-font-smoothing:antialiased}.galleria-theme-fullscreen img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none}.galleria-theme-fullscreen .galleria-stage{width:100%;height:100%;position:absolute}.galleria-theme-fullscreen .galleria-thumbnails-container{position:absolute;bottom:0;z-index:2;padding-top:16px;width:100%}.galleria-theme-fullscreen.videoplay .galleria-thumbnails-container{display:none!important}.galleria-theme-fullscreen.videoplay .galleria-image-nav{top:80px;bottom:80px;height:auto}.galleria-theme-fullscreen .galleria-thumbnails-tab{opacity:.7;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";filter:alpha(opacity=70);position:absolute;left:50%;margin-left:-50px;top:0;height:16px;width:100px;background:url(up.gif) 50% 5px no-repeat #000;cursor:pointer;-moz-border-radius-topleft:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-webkit-border-top-left-radius:4px}.galleria-theme-fullscreen.light .galleria-thumbnails-tab{background:url(up-neg.gif) 50% 50% no-repeat #fff;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen .galleria-thumbnails-tab:hover{opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen .galleria-thumbnails-tab.open,.galleria-theme-fullscreen .galleria-thumbnails-tab.open:hover{background-image:url(down.gif);opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open,.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open:hover{background-image:url(down-neg.gif)}.galleria-theme-fullscreen .galleria-thumbnails{background:#000;overflow:hidden}.galleria-theme-fullscreen .galleria-thumbnails-list{background:#000;padding-top:5px;padding-bottom:5px;overflow:hidden}.galleria-theme-fullscreen.light .galleria-thumbnails,.galleria-theme-fullscreen.light .galleria-thumbnails-list{background:#fff}.galleria-theme-fullscreen .galleria-thumbnails .galleria-image{width:80px;height:50px;float:left;cursor:pointer;margin-right:5px}.galleria-theme-fullscreen .galleria-thumbnails .galleria-image img{background:#000}.galleria-theme-fullscreen .galleria-thumbnails .active{cursor:default}.galleria-theme-fullscreen .galleria-carousel .galleria-thumbnails-list{border-left:30px solid #000;border-right:30px solid #000}.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumbnails-list{border-color:#fff}.galleria-theme-fullscreen .galleria-image-nav{width:100%;height:100%;position:absolute;top:0;left:0}.galleria-theme-fullscreen .galleria-image-nav-left,.galleria-theme-fullscreen .galleria-image-nav-right{width:100px;right:0;top:0;bottom:0;background:url(r.gif) 50% 50% no-repeat;position:absolute;cursor:pointer;z-index:2;display:none}.galleria-theme-fullscreen.smallarrows .galleria-image-nav-right{background-image:url(r-neg.png)}.galleria-theme-fullscreen .galleria-image-nav-left{left:0;right:auto;background-image:url(l.gif)}.galleria-theme-fullscreen.smallarrows .galleria-image-nav-left{background-image:url(l-neg.png)}.galleria-theme-fullscreen .galleria-loader{width:30px;height:30px;background:url(loader.gif) 50% 50% no-repeat #fff;position:absolute;top:50%;left:50%;margin-top:-15px;margin-left:-15px;z-index:3}.galleria-theme-fullscreen .galleria-info{z-index:4;font:13px/1.4 helvetica,arial,sans-serif;color:#fff;position:absolute;top:0;width:100%;border-top:2px solid #000;display:none;text-align:center;padding:10px 0;background:rgba(0,0,0,.5);border-bottom:1px solid rgba(0,0,0,.1)}.galleria-theme-fullscreen.light .galleria-info{background:rgba(255,255,255,.5);color:#000}.galleria-theme-fullscreen .galleria-info-text{width:50%;margin:0 auto}.galleria-theme-fullscreen .galleria-info-title{font-weight:700;display:inline-block;margin-right:10px}.galleria-theme-fullscreen .galleria-info-description{display:inline-block}.galleria-theme-fullscreen .galleria-thumb-nav-left,.galleria-theme-fullscreen .galleria-thumb-nav-right{cursor:pointer;display:none;background:url(p.gif) 50% 50% no-repeat;position:absolute;left:5px;top:21px;bottom:5px;width:20px;z-index:3;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.galleria-theme-fullscreen.light .galleria-thumb-nav-left{background-image:url(p-neg.png)}.galleria-theme-fullscreen .galleria-thumb-nav-right{background-image:url(n.gif);left:auto;right:5px}.galleria-theme-fullscreen.light .galleria-thumb-nav-right{background-image:url(n-neg.png)}.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left,.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right{display:block}.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left:hover,.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right:hover{background-color:#222}.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled,.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled:hover,.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled,.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled:hover{opacity:.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20);cursor:default}.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-left:hover,.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-right:hover{background-color:#ddd}
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.min.js b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c8118cd0969d47c23d6f2db5bd8d2461782b4ee
--- /dev/null
+++ b/assets/scripts/galleria/themes/fullscreen/galleria.fullscreen.min.js
@@ -0,0 +1 @@
+(function($){Galleria.addTheme({name:"fullscreen",version:"1.5.4",author:"Galleria",css:"galleria.fullscreen.css",defaults:{transition:"none",imageCrop:true,thumbCrop:"height",easing:"galleriaOut",trueFullscreen:false,_hideDock:Galleria.TOUCH?false:true,_closeOnClick:false},init:function(options){Galleria.requires(1.5,"This version of Fullscreen theme requires Galleria version 1.5 or later");this.addElement("thumbnails-tab");this.appendChild("thumbnails-container","thumbnails-tab");var tab=this.$("thumbnails-tab"),loader=this.$("loader"),thumbs=this.$("thumbnails-container"),list=this.$("thumbnails-list"),infotext=this.$("info-text"),info=this.$("info"),OPEN=!options._hideDock,POS=0;if(Galleria.IE){this.addElement("iefix");this.appendChild("container","iefix");this.$("iefix").css({zIndex:3,position:"absolute",backgroundColor:this.hasVariation("light")?"#fff":"#000",opacity:.4,top:0})}if(options.thumbnails===false){thumbs.hide()}var fixCaption=this.proxy(function(img){var w=img.width||$(img).width();if(!(img||w)){return}w=Math.min(w,$(window).width());infotext.width(w-40);if(Galleria.IE&&this.getOptions("showInfo")){this.$("iefix").width(info.outerWidth()).height(info.outerHeight())}});this.bind("rescale",function(){POS=this.getStageHeight()-tab.height()-2;thumbs.css("top",OPEN?POS-list.outerHeight()+2:POS);var img=this.getActiveImage();if(img){fixCaption(img)}});this.bind("loadstart",function(e){if(!e.cached){loader.show().fadeTo(100,1)}$(e.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)});this.bind("loadfinish",function(e){loader.fadeOut(300);this.$("info, iefix").toggle(this.hasInfo())});this.bind("image",function(e){e.imageTarget&&fixCaption(e.imageTarget)});this.bind("thumbnail",function(e){$(e.thumbTarget).parent(":not(.active)").children().css("opacity",.6);$(e.thumbTarget).on("click:fast",function(){if(OPEN&&options._closeOnClick){tab.trigger("click:fast")}})});this.trigger("rescale");if(!Galleria.TOUCH){this.addIdleState(thumbs,{opacity:0});this.addIdleState(this.get("info"),{opacity:0});this.$("image-nav-left, image-nav-right").css("opacity",.01).hover(function(){$(this).animate({opacity:1},100)},function(){$(this).animate({opacity:0})}).show()}if(Galleria.IE){this.addIdleState(this.get("iefix"),{opacity:0})}if(options._hideDock){tab.on("click:fast",this.proxy(function(){tab.toggleClass("open",!OPEN);if(!OPEN){thumbs.animate({top:POS-list.outerHeight()+2},400,options.easing)}else{thumbs.animate({top:POS},400,options.easing)}OPEN=!OPEN}))}else{this.bind("thumbnail",function(){thumbs.css("top",POS-list.outerHeight()+2)});tab.css("visibility","hidden")}this.$("thumbnails").children().hover(function(){$(this).not(".active").children().stop().fadeTo(100,1)},function(){$(this).not(".active").children().stop().fadeTo(400,.6)});this.enterFullscreen();this.attachKeyboard({escape:function(e){return false},up:function(e){if(!OPEN){tab.trigger("click:fast")}e.preventDefault()},down:function(e){if(OPEN){tab.trigger("click:fast")}e.preventDefault()}})}})})(jQuery);
\ No newline at end of file
diff --git a/assets/scripts/galleria/themes/fullscreen/i.png b/assets/scripts/galleria/themes/fullscreen/i.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e61d85cf5c3d76932e0ddb3bf988d9a56faec7a
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/i.png differ
diff --git a/assets/scripts/galleria/themes/fullscreen/index.html b/assets/scripts/galleria/themes/fullscreen/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/assets/scripts/galleria/themes/fullscreen/l-neg.png b/assets/scripts/galleria/themes/fullscreen/l-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c47490397a25816e3e193da19b094b8a0afb24d
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/l-neg.png differ
diff --git a/assets/scripts/galleria/themes/fullscreen/l.gif b/assets/scripts/galleria/themes/fullscreen/l.gif
new file mode 100644
index 0000000000000000000000000000000000000000..36b43faf7eb2c02e76ed30359dc95375324977db
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/l.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/loader.gif b/assets/scripts/galleria/themes/fullscreen/loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e0057080d42b2b892e0c5c4ebd59cde3fc420afd
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/loader.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/n-neg.png b/assets/scripts/galleria/themes/fullscreen/n-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..61c9b3f94052bc80411a0873e03f751f333ac1ba
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/n-neg.png differ
diff --git a/assets/scripts/galleria/themes/fullscreen/n.gif b/assets/scripts/galleria/themes/fullscreen/n.gif
new file mode 100644
index 0000000000000000000000000000000000000000..df1d4ed9e08d32abb0517b55471e3e56a2078aac
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/n.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/p-neg.png b/assets/scripts/galleria/themes/fullscreen/p-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..aeee4121d16b2950aabba0d8f6a0ed85f2de6327
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/p-neg.png differ
diff --git a/assets/scripts/galleria/themes/fullscreen/p.gif b/assets/scripts/galleria/themes/fullscreen/p.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9626e4ecdda1b24eb8092850a3d59213ccf52c70
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/p.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/r-neg.png b/assets/scripts/galleria/themes/fullscreen/r-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..dc909aa59507e3f164d8558191a3fa51e76aa850
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/r-neg.png differ
diff --git a/assets/scripts/galleria/themes/fullscreen/r.gif b/assets/scripts/galleria/themes/fullscreen/r.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2d6a6ead72fd83cf98b13f92af559ac4fe0bf517
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/r.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/up-neg.gif b/assets/scripts/galleria/themes/fullscreen/up-neg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d9556e7fc6a844cec4dd0b415223af7d33934977
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/up-neg.gif differ
diff --git a/assets/scripts/galleria/themes/fullscreen/up.gif b/assets/scripts/galleria/themes/fullscreen/up.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fc00d14fffcec4330eaf8b5afe7360a7c9fd786e
Binary files /dev/null and b/assets/scripts/galleria/themes/fullscreen/up.gif differ
diff --git a/beitragsordnung.md b/beitragsordnung.md
new file mode 100644
index 0000000000000000000000000000000000000000..d93e541fe3979e46fc1b42fa9d0b374d5cc9d956
--- /dev/null
+++ b/beitragsordnung.md
@@ -0,0 +1,18 @@
+---
+layout: verein
+title: Verein
+permalink: /verein/beitrag
+aside: true
+feature_image: "https://chaotikum.org/_media/hackerspace:nbsp:nbspvonoben.jpg"
+---
+
+### Beitragsordnung
+
+- Der Mitgliedsbeitrag ist frei wählbar.
+- Der Beitrag eines ordentlichen Mitgliedes muss mindestens 10 Euro betragen; der Vorstand kann in Einzelfällen Ausnahmen von diesem Mindestbeitrag erlauben.
+- Der Vorstand kann einen Regelbeitrag festsetzen und diesen jederzeit an die aktuelle finanzielle Situation des Vereins anpassen. Der Regelbeitrag ist eine Empfehlung an die Mitglieder und nicht bindend.
+- Der Beitrag ist monatlich im Voraus zu entrichten.
+- Die Mitgliedschaft beginnt mit dem Monat, zu dem der erste Beitrag vollständig gezahlt wurde.
+- Die Zahlung kann in Bar oder per Überweisung erfolgen. Alternative Zahlungsmethoden sind nur mit Zustimmung des Vorstandes möglich.
+
+*Die aktuelle Beitragsordnung ist zum 2Q 2016 in Kraft getreten.*
diff --git a/membership.md b/membership.md
new file mode 100644
index 0000000000000000000000000000000000000000..7cf3828ed7bcff2ede7775908fa9d80c4ab20a08
--- /dev/null
+++ b/membership.md
@@ -0,0 +1,17 @@
+---
+layout: verein
+title: Verein
+permalink: /verein/membership
+aside: true
+feature_image: "https://chaotikum.org/_media/hackerspace:nbsp:nbspvonoben.jpg"
+---
+
+### Mitglied werden
+
+Es gibt viele Wege auf denen Du uns unterstützen kannst, einer ist die Mitgliedschaft. Unser Verein unterscheidet in der [Satzung]({{site.url}}{{site.baseurl}}/verein/satzung) ordentlichen und fördernden Mitgliedern.
+
+Alle natürlichen Personen können ordentliches Mitglied werden, den Mitgliedsbeitrag kannst du dabei selber entscheiden (siehe auch [Beitragsordnung]({{site.url}}{{site.baseurl}}/verein/beitrag)).
+
+Förderndes Mitglied können zusätzlich auch juristische Personen sein, auch sie können ihren Mitgliedsbeitrag frei wählen, sind bei Mitgliederversammlungen jedoch nicht stimmberechtigt.
+
+Wenn Du Mitglied werden willst, fülle einfach das [Mitgliedschaftsformular](http://chaotikum.org/_media/mitgliedschaftsformular_neu.pdf) aus und gib es unterschrieben dem Vorstand. Im Nbsp steht aber auch ein Briefkasten, wenn mal kein Vorstandsmitglied in greifbarer Nähe ist.
diff --git a/script/.DS_Store b/script/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..0fed445a0bf83684274f1b5a2a19e6216cd209fc
Binary files /dev/null and b/script/.DS_Store differ
diff --git a/script/galleria/.DS_Store b/script/galleria/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..205a45f17ae7720b643f07bc5b0f62a9b3d3fb38
Binary files /dev/null and b/script/galleria/.DS_Store differ
diff --git a/script/galleria/galleria-1.5.7.js b/script/galleria/galleria-1.5.7.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e3a27f46b90f5f8f3f84a8c6aa0ba930d5995a0
--- /dev/null
+++ b/script/galleria/galleria-1.5.7.js
@@ -0,0 +1,6930 @@
+/**
+ * Galleria v1.5.7 2017-05-10
+ * 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.57,
+    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; },
+    MOBILE = !(
+        ( window.screen.width > 1279 && window.devicePixelRatio == 1 ) || // there are not so many mobile devices with more than 1280px and pixelRatio equal to 1 (i.e. retina displays are equal to 2...)
+        ( window.screen.width > 1000 && window.innerWidth < (window.screen.width * .9) ) // this checks in the end if a user is using a resized browser window which is not common on mobile devices
+    ),
+    IE = (function() {
+
+        var v = 3,
+            div = doc.createElement( 'div' ),
+            all = div.getElementsByTagName( 'i' );
+
+        do {
+            div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->';
+        } 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;(?:amp;)?)*v(?:&lt;[A-Z]+&gt;)?=([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 = $('<scr'+'ipt>').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 = $( '<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 = $('<s>').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( '<i></i>' ).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/, '&#160;') );
+
+            // 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('&#215;') );
+
+            $.each( ['Prev','Next'], function(i, dir) {
+
+                var $d = $( el[ dir.toLowerCase() ] ).html( /v/.test( dir ) ? '&#8249;&#160;' : '&#160;&#8250;' ),
+                    $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('&#8211;');
+
+        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 (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<len; i++ ) {
+            temp.push(i);
+            if ( ++n == size || i == len-1 ) {
+                arr.push( temp );
+                n = 0;
+                temp = [];
+            }
+        }
+
+        var init = function( wait ) {
+            var a = arr.shift();
+            if ( a ) {
+                window.setTimeout(function() {
+                    self.lazyLoad(a, function() {
+                        init( true );
+                    });
+                }, ( delay && wait ) ? delay : 0 );
+            }
+        };
+
+        init( false );
+
+        return this;
+
+    },
+
+    // the internal _run method should be called after loading data into galleria
+    // makes sure the gallery has proper measurements before postrun & ready
+    _run : function() {
+
+        var self = this;
+
+        self._createThumbnails();
+
+        // make sure we have a stageHeight && stageWidth
+
+        Utils.wait({
+
+            timeout: 10000,
+
+            until: function() {
+
+                // Opera crap
+                if ( Galleria.OPERA ) {
+                    self.$( 'stage' ).css( 'display', 'inline-block' );
+                }
+
+                self._stageWidth  = self.$( 'stage' ).width();
+                self._stageHeight = self.$( 'stage' ).height();
+
+                return( self._stageWidth &&
+                        self._stageHeight > 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 !== undefined && 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 ) && MOBILE // rule out false positives on Win10
+
+});
+
+// Galleria static methods
+
+/**
+    Adds a theme that you can use for your Gallery
+
+    @param {Object} theme Object that should contain all your theme settings.
+    <ul>
+        <li>name - name of the theme</li>
+        <li>author - name of the author</li>
+        <li>css - css file name (not path)</li>
+        <li>defaults - default options to apply, including theme-specific options</li>
+        <li>init - the init function</li>
+    </ul>
+
+    @returns {Object} theme
+*/
+
+Galleria.addTheme = function( theme ) {
+
+    // make sure we have a name
+    if ( !theme.name ) {
+        Galleria.raise('No theme name specified');
+    }
+
+    // make sure it's compatible
+    if ( !theme.version || parseInt(Galleria.version*10) > parseInt(theme.version*10) ) {
+        Galleria.raise('This version of Galleria requires '+theme.name+' theme version '+parseInt(Galleria.version*10)/10+' or later', true);
+    }
+
+    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 ).on('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('<br>') );
+    }
+};
+
+/**
+    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 = '<div style="padding:4px;margin:0 0 2px;background:#' +
+                ( fatal ? '811' : '222' ) + ';">' +
+                ( fatal ? '<strong>' + type + ': </strong>' : '' ) +
+                msg + '</div>';
+
+            $.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 ) {
+                $('<div>').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() ).on( '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 = $('<iframe>', {
+                src: src,
+                frameborder: 0,
+                id: id,
+                allowfullscreen: true,
+                css: { visibility: 'hidden' }
+            })[0];
+
+            if ( size ) {
+                $( iframe ).css( size );
+            }
+
+            $( this.container ).find( 'iframe,img' ).remove();
+
+            this.container.appendChild( this.image );
+
+            $('#'+id).on( 'load', (function( self, callback ) {
+                return function() {
+                    window.setTimeout(function() {
+                        $( self.image ).css( 'visibility', 'visible' );
+                        if( typeof callback == 'function' ) {
+                            callback.call( self, self );
+                        }
+                    }, 10);
+                };
+            }( this, callback )));
+
+            return this.container;
+        }
+
+        this.image = new Image();
+
+        // IE8 opacity inherit bug
+        if ( Galleria.IE8 ) {
+            $( this.image ).css( 'filter', 'inherit' );
+        }
+
+        // FF shaking images bug:
+        // http://support.galleria.io/discussions/problems/12245-shaking-photos
+        if ( !Galleria.IE && !Galleria.CHROME && !Galleria.SAFARI ) {
+            $( this.image ).css( 'image-rendering', 'optimizequality' );
+        }
+
+        var reload = false,
+            resort = false,
+
+            // some jquery cache
+            $container = $( this.container ),
+            $image = $( this.image ),
+
+            onerror = function() {
+                if ( !reload ) {
+                    reload = true;
+                    // reload the image with a timestamp
+                    window.setTimeout((function(image, src) {
+                        return function() {
+                            image.attr('src', src + (src.indexOf('?') > -1 ? '&' : '?') + Utils.timestamp() );
+                        };
+                    }( $(this), src )), 50);
+                } else {
+                    // apply the dummy image if it exists
+                    if ( DUMMY ) {
+                        $( this ).attr( 'src', DUMMY );
+                    } else {
+                        Galleria.raise('Image not found: ' + src);
+                    }
+                }
+            },
+
+            // the onload method
+            onload = (function( self, callback, src ) {
+
+                return function() {
+
+                    var complete = function() {
+
+                        $( this ).off( 'load' );
+
+                        // save the original size
+                        self.original = size || {
+                            height: this.height,
+                            width: this.width
+                        };
+
+                        // translate3d if needed
+                        if ( Galleria.HAS3D ) {
+                            this.style.MozTransform = this.style.webkitTransform = 'translate3d(0,0,0)';
+                        }
+
+                        $container.append( this );
+
+                        self.cache[ src ] = src; // will override old cache
+
+                        if (typeof callback == 'function' ) {
+                            window.setTimeout(function() {
+                                callback.call( self, self );
+                            },1);
+                        }
+                    };
+
+                    // Delay the callback to "fix" the Adblock Bug
+                    // http://code.google.com/p/adblockforchrome/issues/detail?id=3701
+                    if ( ( !this.width || !this.height ) ) {
+                        (function( img ) {
+                            Utils.wait({
+                                until: function() {
+                                    return img.width && img.height;
+                                },
+                                success: function() {
+                                    complete.call( img );
+                                },
+                                error: function() {
+                                    if ( !resort ) {
+                                        $(new Image()).on( 'load', onload ).attr( 'src', img.src );
+                                        resort = true;
+                                    } else {
+                                        Galleria.raise('Could not extract width/height from image: ' + img.src +
+                                            '. Traced measures: width:' + img.width + 'px, height: ' + img.height + 'px.');
+                                    }
+                                },
+                                timeout: 100
+                            });
+                        }( this ));
+                    } else {
+                        complete.call( this );
+                    }
+                };
+            }( this, callback, src ));
+
+        // remove any previous images
+        $container.find( 'iframe,img' ).remove();
+
+        // append the image
+        $image.css( 'display', 'block');
+
+        // hide it for now
+        Utils.hide( this.image );
+
+        // remove any max/min scaling
+        $.each('minWidth minHeight maxWidth maxHeight'.split(' '), function(i, prop) {
+            $image.css(prop, (/min/.test(prop) ? '0' : 'none'));
+        });
+
+        // begin load and insert in cache when done
+        $image.on( 'load', onload ).on( 'error', onerror ).attr( 'src', src );
+
+        // return the container
+        return this.container;
+    },
+
+    /**
+        Scales and crops the image
+
+        @param {Object} options The method takes an object with a number of options:
+
+        <ul>
+            <li>width - width of the container</li>
+            <li>height - height of the container</li>
+            <li>min - minimum scale ratio</li>
+            <li>max - maximum scale ratio</li>
+            <li>margin - distance in pixels from the image border to the container</li>
+            <li>complete - a callback that fires when scaling is complete</li>
+            <li>position - positions the image, works like the css background-image property.</li>
+            <li>crop - defines how to crop. Can be true, false, 'width' or 'height'</li>
+            <li>canvas - set to true to try a canvas-based rescale</li>
+        </ul>
+
+        @returns The image container object (jQuery)
+    */
+
+    scale: function( options ) {
+
+        var self = this;
+
+        // extend some defaults
+        options = $.extend({
+            width: 0,
+            height: 0,
+            min: undef,
+            max: undef,
+            margin: 0,
+            complete: F,
+            position: 'center',
+            crop: false,
+            canvas: false,
+            iframelimit: undef
+        }, options);
+
+        if( this.isIframe ) {
+
+            var cw = options.width,
+                ch = options.height,
+                nw, nh;
+            if ( options.iframelimit ) {
+                var r = M.min( options.iframelimit/cw, options.iframelimit/ch );
+                if ( r < 1 ) {
+                    nw = cw * r;
+                    nh = ch * r;
+
+                    $( this.image ).css({
+                        top: ch/2-nh/2,
+                        left: cw/2-nw/2,
+                        position: 'absolute'
+                    });
+                } else {
+                    $( this.image ).css({
+                        top: 0,
+                        left: 0
+                    });
+                }
+            }
+            $( this.image ).width( nw || cw ).height( nh || ch ).removeAttr( 'width' ).removeAttr( 'height' );
+            $( this.container ).width( cw ).height( ch );
+            options.complete.call(self, self);
+            try {
+                if( this.image.contentWindow ) {
+                    $( this.image.contentWindow ).trigger('resize');
+                }
+            } catch(e) {}
+            return this.container;
+
+        }
+
+        // return the element if no image found
+        if (!this.image) {
+            return this.container;
+        }
+
+        // store locale variables
+        var width,
+            height,
+            $container = $( self.container ),
+            data;
+
+        // wait for the width/height
+        Utils.wait({
+            until: function() {
+                width  = options.width ||
+                         $container.width() ||
+                         Utils.parseValue( $container.css('width') );
+
+                height = options.height ||
+                         $container.height() ||
+                         Utils.parseValue( $container.css('height') );
+
+                return width && height;
+            },
+            success: function() {
+
+                // calculate some cropping
+                var newWidth = ( width - options.margin * 2 ) / self.original.width,
+                    newHeight = ( height - options.margin * 2 ) / self.original.height,
+                    min = M.min( newWidth, newHeight ),
+                    max = M.max( newWidth, newHeight ),
+                    cropMap = {
+                        'true'  : max,
+                        'width' : newWidth,
+                        'height': newHeight,
+                        'false' : min,
+                        'landscape': self.original.width > self.original.height ? max : min,
+                        'portrait': self.original.width < self.original.height ? max : min
+                    },
+                    ratio = cropMap[ options.crop.toString() ],
+                    canvasKey = '';
+
+                // allow maxScaleRatio
+                if ( options.max ) {
+                    ratio = M.min( options.max, ratio );
+                }
+
+                // allow minScaleRatio
+                if ( options.min ) {
+                    ratio = M.max( options.min, ratio );
+                }
+
+                $.each( ['width','height'], function( i, m ) {
+                    $( self.image )[ m ]( self[ m ] = self.image[ m ] = M.round( self.original[ m ] * ratio ) );
+                });
+
+                $( self.container ).width( width ).height( height );
+
+                if ( options.canvas && _canvas ) {
+
+                    _canvas.elem.width = self.width;
+                    _canvas.elem.height = self.height;
+
+                    canvasKey = self.image.src + ':' + self.width + 'x' + self.height;
+
+                    self.image.src = _canvas.cache[ canvasKey ] || (function( key ) {
+
+                        _canvas.context.drawImage(self.image, 0, 0, self.original.width*ratio, self.original.height*ratio);
+
+                        try {
+
+                            data = _canvas.elem.toDataURL();
+                            _canvas.length += data.length;
+                            _canvas.cache[ key ] = data;
+                            return data;
+
+                        } catch( e ) {
+                            return self.image.src;
+                        }
+
+                    }( canvasKey ) );
+
+                }
+
+                // calculate image_position
+                var pos = {},
+                    mix = {},
+                    getPosition = function(value, measure, margin) {
+                        var result = 0;
+                        if (/\%/.test(value)) {
+                            var flt = parseInt( value, 10 ) / 100,
+                                m = self.image[ measure ] || $( self.image )[ measure ]();
+
+                            result = M.ceil( m * -1 * flt + margin * flt );
+                        } else {
+                            result = Utils.parseValue( value );
+                        }
+                        return result;
+                    },
+                    positionMap = {
+                        'top': { top: 0 },
+                        'left': { left: 0 },
+                        'right': { left: '100%' },
+                        'bottom': { top: '100%' }
+                    };
+
+                $.each( options.position.toLowerCase().split(' '), function( i, value ) {
+                    if ( value === 'center' ) {
+                        value = '50%';
+                    }
+                    pos[i ? 'top' : 'left'] = value;
+                });
+
+                $.each( pos, function( i, value ) {
+                    if ( positionMap.hasOwnProperty( value ) ) {
+                        $.extend( mix, positionMap[ value ] );
+                    }
+                });
+
+                pos = pos.top ? $.extend( pos, mix ) : mix;
+
+                pos = $.extend({
+                    top: '50%',
+                    left: '50%'
+                }, pos);
+
+                // apply position
+                $( self.image ).css({
+                    position : 'absolute',
+                    top :  getPosition(pos.top, 'height', height),
+                    left : getPosition(pos.left, 'width', width)
+                });
+
+                // show the image
+                self.show();
+
+                // flag ready and call the callback
+                self.ready = true;
+                options.complete.call( self, self );
+
+            },
+            error: function() {
+                Galleria.raise('Could not scale image: '+self.image.src);
+            },
+            timeout: 1000
+        });
+        return this;
+    }
+};
+
+// our own easings
+$.extend( $.easing, {
+
+    galleria: function (_, t, b, c, d) {
+        if ((t/=d/2) < 1) {
+            return c/2*t*t*t + b;
+        }
+        return c/2*((t-=2)*t*t + 2) + b;
+    },
+
+    galleriaIn: function (_, t, b, c, d) {
+        return c*(t/=d)*t + b;
+    },
+
+    galleriaOut: function (_, t, b, c, d) {
+        return -c *(t/=d)*(t-2) + b;
+    }
+
+});
+
+
+// Forked version of Ainos Finger.js for native-style touch
+
+Galleria.Finger = (function() {
+
+    var abs = M.abs;
+
+    // test for translate3d support
+    var has3d = Galleria.HAS3D = (function() {
+
+        var el = doc.createElement('p'),
+            has3d,
+            t = ['webkit','O','ms','Moz',''],
+            s,
+            i=0,
+            a = 'transform';
+
+        DOM().html.insertBefore(el, null);
+
+        for (; t[i]; i++) {
+            s = t[i] ? t[i]+'Transform' : a;
+            if (el.style[s] !== undefined) {
+                el.style[s] = "translate3d(1px,1px,1px)";
+                has3d = $(el).css(t[i] ? '-'+t[i].toLowerCase()+'-'+a : a);
+            }
+        }
+
+        DOM().html.removeChild(el);
+        return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
+    }());
+
+    // request animation shim
+    var requestFrame = (function(){
+        var r = 'RequestAnimationFrame';
+        return window.requestAnimationFrame ||
+               window['webkit'+r] ||
+               window['moz'+r] ||
+               window['o'+r] ||
+               window['ms'+r] ||
+               function( callback ) {
+                   window.setTimeout(callback, 1000 / 60);
+               };
+    }());
+
+    var Finger = function(elem, options) {
+
+        // default options
+        this.config = {
+            start: 0,
+            duration: 500,
+            onchange: function() {},
+            oncomplete: function() {},
+            easing: function(x,t,b,c,d) {
+                return -c * ((t=t/d-1)*t*t*t - 1) + b; // easeOutQuart
+            }
+        };
+
+        this.easeout = function (x, t, b, c, d) {
+            return c*((t=t/d-1)*t*t*t*t + 1) + b;
+        };
+
+        if ( !elem.children.length ) {
+            return;
+        }
+
+        var self = this;
+
+        // extend options
+        $.extend(this.config, options);
+
+        this.elem = elem;
+        this.child = elem.children[0];
+        this.to = this.pos = 0;
+        this.touching = false;
+        this.start = {};
+        this.index = this.config.start;
+        this.anim = 0;
+        this.easing = this.config.easing;
+
+        if ( !has3d ) {
+          this.child.style.position = 'absolute';
+          this.elem.style.position = 'relative';
+        }
+
+        // Bind event handlers to context
+        $.each(['ontouchstart','ontouchmove','ontouchend','setup'], function(i, fn) {
+            self[fn] = (function(caller) {
+                return function() {
+                    caller.apply( self, arguments );
+                };
+            }(self[fn]));
+        });
+
+        // the physical animator
+        this.setX = function() {
+
+            var style = self.child.style;
+
+            if (!has3d) {
+                // this is actually faster than CSS3 translate
+                style.left = self.pos+'px';
+                return;
+            }
+            style.MozTransform = style.webkitTransform = style.transform = 'translate3d(' + self.pos + 'px,0,0)';
+            return;
+        };
+
+        // bind events
+        $(elem).on('touchstart', this.ontouchstart);
+        $(window).on('resize', this.setup);
+        $(window).on('orientationchange', this.setup);
+
+        // set up width
+        this.setup();
+
+        // start the animations
+        (function animloop(){
+          requestFrame(animloop);
+          self.loop.call( self );
+        }());
+
+    };
+
+    Finger.prototype = {
+
+        constructor: Finger,
+
+        setup: function() {
+            this.width = $( this.elem ).width();
+            this.length = M.ceil( $(this.child).width() / this.width );
+            if ( this.index !== 0 ) {
+                this.index = M.max(0, M.min( this.index, this.length-1 ) );
+                this.pos = this.to = -this.width*this.index;
+            }
+        },
+
+        setPosition: function(pos) {
+            this.pos = pos;
+            this.to = pos;
+        },
+
+        ontouchstart: function(e) {
+
+            var touch = e.originalEvent.touches;
+
+            this.start = {
+                pageX: touch[0].pageX,
+                pageY: touch[0].pageY,
+                time:  +new Date()
+            };
+
+            this.isScrolling = null;
+            this.touching = true;
+            this.deltaX = 0;
+
+            $doc.on('touchmove', this.ontouchmove);
+            $doc.on('touchend', this.ontouchend);
+        },
+
+        ontouchmove: function(e) {
+
+            var touch = e.originalEvent.touches;
+
+            // ensure swiping with one touch and not pinching
+            if( touch && touch.length > 1 || e.scale && e.scale !== 1 ) {
+                return;
+            }
+
+            this.deltaX = touch[0].pageX - this.start.pageX;
+
+            // determine if scrolling test has run - one time test
+            if ( this.isScrolling === null ) {
+                this.isScrolling = !!(
+                    this.isScrolling ||
+                    M.abs(this.deltaX) < M.abs(touch[0].pageY - this.start.pageY)
+                );
+            }
+
+            // if user is not trying to scroll vertically
+            if (!this.isScrolling) {
+
+                // prevent native scrolling
+                e.preventDefault();
+
+                // increase resistance if first or last slide
+                this.deltaX /= ( (!this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0 ) ?
+                    ( M.abs(this.deltaX) / this.width + 1.8 )  : 1 );
+                this.to = this.deltaX - this.index * this.width;
+            }
+            e.stopPropagation();
+        },
+
+        ontouchend: function(e) {
+
+            this.touching = false;
+
+            // determine if slide attempt triggers next/prev slide
+            var isValidSlide = +new Date() - this.start.time < 250 &&
+                M.abs(this.deltaX) > 40 ||
+                M.abs(this.deltaX) > this.width/2,
+
+                isPastBounds = !this.index && this.deltaX > 0 ||
+                    this.index == this.length - 1 && this.deltaX < 0;
+
+            // if not scrolling vertically
+            if ( !this.isScrolling ) {
+                this.show( this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ) );
+            }
+
+            $doc.off('touchmove', this.ontouchmove);
+            $doc.off('touchend', this.ontouchend);
+        },
+
+        show: function( index ) {
+            if ( index != this.index ) {
+                this.config.onchange.call(this, index);
+            } else {
+                this.to = -( index*this.width );
+            }
+        },
+
+        moveTo: function( index ) {
+            if ( index != this.index ) {
+                this.pos = this.to = -( index*this.width );
+                this.index = index;
+            }
+        },
+
+        loop: function() {
+
+            var distance = this.to - this.pos,
+                factor = 1;
+
+            if ( this.width && distance ) {
+                factor = M.max(0.5, M.min(1.5, M.abs(distance / this.width) ) );
+            }
+
+            // if distance is short or the user is touching, do a 1-1 animation
+            if ( this.touching || M.abs(distance) <= 1 ) {
+                this.pos = this.to;
+                distance = 0;
+                if ( this.anim && !this.touching ) {
+                    this.config.oncomplete( this.index );
+                }
+                this.anim = 0;
+                this.easing = this.config.easing;
+            } else {
+                if ( !this.anim ) {
+                    // save animation parameters
+                    this.anim = { start: this.pos, time: +new Date(), distance: distance, factor: factor, destination: this.to };
+                }
+                // check if to has changed or time has run out
+                var elapsed = +new Date() - this.anim.time;
+                var duration = this.config.duration*this.anim.factor;
+
+                if ( elapsed > duration || this.anim.destination != this.to ) {
+                    this.anim = 0;
+                    this.easing = this.easeout;
+                    return;
+                }
+                // apply easing
+                this.pos = this.easing(
+                    null,
+                    elapsed,
+                    this.anim.start,
+                    this.anim.distance,
+                    duration
+                );
+            }
+            this.setX();
+        }
+    };
+
+    return Finger;
+
+}());
+
+// the plugin initializer
+$.fn.galleria = function( options ) {
+
+    var selector = this.selector;
+
+    // try domReady if element not found
+    if ( !$(this).length ) {
+
+        $(function() {
+            if ( $( selector ).length ) {
+
+                // if found on domReady, go ahead
+                $( selector ).galleria( options );
+
+            } else {
+
+                // if not, try fetching the element for 5 secs, then raise a warning.
+                Galleria.utils.wait({
+                    until: function() {
+                        return $( selector ).length;
+                    },
+                    success: function() {
+                        $( selector ).galleria( options );
+                    },
+                    error: function() {
+                        Galleria.raise('Init failed: Galleria could not find the element "'+selector+'".');
+                    },
+                    timeout: 5000
+                });
+
+            }
+        });
+        return this;
+    }
+
+    return this.each(function() {
+
+        // destroy previous instance and prepare for new load
+        if ( $.data(this, 'galleria') ) {
+            $.data( this, 'galleria' ).destroy();
+            $( this ).find( '*' ).hide();
+        }
+
+        // load the new gallery
+        $.data( this, 'galleria', new Galleria().init( this, options ) );
+    });
+
+};
+
+// export as AMD or CommonJS
+if ( typeof module === "object" && module && typeof module.exports === "object" ) {
+    module.exports = Galleria;
+} else {
+    window.Galleria = Galleria;
+    if ( typeof define === "function" && define.amd ) {
+        define( "galleria", ['jquery'], function() { return Galleria; } );
+    }
+}
+
+// phew
+
+}( jQuery, this ) );
diff --git a/script/galleria/galleria-1.5.7.min.js b/script/galleria/galleria-1.5.7.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..cfda735ce8078b51893384e05078257ca329e7ea
--- /dev/null
+++ b/script/galleria/galleria-1.5.7.min.js
@@ -0,0 +1,13 @@
+/**
+ * Galleria - v1.5.7 2017-05-10
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a,b,c,d){var e=b.document,f=a(e),g=a(b),h=Array.prototype,i=1.57,j=!0,k=3e4,l=!1,m=navigator.userAgent.toLowerCase(),n=b.location.hash.replace(/#\//,""),o="file:"==b.location.protocol?"http:":b.location.protocol,p=Math,q=function(){},r=function(){return!1},s=!(b.screen.width>1279&&1==b.devicePixelRatio||b.screen.width>1e3&&b.innerWidth<.9*b.screen.width),t=function(){var a=3,b=e.createElement("div"),c=b.getElementsByTagName("i");do b.innerHTML="<!--[if gt IE "+ ++a+"]><i></i><![endif]-->";while(c[0]);return a>4?a:e.documentMode||d}(),u=function(){return{html:e.documentElement,body:e.body,head:e.getElementsByTagName("head")[0],title:e.title}},v=b.parent!==b.self,w="data ready thumbnail loadstart loadfinish image play pause progress fullscreen_enter fullscreen_exit idle_enter idle_exit rescale lightbox_open lightbox_close lightbox_image",x=function(){var b=[];return a.each(w.split(" "),function(a,c){b.push(c),/_/.test(c)&&b.push(c.replace(/_/g,""))}),b}(),y=function(b){var c;return"object"!=typeof b?b:(a.each(b,function(d,e){/^[a-z]+_/.test(d)&&(c="",a.each(d.split("_"),function(a,b){c+=a>0?b.substr(0,1).toUpperCase()+b.substr(1):b}),b[c]=e,delete b[d])}),b)},z=function(b){return a.inArray(b,x)>-1?c[b.toUpperCase()]:b},A={youtube:{reg:/https?:\/\/(?:[a-zA_Z]{2,3}.)?(?:youtube\.com\/watch\?)((?:[\w\d\-\_\=]+&amp;(?:amp;)?)*v(?:&lt;[A-Z]+&gt;)?=([0-9a-zA-Z\-\_]+))/i,embed:function(){return o+"//www.youtube.com/embed/"+this.id},get_thumb:function(a){return o+"//img.youtube.com/vi/"+this.id+"/default.jpg"},get_image:function(a){return o+"//img.youtube.com/vi/"+this.id+"/hqdefault.jpg"}},vimeo:{reg:/https?:\/\/(?:www\.)?(vimeo\.com)\/(?:hd#)?([0-9]+)/i,embed:function(){return o+"//player.vimeo.com/video/"+this.id},getUrl:function(){return o+"//vimeo.com/api/v2/video/"+this.id+".json?callback=?"},get_thumb:function(a){return a[0].thumbnail_medium},get_image:function(a){return a[0].thumbnail_large}},dailymotion:{reg:/https?:\/\/(?:www\.)?(dailymotion\.com)\/video\/([^_]+)/,embed:function(){return o+"//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(a){return a.thumbnail_240_url},get_image:function(a){return a.thumbnail_720_url}},_inst:[]},B=function(c,d){for(var e=0;e<A._inst.length;e++)if(A._inst[e].id===d&&A._inst[e].type==c)return A._inst[e];this.type=c,this.id=d,this.readys=[],A._inst.push(this);var f=this;a.extend(this,A[c]),_videoThumbs=function(b){f.data=b,a.each(f.readys,function(a,b){b(f.data)}),f.readys=[]},this.hasOwnProperty("getUrl")?a.getJSON(this.getUrl(),_videoThumbs):b.setTimeout(_videoThumbs,400),this.getMedia=function(a,b,c){c=c||q;var d=this,e=function(c){b(d["get_"+a](c))};try{d.data?e(d.data):d.readys.push(e)}catch(a){c()}}},C=function(a){var b;for(var c in A)if(b=a&&A[c].reg&&a.match(A[c].reg),b&&b.length)return{id:b[2],provider:c};return!1},D={support:function(){var a=u().html;return!v&&(a.requestFullscreen||a.msRequestFullscreen||a.mozRequestFullScreen||a.webkitRequestFullScreen)}(),callback:q,enter:function(a,b,c){this.instance=a,this.callback=b||q,c=c||u().html,c.requestFullscreen?c.requestFullscreen():c.msRequestFullscreen?c.msRequestFullscreen():c.mozRequestFullScreen?c.mozRequestFullScreen():c.webkitRequestFullScreen&&c.webkitRequestFullScreen()},exit:function(a){this.callback=a||q,e.exitFullscreen?e.exitFullscreen():e.msExitFullscreen?e.msExitFullscreen():e.mozCancelFullScreen?e.mozCancelFullScreen():e.webkitCancelFullScreen&&e.webkitCancelFullScreen()},instance:null,listen:function(){if(this.support){var a=function(){if(D.instance){var a=D.instance._fullscreen;e.fullscreen||e.mozFullScreen||e.webkitIsFullScreen||e.msFullscreenElement&&null!==e.msFullscreenElement?a._enter(D.callback):a._exit(D.callback)}};e.addEventListener("fullscreenchange",a,!1),e.addEventListener("MSFullscreenChange",a,!1),e.addEventListener("mozfullscreenchange",a,!1),e.addEventListener("webkitfullscreenchange",a,!1)}}},E=[],F=[],G=!1,H=!1,I=[],J=[],K=function(b){J.push(b),a.each(I,function(a,c){c._options.theme!=b.name&&(c._initialized||c._options.theme)||(c.theme=b,c._init.call(c))})},L=function(){return{clearTimer:function(b){a.each(c.get(),function(){this.clearTimer(b)})},addTimer:function(b){a.each(c.get(),function(){this.addTimer(b)})},array:function(a){return h.slice.call(a,0)},create:function(a,b){b=b||"div";var c=e.createElement(b);return c.className=a,c},removeFromArray:function(b,c){return a.each(b,function(a,d){if(d==c)return b.splice(a,1),!1}),b},getScriptPath:function(b){b=b||a("script:last").attr("src");var c=b.split("/");return 1==c.length?"":(c.pop(),c.join("/")+"/")},animate:function(){var d,f,g,h,i,j,k,l=function(a){var c,d="transition WebkitTransition MozTransition OTransition".split(" ");if(b.opera)return!1;for(c=0;d[c];c++)if("undefined"!=typeof a[d[c]])return d[c];return!1}((e.body||e.documentElement).style),m={MozTransition:"transitionend",OTransition:"oTransitionEnd",WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[l],n={_default:[.25,.1,.25,1],galleria:[.645,.045,.355,1],galleriaIn:[.55,.085,.68,.53],galleriaOut:[.25,.46,.45,.94],ease:[.25,0,.25,1],linear:[.25,.25,.75,.75],"ease-in":[.42,0,1,1],"ease-out":[0,0,.58,1],"ease-in-out":[.42,0,.58,1]},o=function(b,c,d){var e={};d=d||"transition",a.each("webkit moz ms o".split(" "),function(){e["-"+this+"-"+d]=c}),b.css(e)},p=function(a){o(a,"none","transition"),c.WEBKIT&&c.TOUCH&&(o(a,"translate3d(0,0,0)","transform"),a.data("revert")&&(a.css(a.data("revert")),a.data("revert",null)))};return function(e,r,s){return s=a.extend({duration:400,complete:q,stop:!1},s),e=a(e),s.duration?l?(s.stop&&(e.off(m),p(e)),d=!1,a.each(r,function(a,b){k=e.css(a),L.parseValue(k)!=L.parseValue(b)&&(d=!0),e.css(a,k)}),d?(f=[],g=s.easing in n?n[s.easing]:n._default,h=" "+s.duration+"ms cubic-bezier("+g.join(",")+")",void b.setTimeout(function(b,d,e,g){return function(){b.one(d,function(a){return function(){p(a),s.complete.call(a[0])}}(b)),c.WEBKIT&&c.TOUCH&&(i={},j=[0,0,0],a.each(["left","top"],function(a,c){c in e&&(j[a]=L.parseValue(e[c])-L.parseValue(b.css(c))+"px",i[c]=e[c],delete e[c])}),(j[0]||j[1])&&(b.data("revert",i),f.push("-webkit-transform"+g),o(b,"translate3d("+j.join(",")+")","transform"))),a.each(e,function(a,b){f.push(a+g)}),o(b,f.join(",")),b.css(e)}}(e,m,r,h),2)):void b.setTimeout(function(){s.complete.call(e[0])},s.duration)):void e.animate(r,s):(e.css(r),void s.complete.call(e[0]))}}(),removeAlpha:function(a){if(a instanceof jQuery&&(a=a[0]),t<9&&a){var b=a.style,c=a.currentStyle,d=c&&c.filter||b.filter||"";/alpha/.test(d)&&(b.filter=d.replace(/alpha\([^)]*\)/i,""))}},forceStyles:function(b,c){b=a(b),b.attr("style")&&b.data("styles",b.attr("style")).removeAttr("style"),b.css(c)},revertStyles:function(){a.each(L.array(arguments),function(b,c){c=a(c),c.removeAttr("style"),c.attr("style",""),c.data("styles")&&c.attr("style",c.data("styles")).data("styles",null)})},moveOut:function(a){L.forceStyles(a,{position:"absolute",left:-1e4})},moveIn:function(){L.revertStyles.apply(L,L.array(arguments))},hide:function(b,c,d){d=d||q;var e=a(b);b=e[0],e.data("opacity")||e.data("opacity",e.css("opacity"));var f={opacity:0};if(c){var g=t<9&&b?function(){L.removeAlpha(b),b.style.visibility="hidden",d.call(b)}:d;L.animate(b,f,{duration:c,complete:g,stop:!0})}else t<9&&b?(L.removeAlpha(b),b.style.visibility="hidden"):e.css(f)},show:function(b,c,d){d=d||q;var e=a(b);b=e[0];var f=parseFloat(e.data("opacity"))||1,g={opacity:f};if(c){t<9&&(e.css("opacity",0),b.style.visibility="visible");var h=t<9&&b?function(){1==g.opacity&&L.removeAlpha(b),d.call(b)}:d;L.animate(b,g,{duration:c,complete:h,stop:!0})}else t<9&&1==g.opacity&&b?(L.removeAlpha(b),b.style.visibility="visible"):e.css(g)},wait:function(d){c._waiters=c._waiters||[],d=a.extend({until:r,success:q,error:function(){c.raise("Could not complete wait function.")},timeout:3e3},d);var e,f,g,h=L.timestamp(),i=function(){return f=L.timestamp(),e=f-h,L.removeFromArray(c._waiters,g),d.until(e)?(d.success(),!1):"number"==typeof d.timeout&&f>=h+d.timeout?(d.error(),!1):void c._waiters.push(g=b.setTimeout(i,10))};c._waiters.push(g=b.setTimeout(i,10))},toggleQuality:function(a,b){7!==t&&8!==t||!a||"IMG"!=a.nodeName.toUpperCase()||("undefined"==typeof b&&(b="nearest-neighbor"===a.style.msInterpolationMode),a.style.msInterpolationMode=b?"bicubic":"nearest-neighbor")},insertStyleTag:function(b,c){if(!c||!a("#"+c).length){var d=e.createElement("style");if(c&&(d.id=c),u().head.appendChild(d),d.styleSheet)d.styleSheet.cssText=b;else{var f=e.createTextNode(b);d.appendChild(f)}}},loadScript:function(b,c){var d=!1,e=a("<script>").attr({src:b,async:!0}).get(0);e.onload=e.onreadystatechange=function(){d||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState||(d=!0,e.onload=e.onreadystatechange=null,"function"==typeof c&&c.call(this,this))},u().head.appendChild(e)},parseValue:function(a){if("number"==typeof a)return a;if("string"==typeof a){var b=a.match(/\-?\d|\./g);return b&&b.constructor===Array?1*b.join(""):0}return 0},timestamp:function(){return(new Date).getTime()},loadCSS:function(b,f,g){var h,i;if(a("link[rel=stylesheet]").each(function(){if(new RegExp(b).test(this.href))return h=this,!1}),"function"==typeof f&&(g=f,f=d),g=g||q,h)return g.call(h,h),h;if(i=e.styleSheets.length,a("#"+f).length)a("#"+f).attr("href",b),i--;else{h=a("<link>").attr({rel:"stylesheet",href:b,id:f}).get(0);var j=a('link[rel="stylesheet"], style');if(j.length?j.get(0).parentNode.insertBefore(h,j[0]):u().head.appendChild(h),t&&i>=31)return void c.raise("You have reached the browser stylesheet limit (31)",!0)}if("function"==typeof g){var k=a("<s>").attr("id","galleria-loader").hide().appendTo(u().body);L.wait({until:function(){return k.height()>0},success:function(){k.remove(),g.call(h,h)},error:function(){k.remove(),c.raise("Theme CSS could not load after 20 sec. "+(c.QUIRK?"Your browser is in Quirks Mode, please add a correct doctype.":"Please download the latest theme at http://galleria.io/customer/."),!0)},timeout:5e3})}return h}}}(),M=function(b){var c=".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}";return L.insertStyleTag(c,"galleria-videoicon"),a(L.create("galleria-videoicon")).html("<i></i>").appendTo(b).click(function(){a(this).siblings("img").mouseup()})},N=function(){var b=function(b,c,d,e){var f=this.getOptions("easing"),g=this.getStageWidth(),h={left:g*(b.rewind?-1:1)},i={left:0};d?(h.opacity=0,i.opacity=1):h.opacity=1,a(b.next).css(h),L.animate(b.next,i,{duration:b.speed,complete:function(a){return function(){c(),a.css({left:0})}}(a(b.next).add(b.prev)),queue:!1,easing:f}),e&&(b.rewind=!b.rewind),b.prev&&(h={left:0},i={left:g*(b.rewind?1:-1)},d&&(h.opacity=1,i.opacity=0),a(b.prev).css(h),L.animate(b.prev,i,{duration:b.speed,queue:!1,easing:f,complete:function(){a(this).css("opacity",0)}}))};return{active:!1,init:function(a,b,c){N.effects.hasOwnProperty(a)&&N.effects[a].call(this,b,c)},effects:{fade:function(b,c){a(b.next).css({opacity:0,left:0}),L.animate(b.next,{opacity:1},{duration:b.speed,complete:c}),b.prev&&(a(b.prev).css("opacity",1).show(),L.animate(b.prev,{opacity:0},{duration:b.speed}))},flash:function(b,c){a(b.next).css({opacity:0,left:0}),b.prev?L.animate(b.prev,{opacity:0},{duration:b.speed/2,complete:function(){L.animate(b.next,{opacity:1},{duration:b.speed,complete:c})}}):L.animate(b.next,{opacity:1},{duration:b.speed,complete:c})},pulse:function(b,c){b.prev&&a(b.prev).hide(),a(b.next).css({opacity:0,left:0}).show(),L.animate(b.next,{opacity:1},{duration:b.speed,complete:c})},slide:function(a,c){b.apply(this,L.array(arguments))},fadeslide:function(a,c){b.apply(this,L.array(arguments).concat([!0]))},doorslide:function(a,c){b.apply(this,L.array(arguments).concat([!1,!0]))}}}}();D.listen(),a.event.special["click:fast"]={propagate:!0,add:function(c){var d=function(a){if(a.touches&&a.touches.length){var b=a.touches[0];return{x:b.pageX,y:b.pageY}}},e={touched:!1,touchdown:!1,coords:{x:0,y:0},evObj:{}};a(this).data({clickstate:e,timer:0}).on("touchstart.fast",function(c){b.clearTimeout(a(this).data("timer")),a(this).data("clickstate",{touched:!0,touchdown:!0,coords:d(c.originalEvent),evObj:c})}).on("touchmove.fast",function(b){var c=d(b.originalEvent),e=a(this).data("clickstate"),f=Math.max(Math.abs(e.coords.x-c.x),Math.abs(e.coords.y-c.y));f>6&&a(this).data("clickstate",a.extend(e,{touchdown:!1}))}).on("touchend.fast",function(d){var f=a(this),g=f.data("clickstate");g.touchdown&&c.handler.call(this,d),f.data("timer",b.setTimeout(function(){f.data("clickstate",e)},400))}).on("click.fast",function(b){var d=a(this).data("clickstate");return!d.touched&&(a(this).data("clickstate",e),void c.handler.call(this,b))})},remove:function(){a(this).off("touchstart.fast touchmove.fast touchend.fast click.fast")}},g.on("orientationchange",function(){a(this).resize()}),c=function(){var h=this;this._options={},this._playing=!1,this._playtime=5e3,this._active=null,this._queue={length:0},this._data=[],this._dom={},this._thumbnails=[],this._layers=[],this._initialized=!1,this._firstrun=!1,this._stageWidth=0,this._stageHeight=0,this._target=d,this._binds=[],this._id=parseInt(1e4*p.random(),10);var i="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",j="current total";a.each(i.split(" "),function(a,b){h._dom[b]=L.create("galleria-"+b)}),a.each(j.split(" "),function(a,b){h._dom[b]=L.create("galleria-"+b,"span")});var k=this._keyboard={keys:{UP:38,DOWN:40,LEFT:37,RIGHT:39,RETURN:13,ESCAPE:27,BACKSPACE:8,SPACE:32},map:{},bound:!1,press:function(a){var b=a.keyCode||a.which;b in k.map&&"function"==typeof k.map[b]&&k.map[b].call(h,a)},attach:function(a){var b,c;for(b in a)a.hasOwnProperty(b)&&(c=b.toUpperCase(),c in k.keys?k.map[k.keys[c]]=a[b]:k.map[c]=a[b]);k.bound||(k.bound=!0,f.on("keydown",k.press))},detach:function(){k.bound=!1,k.map={},f.off("keydown",k.press)}},l=this._controls={0:d,1:d,active:0,swap:function(){l.active=l.active?0:1},getActive:function(){return h._options.swipe?l.slides[h._active]:l[l.active]},getNext:function(){return h._options.swipe?l.slides[h.getNext(h._active)]:l[1-l.active]},slides:[],frames:[],layers:[]},n=this._carousel={next:h.$("thumb-nav-right"),prev:h.$("thumb-nav-left"),width:0,current:0,max:0,hooks:[],update:function(){var b=0,c=0,d=[0];a.each(h._thumbnails,function(e,f){if(f.ready){b+=f.outerWidth||a(f.container).outerWidth(!0);var g=a(f.container).width();b+=g-p.floor(g),d[e+1]=b,c=p.max(c,f.outerHeight||a(f.container).outerHeight(!0))}}),h.$("thumbnails").css({width:b,height:c}),n.max=b,n.hooks=d,n.width=h.$("thumbnails-list").width(),n.setClasses(),h.$("thumbnails-container").toggleClass("galleria-carousel",b>n.width),n.width=h.$("thumbnails-list").width()},bindControls:function(){var a;n.next.on("click:fast",function(b){if(b.preventDefault(),"auto"===h._options.carouselSteps){for(a=n.current;a<n.hooks.length;a++)if(n.hooks[a]-n.hooks[n.current]>n.width){n.set(a-2);break}}else n.set(n.current+h._options.carouselSteps)}),n.prev.on("click:fast",function(b){if(b.preventDefault(),"auto"===h._options.carouselSteps)for(a=n.current;a>=0;a--){if(n.hooks[n.current]-n.hooks[a]>n.width){n.set(a+2);break}if(0===a){n.set(0);break}}else n.set(n.current-h._options.carouselSteps)})},set:function(a){for(a=p.max(a,0);n.hooks[a-1]+n.width>=n.max&&a>=0;)a--;n.current=a,n.animate()},getLast:function(a){return(a||n.current)-1},follow:function(a){if(0===a||a===n.hooks.length-2)return void n.set(a);for(var b=n.current;n.hooks[b]-n.hooks[n.current]<n.width&&b<=n.hooks.length;)b++;a-1<n.current?n.set(a-1):a+2>b&&n.set(a-b+n.current+2)},setClasses:function(){n.prev.toggleClass("disabled",!n.current),n.next.toggleClass("disabled",n.hooks[n.current]+n.width>=n.max)},animate:function(b){n.setClasses();var c=n.hooks[n.current]*-1;isNaN(c)||(h.$("thumbnails").css("left",function(){return a(this).css("left")}),L.animate(h.get("thumbnails"),{left:c},{duration:h._options.carouselSpeed,easing:h._options.easing,queue:!1}))}},o=this._tooltip={initialized:!1,open:!1,timer:"tooltip"+h._id,swapTimer:"swap"+h._id,init:function(){o.initialized=!0;var a=".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);}";L.insertStyleTag(a,"galleria-tooltip"),h.$("tooltip").css({opacity:.8,visibility:"visible",display:"none"})},move:function(a){var b=h.getMousePosition(a).x,c=h.getMousePosition(a).y,d=h.$("tooltip"),e=b,f=c,g=d.outerHeight(!0)+1,i=d.outerWidth(!0),j=g+15,k=h.$("container").width()-i-2,l=h.$("container").height()-g-2;isNaN(e)||isNaN(f)||(e+=10,f-=g+8,e=p.max(0,p.min(k,e)),f=p.max(0,p.min(l,f)),c<j&&(f=j),d.css({left:e,top:f}))},bind:function(b,d){if(!c.TOUCH){o.initialized||o.init();var e=function(){h.$("container").off("mousemove",o.move),h.clearTimer(o.timer),h.$("tooltip").stop().animate({opacity:0},200,function(){h.$("tooltip").hide(),h.addTimer(o.swapTimer,function(){o.open=!1},1e3)})},f=function(b,c){o.define(b,c),a(b).hover(function(){h.clearTimer(o.swapTimer),h.$("container").off("mousemove",o.move).on("mousemove",o.move).trigger("mousemove"),o.show(b),h.addTimer(o.timer,function(){h.$("tooltip").stop().show().animate({opacity:1}),o.open=!0},o.open?0:500)},e).click(e)};"string"==typeof d?f(b in h._dom?h.get(b):b,d):a.each(b,function(a,b){f(h.get(a),b)})}},show:function(c){c=a(c in h._dom?h.get(c):c);var d=c.data("tt"),e=function(a){b.setTimeout(function(a){return function(){o.move(a)}}(a),10),c.off("mouseup",e)};d="function"==typeof d?d():d,d&&(h.$("tooltip").html(d.replace(/\s/,"&#160;")),c.on("mouseup",e))},define:function(b,c){if("function"!=typeof c){var d=c;c=function(){return d}}b=a(b in h._dom?h.get(b):b).data("tt",c),o.show(b)}},q=this._fullscreen={scrolled:0,crop:d,active:!1,prev:a(),beforeEnter:function(a){a()},beforeExit:function(a){a()},keymap:h._keyboard.map,parseCallback:function(b,c){return N.active?function(){"function"==typeof b&&b.call(h);var d=h._controls.getActive(),e=h._controls.getNext();h._scaleImage(e),h._scaleImage(d),c&&h._options.trueFullscreen&&a(d.container).add(e.container).trigger("transitionend")}:b},enter:function(a){q.beforeEnter(function(){a=q.parseCallback(a,!0),h._options.trueFullscreen&&D.support?(q.active=!0,L.forceStyles(h.get("container"),{width:"100%",height:"100%"}),h.rescale(),c.MAC?c.SAFARI&&/version\/[1-5]/.test(m)?(h.$("stage").css("opacity",0),b.setTimeout(function(){q.scale(),h.$("stage").css("opacity",1)},4)):(h.$("container").css("opacity",0).addClass("fullscreen"),b.setTimeout(function(){q.scale(),h.$("container").css("opacity",1)},50)):h.$("container").addClass("fullscreen"),g.resize(q.scale),D.enter(h,a,h.get("container"))):(q.scrolled=g.scrollTop(),c.TOUCH||b.scrollTo(0,0),q._enter(a))})},_enter:function(f){q.active=!0,v&&(q.iframe=function(){var d,f=e.referrer,g=e.createElement("a"),h=b.location;return g.href=f,g.protocol!=h.protocol||g.hostname!=h.hostname||g.port!=h.port?(c.raise("Parent fullscreen not available. Iframe protocol, domains and ports must match."),!1):(q.pd=b.parent.document,a(q.pd).find("iframe").each(function(){var a=this.contentDocument||this.contentWindow.document;if(a===e)return d=this,!1}),d)}()),L.hide(h.getActiveImage()),v&&q.iframe&&(q.iframe.scrolled=a(b.parent).scrollTop(),b.parent.scrollTo(0,0));var i=h.getData(),j=h._options,k=!h._options.trueFullscreen||!D.support,l={height:"100%",overflow:"hidden",margin:0,padding:0};if(k&&(h.$("container").addClass("fullscreen"),q.prev=h.$("container").prev(),q.prev.length||(q.parent=h.$("container").parent()),h.$("container").appendTo("body"),L.forceStyles(h.get("container"),{position:c.TOUCH?"absolute":"fixed",top:0,left:0,width:"100%",height:"100%",zIndex:1e4}),L.forceStyles(u().html,l),L.forceStyles(u().body,l)),v&&q.iframe&&(L.forceStyles(q.pd.documentElement,l),L.forceStyles(q.pd.body,l),L.forceStyles(q.iframe,a.extend(l,{width:"100%",height:"100%",top:0,left:0,position:"fixed",zIndex:1e4,border:"none"}))),q.keymap=a.extend({},h._keyboard.map),h.attachKeyboard({escape:h.exitFullscreen,right:h.next,left:h.prev}),q.crop=j.imageCrop,j.fullscreenCrop!=d&&(j.imageCrop=j.fullscreenCrop),i&&i.big&&i.image!==i.big){var m=new c.Picture,n=m.isCached(i.big),o=h.getIndex(),p=h._thumbnails[o];h.trigger({type:c.LOADSTART,cached:n,rewind:!1,index:o,imageTarget:h.getActiveImage(),thumbTarget:p,galleriaData:i}),m.load(i.big,function(b){h._scaleImage(b,{complete:function(b){h.trigger({type:c.LOADFINISH,cached:n,index:o,rewind:!1,imageTarget:b.image,thumbTarget:p});var d=h._controls.getActive().image;d&&a(d).width(b.image.width).height(b.image.height).attr("style",a(b.image).attr("style")).attr("src",b.image.src)}})});var r=h.getNext(o),s=new c.Picture,t=h.getData(r);s.preload(h.isFullscreen()&&t.big?t.big:t.image)}h.rescale(function(){h.addTimer(!1,function(){k&&L.show(h.getActiveImage()),"function"==typeof f&&f.call(h),h.rescale()},100),h.trigger(c.FULLSCREEN_ENTER)}),k?g.resize(q.scale):L.show(h.getActiveImage())},scale:function(){h.rescale()},exit:function(a){q.beforeExit(function(){a=q.parseCallback(a),h._options.trueFullscreen&&D.support?D.exit(a):q._exit(a)})},_exit:function(a){q.active=!1;var d=!h._options.trueFullscreen||!D.support,e=h.$("container").removeClass("fullscreen");if(q.parent?q.parent.prepend(e):e.insertAfter(q.prev),d){L.hide(h.getActiveImage()),L.revertStyles(h.get("container"),u().html,u().body),c.TOUCH||b.scrollTo(0,q.scrolled);var f=h._controls.frames[h._controls.active];f&&f.image&&(f.image.src=f.image.src)}v&&q.iframe&&(L.revertStyles(q.pd.documentElement,q.pd.body,q.iframe),q.iframe.scrolled&&b.parent.scrollTo(0,q.iframe.scrolled)),h.detachKeyboard(),h.attachKeyboard(q.keymap),h._options.imageCrop=q.crop;var i=h.getData().big,j=h._controls.getActive().image;!h.getData().iframe&&j&&i&&i==j.src&&b.setTimeout(function(a){return function(){j.src=a}}(h.getData().image),1),h.rescale(function(){h.addTimer(!1,function(){d&&L.show(h.getActiveImage()),"function"==typeof a&&a.call(h),g.trigger("resize")},50),h.trigger(c.FULLSCREEN_EXIT)}),g.off("resize",q.scale)}},r=this._idle={trunk:[],bound:!1,active:!1,add:function(b,d,e,f){if(b&&!c.TOUCH){r.bound||r.addEvent(),b=a(b),"boolean"==typeof e&&(f=e,e={}),e=e||{};var g,h={};for(g in d)d.hasOwnProperty(g)&&(h[g]=b.css(g));b.data("idle",{from:a.extend(h,e),to:d,complete:!0,busy:!1}),f?b.css(d):r.addTimer(),r.trunk.push(b)}},remove:function(b){b=a(b),a.each(r.trunk,function(a,c){c&&c.length&&!c.not(b).length&&(b.css(b.data("idle").from),r.trunk.splice(a,1))}),r.trunk.length||(r.removeEvent(),h.clearTimer(r.timer))},addEvent:function(){r.bound=!0,h.$("container").on("mousemove click",r.showAll),"hover"==h._options.idleMode&&h.$("container").on("mouseleave",r.hide)},removeEvent:function(){r.bound=!1,h.$("container").on("mousemove click",r.showAll),"hover"==h._options.idleMode&&h.$("container").off("mouseleave",r.hide)},addTimer:function(){"hover"!=h._options.idleMode&&h.addTimer("idle",function(){r.hide()},h._options.idleTime)},hide:function(){if(h._options.idleMode&&h.getIndex()!==!1){h.trigger(c.IDLE_ENTER);var b=r.trunk.length;a.each(r.trunk,function(a,c){var d=c.data("idle");d&&(c.data("idle").complete=!1,L.animate(c,d.to,{duration:h._options.idleSpeed,complete:function(){a==b-1&&(r.active=!1)}}))})}},showAll:function(){h.clearTimer("idle"),a.each(r.trunk,function(a,b){r.show(b)})},show:function(b){var d=b.data("idle");r.active&&(d.busy||d.complete)||(d.busy=!0,h.trigger(c.IDLE_EXIT),h.clearTimer("idle"),L.animate(b,d.from,{duration:h._options.idleSpeed/2,complete:function(){r.active=!0,a(b).data("idle").busy=!1,a(b).data("idle").complete=!0}})),r.addTimer()}},s=this._lightbox={width:0,height:0,initialized:!1,active:null,image:null,elems:{},keymap:!1,init:function(){if(!s.initialized){s.initialized=!0;var b="overlay box content shadow title info close prevholder prev nextholder next counter image",d={},e=h._options,f="",g="position:absolute;",i="lightbox-",j={overlay:"position:fixed;display:none;opacity:"+e.overlayOpacity+";filter:alpha(opacity="+100*e.overlayOpacity+");top:0;left:0;width:100%;height:100%;background:"+e.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:g+"background:#000;width:100%;height:100%;",content:g+"background-color:#fff;top:10px;left:10px;right:10px;bottom:10px;overflow:hidden",info:g+"bottom:10px;left:10px;right:10px;color:#444;font:11px/13px arial,sans-serif;height:13px",close:g+"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:g+"top:10px;left:10px;right:10px;bottom:30px;overflow:hidden;display:block;",prevholder:g+"width:50%;top:0;bottom:40px;cursor:pointer;",nextholder:g+"width:50%;top:0;bottom:40px;right:-1px;cursor:pointer;",prev:g+"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:g+"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;"},k=function(b){return b.hover(function(){a(this).css("color","#bbb")},function(){a(this).css("color","#444")})},l={},m="";m=t>7?t<9?"background:#000;filter:alpha(opacity=0);":"background:rgba(0,0,0,0);":"z-index:99999",j.nextholder+=m,j.prevholder+=m,a.each(j,function(a,b){f+=".galleria-"+i+a+"{"+b+"}"}),f+=".galleria-"+i+"box.iframe .galleria-"+i+"prevholder,.galleria-"+i+"box.iframe .galleria-"+i+"nextholder{width:100px;height:100px;top:50%;margin-top:-70px}",L.insertStyleTag(f,"galleria-lightbox"),a.each(b.split(" "),function(a,b){h.addElement("lightbox-"+b),d[b]=s.elems[b]=h.get("lightbox-"+b)}),s.image=new c.Picture,a.each({box:"shadow content close prevholder nextholder",info:"title counter",content:"info image",prevholder:"prev",nextholder:"next"},function(b,c){var d=[];a.each(c.split(" "),function(a,b){d.push(i+b)}),l[i+b]=d}),h.append(l),a(d.image).append(s.image.container),a(u().body).append(d.overlay,d.box),k(a(d.close).on("click:fast",s.hide).html("&#215;")),a.each(["Prev","Next"],function(b,e){var f=a(d[e.toLowerCase()]).html(/v/.test(e)?"&#8249;&#160;":"&#160;&#8250;"),g=a(d[e.toLowerCase()+"holder"]);return g.on("click:fast",function(){s["show"+e]()}),t<8||c.TOUCH?void f.show():void g.hover(function(){f.show()},function(a){f.stop().fadeOut(200)})}),a(d.overlay).on("click:fast",s.hide),c.IPAD&&(h._options.lightboxTransitionSpeed=0)}},rescale:function(b){var d=p.min(g.width()-40,s.width),e=p.min(g.height()-60,s.height),f=p.min(d/s.width,e/s.height),i=p.round(s.width*f)+40,j=p.round(s.height*f)+60,k={width:i,height:j,"margin-top":p.ceil(j/2)*-1,"margin-left":p.ceil(i/2)*-1};b?a(s.elems.box).css(k):a(s.elems.box).animate(k,{duration:h._options.lightboxTransitionSpeed,easing:h._options.easing,complete:function(){var b=s.image,d=h._options.lightboxFadeSpeed;h.trigger({type:c.LIGHTBOX_IMAGE,imageTarget:b.image}),a(b.container).show(),a(b.image).animate({opacity:1},d),L.show(s.elems.info,d)}})},hide:function(){s.image.image=null,g.off("resize",s.rescale),a(s.elems.box).hide().find("iframe").remove(),L.hide(s.elems.info),h.detachKeyboard(),h.attachKeyboard(s.keymap),s.keymap=!1,L.hide(s.elems.overlay,200,function(){a(this).hide().css("opacity",h._options.overlayOpacity),h.trigger(c.LIGHTBOX_CLOSE)})},showNext:function(){s.show(h.getNext(s.active))},showPrev:function(){s.show(h.getPrev(s.active))},show:function(d){s.active=d="number"==typeof d?d:h.getIndex()||0,s.initialized||s.init(),h.trigger(c.LIGHTBOX_OPEN),s.keymap||(s.keymap=a.extend({},h._keyboard.map),h.attachKeyboard({escape:s.hide,right:s.showNext,left:s.showPrev})),g.off("resize",s.rescale);var e,f,i,j=h.getData(d),k=h.getDataLength(),l=h.getNext(d);L.hide(s.elems.info);try{for(i=h._options.preload;i>0;i--)f=new c.Picture,e=h.getData(l),f.preload(e.big?e.big:e.image),l=h.getNext(l)}catch(a){}s.image.isIframe=j.iframe&&!j.image,a(s.elems.box).toggleClass("iframe",s.image.isIframe),a(s.image.container).find(".galleria-videoicon").remove(),s.image.load(j.big||j.image||j.iframe,function(c){if(c.isIframe){var e=a(b).width(),f=a(b).height();if(c.video&&h._options.maxVideoSize){var i=p.min(h._options.maxVideoSize/e,h._options.maxVideoSize/f);i<1&&(e*=i,f*=i)}s.width=e,s.height=f}else s.width=c.original.width,s.height=c.original.height;if(a(c.image).css({width:c.isIframe?"100%":"100.1%",height:c.isIframe?"100%":"100.1%",top:0,bottom:0,zIndex:99998,opacity:0,visibility:"visible"}).parent().height("100%"),s.elems.title.innerHTML=j.title||"",s.elems.counter.innerHTML=d+1+" / "+k,g.resize(s.rescale),s.rescale(),j.image&&j.iframe){if(a(s.elems.box).addClass("iframe"),j.video){var l=M(c.container).hide();b.setTimeout(function(){l.fadeIn(200)},200)}a(c.image).css("cursor","pointer").mouseup(function(b,c){return function(d){a(s.image.container).find(".galleria-videoicon").remove(),d.preventDefault(),c.isIframe=!0,c.load(b.iframe+(b.video?"&autoplay=1":""),{width:"100%",height:t<8?a(s.image.container).height():"100%"})}}(j,c))}}),a(s.elems.overlay).show().css("visibility","visible"),a(s.elems.box).show()}},w=this._timer={trunk:{},add:function(a,c,d,e){if(a=a||(new Date).getTime(),e=e||!1,this.clear(a),e){var f=c;c=function(){f(),w.add(a,c,d)}}this.trunk[a]=b.setTimeout(c,d)},clear:function(a){var c,d=function(a){b.clearTimeout(this.trunk[a]),delete this.trunk[a]};if(a&&a in this.trunk)d.call(this,a);else if("undefined"==typeof a)for(c in this.trunk)this.trunk.hasOwnProperty(c)&&d.call(this,c)}};return this},c.prototype={constructor:c,init:function(b,e){if(e=y(e),this._original={target:b,options:e,data:null},this._target=this._dom.target=b.nodeName?b:a(b).get(0),this._original.html=this._target.innerHTML,F.push(this),!this._target)return void c.raise("Target not found",!0);if(this._options={autoplay:!1,carousel:!0,carouselFollow:!0,carouselSpeed:400,carouselSteps:"auto",clicknext:!1,dailymotion:{foreground:"%23EEEEEE",highlight:"%235BCEC5",background:"%23222222",logo:0,hideInfos:1},dataConfig:function(a){return{}},dataSelector:"img",dataSort:!1,dataSource:this._target,debug:d,dummy:d,easing:"galleria",extend:function(a){},fullscreenCrop:d,fullscreenDoubleTap:!0,fullscreenTransition:d,height:0,idleMode:!0,idleTime:3e3,idleSpeed:200,imageCrop:!1,imageMargin:0,imagePan:!1,imagePanSmoothness:12,imagePosition:"50%",imageTimeout:d,initialTransition:d,keepSource:!1,layerFollow:!0,lightbox:!1,lightboxFadeSpeed:200,lightboxTransitionSpeed:200,linkSourceImages:!0,maxScaleRatio:d,maxVideoSize:d,minScaleRatio:d,overlayOpacity:.85,overlayBackground:"#0b0b0b",pauseOnInteraction:!0,popupLinks:!1,preload:2,queue:!0,responsive:!0,show:0,showInfo:!0,showCounter:!0,showImagenav:!0,swipe:"auto",theme:null,thumbCrop:!0,thumbEventType:"click:fast",thumbMargin:0,thumbQuality:"auto",thumbDisplayOrder:!0,thumbPosition:"50%",thumbnails:!0,touchTransition:d,transition:"fade",transitionInitial:d,transitionSpeed:400,trueFullscreen:!0,useCanvas:!1,variation:"",videoPoster:!0,vimeo:{title:0,byline:0,portrait:0,color:"aaaaaa"},wait:5e3,
+width:"auto",youtube:{modestbranding:1,autohide:1,color:"white",hd:1,rel:0,showinfo:0}},this._options.initialTransition=this._options.initialTransition||this._options.transitionInitial,e&&(e.debug===!1&&(j=!1),"number"==typeof e.imageTimeout&&(k=e.imageTimeout),"string"==typeof e.dummy&&(l=e.dummy),"string"==typeof e.theme&&(this._options.theme=e.theme)),a(this._target).children().hide(),c.QUIRK&&c.raise("Your page is in Quirks mode, Galleria may not render correctly. Please validate your HTML and add a correct doctype."),J.length)if(this._options.theme){for(var f=0;f<J.length;f++)if(this._options.theme===J[f].name){this.theme=J[f];break}}else this.theme=J[0];return"object"==typeof this.theme?this._init():I.push(this),this},_init:function(){var f=this,h=this._options;if(this._initialized)return c.raise("Init failed: Gallery instance already initialized."),this;if(this._initialized=!0,!this.theme)return c.raise("Init failed: No theme found.",!0),this;if(a.extend(!0,h,this.theme.defaults,this._original.options,c.configure.options),h.swipe=function(a){return"enforced"==a||a!==!1&&"disabled"!=a&&!!c.TOUCH}(h.swipe),h.swipe&&(h.clicknext=!1,h.imagePan=!1),function(a){return"getContext"in a?void(H=H||{elem:a,context:a.getContext("2d"),cache:{},length:0}):void(a=null)}(e.createElement("canvas")),this.bind(c.DATA,function(){b.screen&&b.screen.width&&Array.prototype.forEach&&this._data.forEach(function(a){var c="devicePixelRatio"in b?b.devicePixelRatio:1,d=p.max(b.screen.width,b.screen.height);d*c<1024&&(a.big=a.image)}),this._original.data=this._data,this.get("total").innerHTML=this.getDataLength();var a=this.$("container");f._options.height<2&&(f._userRatio=f._ratio=f._options.height);var d={width:0,height:0},e=function(){return f.$("stage").height()};L.wait({until:function(){return d=f._getWH(),a.width(d.width).height(d.height),e()&&d.width&&d.height>50},success:function(){f._width=d.width,f._height=d.height,f._ratio=f._ratio||d.height/d.width,c.WEBKIT?b.setTimeout(function(){f._run()},1):f._run()},error:function(){e()?c.raise("Could not extract sufficient width/height of the gallery container. Traced measures: width:"+d.width+"px, height: "+d.height+"px.",!0):c.raise("Could not extract a stage height from the CSS. Traced height: "+e()+"px.",!0)},timeout:"number"==typeof this._options.wait&&this._options.wait})}),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"]}),L.hide(this.$("counter").append(this.get("current"),e.createTextNode(" / "),this.get("total"))),this.setCounter("&#8211;"),L.hide(f.get("tooltip")),this.$("container").addClass([c.TOUCH?"touch":"notouch",this._options.variation,"galleria-theme-"+this.theme.name].join(" ")),this._options.swipe||a.each(new Array(2),function(b){var d=new c.Picture;a(d.container).css({position:"absolute",top:0,left:0}).prepend(f._layers[b]=a(L.create("galleria-layer")).css({position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:2})[0]),f.$("images").append(d.container),f._controls[b]=d;var e=new c.Picture;e.isIframe=!0,a(e.container).attr("class","galleria-frame").css({position:"absolute",top:0,left:0,zIndex:4,background:"#000",display:"none"}).appendTo(d.container),f._controls.frames[b]=e}),this.$("images").css({position:"relative",top:0,left:0,width:"100%",height:"100%"}),h.swipe&&(this.$("images").css({position:"absolute",top:0,left:0,width:0,height:"100%"}),this.finger=new c.Finger(this.get("stage"),{onchange:function(a){f.pause().show(a)},oncomplete:function(b){var c=p.max(0,p.min(parseInt(b,10),f.getDataLength()-1)),d=f.getData(c);a(f._thumbnails[c].container).addClass("active").siblings(".active").removeClass("active"),d&&(f.$("images").find(".galleria-frame").css("opacity",0).hide().find("iframe").remove(),f._options.carousel&&f._options.carouselFollow&&f._carousel.follow(c))}}),this.bind(c.RESCALE,function(){this.finger.setup()}),this.$("stage").on("click",function(c){var e=f.getData();if(e){if(e.iframe){f.isPlaying()&&f.pause();var g=f._controls.frames[f._active],h=f._stageWidth,i=f._stageHeight;if(a(g.container).find("iframe").length)return;return a(g.container).css({width:h,height:i,opacity:0}).show().animate({opacity:1},200),void b.setTimeout(function(){g.load(e.iframe+(e.video?"&autoplay=1":""),{width:h,height:i},function(a){f.$("container").addClass("videoplay"),a.scale({width:f._stageWidth,height:f._stageHeight,iframelimit:e.video?f._options.maxVideoSize:d})})},100)}if(e.link)if(f._options.popupLinks){b.open(e.link,"_blank")}else b.location.href=e.link;else;}}),this.bind(c.IMAGE,function(b){f.setCounter(b.index),f.setInfo(b.index);var c=this.getNext(),d=this.getPrev(),e=[d,c];e.push(this.getNext(c),this.getPrev(d),f._controls.slides.length-1);var g=[];a.each(e,function(b,c){a.inArray(c,g)==-1&&g.push(c)}),a.each(g,function(b,c){var d=f.getData(c),e=f._controls.slides[c],g=f.isFullscreen()&&d.big?d.big:d.image||d.iframe;d.iframe&&!d.image&&(e.isIframe=!0),e.ready||f._controls.slides[c].load(g,function(b){b.isIframe||a(b.image).css("visibility","hidden"),f._scaleImage(b,{complete:function(b){b.isIframe||a(b.image).css({opacity:0,visibility:"visible"}).animate({opacity:1},200)}})})})})),this.$("thumbnails, thumbnails-list").css({overflow:"hidden",position:"relative"}),this.$("image-nav-right, image-nav-left").on("click:fast",function(a){h.pauseOnInteraction&&f.pause();var b=/right/.test(this.className)?"next":"prev";f[b]()}).on("click",function(a){a.preventDefault(),(h.clicknext||h.swipe)&&a.stopPropagation()}),a.each(["info","counter","image-nav"],function(a,b){h["show"+b.substr(0,1).toUpperCase()+b.substr(1).replace(/-/,"")]===!1&&L.moveOut(f.get(b.toLowerCase()))}),this.load(),h.keepSource||t||(this._target.innerHTML=""),this.get("errors")&&this.appendChild("target","errors"),this.appendChild("target","container"),h.carousel){var i=0,j=h.show;this.bind(c.THUMBNAIL,function(){this.updateCarousel(),++i==this.getDataLength()&&"number"==typeof j&&j>0&&this._carousel.follow(j)})}return h.responsive&&g.on("resize",function(){f.isFullscreen()||f.resize()}),h.fullscreenDoubleTap&&this.$("stage").on("touchstart",function(){var a,b,c,d,e,g,h=function(a){return a.originalEvent.touches?a.originalEvent.touches[0]:a};return f.$("stage").on("touchmove",function(){a=0}),function(i){if(!/(-left|-right)/.test(i.target.className)){if(g=L.timestamp(),b=h(i).pageX,c=h(i).pageY,i.originalEvent.touches.length<2&&g-a<300&&b-d<20&&c-e<20)return f.toggleFullscreen(),void i.preventDefault();a=g,d=b,e=c}}}()),a.each(c.on.binds,function(b,c){a.inArray(c.hash,f._binds)==-1&&f.bind(c.type,c.callback)}),this},addTimer:function(){return this._timer.add.apply(this._timer,L.array(arguments)),this},clearTimer:function(){return this._timer.clear.apply(this._timer,L.array(arguments)),this},_getWH:function(){var b,c=this.$("container"),d=this.$("target"),e=this,f={};return a.each(["width","height"],function(a,g){e._options[g]&&"number"==typeof e._options[g]?f[g]=e._options[g]:(b=[L.parseValue(c.css(g)),L.parseValue(d.css(g)),c[g](),d[g]()],e["_"+g]||b.splice(b.length,L.parseValue(c.css("min-"+g)),L.parseValue(d.css("min-"+g))),f[g]=p.max.apply(p,b))}),e._userRatio&&(f.height=f.width*e._userRatio),f},_createThumbnails:function(d){this.get("total").innerHTML=this.getDataLength();var f,g,h,i,j=this,k=this._options,l=d?this._data.length-d.length:0,m=l,n=[],o=0,p=t<8?"http://upload.wikimedia.org/wikipedia/commons/c/c0/Blank.gif":"data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D",q=function(){var a=j.$("thumbnails").find(".active");return!!a.length&&a.find("img").attr("src")}(),r="string"==typeof k.thumbnails?k.thumbnails.toLowerCase():null,s=function(a){return e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g.container,null)[a]:i.css(a)},u=function(b,d,e){return function(){a(e).append(b),j.trigger({type:c.THUMBNAIL,thumbTarget:b,index:d,galleriaData:j.getData(d)})}},v=function(b){k.pauseOnInteraction&&j.pause();var c=a(b.currentTarget).data("index");j.getIndex()!==c&&j.show(c),b.preventDefault()},w=function(b,d){a(b.container).css("visibility","visible"),j.trigger({type:c.THUMBNAIL,thumbTarget:b.image,index:b.data.order,galleriaData:j.getData(b.data.order)}),"function"==typeof d&&d.call(j,b)},x=function(b,c){b.scale({width:b.data.width,height:b.data.height,crop:k.thumbCrop,margin:k.thumbMargin,canvas:k.useCanvas,position:k.thumbPosition,complete:function(b){var d,e,f=["left","top"],g=["Width","Height"];j.getData(b.index);a.each(g,function(c,g){d=g.toLowerCase(),k.thumbCrop===!0&&k.thumbCrop!==d||(e={},e[d]=b[d],a(b.container).css(e),e={},e[f[c]]=0,a(b.image).css(e)),b["outer"+g]=a(b.container)["outer"+g](!0)}),L.toggleQuality(b.image,k.thumbQuality===!0||"auto"===k.thumbQuality&&b.original.width<3*b.width),k.thumbDisplayOrder&&!b.lazy?a.each(n,function(a,b){if(a===o&&b.ready&&!b.displayed)return o++,b.displayed=!0,void w(b,c)}):w(b,c)}})};for(d||(this._thumbnails=[],this.$("thumbnails").empty());this._data[l];l++)h=this._data[l],f=h.thumb||h.image,k.thumbnails!==!0&&"lazy"!=r||!h.thumb&&!h.image?h.iframe&&null!==r||"empty"===r||"numbers"===r?(g={container:L.create("galleria-image"),image:L.create("img","span"),ready:!0,data:{order:l}},"numbers"===r&&a(g.image).text(l+1),h.iframe&&a(g.image).addClass("iframe"),this.$("thumbnails").append(g.container),b.setTimeout(u(g.image,l,g.container),50+20*l)):g={container:null,image:null}:(g=new c.Picture(l),g.index=l,g.displayed=!1,g.lazy=!1,g.video=!1,this.$("thumbnails").append(g.container),i=a(g.container),i.css("visibility","hidden"),g.data={width:L.parseValue(s("width")),height:L.parseValue(s("height")),order:l,src:f},k.thumbCrop!==!0?i.css({width:"auto",height:"auto"}):i.css({width:g.data.width,height:g.data.height}),"lazy"==r?(i.addClass("lazy"),g.lazy=!0,g.load(p,{height:g.data.height,width:g.data.width})):g.load(f,x),"all"===k.preload&&g.preload(h.image)),a(g.container).add(k.keepSource&&k.linkSourceImages?h.original:null).data("index",l).on(k.thumbEventType,v).data("thumbload",x),q===f&&a(g.container).addClass("active"),this._thumbnails.push(g);return n=this._thumbnails.slice(m),this},lazyLoad:function(b,c){var d=b.constructor==Array?b:[b],e=this,f=0;return a.each(d,function(b,g){if(!(g>e._thumbnails.length-1)){var h=e._thumbnails[g],i=h.data,j=function(){++f==d.length&&"function"==typeof c&&c.call(e)},k=a(h.container).data("thumbload");k&&(h.video?k.call(e,h,j):h.load(i.src,function(a){k.call(e,a,j)}))}}),this},lazyLoadChunks:function(a,c){var d=this.getDataLength(),e=0,f=0,g=[],h=[],i=this;for(c=c||0;e<d;e++)h.push(e),++f!=a&&e!=d-1||(g.push(h),f=0,h=[]);var j=function(a){var d=g.shift();d&&b.setTimeout(function(){i.lazyLoad(d,function(){j(!0)})},c&&a?c:0)};return j(!1),this},_run:function(){var e=this;e._createThumbnails(),L.wait({timeout:1e4,until:function(){return c.OPERA&&e.$("stage").css("display","inline-block"),e._stageWidth=e.$("stage").width(),e._stageHeight=e.$("stage").height(),e._stageWidth&&e._stageHeight>50},success:function(){if(E.push(e),e._options.swipe){var f=e.$("images").width(e.getDataLength()*e._stageWidth);a.each(new Array(e.getDataLength()),function(b){var d=new c.Picture,g=e.getData(b);a(d.container).css({position:"absolute",top:0,left:e._stageWidth*b}).prepend(e._layers[b]=a(L.create("galleria-layer")).css({position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:2})[0]).appendTo(f),g.video&&M(d.container),e._controls.slides.push(d);var h=new c.Picture;h.isIframe=!0,a(h.container).attr("class","galleria-frame").css({position:"absolute",top:0,left:0,zIndex:4,background:"#000",display:"none"}).appendTo(d.container),e._controls.frames.push(h)}),e.finger.setup()}return L.show(e.get("counter")),e._options.carousel&&e._carousel.bindControls(),e._options.autoplay&&(e.pause(),"number"==typeof e._options.autoplay&&(e._playtime=e._options.autoplay),e._playing=!0),e._firstrun?(e._options.autoplay&&e.trigger(c.PLAY),void("number"==typeof e._options.show&&e.show(e._options.show))):(e._firstrun=!0,c.History&&c.History.change(function(a){isNaN(a)?b.history.go(-1):e.show(a,d,!0)}),e.trigger(c.READY),e.theme.init.call(e,e._options),a.each(c.ready.callbacks,function(a,b){"function"==typeof b&&b.call(e,e._options)}),e._options.extend.call(e,e._options),/^[0-9]{1,4}$/.test(n)&&c.History?e.show(n,d,!0):e._data[e._options.show]&&e.show(e._options.show),void(e._options.autoplay&&e.trigger(c.PLAY)))},error:function(){c.raise("Stage width or height is too small to show the gallery. Traced measures: width:"+e._stageWidth+"px, height: "+e._stageHeight+"px.",!0)}})},load:function(b,d,e){var f=this,g=this._options;return this._data=[],this._thumbnails=[],this.$("thumbnails").empty(),"function"==typeof d&&(e=d,d=null),b=b||g.dataSource,d=d||g.dataSelector,e=e||g.dataConfig,a.isPlainObject(b)&&(b=[b]),a.isArray(b)?this.validate(b)?this._data=b:c.raise("Load failed: JSON Array not valid."):(d+=",.video,.iframe",a(b).find(d).each(function(b,c){c=a(c);var d={},g=c.parent(),h=g.attr("href"),i=g.attr("rel");h&&("IMG"==c[0].nodeName||c.hasClass("video"))&&C(h)?d.video=h:h&&c.hasClass("iframe")?d.iframe=h:d.image=d.big=h,i&&(d.big=i),a.each("big title description link layer image".split(" "),function(a,b){c.data(b)&&(d[b]=c.data(b).toString())}),d.big||(d.big=d.image),f._data.push(a.extend({title:c.attr("title")||"",thumb:c.attr("src"),image:c.attr("src"),big:c.attr("src"),description:c.attr("alt")||"",link:c.attr("longdesc"),original:c.get(0)},d,e(c)))})),"function"==typeof g.dataSort?h.sort.call(this._data,g.dataSort):"random"==g.dataSort&&this._data.sort(function(){return p.round(p.random())-.5}),this.getDataLength()&&this._parseData(function(){this.trigger(c.DATA)}),this},_parseData:function(b){var c,e=this,f=!1,g=function(){var c=!0;a.each(e._data,function(a,b){if(b.loading)return c=!1,!1}),c&&!f&&(f=!0,b.call(e))};return a.each(this._data,function(b,f){if(c=e._data[b],"thumb"in f==!1&&(c.thumb=f.image),f.big||(c.big=f.image),"video"in f){var h=C(f.video);h&&(c.iframe=new B(h.provider,h.id).embed()+function(){if("object"==typeof e._options[h.provider]){var b="?",c=[];return a.each(e._options[h.provider],function(a,b){c.push(a+"="+b)}),"youtube"==h.provider&&(c=["wmode=opaque"].concat(c)),b+c.join("&")}return""}(),c.thumb&&c.image||a.each(["thumb","image"],function(a,b){if("image"==b&&!e._options.videoPoster)return void(c.image=d);var f=new B(h.provider,h.id);c[b]||(c.loading=!0,f.getMedia(b,function(a,b){return function(c){a[b]=c,"image"!=b||a.big||(a.big=a.image),delete a.loading,g()}}(c,b)))}))}}),g(),this},destroy:function(){return this.$("target").data("galleria",null),this.$("container").off("galleria"),this.get("target").innerHTML=this._original.html,this.clearTimer(),L.removeFromArray(F,this),L.removeFromArray(E,this),void 0!==c._waiters&&c._waiters.length&&a.each(c._waiters,function(a,c){c&&b.clearTimeout(c)}),this},splice:function(){var a=this,c=L.array(arguments);return b.setTimeout(function(){h.splice.apply(a._data,c),a._parseData(function(){a._createThumbnails()})},2),a},push:function(){var a=this,c=L.array(arguments);return 1==c.length&&c[0].constructor==Array&&(c=c[0]),b.setTimeout(function(){h.push.apply(a._data,c),a._parseData(function(){a._createThumbnails(c)})},2),a},_getActive:function(){return this._controls.getActive()},validate:function(a){return!0},bind:function(a,b){return a=z(a),this.$("container").on(a,this.proxy(b)),this},unbind:function(a){return a=z(a),this.$("container").off(a),this},trigger:function(b){return b="object"==typeof b?a.extend(b,{scope:this}):{type:z(b),scope:this},this.$("container").trigger(b),this},addIdleState:function(a,b,c,d){return this._idle.add.apply(this._idle,L.array(arguments)),this},removeIdleState:function(a){return this._idle.remove.apply(this._idle,L.array(arguments)),this},enterIdleMode:function(){return this._idle.hide(),this},exitIdleMode:function(){return this._idle.showAll(),this},enterFullscreen:function(a){return this._fullscreen.enter.apply(this,L.array(arguments)),this},exitFullscreen:function(a){return this._fullscreen.exit.apply(this,L.array(arguments)),this},toggleFullscreen:function(a){return this._fullscreen[this.isFullscreen()?"exit":"enter"].apply(this,L.array(arguments)),this},bindTooltip:function(a,b){return this._tooltip.bind.apply(this._tooltip,L.array(arguments)),this},defineTooltip:function(a,b){return this._tooltip.define.apply(this._tooltip,L.array(arguments)),this},refreshTooltip:function(a){return this._tooltip.show.apply(this._tooltip,L.array(arguments)),this},openLightbox:function(){return this._lightbox.show.apply(this._lightbox,L.array(arguments)),this},closeLightbox:function(){return this._lightbox.hide.apply(this._lightbox,L.array(arguments)),this},hasVariation:function(b){return a.inArray(b,this._options.variation.split(/\s+/))>-1},getActiveImage:function(){var a=this._getActive();return a?a.image:d},getActiveThumb:function(){return this._thumbnails[this._active].image||d},getMousePosition:function(a){return{x:a.pageX-this.$("container").offset().left,y:a.pageY-this.$("container").offset().top}},addPan:function(b){if(this._options.imageCrop!==!1){b=a(b||this.getActiveImage());var c=this,d=b.width()/2,e=b.height()/2,f=parseInt(b.css("left"),10),g=parseInt(b.css("top"),10),h=f||0,i=g||0,j=0,k=0,l=!1,m=L.timestamp(),n=0,o=0,q=function(a,c,d){if(a>0&&(o=p.round(p.max(a*-1,p.min(0,c))),n!==o))if(n=o,8===t)b.parent()["scroll"+d](o*-1);else{var e={};e[d.toLowerCase()]=o,b.css(e)}},r=function(a){L.timestamp()-m<50||(l=!0,d=c.getMousePosition(a).x,e=c.getMousePosition(a).y)},s=function(a){l&&(j=b.width()-c._stageWidth,k=b.height()-c._stageHeight,f=d/c._stageWidth*j*-1,g=e/c._stageHeight*k*-1,h+=(f-h)/c._options.imagePanSmoothness,i+=(g-i)/c._options.imagePanSmoothness,q(k,i,"Top"),q(j,h,"Left"))};return 8===t&&(b.parent().scrollTop(i*-1).scrollLeft(h*-1),b.css({top:0,left:0})),this.$("stage").off("mousemove",r).on("mousemove",r),this.addTimer("pan"+c._id,s,50,!0),this}},proxy:function(a,b){return"function"!=typeof a?q:(b=b||this,function(){return a.apply(b,L.array(arguments))})},getThemeName:function(){return this.theme.name},removePan:function(){return this.$("stage").off("mousemove"),this.clearTimer("pan"+this._id),this},addElement:function(b){var c=this._dom;return a.each(L.array(arguments),function(a,b){c[b]=L.create("galleria-"+b)}),this},attachKeyboard:function(a){return this._keyboard.attach.apply(this._keyboard,L.array(arguments)),this},detachKeyboard:function(){return this._keyboard.detach.apply(this._keyboard,L.array(arguments)),this},appendChild:function(a,b){return this.$(a).append(this.get(b)||b),this},prependChild:function(a,b){return this.$(a).prepend(this.get(b)||b),this},remove:function(a){return this.$(L.array(arguments).join(",")).remove(),this},append:function(a){var b,c;for(b in a)if(a.hasOwnProperty(b))if(a[b].constructor===Array)for(c=0;a[b][c];c++)this.appendChild(b,a[b][c]);else this.appendChild(b,a[b]);return this},_scaleImage:function(b,c){if(b=b||this._controls.getActive()){var d,e=function(b){a(b.container).children(":first").css({top:p.max(0,L.parseValue(b.image.style.top)),left:p.max(0,L.parseValue(b.image.style.left)),width:L.parseValue(b.image.width),height:L.parseValue(b.image.height)})};return c=a.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},c),this._options.layerFollow&&this._options.imageCrop!==!0?"function"==typeof c.complete?(d=c.complete,c.complete=function(){d.call(b,b),e(b)}):c.complete=e:a(b.container).children(":first").css({top:0,left:0}),b.scale(c),this}},updateCarousel:function(){return this._carousel.update(),this},resize:function(b,c){"function"==typeof b&&(c=b,b=d),b=a.extend({width:0,height:0},b);var e=this,f=this.$("container");return a.each(b,function(a,c){c||(f[a]("auto"),b[a]=e._getWH()[a])}),a.each(b,function(a,b){f[a](b)}),this.rescale(c)},rescale:function(b,e,f){var g=this;"function"==typeof b&&(f=b,b=d);var h=function(){g._stageWidth=b||g.$("stage").width(),g._stageHeight=e||g.$("stage").height(),g._options.swipe?(a.each(g._controls.slides,function(b,c){g._scaleImage(c),a(c.container).css("left",g._stageWidth*b)}),g.$("images").css("width",g._stageWidth*g.getDataLength())):g._scaleImage(),g._options.carousel&&g.updateCarousel();var d=g._controls.frames[g._controls.active];d&&g._controls.frames[g._controls.active].scale({width:g._stageWidth,height:g._stageHeight,iframelimit:g._options.maxVideoSize}),g.trigger(c.RESCALE),"function"==typeof f&&f.call(g)};return h.call(g),this},refreshImage:function(){return this._scaleImage(),this._options.imagePan&&this.addPan(),this},_preload:function(){if(this._options.preload){var a,b,d,e=this.getNext();try{for(b=this._options.preload;b>0;b--)a=new c.Picture,d=this.getData(e),a.preload(this.isFullscreen()&&d.big?d.big:d.image),e=this.getNext(e)}catch(a){}}},show:function(d,e,f){var g=this._options.swipe;if(g||!(this._queue.length>3||d===!1||!this._options.queue&&this._queue.stalled)){if(d=p.max(0,p.min(parseInt(d,10),this.getDataLength()-1)),e="undefined"!=typeof e?!!e:d<this.getIndex(),f=f||!1,!f&&c.History)return void c.History.set(d.toString());if(this.finger&&d!==this._active&&(this.finger.to=-(d*this.finger.width),this.finger.index=d),this._active=d,g){var i=this.getData(d),j=this;if(!i)return;var k=this.isFullscreen()&&i.big?i.big:i.image||i.iframe,l=this._controls.slides[d],m=l.isCached(k),n=this._thumbnails[d],o={cached:m,index:d,rewind:e,imageTarget:l.image,thumbTarget:n.image,galleriaData:i};this.trigger(a.extend(o,{type:c.LOADSTART})),j.$("container").removeClass("videoplay");var q=function(){j._layers[d].innerHTML=j.getData().layer||"",j.trigger(a.extend(o,{type:c.LOADFINISH})),j._playCheck()};j._preload(),b.setTimeout(function(){l.ready&&a(l.image).attr("src")==k?(j.trigger(a.extend(o,{type:c.IMAGE})),q()):(i.iframe&&!i.image&&(l.isIframe=!0),l.load(k,function(b){o.imageTarget=b.image,j._scaleImage(b,q).trigger(a.extend(o,{type:c.IMAGE})),q()}))},100)}else h.push.call(this._queue,{index:d,rewind:e}),this._queue.stalled||this._show();return this}},_show:function(){var e=this,f=this._queue[0],g=this.getData(f.index);if(g){var i=this.isFullscreen()&&g.big?g.big:g.image||g.iframe,j=this._controls.getActive(),k=this._controls.getNext(),l=k.isCached(i),m=this._thumbnails[f.index],n=function(){a(k.image).trigger("mouseup")};e.$("container").toggleClass("iframe",!!g.isIframe).removeClass("videoplay");var o=function(f,g,i,j,k){return function(){var l;N.active=!1,L.toggleQuality(g.image,e._options.imageQuality),e._layers[e._controls.active].innerHTML="",a(i.container).css({zIndex:0,opacity:0}).show(),a(i.container).find("iframe, .galleria-videoicon").remove(),a(e._controls.frames[e._controls.active].container).hide(),a(g.container).css({zIndex:1,left:0,top:0}).show(),e._controls.swap(),e._options.imagePan&&e.addPan(g.image),(f.iframe&&f.image||f.link||e._options.lightbox||e._options.clicknext)&&a(g.image).css({cursor:"pointer"}).on("mouseup",function(g){if(!("number"==typeof g.which&&g.which>1)){if(f.iframe){e.isPlaying()&&e.pause();var h=e._controls.frames[e._controls.active],i=e._stageWidth,j=e._stageHeight;return a(h.container).css({width:i,height:j,opacity:0}).show().animate({opacity:1},200),void b.setTimeout(function(){h.load(f.iframe+(f.video?"&autoplay=1":""),{width:i,height:j},function(a){e.$("container").addClass("videoplay"),a.scale({width:e._stageWidth,height:e._stageHeight,iframelimit:f.video?e._options.maxVideoSize:d})})},100)}return e._options.clicknext&&!c.TOUCH?(e._options.pauseOnInteraction&&e.pause(),void e.next()):f.link?void(e._options.popupLinks?l=b.open(f.link,"_blank"):b.location.href=f.link):void(e._options.lightbox&&e.openLightbox())}}),e._playCheck(),e.trigger({type:c.IMAGE,index:j.index,imageTarget:g.image,thumbTarget:k.image,galleriaData:f}),h.shift.call(e._queue),e._queue.stalled=!1,e._queue.length&&e._show()}}(g,k,j,f,m);this._options.carousel&&this._options.carouselFollow&&this._carousel.follow(f.index),e._preload(),L.show(k.container),k.isIframe=g.iframe&&!g.image,a(e._thumbnails[f.index].container).addClass("active").siblings(".active").removeClass("active"),e.trigger({type:c.LOADSTART,cached:l,index:f.index,rewind:f.rewind,imageTarget:k.image,thumbTarget:m.image,galleriaData:g}),e._queue.stalled=!0,k.load(i,function(b){var h=a(e._layers[1-e._controls.active]).html(g.layer||"").hide();e._scaleImage(b,{complete:function(b){"image"in j&&L.toggleQuality(j.image,!1),L.toggleQuality(b.image,!1),e.removePan(),e.setInfo(f.index),e.setCounter(f.index),g.layer&&(h.show(),(g.iframe&&g.image||g.link||e._options.lightbox||e._options.clicknext)&&h.css("cursor","pointer").off("mouseup").mouseup(n)),g.video&&g.image&&M(b.container);var i=e._options.transition;if(a.each({initial:null===j.image,touch:c.TOUCH,fullscreen:e.isFullscreen()},function(a,b){if(b&&e._options[a+"Transition"]!==d)return i=e._options[a+"Transition"],!1}),i in N.effects==!1)o();else{var k={prev:j.container,next:b.container,rewind:f.rewind,speed:e._options.transitionSpeed||400};N.active=!0,N.init.call(e,i,k,o)}e.trigger({type:c.LOADFINISH,cached:l,index:f.index,rewind:f.rewind,imageTarget:b.image,thumbTarget:e._thumbnails[f.index].image,galleriaData:e.getData(f.index)})}})})}},getNext:function(a){return a="number"==typeof a?a:this.getIndex(),a===this.getDataLength()-1?0:a+1},getPrev:function(a){return a="number"==typeof a?a:this.getIndex(),0===a?this.getDataLength()-1:a-1},next:function(){return this.getDataLength()>1&&this.show(this.getNext(),!1),this},prev:function(){return this.getDataLength()>1&&this.show(this.getPrev(),!0),this},get:function(a){return a in this._dom?this._dom[a]:null},getData:function(a){return a in this._data?this._data[a]:this._data[this._active]},getDataLength:function(){return this._data.length},getIndex:function(){return"number"==typeof this._active&&this._active},getStageHeight:function(){return this._stageHeight},getStageWidth:function(){return this._stageWidth},getOptions:function(a){return"undefined"==typeof a?this._options:this._options[a]},setOptions:function(b,c){return"object"==typeof b?a.extend(this._options,b):this._options[b]=c,this},play:function(a){return this._playing=!0,this._playtime=a||this._playtime,this._playCheck(),this.trigger(c.PLAY),this},pause:function(){return this._playing=!1,this.trigger(c.PAUSE),this},playToggle:function(a){return this._playing?this.pause():this.play(a)},isPlaying:function(){return this._playing},isFullscreen:function(){return this._fullscreen.active},_playCheck:function(){var a=this,b=0,d=20,e=L.timestamp(),f="play"+this._id;if(this._playing){this.clearTimer(f);var g=function(){return b=L.timestamp()-e,b>=a._playtime&&a._playing?(a.clearTimer(f),void a.next()):void(a._playing&&(a.trigger({type:c.PROGRESS,percent:p.ceil(b/a._playtime*100),seconds:p.floor(b/1e3),milliseconds:b}),a.addTimer(f,g,d)))};a.addTimer(f,g,d)}},setPlaytime:function(a){return this._playtime=a,this},setIndex:function(a){return this._active=a,this},setCounter:function(a){if("number"==typeof a?a++:"undefined"==typeof a&&(a=this.getIndex()+1),this.get("current").innerHTML=a,t){var b=this.$("counter"),c=b.css("opacity");1===parseInt(c,10)?L.removeAlpha(b[0]):this.$("counter").css("opacity",c)}return this},setInfo:function(b){var c=this,d=this.getData(b);return a.each(["title","description"],function(a,b){var e=c.$("info-"+b);d[b]?e[d[b].length?"show":"hide"]().html(d[b]):e.empty().hide()}),this},hasInfo:function(a){var b,c="title description".split(" ");for(b=0;c[b];b++)if(this.getData(a)[c[b]])return!0;return!1},jQuery:function(b){var c=this,d=[];a.each(b.split(","),function(b,e){e=a.trim(e),c.get(e)&&d.push(e)});var e=a(c.get(d.shift()));return a.each(d,function(a,b){e=e.add(c.get(b))}),e},$:function(a){return this.jQuery.apply(this,L.array(arguments))}},a.each(x,function(a,b){var d=/_/.test(b)?b.replace(/_/g,""):b;c[b.toUpperCase()]="galleria."+d}),a.extend(c,{IE9:9===t,IE8:8===t,IE7:7===t,IE6:6===t,IE:t,WEBKIT:/webkit/.test(m),CHROME:/chrome/.test(m),SAFARI:/safari/.test(m)&&!/chrome/.test(m),QUIRK:t&&e.compatMode&&"BackCompat"===e.compatMode,MAC:/mac/.test(navigator.platform.toLowerCase()),OPERA:!!b.opera,IPHONE:/iphone/.test(m),IPAD:/ipad/.test(m),ANDROID:/android/.test(m),TOUCH:"ontouchstart"in e&&s}),c.addTheme=function(d){d.name||c.raise("No theme name specified"),(!d.version||parseInt(10*c.version)>parseInt(10*d.version))&&c.raise("This version of Galleria requires "+d.name+" theme version "+parseInt(10*c.version)/10+" or later",!0),"object"!=typeof d.defaults?d.defaults={}:d.defaults=y(d.defaults);var e,f,g=!1;return"string"==typeof d.css?(a("link").each(function(a,b){if(e=new RegExp(d.css),e.test(b.href))return g=!0,K(d),!1}),g||a(function(){var h=0,i=function(){a("script").each(function(a,c){e=new RegExp("galleria\\."+d.name.toLowerCase()+"\\."),f=new RegExp("galleria\\.io\\/theme\\/"+d.name.toLowerCase()+"\\/(\\d*\\.*)?(\\d*\\.*)?(\\d*\\/)?js"),(e.test(c.src)||f.test(c.src))&&(g=c.src.replace(/[^\/]*$/,"")+d.css,b.setTimeout(function(){L.loadCSS(g,"galleria-theme-"+d.name,function(){K(d)})},1))}),g||(h++>5?c.raise("No theme CSS loaded"):b.setTimeout(i,500))};i()})):K(d),d},c.loadTheme=function(d,e){if(!a("script").filter(function(){return a(this).attr("src")==d}).length){var f,g=!1;return a(b).on("load",function(){g||(f=b.setTimeout(function(){g||c.raise("Galleria had problems loading theme at "+d+". Please check theme path or load manually.",!0)},2e4))}),L.loadScript(d,function(){g=!0,b.clearTimeout(f)}),c}},c.get=function(a){return F[a]?F[a]:"number"!=typeof a?F:void c.raise("Gallery index "+a+" not found")},c.configure=function(b,d){var e={};return"string"==typeof b&&d?(e[b]=d,b=e):a.extend(e,b),c.configure.options=e,a.each(c.get(),function(a,b){b.setOptions(e)}),c},c.configure.options={},c.on=function(b,d){if(b){d=d||q;var e=b+d.toString().replace(/\s/g,"")+L.timestamp();return a.each(c.get(),function(a,c){c._binds.push(e),c.bind(b,d)}),c.on.binds.push({type:b,callback:d,hash:e}),c}},c.on.binds=[],c.run=function(b,d){return a.isFunction(d)&&(d={extend:d}),a(b||"#galleria").galleria(d),c},c.addTransition=function(a,b){return N.effects[a]=b,c},c.utils=L,c.log=function(){var c=L.array(arguments);if(!("console"in b&&"log"in b.console))return b.alert(c.join("<br>"));try{return b.console.log.apply(b.console,c)}catch(d){a.each(c,function(){b.console.log(this)})}},c.ready=function(b){return"function"!=typeof b?c:(a.each(E,function(a,c){b.call(c,c._options)}),c.ready.callbacks.push(b),c)},c.ready.callbacks=[],c.raise=function(b,c){var d=c?"Fatal error":"Error",e={color:"#fff",position:"absolute",top:0,left:0,zIndex:1e5},f=function(b){var f='<div style="padding:4px;margin:0 0 2px;background:#'+(c?"811":"222")+';">'+(c?"<strong>"+d+": </strong>":"")+b+"</div>";a.each(F,function(){var a=this.$("errors"),b=this.$("target");a.length||(b.css("position","relative"),a=this.addElement("errors").appendChild("target","errors").$("errors").css(e)),a.append(f)}),F.length||a("<div>").css(a.extend(e,{position:"fixed"})).append(f).appendTo(u().body)};if(j){if(f(b),c)throw new Error(d+": "+b)}else if(c){if(G)return;G=!0,c=!1,f("Gallery could not load.")}},c.version=i,c.getLoadedThemes=function(){return a.map(J,function(a){return a.name})},c.requires=function(a,b){return b=b||"You need to upgrade Galleria to version "+a+" to use one or more components.",c.version<a&&c.raise(b,!0),c},c.Picture=function(b){this.id=b||null,this.image=null,this.container=L.create("galleria-image"),a(this.container).css({overflow:"hidden",position:"relative"}),this.original={width:0,height:0
+},this.ready=!1,this.isIframe=!1},c.Picture.prototype={cache:{},show:function(){L.show(this.image)},hide:function(){L.moveOut(this.image)},clear:function(){this.image=null},isCached:function(a){return!!this.cache[a]},preload:function(b){a(new Image).on("load",function(a,b){return function(){b[a]=a}}(b,this.cache)).attr("src",b)},load:function(d,e,f){if("function"==typeof e&&(f=e,e=null),this.isIframe){var g="if"+(new Date).getTime(),h=this.image=a("<iframe>",{src:d,frameborder:0,id:g,allowfullscreen:!0,css:{visibility:"hidden"}})[0];return e&&a(h).css(e),a(this.container).find("iframe,img").remove(),this.container.appendChild(this.image),a("#"+g).on("load",function(c,d){return function(){b.setTimeout(function(){a(c.image).css("visibility","visible"),"function"==typeof d&&d.call(c,c)},10)}}(this,f)),this.container}this.image=new Image,c.IE8&&a(this.image).css("filter","inherit"),c.IE||c.CHROME||c.SAFARI||a(this.image).css("image-rendering","optimizequality");var i=!1,j=!1,k=a(this.container),m=a(this.image),n=function(){i?l?a(this).attr("src",l):c.raise("Image not found: "+d):(i=!0,b.setTimeout(function(a,b){return function(){a.attr("src",b+(b.indexOf("?")>-1?"&":"?")+L.timestamp())}}(a(this),d),50))},o=function(d,f,g){return function(){var h=function(){a(this).off("load"),d.original=e||{height:this.height,width:this.width},c.HAS3D&&(this.style.MozTransform=this.style.webkitTransform="translate3d(0,0,0)"),k.append(this),d.cache[g]=g,"function"==typeof f&&b.setTimeout(function(){f.call(d,d)},1)};this.width&&this.height?h.call(this):!function(b){L.wait({until:function(){return b.width&&b.height},success:function(){h.call(b)},error:function(){j?c.raise("Could not extract width/height from image: "+b.src+". Traced measures: width:"+b.width+"px, height: "+b.height+"px."):(a(new Image).on("load",o).attr("src",b.src),j=!0)},timeout:100})}(this)}}(this,f,d);return k.find("iframe,img").remove(),m.css("display","block"),L.hide(this.image),a.each("minWidth minHeight maxWidth maxHeight".split(" "),function(a,b){m.css(b,/min/.test(b)?"0":"none")}),m.on("load",o).on("error",n).attr("src",d),this.container},scale:function(b){var e=this;if(b=a.extend({width:0,height:0,min:d,max:d,margin:0,complete:q,position:"center",crop:!1,canvas:!1,iframelimit:d},b),this.isIframe){var f,g,h=b.width,i=b.height;if(b.iframelimit){var j=p.min(b.iframelimit/h,b.iframelimit/i);j<1?(f=h*j,g=i*j,a(this.image).css({top:i/2-g/2,left:h/2-f/2,position:"absolute"})):a(this.image).css({top:0,left:0})}a(this.image).width(f||h).height(g||i).removeAttr("width").removeAttr("height"),a(this.container).width(h).height(i),b.complete.call(e,e);try{this.image.contentWindow&&a(this.image.contentWindow).trigger("resize")}catch(a){}return this.container}if(!this.image)return this.container;var k,l,m,n=a(e.container);return L.wait({until:function(){return k=b.width||n.width()||L.parseValue(n.css("width")),l=b.height||n.height()||L.parseValue(n.css("height")),k&&l},success:function(){var c=(k-2*b.margin)/e.original.width,d=(l-2*b.margin)/e.original.height,f=p.min(c,d),g=p.max(c,d),h={true:g,width:c,height:d,false:f,landscape:e.original.width>e.original.height?g:f,portrait:e.original.width<e.original.height?g:f},i=h[b.crop.toString()],j="";b.max&&(i=p.min(b.max,i)),b.min&&(i=p.max(b.min,i)),a.each(["width","height"],function(b,c){a(e.image)[c](e[c]=e.image[c]=p.round(e.original[c]*i))}),a(e.container).width(k).height(l),b.canvas&&H&&(H.elem.width=e.width,H.elem.height=e.height,j=e.image.src+":"+e.width+"x"+e.height,e.image.src=H.cache[j]||function(a){H.context.drawImage(e.image,0,0,e.original.width*i,e.original.height*i);try{return m=H.elem.toDataURL(),H.length+=m.length,H.cache[a]=m,m}catch(a){return e.image.src}}(j));var n={},o={},q=function(b,c,d){var f=0;if(/\%/.test(b)){var g=parseInt(b,10)/100,h=e.image[c]||a(e.image)[c]();f=p.ceil(h*-1*g+d*g)}else f=L.parseValue(b);return f},r={top:{top:0},left:{left:0},right:{left:"100%"},bottom:{top:"100%"}};a.each(b.position.toLowerCase().split(" "),function(a,b){"center"===b&&(b="50%"),n[a?"top":"left"]=b}),a.each(n,function(b,c){r.hasOwnProperty(c)&&a.extend(o,r[c])}),n=n.top?a.extend(n,o):o,n=a.extend({top:"50%",left:"50%"},n),a(e.image).css({position:"absolute",top:q(n.top,"height",l),left:q(n.left,"width",k)}),e.show(),e.ready=!0,b.complete.call(e,e)},error:function(){c.raise("Could not scale image: "+e.image.src)},timeout:1e3}),this}},a.extend(a.easing,{galleria:function(a,b,c,d,e){return(b/=e/2)<1?d/2*b*b*b+c:d/2*((b-=2)*b*b+2)+c},galleriaIn:function(a,b,c,d,e){return d*(b/=e)*b+c},galleriaOut:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}}),c.Finger=function(){var d=(p.abs,c.HAS3D=function(){var b,c,d=e.createElement("p"),f=["webkit","O","ms","Moz",""],g=0,h="transform";for(u().html.insertBefore(d,null);f[g];g++)c=f[g]?f[g]+"Transform":h,void 0!==d.style[c]&&(d.style[c]="translate3d(1px,1px,1px)",b=a(d).css(f[g]?"-"+f[g].toLowerCase()+"-"+h:h));return u().html.removeChild(d),void 0!==b&&b.length>0&&"none"!==b}()),g=function(){var a="RequestAnimationFrame";return b.requestAnimationFrame||b["webkit"+a]||b["moz"+a]||b["o"+a]||b["ms"+a]||function(a){b.setTimeout(a,1e3/60)}}(),h=function(c,e){if(this.config={start:0,duration:500,onchange:function(){},oncomplete:function(){},easing:function(a,b,c,d,e){return-d*((b=b/e-1)*b*b*b-1)+c}},this.easeout=function(a,b,c,d,e){return d*((b=b/e-1)*b*b*b*b+1)+c},c.children.length){var f=this;a.extend(this.config,e),this.elem=c,this.child=c.children[0],this.to=this.pos=0,this.touching=!1,this.start={},this.index=this.config.start,this.anim=0,this.easing=this.config.easing,d||(this.child.style.position="absolute",this.elem.style.position="relative"),a.each(["ontouchstart","ontouchmove","ontouchend","setup"],function(a,b){f[b]=function(a){return function(){a.apply(f,arguments)}}(f[b])}),this.setX=function(){var a=f.child.style;return d?void(a.MozTransform=a.webkitTransform=a.transform="translate3d("+f.pos+"px,0,0)"):void(a.left=f.pos+"px")},a(c).on("touchstart",this.ontouchstart),a(b).on("resize",this.setup),a(b).on("orientationchange",this.setup),this.setup(),function a(){g(a),f.loop.call(f)}()}};return h.prototype={constructor:h,setup:function(){this.width=a(this.elem).width(),this.length=p.ceil(a(this.child).width()/this.width),0!==this.index&&(this.index=p.max(0,p.min(this.index,this.length-1)),this.pos=this.to=-this.width*this.index)},setPosition:function(a){this.pos=a,this.to=a},ontouchstart:function(a){var b=a.originalEvent.touches;this.start={pageX:b[0].pageX,pageY:b[0].pageY,time:+new Date},this.isScrolling=null,this.touching=!0,this.deltaX=0,f.on("touchmove",this.ontouchmove),f.on("touchend",this.ontouchend)},ontouchmove:function(a){var b=a.originalEvent.touches;b&&b.length>1||a.scale&&1!==a.scale||(this.deltaX=b[0].pageX-this.start.pageX,null===this.isScrolling&&(this.isScrolling=!!(this.isScrolling||p.abs(this.deltaX)<p.abs(b[0].pageY-this.start.pageY))),this.isScrolling||(a.preventDefault(),this.deltaX/=!this.index&&this.deltaX>0||this.index==this.length-1&&this.deltaX<0?p.abs(this.deltaX)/this.width+1.8:1,this.to=this.deltaX-this.index*this.width),a.stopPropagation())},ontouchend:function(a){this.touching=!1;var b=+new Date-this.start.time<250&&p.abs(this.deltaX)>40||p.abs(this.deltaX)>this.width/2,c=!this.index&&this.deltaX>0||this.index==this.length-1&&this.deltaX<0;this.isScrolling||this.show(this.index+(b&&!c?this.deltaX<0?1:-1:0)),f.off("touchmove",this.ontouchmove),f.off("touchend",this.ontouchend)},show:function(a){a!=this.index?this.config.onchange.call(this,a):this.to=-(a*this.width)},moveTo:function(a){a!=this.index&&(this.pos=this.to=-(a*this.width),this.index=a)},loop:function(){var a=this.to-this.pos,b=1;if(this.width&&a&&(b=p.max(.5,p.min(1.5,p.abs(a/this.width)))),this.touching||p.abs(a)<=1)this.pos=this.to,a=0,this.anim&&!this.touching&&this.config.oncomplete(this.index),this.anim=0,this.easing=this.config.easing;else{this.anim||(this.anim={start:this.pos,time:+new Date,distance:a,factor:b,destination:this.to});var c=+new Date-this.anim.time,d=this.config.duration*this.anim.factor;if(c>d||this.anim.destination!=this.to)return this.anim=0,void(this.easing=this.easeout);this.pos=this.easing(null,c,this.anim.start,this.anim.distance,d)}this.setX()}},h}(),a.fn.galleria=function(b){var d=this.selector;return a(this).length?this.each(function(){a.data(this,"galleria")&&(a.data(this,"galleria").destroy(),a(this).find("*").hide()),a.data(this,"galleria",(new c).init(this,b))}):(a(function(){a(d).length?a(d).galleria(b):c.utils.wait({until:function(){return a(d).length},success:function(){a(d).galleria(b)},error:function(){c.raise('Init failed: Galleria could not find the element "'+d+'".')},timeout:5e3})}),this)},"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=c:(b.Galleria=c,"function"==typeof define&&define.amd&&define("galleria",["jquery"],function(){return c}))}(jQuery,this);
\ No newline at end of file
diff --git a/script/galleria/plugins/flickr/flickr-demo.html b/script/galleria/plugins/flickr/flickr-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..1b3ccb200f26302496ea60f56f74d28b96259298
--- /dev/null
+++ b/script/galleria/plugins/flickr/flickr-demo.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Flickr Plugin</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px;}
+
+        </style>
+
+        <!-- load jQuery -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <!-- load flickr plugin -->
+        <script src="galleria.flickr.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Flickr Plugin Demo</h1>
+        <p>Demonstrating a basic gallery example with a Flickr search.</p>
+
+        <!-- Adding gallery images. This is just a container for the dynamic flickr images -->
+
+        <div id="galleria"></div>
+
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+        <a href="#" id="close">cloase</a>
+    </div>
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('../../themes/classic/galleria.classic.min.js');
+
+        // Initialize Galleria
+        Galleria.run('#galleria', {
+
+            // search flickr for "galleria"
+            flickr: 'search:galleria',
+
+            flickrOptions: {
+                // sort by interestingness
+                sort: 'interestingness-desc'
+            }
+        });
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/script/galleria/plugins/flickr/flickr-loader.gif b/script/galleria/plugins/flickr/flickr-loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..beaacacc93292a68ac6f21016d8affad0f9cca16
Binary files /dev/null and b/script/galleria/plugins/flickr/flickr-loader.gif differ
diff --git a/script/galleria/plugins/flickr/galleria.flickr.js b/script/galleria/plugins/flickr/galleria.flickr.js
new file mode 100644
index 0000000000000000000000000000000000000000..9487b738a7e3231ee38334c07e79c09ff8059b90
--- /dev/null
+++ b/script/galleria/plugins/flickr/galleria.flickr.js
@@ -0,0 +1,384 @@
+/**
+ * Galleria Flickr Plugin 2016-09-03
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.requires(1.25, 'The Flickr Plugin requires Galleria version 1.2.5 or later.');
+
+// The script path
+var PATH = Galleria.utils.getScriptPath();
+
+/**
+
+    @class
+    @constructor
+
+    @example var flickr = new Galleria.Flickr();
+
+    @author http://galleria.io
+
+    @requires jQuery
+    @requires Galleria
+
+    @param {String} [api_key] Flickr API key to be used, defaults to the Galleria key
+
+    @returns Instance
+*/
+
+Galleria.Flickr = function( api_key ) {
+
+    this.api_key = api_key || '2a2ce06c15780ebeb0b706650fc890b2';
+
+    this.options = {
+        max: 30,                       // photos to return
+        imageSize: 'medium',           // photo size ( thumb,small,medium,big,original )
+        thumbSize: 'thumb',            // thumbnail size ( thumb,small,medium,big,original )
+        sort: 'interestingness-desc',  // sort option ( date-posted-asc, date-posted-desc, date-taken-asc, date-taken-desc, interestingness-desc, interestingness-asc, relevance )
+        description: false,            // set this to true to get description as caption
+        complete: function(){},        // callback to be called inside the Galleria.prototype.load
+        backlink: false                // set this to true if you want to pass a link back to the original image
+    };
+};
+
+Galleria.Flickr.prototype = {
+
+    // bring back the constructor reference
+
+    constructor: Galleria.Flickr,
+
+    /**
+        Search for anything at Flickr
+
+        @param {String} phrase The string to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    search: function( phrase, callback ) {
+        return this._find({
+            text: phrase
+        }, callback );
+    },
+
+    /**
+        Search for anything at Flickr by tag
+
+        @param {String} tag The tag(s) to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    tags: function( tag, callback ) {
+        return this._find({
+            tags: tag
+        }, callback);
+    },
+
+    /**
+        Get a user's public photos
+
+        @param {String} username The username as shown in the URL to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    user: function( username, callback ) {
+        return this._call({
+            method: 'flickr.urls.lookupUser',
+            url: 'flickr.com/photos/' + username
+        }, function( data ) {
+            this._find({
+                user_id: data.user.id,
+                method: 'flickr.people.getPublicPhotos'
+            }, callback);
+        });
+    },
+
+    /**
+        Get photos from a photoset by ID
+
+        @param {String|Number} photoset_id The photoset id to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    set: function( photoset_id, callback ) {
+        return this._find({
+            photoset_id: photoset_id,
+            method: 'flickr.photosets.getPhotos'
+        }, callback);
+    },
+
+    /**
+        Get photos from a gallery by ID
+
+        @param {String|Number} gallery_id The gallery id to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    gallery: function( gallery_id, callback ) {
+        return this._find({
+            gallery_id: gallery_id,
+            method: 'flickr.galleries.getPhotos'
+        }, callback);
+    },
+
+    /**
+        Search groups and fetch photos from the first group found
+        Useful if you know the exact name of a group and want to show the groups photos.
+
+        @param {String} group The group name to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    groupsearch: function( group, callback ) {
+        return this._call({
+            text: group,
+            method: 'flickr.groups.search'
+        }, function( data ) {
+            this.group( data.groups.group[0].nsid, callback );
+        });
+    },
+
+    /**
+        Get photos from a group by ID
+
+        @param {String} group_id The group id to fetch
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    group: function ( group_id, callback ) {
+        return this._find({
+            group_id: group_id,
+            method: 'flickr.groups.pools.getPhotos'
+        }, callback );
+    },
+
+    /**
+        Set flickr options
+
+        @param {Object} options The options object to blend
+
+        @returns Instance
+    */
+
+    setOptions: function( options ) {
+        $.extend(this.options, options);
+        return this;
+    },
+
+
+    // call Flickr and raise errors
+
+    _call: function( params, callback ) {
+
+        var url = 'https://api.flickr.com/services/rest/?';
+
+        var scope = this;
+
+        params = $.extend({
+            format : 'json',
+            jsoncallback : '?',
+            api_key: this.api_key
+        }, params );
+
+        $.each(params, function( key, value ) {
+            url += '&' + key + '=' + value;
+        });
+
+        $.getJSON(url, function(data) {
+            if ( data.stat === 'ok' ) {
+                callback.call(scope, data);
+            } else {
+                Galleria.raise( data.code.toString() + ' ' + data.stat + ': ' + data.message, true );
+            }
+        });
+        return scope;
+    },
+
+
+    // "hidden" way of getting a big image (~1024) from flickr
+
+    _getBig: function( photo ) {
+
+        if ( photo.url_l ) {
+            return photo.url_l;
+        } else if ( parseInt( photo.width_o, 10 ) > 1280 ) {
+
+            return 'https://farm'+photo.farm + '.static.flickr.com/'+photo.server +
+                '/' + photo.id + '_' + photo.secret + '_b.jpg';
+        }
+
+        return photo.url_o || photo.url_z || photo.url_m;
+
+    },
+
+
+    // get image size by option name
+
+    _getSize: function( photo, size ) {
+
+        var img;
+
+        switch(size) {
+
+            case 'thumb':
+                img = photo.url_t;
+                break;
+
+            case 'small':
+                img = photo.url_s;
+                break;
+
+            case 'big':
+                img = this._getBig( photo );
+                break;
+
+            case 'original':
+                img = photo.url_o ? photo.url_o : this._getBig( photo );
+                break;
+
+            default:
+                img = photo.url_z || photo.url_m;
+                break;
+        }
+        return img;
+    },
+
+
+    // ask flickr for photos, parse the result and call the callback with the galleria-ready data array
+
+    _find: function( params, callback ) {
+
+        params = $.extend({
+            method: 'flickr.photos.search',
+            extras: 'url_t,url_m,url_o,url_s,url_l,url_z,description',
+            sort: this.options.sort,
+            per_page: Math.min( this.options.max, 500 )
+        }, params );
+
+        return this._call( params, function(data) {
+
+            var gallery = [],
+                photos = data.photos ? data.photos.photo : data.photoset.photo,
+                len = photos.length,
+                photo,
+                i;
+
+            for ( i=0; i<len; i++ ) {
+
+                photo = photos[i];
+
+                gallery.push({
+                    thumb: this._getSize( photo, this.options.thumbSize ),
+                    image: this._getSize( photo, this.options.imageSize ),
+                    big: this._getBig( photo ),
+                    title: photos[i].title,
+                    description: this.options.description && photos[i].description ? photos[i].description._content : '',
+                    link: this.options.backlink ? 'https://flickr.com/photos/' + photo.owner + '/' + photo.id : ''
+                });
+            }
+            callback.call( this, gallery );
+        });
+    }
+};
+
+
+/**
+    Galleria modifications
+    We fake-extend the load prototype to make Flickr integration as simple as possible
+*/
+
+
+// save the old prototype in a local variable
+
+var load = Galleria.prototype.load;
+
+
+// fake-extend the load prototype using the flickr data
+
+Galleria.prototype.load = function() {
+
+    // pass if no data is provided or flickr option not found
+    if ( arguments.length || typeof this._options.flickr !== 'string' ) {
+        load.apply( this, Galleria.utils.array( arguments ) );
+        return;
+    }
+
+    // define some local vars
+    var self = this,
+        args = Galleria.utils.array( arguments ),
+        flickr = this._options.flickr.split(':'),
+        f,
+        opts = $.extend({}, self._options.flickrOptions),
+        loader = typeof opts.loader !== 'undefined' ?
+            opts.loader : $('<div>').css({
+                width: 48,
+                height: 48,
+                opacity: 0.7,
+                background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%'
+            });
+
+    if ( flickr.length ) {
+
+        // validate the method
+        if ( typeof Galleria.Flickr.prototype[ flickr[0] ] !== 'function' ) {
+            Galleria.raise( flickr[0] + ' method not found in Flickr plugin' );
+            return load.apply( this, args );
+        }
+
+        // validate the argument
+        if ( !flickr[1] ) {
+            Galleria.raise( 'No flickr argument found' );
+            return load.apply( this, args );
+        }
+
+        // apply the preloader
+        window.setTimeout(function() {
+            self.$( 'target' ).append( loader );
+        },100);
+
+        // create the instance
+        f = new Galleria.Flickr();
+
+        // apply Flickr options
+        if ( typeof self._options.flickrOptions === 'object' ) {
+            f.setOptions( self._options.flickrOptions );
+        }
+
+        // call the flickr method and trigger the DATA event
+        f[ flickr[0] ]( flickr[1], function( data ) {
+
+            self._data = data;
+            loader.remove();
+            self.trigger( Galleria.DATA );
+            f.options.complete.call(f, data);
+
+        });
+    } else {
+
+        // if flickr array not found, pass
+        load.apply( this, args );
+    }
+};
+
+}( jQuery ) );
\ No newline at end of file
diff --git a/script/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/script/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..2eb9b36366cc1cf1fb1759cdc0b46736e7c5582e
--- /dev/null
+++ b/script/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a){Galleria.requires(1.25,"The Flickr Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Flickr=function(a){this.api_key=a||"2a2ce06c15780ebeb0b706650fc890b2",this.options={max:30,imageSize:"medium",thumbSize:"thumb",sort:"interestingness-desc",description:!1,complete:function(){},backlink:!1}},Galleria.Flickr.prototype={constructor:Galleria.Flickr,search:function(a,b){return this._find({text:a},b)},tags:function(a,b){return this._find({tags:a},b)},user:function(a,b){return this._call({method:"flickr.urls.lookupUser",url:"flickr.com/photos/"+a},function(a){this._find({user_id:a.user.id,method:"flickr.people.getPublicPhotos"},b)})},set:function(a,b){return this._find({photoset_id:a,method:"flickr.photosets.getPhotos"},b)},gallery:function(a,b){return this._find({gallery_id:a,method:"flickr.galleries.getPhotos"},b)},groupsearch:function(a,b){return this._call({text:a,method:"flickr.groups.search"},function(a){this.group(a.groups.group[0].nsid,b)})},group:function(a,b){return this._find({group_id:a,method:"flickr.groups.pools.getPhotos"},b)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c){var d="https://api.flickr.com/services/rest/?",e=this;return b=a.extend({format:"json",jsoncallback:"?",api_key:this.api_key},b),a.each(b,function(a,b){d+="&"+a+"="+b}),a.getJSON(d,function(a){"ok"===a.stat?c.call(e,a):Galleria.raise(a.code.toString()+" "+a.stat+": "+a.message,!0)}),e},_getBig:function(a){return a.url_l?a.url_l:parseInt(a.width_o,10)>1280?"https://farm"+a.farm+".static.flickr.com/"+a.server+"/"+a.id+"_"+a.secret+"_b.jpg":a.url_o||a.url_z||a.url_m},_getSize:function(a,b){var c;switch(b){case"thumb":c=a.url_t;break;case"small":c=a.url_s;break;case"big":c=this._getBig(a);break;case"original":c=a.url_o?a.url_o:this._getBig(a);break;default:c=a.url_z||a.url_m}return c},_find:function(b,c){return b=a.extend({method:"flickr.photos.search",extras:"url_t,url_m,url_o,url_s,url_l,url_z,description",sort:this.options.sort,per_page:Math.min(this.options.max,500)},b),this._call(b,function(a){var b,d,e=[],f=a.photos?a.photos.photo:a.photoset.photo,g=f.length;for(d=0;d<g;d++)b=f[d],e.push({thumb:this._getSize(b,this.options.thumbSize),image:this._getSize(b,this.options.imageSize),big:this._getBig(b),title:f[d].title,description:this.options.description&&f[d].description?f[d].description._content:"",link:this.options.backlink?"https://flickr.com/photos/"+b.owner+"/"+b.id:""});c.call(this,e)})}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.flickr)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.flickr.split(":"),h=a.extend({},e._options.flickrOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Flickr.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Flickr plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No flickr argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Flickr,"object"==typeof e._options.flickrOptions&&d.setOptions(e._options.flickrOptions),d[g[0]](g[1],function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)})}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/script/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/script/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..2413313da9d3c55f3afdf3e68e2441cc8bab7fe8
--- /dev/null
+++ b/script/galleria/plugins/flickr/galleria.flickr.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a){Galleria.requires(1.25,"The Flickr Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Flickr=function(a){this.api_key=a||"2a2ce06c15780ebeb0b706650fc890b2",this.options={max:30,imageSize:"medium",thumbSize:"thumb",sort:"interestingness-desc",description:!1,complete:function(){},backlink:!1}},Galleria.Flickr.prototype={constructor:Galleria.Flickr,search:function(a,b){return this._find({text:a},b)},tags:function(a,b){return this._find({tags:a},b)},user:function(a,b){return this._call({method:"flickr.urls.lookupUser",url:"flickr.com/photos/"+a},function(a){this._find({user_id:a.user.id,method:"flickr.people.getPublicPhotos"},b)})},set:function(a,b){return this._find({photoset_id:a,method:"flickr.photosets.getPhotos"},b)},gallery:function(a,b){return this._find({gallery_id:a,method:"flickr.galleries.getPhotos"},b)},groupsearch:function(a,b){return this._call({text:a,method:"flickr.groups.search"},function(a){this.group(a.groups.group[0].nsid,b)})},group:function(a,b){return this._find({group_id:a,method:"flickr.groups.pools.getPhotos"},b)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c){var d="https://api.flickr.com/services/rest/?",e=this;return b=a.extend({format:"json",jsoncallback:"?",api_key:this.api_key},b),a.each(b,function(a,b){d+="&"+a+"="+b}),a.getJSON(d,function(a){"ok"===a.stat?c.call(e,a):Galleria.raise(a.code.toString()+" "+a.stat+": "+a.message,!0)}),e},_getBig:function(a){return a.url_l?a.url_l:parseInt(a.width_o,10)>1280?"https://farm"+a.farm+".static.flickr.com/"+a.server+"/"+a.id+"_"+a.secret+"_b.jpg":a.url_o||a.url_z||a.url_m},_getSize:function(a,b){var c;switch(b){case"thumb":c=a.url_t;break;case"small":c=a.url_s;break;case"big":c=this._getBig(a);break;case"original":c=a.url_o?a.url_o:this._getBig(a);break;default:c=a.url_z||a.url_m}return c},_find:function(b,c){return b=a.extend({method:"flickr.photos.search",extras:"url_t,url_m,url_o,url_s,url_l,url_z,description",sort:this.options.sort,per_page:Math.min(this.options.max,500)},b),this._call(b,function(a){var b,d,e=[],f=a.photos?a.photos.photo:a.photoset.photo,g=f.length;for(d=0;d<g;d++)b=f[d],e.push({thumb:this._getSize(b,this.options.thumbSize),image:this._getSize(b,this.options.imageSize),big:this._getBig(b),title:f[d].title,description:this.options.description&&f[d].description?f[d].description._content:"",link:this.options.backlink?"https://flickr.com/photos/"+b.owner+"/"+b.id:""});c.call(this,e)})}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.flickr)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.flickr.split(":"),h=a.extend({},e._options.flickrOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Flickr.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Flickr plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No flickr argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Flickr,"object"==typeof e._options.flickrOptions&&d.setOptions(e._options.flickrOptions),d[g[0]](g[1],function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)})}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/script/galleria/plugins/flickr/galleria.flickr.min.js b/script/galleria/plugins/flickr/galleria.flickr.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..4b79ca35be47830b88aa9b0b77ae8de76a33a8ed
--- /dev/null
+++ b/script/galleria/plugins/flickr/galleria.flickr.min.js
@@ -0,0 +1 @@
+(function($){Galleria.requires(1.25,"The Flickr Plugin requires Galleria version 1.2.5 or later.");var PATH=Galleria.utils.getScriptPath();Galleria.Flickr=function(api_key){this.api_key=api_key||"2a2ce06c15780ebeb0b706650fc890b2";this.options={max:30,imageSize:"medium",thumbSize:"thumb",sort:"interestingness-desc",description:false,complete:function(){},backlink:false}};Galleria.Flickr.prototype={constructor:Galleria.Flickr,search:function(phrase,callback){return this._find({text:phrase},callback)},tags:function(tag,callback){return this._find({tags:tag},callback)},user:function(username,callback){return this._call({method:"flickr.urls.lookupUser",url:"flickr.com/photos/"+username},function(data){this._find({user_id:data.user.id,method:"flickr.people.getPublicPhotos"},callback)})},set:function(photoset_id,callback){return this._find({photoset_id:photoset_id,method:"flickr.photosets.getPhotos"},callback)},gallery:function(gallery_id,callback){return this._find({gallery_id:gallery_id,method:"flickr.galleries.getPhotos"},callback)},groupsearch:function(group,callback){return this._call({text:group,method:"flickr.groups.search"},function(data){this.group(data.groups.group[0].nsid,callback)})},group:function(group_id,callback){return this._find({group_id:group_id,method:"flickr.groups.pools.getPhotos"},callback)},setOptions:function(options){$.extend(this.options,options);return this},_call:function(params,callback){var url="https://api.flickr.com/services/rest/?";var scope=this;params=$.extend({format:"json",jsoncallback:"?",api_key:this.api_key},params);$.each(params,function(key,value){url+="&"+key+"="+value});$.getJSON(url,function(data){if(data.stat==="ok"){callback.call(scope,data)}else{Galleria.raise(data.code.toString()+" "+data.stat+": "+data.message,true)}});return scope},_getBig:function(photo){if(photo.url_l){return photo.url_l}else if(parseInt(photo.width_o,10)>1280){return"https://farm"+photo.farm+".static.flickr.com/"+photo.server+"/"+photo.id+"_"+photo.secret+"_b.jpg"}return photo.url_o||photo.url_z||photo.url_m},_getSize:function(photo,size){var img;switch(size){case"thumb":img=photo.url_t;break;case"small":img=photo.url_s;break;case"big":img=this._getBig(photo);break;case"original":img=photo.url_o?photo.url_o:this._getBig(photo);break;default:img=photo.url_z||photo.url_m;break}return img},_find:function(params,callback){params=$.extend({method:"flickr.photos.search",extras:"url_t,url_m,url_o,url_s,url_l,url_z,description",sort:this.options.sort,per_page:Math.min(this.options.max,500)},params);return this._call(params,function(data){var gallery=[],photos=data.photos?data.photos.photo:data.photoset.photo,len=photos.length,photo,i;for(i=0;i<len;i++){photo=photos[i];gallery.push({thumb:this._getSize(photo,this.options.thumbSize),image:this._getSize(photo,this.options.imageSize),big:this._getBig(photo),title:photos[i].title,description:this.options.description&&photos[i].description?photos[i].description._content:"",link:this.options.backlink?"https://flickr.com/photos/"+photo.owner+"/"+photo.id:""})}callback.call(this,gallery)})}};var load=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||typeof this._options.flickr!=="string"){load.apply(this,Galleria.utils.array(arguments));return}var self=this,args=Galleria.utils.array(arguments),flickr=this._options.flickr.split(":"),f,opts=$.extend({},self._options.flickrOptions),loader=typeof opts.loader!=="undefined"?opts.loader:$("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+PATH+"loader.gif) no-repeat 50% 50%"});if(flickr.length){if(typeof Galleria.Flickr.prototype[flickr[0]]!=="function"){Galleria.raise(flickr[0]+" method not found in Flickr plugin");return load.apply(this,args)}if(!flickr[1]){Galleria.raise("No flickr argument found");return load.apply(this,args)}window.setTimeout(function(){self.$("target").append(loader)},100);f=new Galleria.Flickr;if(typeof self._options.flickrOptions==="object"){f.setOptions(self._options.flickrOptions)}f[flickr[0]](flickr[1],function(data){self._data=data;loader.remove();self.trigger(Galleria.DATA);f.options.complete.call(f,data)})}else{load.apply(this,args)}}})(jQuery);
\ No newline at end of file
diff --git a/script/galleria/plugins/flickr/loader.gif b/script/galleria/plugins/flickr/loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750
Binary files /dev/null and b/script/galleria/plugins/flickr/loader.gif differ
diff --git a/script/galleria/plugins/history/galleria.history.js b/script/galleria/plugins/history/galleria.history.js
new file mode 100644
index 0000000000000000000000000000000000000000..45688c8216c719b739616f8d0b6b3bb54325f262
--- /dev/null
+++ b/script/galleria/plugins/history/galleria.history.js
@@ -0,0 +1,147 @@
+/**
+ * Galleria History Plugin 2016-09-03
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function( $, window ) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.requires(1.25, 'The History Plugin requires Galleria version 1.2.5 or later.');
+
+Galleria.History = (function() {
+
+    var onloads = [],
+
+        init = false,
+
+        loc = window.location,
+
+        doc = window.document,
+
+        ie = Galleria.IE,
+
+        support = 'onhashchange' in window && ( doc.mode === undefined || doc.mode > 7 ),
+
+        iframe,
+
+        get = function( winloc ) {
+            if( iframe && !support && Galleria.IE ) {
+                winloc = winloc || iframe.location;
+            }  else {
+                winloc = loc;
+            }
+            return parseInt( winloc.hash.substr(2), 10 );
+        },
+
+        saved = get( loc ),
+
+        callbacks = [],
+
+        onchange = function() {
+            $.each( callbacks, function( i, fn ) {
+                fn.call( window, get() );
+            });
+        },
+
+        ready = function() {
+            $.each( onloads, function(i, fn) {
+                fn();
+            });
+
+            init = true;
+        },
+
+        setHash = function( val ) {
+            return '/' + val;
+        };
+
+    // always remove support if IE < 8
+    if ( support && ie < 8 ) {
+        support = false;
+    }
+
+    if ( !support ) {
+
+        $(function() {
+
+            var interval = window.setInterval(function() {
+
+                var hash = get();
+
+                if ( !isNaN( hash ) && hash != saved ) {
+                    saved = hash;
+                    loc.hash = setHash( hash );
+                    onchange();
+                }
+
+            }, 50);
+
+            if ( ie ) {
+
+                $('<iframe tabindex="-1" title="empty">').hide().attr( 'src', 'about:blank' ).one('load', function() {
+
+                    iframe = this.contentWindow;
+
+                    ready();
+
+                }).insertAfter(doc.body);
+
+            } else {
+                ready();
+            }
+        });
+    } else {
+        ready();
+    }
+
+    return {
+
+        change: function( fn ) {
+
+            callbacks.push( fn );
+
+            if( support ) {
+                window.onhashchange = onchange;
+            }
+        },
+
+        set: function( val ) {
+
+            if ( isNaN( val ) ) {
+                return;
+            }
+
+            if ( !support && ie ) {
+
+                this.ready(function() {
+
+                    var idoc = iframe.document;
+                    idoc.open();
+                    idoc.close();
+
+                    iframe.location.hash = setHash( val );
+
+                });
+            }
+
+            loc.hash = setHash( val );
+        },
+
+        ready: function(fn) {
+            if (!init) {
+                onloads.push(fn);
+            } else {
+                fn();
+            }
+        }
+    };
+}());
+
+}( jQuery, this ));
+
diff --git a/script/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/script/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..58c5ac07b3f408dd22f4ff250d70ba3e6e0c4176
--- /dev/null
+++ b/script/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a,b){Galleria.requires(1.25,"The History Plugin requires Galleria version 1.2.5 or later."),Galleria.History=function(){var c,d=[],e=!1,f=b.location,g=b.document,h=Galleria.IE,i="onhashchange"in b&&(void 0===g.mode||g.mode>7),j=function(a){return a=c&&!i&&Galleria.IE?a||c.location:f,parseInt(a.hash.substr(2),10)},k=j(f),l=[],m=function(){a.each(l,function(a,c){c.call(b,j())})},n=function(){a.each(d,function(a,b){b()}),e=!0},o=function(a){return"/"+a};return i&&h<8&&(i=!1),i?n():a(function(){b.setInterval(function(){var a=j();isNaN(a)||a==k||(k=a,f.hash=o(a),m())},50);h?a('<iframe tabindex="-1" title="empty">').hide().attr("src","about:blank").one("load",function(){c=this.contentWindow,n()}).insertAfter(g.body):n()}),{change:function(a){l.push(a),i&&(b.onhashchange=m)},set:function(a){isNaN(a)||(!i&&h&&this.ready(function(){var b=c.document;b.open(),b.close(),c.location.hash=o(a)}),f.hash=o(a))},ready:function(a){e?a():d.push(a)}}}()}(jQuery,this);
\ No newline at end of file
diff --git a/script/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/script/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..e727328b6edd5264ac1759f41da8cbb1ce8ce80a
--- /dev/null
+++ b/script/galleria/plugins/history/galleria.history.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a,b){Galleria.requires(1.25,"The History Plugin requires Galleria version 1.2.5 or later."),Galleria.History=function(){var c,d=[],e=!1,f=b.location,g=b.document,h=Galleria.IE,i="onhashchange"in b&&(void 0===g.mode||g.mode>7),j=function(a){return a=c&&!i&&Galleria.IE?a||c.location:f,parseInt(a.hash.substr(2),10)},k=j(f),l=[],m=function(){a.each(l,function(a,c){c.call(b,j())})},n=function(){a.each(d,function(a,b){b()}),e=!0},o=function(a){return"/"+a};return i&&h<8&&(i=!1),i?n():a(function(){b.setInterval(function(){var a=j();isNaN(a)||a==k||(k=a,f.hash=o(a),m())},50);h?a('<iframe tabindex="-1" title="empty">').hide().attr("src","about:blank").one("load",function(){c=this.contentWindow,n()}).insertAfter(g.body):n()}),{change:function(a){l.push(a),i&&(b.onhashchange=m)},set:function(a){isNaN(a)||(!i&&h&&this.ready(function(){var b=c.document;b.open(),b.close(),c.location.hash=o(a)}),f.hash=o(a))},ready:function(a){e?a():d.push(a)}}}()}(jQuery,this);
\ No newline at end of file
diff --git a/script/galleria/plugins/history/galleria.history.min.js b/script/galleria/plugins/history/galleria.history.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..13e87be547eee86f6acca3ca6c8e469d18b35d8b
--- /dev/null
+++ b/script/galleria/plugins/history/galleria.history.min.js
@@ -0,0 +1 @@
+(function($,window){Galleria.requires(1.25,"The History Plugin requires Galleria version 1.2.5 or later.");Galleria.History=function(){var onloads=[],init=false,loc=window.location,doc=window.document,ie=Galleria.IE,support="onhashchange"in window&&(doc.mode===undefined||doc.mode>7),iframe,get=function(winloc){if(iframe&&!support&&Galleria.IE){winloc=winloc||iframe.location}else{winloc=loc}return parseInt(winloc.hash.substr(2),10)},saved=get(loc),callbacks=[],onchange=function(){$.each(callbacks,function(i,fn){fn.call(window,get())})},ready=function(){$.each(onloads,function(i,fn){fn()});init=true},setHash=function(val){return"/"+val};if(support&&ie<8){support=false}if(!support){$(function(){var interval=window.setInterval(function(){var hash=get();if(!isNaN(hash)&&hash!=saved){saved=hash;loc.hash=setHash(hash);onchange()}},50);if(ie){$('<iframe tabindex="-1" title="empty">').hide().attr("src","about:blank").one("load",function(){iframe=this.contentWindow;ready()}).insertAfter(doc.body)}else{ready()}})}else{ready()}return{change:function(fn){callbacks.push(fn);if(support){window.onhashchange=onchange}},set:function(val){if(isNaN(val)){return}if(!support&&ie){this.ready(function(){var idoc=iframe.document;idoc.open();idoc.close();iframe.location.hash=setHash(val)})}loc.hash=setHash(val)},ready:function(fn){if(!init){onloads.push(fn)}else{fn()}}}}()})(jQuery,this);
\ No newline at end of file
diff --git a/script/galleria/plugins/history/history-demo.html b/script/galleria/plugins/history/history-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..5819b8e7b7c3fbf8702b5e6c2896312288187140
--- /dev/null
+++ b/script/galleria/plugins/history/history-demo.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria History Plugin</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+
+        <!-- load jQuery -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <!-- load the History plugin, no need for further scripting -->
+        <script src="galleria.history.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria History Plugin</h1>
+        <p>Demonstrating a basic history example. Supports most browsers, including FF 3.0+ and IE 7+</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Locomotives-Roundhouse2.jpg/800px-Locomotives-Roundhouse2.jpg">
+                <img title="Locomotives Roundhouse"
+                     alt="Steam locomotives of the Chicago &amp; North Western Railway."
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Locomotives-Roundhouse2.jpg/100px-Locomotives-Roundhouse2.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Icebergs_in_the_High_Arctic_-_20050907.jpg/1000px-Icebergs_in_the_High_Arctic_-_20050907.jpg">
+                <img title="Icebergs in the High Arctic"
+                     alt="”The debris loading isn't particularly extensive, but the color is usual.”"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Icebergs_in_the_High_Arctic_-_20050907.jpg/100px-Icebergs_in_the_High_Arctic_-_20050907.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg/1000px-Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg">
+                <img title="Araña"
+                     alt="Xysticus cristatus, A Estrada, Galicia, Spain"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg/100px-Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg/1000px-9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg">
+                <img title="Museo storia naturale"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg/100px-9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg/1000px-Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg">
+                <img title="Grjótagjá caves in summer 2009"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg/100px-Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/9/90/20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg/1000px-20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg">
+                <img title="Thermes"
+                     alt="Xanthi hot-spa springs, Xanthi Prefecture, Greece"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/90/20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg/100px-20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Polish_Army_Ko%C5%82obrzeg_077.JPG/1024px-Polish_Army_Ko%C5%82obrzeg_077.JPG">
+                <img title="Polish Army Kołobrzeg"
+                     alt="A display of the Polish Army. Both the soldier, and the vehicle belong to the 7th Pomeranian Coastal Defence Brigade, a part of the Szczecin-based 12th Mechanized Division ”Bolesław Krzywousty”"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Polish_Army_Ko%C5%82obrzeg_077.JPG/100px-Polish_Army_Ko%C5%82obrzeg_077.JPG">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/20100213_Zlatograd_Bulgaria_3.jpg/1024px-20100213_Zlatograd_Bulgaria_3.jpg">
+                <img title="Zlatograd Bulgaria"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/20100213_Zlatograd_Bulgaria_3.jpg/100px-20100213_Zlatograd_Bulgaria_3.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg/1024px-FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg">
+                <img title="09-28-2001 in New York City"
+                     alt="New York, NY, September 28, 2001 -- Debris on surrounding roofs at the site of the World Trade Center. Photo by Andrea Booher/ FEMA News Photo"
+                     src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg/100px-FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg">
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Antennae%2C_Hubble_images.jpg/1024px-Antennae%2C_Hubble_images.jpg">
+                <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Antennae%2C_Hubble_images.jpg/100px-Antennae%2C_Hubble_images.jpg">
+            </a>
+        </div>
+
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('../../themes/classic/galleria.classic.min.js');
+
+        // Initialize Galleria
+        Galleria.run('#galleria');
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/script/galleria/plugins/picasa/galleria.picasa.js b/script/galleria/plugins/picasa/galleria.picasa.js
new file mode 100644
index 0000000000000000000000000000000000000000..8cf1ead15abfe8e16a0efcb51cdd20a4654d28c0
--- /dev/null
+++ b/script/galleria/plugins/picasa/galleria.picasa.js
@@ -0,0 +1,321 @@
+/**
+ * Galleria Picasa Plugin 2016-09-03
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.requires(1.25, 'The Picasa Plugin requires Galleria version 1.2.5 or later.');
+
+// The script path
+var PATH = Galleria.utils.getScriptPath();
+
+/**
+
+    @class
+    @constructor
+
+    @example var picasa = new Galleria.Picasa();
+
+    @author http://wib.io
+
+    @requires jQuery
+    @requires Galleria
+
+    @returns Instance
+*/
+
+Galleria.Picasa = function() {
+
+    this.options = {
+        max: 30,                       // photos to return
+        imageSize: 'medium',           // photo size ( thumb,small,medium,big,original ) or a number
+        thumbSize: 'thumb',            // thumbnail size ( thumb,small,medium,big,original ) or a number
+        complete: function(){}         // callback to be called inside the Galleria.prototype.load
+    };
+
+};
+
+Galleria.Picasa.prototype = {
+
+    // bring back the constructor reference
+
+    constructor: Galleria.Picasa,
+
+    /**
+        Search for anything at Picasa
+
+        @param {String} phrase The string to search for
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    search: function( phrase, callback ) {
+        return this._call( 'search', 'all', {
+            q: phrase
+        }, callback );
+    },
+
+    /**
+        Get a user's public photos
+
+        @param {String} username The username to fetch photos from
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    user: function( username, callback ) {
+        return this._call( 'user', 'user/' + username, callback );
+    },
+
+    /**
+        Get photos from an album
+
+        @param {String} username The username that owns the album
+        @param {String} album The album ID
+        @param {Function} [callback] The callback to be called when the data is ready
+
+        @returns Instance
+    */
+
+    useralbum: function( username, album, callback ) {
+        return this._call( 'useralbum', 'user/' + username + '/album/' + album, callback );
+    },
+
+    /**
+        Set picasa options
+
+        @param {Object} options The options object to blend
+
+        @returns Instance
+    */
+
+    setOptions: function( options ) {
+        $.extend(this.options, options);
+        return this;
+    },
+
+
+    // call Picasa
+
+    _call: function( type, url, params, callback ) {
+
+        url = 'https://picasaweb.google.com/data/feed/api/' + url + '?';
+
+        if (typeof params == 'function') {
+            callback = params;
+            params = {};
+        }
+
+        var self = this;
+
+        params = $.extend({
+            'kind': 'photo',
+            'access': 'public',
+            'max-results': this.options.max,
+            'thumbsize': this._getSizes().join(','),
+            'alt': 'json-in-script',
+            'callback': '?'
+        }, params );
+
+        $.each(params, function( key, value ) {
+            url += '&' + key + '=' + value;
+        });
+
+        // since Picasa throws 404 when the call is malformed, we must set a timeout here:
+
+        var data = false;
+
+        Galleria.utils.wait({
+            until: function() {
+                return data;
+            },
+            success: function() {
+                self._parse.call( self, data.feed.entry, callback );
+            },
+            error: function() {
+                var msg = '';
+                if ( type == 'user' ) {
+                    msg = 'user not found.';
+                } else if ( type == 'useralbum' ) {
+                    msg = 'album or user not found.';
+                }
+                Galleria.raise('Picasa request failed' + (msg ? ': ' + msg : '.'));
+            },
+            timeout: 5000
+        });
+
+        $.getJSON( url, function( result ) {
+            data = result;
+        });
+
+        return self;
+    },
+
+
+    // parse image sizes and return an array of three
+
+    _getSizes: function() {
+
+        var self = this,
+            norm = {
+                small: '72c',
+                thumb: '104u',
+                medium: '640u',
+                big: '1024u',
+                original: '1600u'
+            },
+            op = self.options,
+            t = {},
+            n,
+            sz = [32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];
+
+        $(['thumbSize', 'imageSize']).each(function() {
+            if( op[this] in norm ) {
+                t[this] = norm[ op[this] ];
+            } else {
+                n = Galleria.utils.parseValue( op[this] );
+                if (n > 1600) {
+                    n = 1600;
+                } else {
+                    $.each( sz, function(i) {
+                        if ( n < this ) {
+                            n = sz[i-1];
+                            return false;
+                        }
+                    });
+                }
+                t[this] = n;
+            }
+        });
+
+        return [ t.thumbSize, t.imageSize, '1280u'];
+
+    },
+
+
+    // parse the result and call the callback with the galleria-ready data array
+
+    _parse: function( data, callback ) {
+
+        var self = this,
+            gallery = [],
+            img;
+
+        $.each( data, function() {
+
+            img = this.media$group.media$thumbnail;
+
+            gallery.push({
+                thumb: img[0].url,
+                image: img[1].url,
+                big: img[2].url,
+                title: this.summary.$t
+            });
+        });
+
+        callback.call( this, gallery );
+    }
+};
+
+
+/**
+    Galleria modifications
+    We fake-extend the load prototype to make Picasa integration as simple as possible
+*/
+
+
+// save the old prototype in a local variable
+
+var load = Galleria.prototype.load;
+
+
+// fake-extend the load prototype using the picasa data
+
+Galleria.prototype.load = function() {
+
+    // pass if no data is provided or picasa option not found
+    if ( arguments.length || typeof this._options.picasa !== 'string' ) {
+        load.apply( this, Galleria.utils.array( arguments ) );
+        return;
+    }
+
+    // define some local vars
+    var self = this,
+        args = Galleria.utils.array( arguments ),
+        picasa = this._options.picasa.split(':'),
+        p,
+        opts = $.extend({}, self._options.picasaOptions),
+        loader = typeof opts.loader !== 'undefined' ?
+            opts.loader : $('<div>').css({
+                width: 48,
+                height: 48,
+                opacity: 0.7,
+                background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%'
+            });
+
+    if ( picasa.length ) {
+
+        // validate the method
+        if ( typeof Galleria.Picasa.prototype[ picasa[0] ] !== 'function' ) {
+            Galleria.raise( picasa[0] + ' method not found in Picasa plugin' );
+            return load.apply( this, args );
+        }
+
+        // validate the argument
+        if ( !picasa[1] ) {
+            Galleria.raise( 'No picasa argument found' );
+            return load.apply( this, args );
+        }
+
+        // apply the preloader
+        window.setTimeout(function() {
+            self.$( 'target' ).append( loader );
+        },100);
+
+        // create the instance
+        p = new Galleria.Picasa();
+
+        // apply Flickr options
+        if ( typeof self._options.picasaOptions === 'object' ) {
+            p.setOptions( self._options.picasaOptions );
+        }
+
+        // call the picasa method and trigger the DATA event
+        var arg = [];
+        if ( picasa[0] == 'useralbum' ) {
+            arg = picasa[1].split('/');
+            if (arg.length != 2) {
+                Galleria.raise( 'Picasa useralbum not correctly formatted (should be [user]/[album])');
+                return;
+            }
+        } else {
+            arg.push( picasa[1] );
+        }
+
+        arg.push(function(data) {
+            self._data = data;
+            loader.remove();
+            self.trigger( Galleria.DATA );
+            p.options.complete.call(p, data);
+        });
+
+        p[ picasa[0] ].apply( p, arg );
+
+    } else {
+
+        // if flickr array not found, pass
+        load.apply( this, args );
+    }
+};
+
+}( jQuery ) );
\ No newline at end of file
diff --git a/script/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/script/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..2480a0258acff955abeddf719646830e425a301f
--- /dev/null
+++ b/script/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a){Galleria.requires(1.25,"The Picasa Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Picasa=function(){this.options={max:30,imageSize:"medium",thumbSize:"thumb",complete:function(){}}},Galleria.Picasa.prototype={constructor:Galleria.Picasa,search:function(a,b){return this._call("search","all",{q:a},b)},user:function(a,b){return this._call("user","user/"+a,b)},useralbum:function(a,b,c){return this._call("useralbum","user/"+a+"/album/"+b,c)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c,d,e){c="https://picasaweb.google.com/data/feed/api/"+c+"?","function"==typeof d&&(e=d,d={});var f=this;d=a.extend({kind:"photo",access:"public","max-results":this.options.max,thumbsize:this._getSizes().join(","),alt:"json-in-script",callback:"?"},d),a.each(d,function(a,b){c+="&"+a+"="+b});var g=!1;return Galleria.utils.wait({until:function(){return g},success:function(){f._parse.call(f,g.feed.entry,e)},error:function(){var a="";"user"==b?a="user not found.":"useralbum"==b&&(a="album or user not found."),Galleria.raise("Picasa request failed"+(a?": "+a:"."))},timeout:5e3}),a.getJSON(c,function(a){g=a}),f},_getSizes:function(){var b,c=this,d={small:"72c",thumb:"104u",medium:"640u",big:"1024u",original:"1600u"},e=c.options,f={},g=[32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];return a(["thumbSize","imageSize"]).each(function(){e[this]in d?f[this]=d[e[this]]:(b=Galleria.utils.parseValue(e[this]),b>1600?b=1600:a.each(g,function(a){if(b<this)return b=g[a-1],!1}),f[this]=b)}),[f.thumbSize,f.imageSize,"1280u"]},_parse:function(b,c){var d,e=[];a.each(b,function(){d=this.media$group.media$thumbnail,e.push({thumb:d[0].url,image:d[1].url,big:d[2].url,title:this.summary.$t})}),c.call(this,e)}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.picasa)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.picasa.split(":"),h=a.extend({},e._options.picasaOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Picasa.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Picasa plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No picasa argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Picasa,"object"==typeof e._options.picasaOptions&&d.setOptions(e._options.picasaOptions);var j=[];if("useralbum"==g[0]){if(j=g[1].split("/"),2!=j.length)return void Galleria.raise("Picasa useralbum not correctly formatted (should be [user]/[album])")}else j.push(g[1]);j.push(function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)}),d[g[0]].apply(d,j)}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/script/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/script/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..991ac2444fbb15ce987b3a51892ed8b87b7c1498
--- /dev/null
+++ b/script/galleria/plugins/picasa/galleria.picasa.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a){Galleria.requires(1.25,"The Picasa Plugin requires Galleria version 1.2.5 or later.");var b=Galleria.utils.getScriptPath();Galleria.Picasa=function(){this.options={max:30,imageSize:"medium",thumbSize:"thumb",complete:function(){}}},Galleria.Picasa.prototype={constructor:Galleria.Picasa,search:function(a,b){return this._call("search","all",{q:a},b)},user:function(a,b){return this._call("user","user/"+a,b)},useralbum:function(a,b,c){return this._call("useralbum","user/"+a+"/album/"+b,c)},setOptions:function(b){return a.extend(this.options,b),this},_call:function(b,c,d,e){c="https://picasaweb.google.com/data/feed/api/"+c+"?","function"==typeof d&&(e=d,d={});var f=this;d=a.extend({kind:"photo",access:"public","max-results":this.options.max,thumbsize:this._getSizes().join(","),alt:"json-in-script",callback:"?"},d),a.each(d,function(a,b){c+="&"+a+"="+b});var g=!1;return Galleria.utils.wait({until:function(){return g},success:function(){f._parse.call(f,g.feed.entry,e)},error:function(){var a="";"user"==b?a="user not found.":"useralbum"==b&&(a="album or user not found."),Galleria.raise("Picasa request failed"+(a?": "+a:"."))},timeout:5e3}),a.getJSON(c,function(a){g=a}),f},_getSizes:function(){var b,c=this,d={small:"72c",thumb:"104u",medium:"640u",big:"1024u",original:"1600u"},e=c.options,f={},g=[32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];return a(["thumbSize","imageSize"]).each(function(){e[this]in d?f[this]=d[e[this]]:(b=Galleria.utils.parseValue(e[this]),b>1600?b=1600:a.each(g,function(a){if(b<this)return b=g[a-1],!1}),f[this]=b)}),[f.thumbSize,f.imageSize,"1280u"]},_parse:function(b,c){var d,e=[];a.each(b,function(){d=this.media$group.media$thumbnail,e.push({thumb:d[0].url,image:d[1].url,big:d[2].url,title:this.summary.$t})}),c.call(this,e)}};var c=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||"string"!=typeof this._options.picasa)return void c.apply(this,Galleria.utils.array(arguments));var d,e=this,f=Galleria.utils.array(arguments),g=this._options.picasa.split(":"),h=a.extend({},e._options.picasaOptions),i="undefined"!=typeof h.loader?h.loader:a("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+b+"loader.gif) no-repeat 50% 50%"});if(g.length){if("function"!=typeof Galleria.Picasa.prototype[g[0]])return Galleria.raise(g[0]+" method not found in Picasa plugin"),c.apply(this,f);if(!g[1])return Galleria.raise("No picasa argument found"),c.apply(this,f);window.setTimeout(function(){e.$("target").append(i)},100),d=new Galleria.Picasa,"object"==typeof e._options.picasaOptions&&d.setOptions(e._options.picasaOptions);var j=[];if("useralbum"==g[0]){if(j=g[1].split("/"),2!=j.length)return void Galleria.raise("Picasa useralbum not correctly formatted (should be [user]/[album])")}else j.push(g[1]);j.push(function(a){e._data=a,i.remove(),e.trigger(Galleria.DATA),d.options.complete.call(d,a)}),d[g[0]].apply(d,j)}else c.apply(this,f)}}(jQuery);
\ No newline at end of file
diff --git a/script/galleria/plugins/picasa/galleria.picasa.min.js b/script/galleria/plugins/picasa/galleria.picasa.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb377ad124b510cec049612b91c0e916638818e0
--- /dev/null
+++ b/script/galleria/plugins/picasa/galleria.picasa.min.js
@@ -0,0 +1 @@
+(function($){Galleria.requires(1.25,"The Picasa Plugin requires Galleria version 1.2.5 or later.");var PATH=Galleria.utils.getScriptPath();Galleria.Picasa=function(){this.options={max:30,imageSize:"medium",thumbSize:"thumb",complete:function(){}}};Galleria.Picasa.prototype={constructor:Galleria.Picasa,search:function(phrase,callback){return this._call("search","all",{q:phrase},callback)},user:function(username,callback){return this._call("user","user/"+username,callback)},useralbum:function(username,album,callback){return this._call("useralbum","user/"+username+"/album/"+album,callback)},setOptions:function(options){$.extend(this.options,options);return this},_call:function(type,url,params,callback){url="https://picasaweb.google.com/data/feed/api/"+url+"?";if(typeof params=="function"){callback=params;params={}}var self=this;params=$.extend({kind:"photo",access:"public","max-results":this.options.max,thumbsize:this._getSizes().join(","),alt:"json-in-script",callback:"?"},params);$.each(params,function(key,value){url+="&"+key+"="+value});var data=false;Galleria.utils.wait({until:function(){return data},success:function(){self._parse.call(self,data.feed.entry,callback)},error:function(){var msg="";if(type=="user"){msg="user not found."}else if(type=="useralbum"){msg="album or user not found."}Galleria.raise("Picasa request failed"+(msg?": "+msg:"."))},timeout:5e3});$.getJSON(url,function(result){data=result});return self},_getSizes:function(){var self=this,norm={small:"72c",thumb:"104u",medium:"640u",big:"1024u",original:"1600u"},op=self.options,t={},n,sz=[32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];$(["thumbSize","imageSize"]).each(function(){if(op[this]in norm){t[this]=norm[op[this]]}else{n=Galleria.utils.parseValue(op[this]);if(n>1600){n=1600}else{$.each(sz,function(i){if(n<this){n=sz[i-1];return false}})}t[this]=n}});return[t.thumbSize,t.imageSize,"1280u"]},_parse:function(data,callback){var self=this,gallery=[],img;$.each(data,function(){img=this.media$group.media$thumbnail;gallery.push({thumb:img[0].url,image:img[1].url,big:img[2].url,title:this.summary.$t})});callback.call(this,gallery)}};var load=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||typeof this._options.picasa!=="string"){load.apply(this,Galleria.utils.array(arguments));return}var self=this,args=Galleria.utils.array(arguments),picasa=this._options.picasa.split(":"),p,opts=$.extend({},self._options.picasaOptions),loader=typeof opts.loader!=="undefined"?opts.loader:$("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+PATH+"loader.gif) no-repeat 50% 50%"});if(picasa.length){if(typeof Galleria.Picasa.prototype[picasa[0]]!=="function"){Galleria.raise(picasa[0]+" method not found in Picasa plugin");return load.apply(this,args)}if(!picasa[1]){Galleria.raise("No picasa argument found");return load.apply(this,args)}window.setTimeout(function(){self.$("target").append(loader)},100);p=new Galleria.Picasa;if(typeof self._options.picasaOptions==="object"){p.setOptions(self._options.picasaOptions)}var arg=[];if(picasa[0]=="useralbum"){arg=picasa[1].split("/");if(arg.length!=2){Galleria.raise("Picasa useralbum not correctly formatted (should be [user]/[album])");return}}else{arg.push(picasa[1])}arg.push(function(data){self._data=data;loader.remove();self.trigger(Galleria.DATA);p.options.complete.call(p,data)});p[picasa[0]].apply(p,arg)}else{load.apply(this,args)}}})(jQuery);
\ No newline at end of file
diff --git a/script/galleria/plugins/picasa/loader.gif b/script/galleria/plugins/picasa/loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750
Binary files /dev/null and b/script/galleria/plugins/picasa/loader.gif differ
diff --git a/script/galleria/plugins/picasa/picasa-demo.html b/script/galleria/plugins/picasa/picasa-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..2e8ba253554cf67e47bcb0fb834d38653058a5b8
--- /dev/null
+++ b/script/galleria/plugins/picasa/picasa-demo.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Picasa Plugin</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px;}
+
+        </style>
+
+        <!-- load jQuery -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <!-- load picasa plugin -->
+        <script src="galleria.picasa.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Picasa Plugin Demo</h1>
+        <p>Demonstrating a basic gallery example with photos from a Picasa album.</p>
+
+        <!-- Adding gallery images. This is just a container for the dynamic picasa images -->
+
+        <div id="galleria"></div>
+
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('../../themes/classic/galleria.classic.min.js');
+
+        Galleria.run('#galleria', {
+            // The user & album. This example fetches the album "Demo" from the user "galleriajs"
+            picasa: 'useralbum:galleriajs/Demo'
+        });
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/script/galleria/themes/classic/classic-demo-cdn (SFConflict me@a1b0n.com 2017-02-12-23-35-56).html b/script/galleria/themes/classic/classic-demo-cdn (SFConflict me@a1b0n.com 2017-02-12-23-35-56).html
new file mode 100644
index 0000000000000000000000000000000000000000..e7189e3f8888739c72c41036195b33b608c22cbf
--- /dev/null
+++ b/script/galleria/themes/classic/classic-demo-cdn (SFConflict me@a1b0n.com 2017-02-12-23-35-56).html	
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Classic Theme</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Classic Theme</h1>
+        <p>Demonstrating a basic gallery example.</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                    data-title="Biandintz eta zaldiak"
+                    data-description="Horses on Bianditz mountain, in Navarre, Spain."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                    data-title="Athabasca Rail"
+                    data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                    data-title="Back-scattering crepuscular rays"
+                    data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                    data-title="Interior convento"
+                    data-description="Interior view of Yuriria Convent, founded in 1550."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                    data-title="Oxbow Bend outlook"
+                    data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                    data-title="Hazy blue hour"
+                    data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                    data-title="Haute Severaisse valley"
+                    data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                    data-title="Bohinj lake"
+                    data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                    data-title="Bowling Balls"
+                    data-description="Mendocino county, California, USA."
+                >
+            </a>
+            <a href="https://vimeo.com/25750735">
+                <span class="video">Works for vimeo too.</span>
+            </a>
+            <a href="https://www.youtube.com/watch?v=GOD-RyVB-3Q">
+                <span class="video">Works for youtube too.</span>
+            </a>
+
+        </div>
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <!-- load jQuery -->
+    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+    <!-- load Galleria -->
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.3/galleria.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.3/themes/classic/galleria.classic.min.js"></script>
+    <script>
+        $(function() {
+            Galleria.run('#galleria');
+        });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/script/galleria/themes/classic/classic-demo-cdn.html b/script/galleria/themes/classic/classic-demo-cdn.html
new file mode 100644
index 0000000000000000000000000000000000000000..a6df2c466654049bf98685a0509cb8d5f5ccab82
--- /dev/null
+++ b/script/galleria/themes/classic/classic-demo-cdn.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Classic Theme</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Classic Theme</h1>
+        <p>Demonstrating a basic gallery example.</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                    data-title="Biandintz eta zaldiak"
+                    data-description="Horses on Bianditz mountain, in Navarre, Spain."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                    data-title="Athabasca Rail"
+                    data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                    data-title="Back-scattering crepuscular rays"
+                    data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                    data-title="Interior convento"
+                    data-description="Interior view of Yuriria Convent, founded in 1550."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                    data-title="Oxbow Bend outlook"
+                    data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                    data-title="Hazy blue hour"
+                    data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                    data-title="Haute Severaisse valley"
+                    data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                    data-title="Bohinj lake"
+                    data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                    data-title="Bowling Balls"
+                    data-description="Mendocino county, California, USA."
+                >
+            </a>
+            <a href="https://vimeo.com/25750735">
+                <span class="video">Works for vimeo too.</span>
+            </a>
+            <a href="https://www.youtube.com/watch?v=GOD-RyVB-3Q">
+                <span class="video">Works for youtube too.</span>
+            </a>
+
+        </div>
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <!-- load jQuery -->
+    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+    <!-- load Galleria -->
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.7/galleria.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.7/themes/classic/galleria.classic.min.js"></script>
+    <script>
+        $(function() {
+            Galleria.run('#galleria');
+        });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/script/galleria/themes/classic/classic-demo.html b/script/galleria/themes/classic/classic-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..b55c93cf2a871e541e217889649928cc6abc0549
--- /dev/null
+++ b/script/galleria/themes/classic/classic-demo.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Galleria Classic Theme</title>
+        <style>
+
+            /* Demo styles */
+            html,body{background:#222;margin:0;}
+            body{border-top:4px solid #000;}
+            .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;}
+            h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;}
+            p{margin:0 0 20px}
+            a {color:#22BCB9;text-decoration:none;}
+            .cred{margin-top:20px;font-size:11px;}
+
+            /* This rule is read by Galleria to define the gallery height: */
+            #galleria{height:320px}
+
+        </style>
+
+        <!-- load jQuery -->
+        <!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+    </head>
+<body>
+    <div class="content">
+        <h1>Galleria Classic Theme</h1>
+        <p>Demonstrating a basic gallery example.</p>
+
+        <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary -->
+
+        <div id="galleria">
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                    data-title="Biandintz eta zaldiak"
+                    data-description="Horses on Bianditz mountain, in Navarre, Spain."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                    data-title="Athabasca Rail"
+                    data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                    data-title="Back-scattering crepuscular rays"
+                    data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                    data-title="Interior convento"
+                    data-description="Interior view of Yuriria Convent, founded in 1550."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                    data-title="Oxbow Bend outlook"
+                    data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                    data-title="Hazy blue hour"
+                    data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                    data-title="Haute Severaisse valley"
+                    data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                    data-title="Bohinj lake"
+                    data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+                >
+            </a>
+            <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+                <img 
+                    src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                    data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                    data-title="Bowling Balls"
+                    data-description="Mendocino county, California, USA."
+                >
+            </a>
+            <a href="https://vimeo.com/25750735">
+                <span class="video">Works for vimeo too.</span>
+            </a>
+            <a href="https://www.youtube.com/watch?v=GOD-RyVB-3Q">
+                <span class="video">Works for youtube too.</span>
+            </a>
+
+        </div>
+        <p class="cred">Made by <a href="http://galleria.io">Galleria</a>.</p>
+    </div>
+
+    <script>
+    $(function() {
+        // Load the classic theme
+        Galleria.loadTheme('galleria.classic.min.js');
+
+        // Initialize Galleria
+        Galleria.run('#galleria');
+    });
+    </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/script/galleria/themes/classic/classic-loader.gif b/script/galleria/themes/classic/classic-loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750
Binary files /dev/null and b/script/galleria/themes/classic/classic-loader.gif differ
diff --git a/script/galleria/themes/classic/classic-map.png b/script/galleria/themes/classic/classic-map.png
new file mode 100644
index 0000000000000000000000000000000000000000..8d3c8c45cf3ccffe1df58634063d61bd6c009125
Binary files /dev/null and b/script/galleria/themes/classic/classic-map.png differ
diff --git a/script/galleria/themes/classic/galleria.classic.css b/script/galleria/themes/classic/galleria.classic.css
new file mode 100644
index 0000000000000000000000000000000000000000..bf312d4ab6886ade841a84c231228236831ad047
--- /dev/null
+++ b/script/galleria/themes/classic/galleria.classic.css
@@ -0,0 +1,227 @@
+/**
+ * Galleria Classic Theme 2017-02-13
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+#galleria-loader{height:1px!important}
+
+.galleria-theme-classic {
+    position: relative;
+    overflow: hidden;
+    background: #000;
+}
+.galleria-theme-classic img {
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -o-user-select: none;
+}
+.galleria-theme-classic .galleria-stage {
+    position: absolute;
+    top: 10px;
+    bottom: 60px;
+    left: 10px;
+    right: 10px;
+    overflow:hidden;
+}
+.galleria-theme-classic .galleria-thumbnails-container {
+    height: 50px;
+    bottom: 0;
+    position: absolute;
+    left: 10px;
+    right: 10px;
+    z-index: 2;
+}
+.galleria-theme-classic .galleria-carousel .galleria-thumbnails-list {
+    margin-left: 30px;
+    margin-right: 30px;
+}
+.galleria-theme-classic .galleria-thumbnails .galleria-image {
+    height: 40px;
+    width: 60px;
+    background: #000;
+    margin: 0 5px 0 0;
+    border: 1px solid #000;
+    float: left;
+    cursor: pointer;
+}
+.galleria-theme-classic .galleria-counter {
+    position: absolute;
+    bottom: 10px;
+    left: 10px;
+    text-align: right;
+    color: #fff;
+    font: normal 11px/1 arial,sans-serif;
+    z-index: 1;
+}
+.galleria-theme-classic .galleria-loader {
+    background: #000;
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    z-index: 2;
+    display: none;
+    background: url(classic-loader.gif) no-repeat 2px 2px;
+}
+.galleria-theme-classic .galleria-info {
+    width: 50%;
+    top: 15px;
+    left: 15px;
+    z-index: 2;
+    position: absolute;
+}
+.galleria-theme-classic .galleria-info-text {
+    background-color: #000;
+    padding: 12px;
+    display: none;
+    /* IE7 */ zoom:1;
+}
+.galleria-theme-classic .galleria-info-title {
+    font: bold 12px/1.1 arial,sans-serif;
+    margin: 0;
+    color: #fff;
+    margin-bottom: 7px;
+}
+.galleria-theme-classic .galleria-info-description {
+    font: italic 12px/1.4 georgia,serif;
+    margin: 0;
+    color: #bbb;
+}
+.galleria-theme-classic .galleria-info-close {
+    width: 9px;
+    height: 9px;
+    position: absolute;
+    top: 5px;
+    right: 5px;
+    background-position: -753px -11px;
+    opacity: .5;
+    filter: alpha(opacity=50);
+    cursor: pointer;
+    display: none;
+}
+.galleria-theme-classic .notouch .galleria-info-close:hover{
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .touch .galleria-info-close:active{
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .galleria-info-link {
+    background-position: -669px -5px;
+    opacity: .7;
+    filter: alpha(opacity=70);
+    position: absolute;
+    width: 20px;
+    height: 20px;
+    cursor: pointer;
+    background-color: #000;
+}
+.galleria-theme-classic.notouch .galleria-info-link:hover {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic.touch .galleria-info-link:active {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .galleria-image-nav {
+    position: absolute;
+    top: 50%;
+    margin-top: -62px;
+    width: 100%;
+    height: 62px;
+    left: 0;
+}
+.galleria-theme-classic .galleria-image-nav-left,
+.galleria-theme-classic .galleria-image-nav-right {
+    opacity: .3;
+    filter: alpha(opacity=30);
+    cursor: pointer;
+    width: 62px;
+    height: 124px;
+    position: absolute;
+    left: 10px;
+    z-index: 2;
+    background-position: 0 46px;
+}
+.galleria-theme-classic .galleria-image-nav-right {
+    left: auto;
+    right: 10px;
+    background-position: -254px 46px;
+    z-index: 2;
+}
+.galleria-theme-classic.notouch .galleria-image-nav-left:hover,
+.galleria-theme-classic.notouch .galleria-image-nav-right:hover {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic.touch .galleria-image-nav-left:active,
+.galleria-theme-classic.touch .galleria-image-nav-right:active {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+.galleria-theme-classic .galleria-thumb-nav-left,
+.galleria-theme-classic .galleria-thumb-nav-right {
+    cursor: pointer;
+    display: none;
+    background-position: -495px 5px;
+    position: absolute;
+    left: 0;
+    top: 0;
+    height: 40px;
+    width: 23px;
+    z-index: 3;
+    opacity: .8;
+    filter: alpha(opacity=80);
+}
+.galleria-theme-classic .galleria-thumb-nav-right {
+    background-position: -578px 5px;
+    border-right: none;
+    right: 0;
+    left: auto;
+}
+.galleria-theme-classic .galleria-thumbnails-container .disabled {
+    opacity: .2;
+    filter: alpha(opacity=20);
+    cursor: default;
+}
+.galleria-theme-classic.notouch .galleria-thumb-nav-left:hover,
+.galleria-theme-classic.notouch .galleria-thumb-nav-right:hover {
+    opacity: 1;
+    filter: alpha(opacity=100);
+    background-color: #111;
+}
+.galleria-theme-classic.touch .galleria-thumb-nav-left:active,
+.galleria-theme-classic.touch .galleria-thumb-nav-right:active {
+    opacity: 1;
+    filter: alpha(opacity=100);
+    background-color: #111;
+}
+.galleria-theme-classic.notouch .galleria-thumbnails-container .disabled:hover {
+    opacity: .2;
+    filter: alpha(opacity=20);
+    background-color: transparent;
+}
+
+.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-left,
+.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-right {
+    display: block;
+}
+.galleria-theme-classic .galleria-thumb-nav-left,
+.galleria-theme-classic .galleria-thumb-nav-right,
+.galleria-theme-classic .galleria-info-link,
+.galleria-theme-classic .galleria-info-close,
+.galleria-theme-classic .galleria-image-nav-left,
+.galleria-theme-classic .galleria-image-nav-right {
+    background-image: url(classic-map.png);
+    background-repeat: no-repeat;
+}
+.galleria-theme-classic.galleria-container.videoplay .galleria-info,
+.galleria-theme-classic.galleria-container.videoplay .galleria-counter{ display:none!important; }
diff --git a/script/galleria/themes/classic/galleria.classic.js b/script/galleria/themes/classic/galleria.classic.js
new file mode 100644
index 0000000000000000000000000000000000000000..20560d87afe1ca9943f7b52145873729dafe3706
--- /dev/null
+++ b/script/galleria/themes/classic/galleria.classic.js
@@ -0,0 +1,102 @@
+/**
+ * Galleria Classic Theme 2017-02-13
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global window, jQuery, Galleria */
+
+Galleria.addTheme({
+    name: 'classic',
+    version: 1.5,
+    author: 'Galleria',
+    css: 'galleria.classic.css',
+    defaults: {
+        transition: 'slide',
+        thumbCrop:  'height',
+
+        // set this to false if you want to show the caption all the time:
+        _toggleInfo: true
+    },
+    init: function(options) {
+
+        Galleria.requires(1.4, 'This version of Classic theme requires Galleria 1.4 or later');
+
+        // add some elements
+        this.addElement('info-link','info-close');
+        this.append({
+            'info' : ['info-link','info-close']
+        });
+
+        // cache some stuff
+        var info = this.$('info-link,info-close,info-text'),
+            touch = Galleria.TOUCH;
+
+        // show loader & counter with opacity
+        this.$('loader,counter').show().css('opacity', 0.4);
+
+        // some stuff for non-touch browsers
+        if (! touch ) {
+            this.addIdleState( this.get('image-nav-left'), { left:-50 });
+            this.addIdleState( this.get('image-nav-right'), { right:-50 });
+            this.addIdleState( this.get('counter'), { opacity:0 });
+        }
+
+        // toggle info
+        if ( options._toggleInfo === true ) {
+            info.bind( 'click:fast', function() {
+                info.toggle();
+            });
+        } else {
+            info.show();
+            this.$('info-link, info-close').hide();
+        }
+
+        // bind some stuff
+        this.bind('thumbnail', function(e) {
+
+            if (! touch ) {
+                // fade thumbnails
+                $(e.thumbTarget).css('opacity', 0.6).parent().hover(function() {
+                    $(this).not('.active').children().stop().fadeTo(100, 1);
+                }, function() {
+                    $(this).not('.active').children().stop().fadeTo(400, 0.6);
+                });
+
+                if ( e.index === this.getIndex() ) {
+                    $(e.thumbTarget).css('opacity',1);
+                }
+            } else {
+                $(e.thumbTarget).css('opacity', this.getIndex() ? 1 : 0.6).bind('click:fast', function() {
+                    $(this).css( 'opacity', 1 ).parent().siblings().children().css('opacity', 0.6);
+                });
+            }
+        });
+
+        var activate = function(e) {
+            $(e.thumbTarget).css('opacity',1).parent().siblings().children().css('opacity', 0.6);
+        };
+
+        this.bind('loadstart', function(e) {
+            if (!e.cached) {
+                this.$('loader').show().fadeTo(200, 0.4);
+            }
+            window.setTimeout(function() {
+                activate(e);
+            }, touch ? 300 : 0);
+            this.$('info').toggle( this.hasInfo() );
+        });
+
+        this.bind('loadfinish', function(e) {
+            this.$('loader').fadeOut(200);
+        });
+    }
+});
+
+}(jQuery));
diff --git a/script/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js b/script/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js
new file mode 100644
index 0000000000000000000000000000000000000000..37e5a3a0ac2250d0af98713c09af8452b8fa783a
--- /dev/null
+++ b/script/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).js	
@@ -0,0 +1,11 @@
+/**
+ * Galleria - v1.5.3 2017-02-13
+ * https://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed under the MIT License.
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+!function(a){Galleria.addTheme({name:"classic",version:1.5,author:"Galleria",css:"galleria.classic.css",defaults:{transition:"slide",thumbCrop:"height",_toggleInfo:!0},init:function(b){Galleria.requires(1.4,"This version of Classic theme requires Galleria 1.4 or later"),this.addElement("info-link","info-close"),this.append({info:["info-link","info-close"]});var c=this.$("info-link,info-close,info-text"),d=Galleria.TOUCH;this.$("loader,counter").show().css("opacity",.4),d||(this.addIdleState(this.get("image-nav-left"),{left:-50}),this.addIdleState(this.get("image-nav-right"),{right:-50}),this.addIdleState(this.get("counter"),{opacity:0})),b._toggleInfo===!0?c.bind("click:fast",function(){c.toggle()}):(c.show(),this.$("info-link, info-close").hide()),this.bind("thumbnail",function(b){d?a(b.thumbTarget).css("opacity",this.getIndex()?1:.6).bind("click:fast",function(){a(this).css("opacity",1).parent().siblings().children().css("opacity",.6)}):(a(b.thumbTarget).css("opacity",.6).parent().hover(function(){a(this).not(".active").children().stop().fadeTo(100,1)},function(){a(this).not(".active").children().stop().fadeTo(400,.6)}),b.index===this.getIndex()&&a(b.thumbTarget).css("opacity",1))});var e=function(b){a(b.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)};this.bind("loadstart",function(a){a.cached||this.$("loader").show().fadeTo(200,.4),window.setTimeout(function(){e(a)},d?300:0),this.$("info").toggle(this.hasInfo())}),this.bind("loadfinish",function(a){this.$("loader").fadeOut(200)})}})}(jQuery);
\ No newline at end of file
diff --git a/script/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js b/script/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js
new file mode 100644
index 0000000000000000000000000000000000000000..85352ccbdd6868823ceb7aa0029f1bbe7c716d6a
--- /dev/null
+++ b/script/galleria/themes/classic/galleria.classic.min (SFConflict me@a1b0n.com 2017-02-12-23-35-56).min.js	
@@ -0,0 +1 @@
+!function(a){Galleria.addTheme({name:"classic",version:1.5,author:"Galleria",css:"galleria.classic.css",defaults:{transition:"slide",thumbCrop:"height",_toggleInfo:!0},init:function(b){Galleria.requires(1.4,"This version of Classic theme requires Galleria 1.4 or later"),this.addElement("info-link","info-close"),this.append({info:["info-link","info-close"]});var c=this.$("info-link,info-close,info-text"),d=Galleria.TOUCH;this.$("loader,counter").show().css("opacity",.4),d||(this.addIdleState(this.get("image-nav-left"),{left:-50}),this.addIdleState(this.get("image-nav-right"),{right:-50}),this.addIdleState(this.get("counter"),{opacity:0})),b._toggleInfo===!0?c.bind("click:fast",function(){c.toggle()}):(c.show(),this.$("info-link, info-close").hide()),this.bind("thumbnail",function(b){d?a(b.thumbTarget).css("opacity",this.getIndex()?1:.6).bind("click:fast",function(){a(this).css("opacity",1).parent().siblings().children().css("opacity",.6)}):(a(b.thumbTarget).css("opacity",.6).parent().hover(function(){a(this).not(".active").children().stop().fadeTo(100,1)},function(){a(this).not(".active").children().stop().fadeTo(400,.6)}),b.index===this.getIndex()&&a(b.thumbTarget).css("opacity",1))});var e=function(b){a(b.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)};this.bind("loadstart",function(a){a.cached||this.$("loader").show().fadeTo(200,.4),window.setTimeout(function(){e(a)},d?300:0),this.$("info").toggle(this.hasInfo())}),this.bind("loadfinish",function(a){this.$("loader").fadeOut(200)})}})}(jQuery);
\ No newline at end of file
diff --git a/script/galleria/themes/classic/galleria.classic.min.css b/script/galleria/themes/classic/galleria.classic.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..0291f8278b9314e78fd8ae54c4bd83d52f480cbe
--- /dev/null
+++ b/script/galleria/themes/classic/galleria.classic.min.css
@@ -0,0 +1 @@
+#galleria-loader{height:1px!important}.galleria-theme-classic{position:relative;overflow:hidden;background:#000}.galleria-theme-classic img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none}.galleria-theme-classic .galleria-stage{position:absolute;top:10px;bottom:60px;left:10px;right:10px;overflow:hidden}.galleria-theme-classic .galleria-thumbnails-container{height:50px;bottom:0;position:absolute;left:10px;right:10px;z-index:2}.galleria-theme-classic .galleria-carousel .galleria-thumbnails-list{margin-left:30px;margin-right:30px}.galleria-theme-classic .galleria-thumbnails .galleria-image{height:40px;width:60px;background:#000;margin:0 5px 0 0;border:1px solid #000;float:left;cursor:pointer}.galleria-theme-classic .galleria-counter{position:absolute;bottom:10px;left:10px;text-align:right;color:#fff;font:400 11px/1 arial,sans-serif;z-index:1}.galleria-theme-classic .galleria-loader{width:20px;height:20px;position:absolute;top:10px;right:10px;z-index:2;display:none;background:url(classic-loader.gif) 2px 2px no-repeat}.galleria-theme-classic .galleria-info{width:50%;top:15px;left:15px;z-index:2;position:absolute}.galleria-theme-classic .galleria-info-text{background-color:#000;padding:12px;display:none;zoom:1}.galleria-theme-classic .galleria-info-title{font:700 12px/1.1 arial,sans-serif;margin:0 0 7px;color:#fff}.galleria-theme-classic .galleria-info-description{font:italic 12px/1.4 georgia,serif;margin:0;color:#bbb}.galleria-theme-classic .galleria-info-close{width:9px;height:9px;position:absolute;top:5px;right:5px;background-position:-753px -11px;opacity:.5;filter:alpha(opacity=50);cursor:pointer;display:none}.galleria-theme-classic .notouch .galleria-info-close:hover,.galleria-theme-classic .touch .galleria-info-close:active{opacity:1;filter:alpha(opacity=100)}.galleria-theme-classic .galleria-info-link{background-position:-669px -5px;opacity:.7;filter:alpha(opacity=70);position:absolute;width:20px;height:20px;cursor:pointer;background-color:#000}.galleria-theme-classic.notouch .galleria-info-link:hover,.galleria-theme-classic.touch .galleria-info-link:active{opacity:1;filter:alpha(opacity=100)}.galleria-theme-classic .galleria-image-nav{position:absolute;top:50%;margin-top:-62px;width:100%;height:62px;left:0}.galleria-theme-classic .galleria-image-nav-left,.galleria-theme-classic .galleria-image-nav-right{opacity:.3;filter:alpha(opacity=30);cursor:pointer;width:62px;height:124px;position:absolute;left:10px;z-index:2;background-position:0 46px}.galleria-theme-classic .galleria-image-nav-right{left:auto;right:10px;background-position:-254px 46px;z-index:2}.galleria-theme-classic.notouch .galleria-image-nav-left:hover,.galleria-theme-classic.notouch .galleria-image-nav-right:hover,.galleria-theme-classic.touch .galleria-image-nav-left:active,.galleria-theme-classic.touch .galleria-image-nav-right:active{opacity:1;filter:alpha(opacity=100)}.galleria-theme-classic .galleria-thumb-nav-left,.galleria-theme-classic .galleria-thumb-nav-right{cursor:pointer;display:none;background-position:-495px 5px;position:absolute;left:0;top:0;height:40px;width:23px;z-index:3;opacity:.8;filter:alpha(opacity=80)}.galleria-theme-classic .galleria-thumb-nav-right{background-position:-578px 5px;border-right:none;right:0;left:auto}.galleria-theme-classic .galleria-thumbnails-container .disabled{opacity:.2;filter:alpha(opacity=20);cursor:default}.galleria-theme-classic.notouch .galleria-thumb-nav-left:hover,.galleria-theme-classic.notouch .galleria-thumb-nav-right:hover,.galleria-theme-classic.touch .galleria-thumb-nav-left:active,.galleria-theme-classic.touch .galleria-thumb-nav-right:active{opacity:1;filter:alpha(opacity=100);background-color:#111}.galleria-theme-classic.notouch .galleria-thumbnails-container .disabled:hover{opacity:.2;filter:alpha(opacity=20);background-color:transparent}.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-left,.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-right{display:block}.galleria-theme-classic .galleria-image-nav-left,.galleria-theme-classic .galleria-image-nav-right,.galleria-theme-classic .galleria-info-close,.galleria-theme-classic .galleria-info-link,.galleria-theme-classic .galleria-thumb-nav-left,.galleria-theme-classic .galleria-thumb-nav-right{background-image:url(classic-map.png);background-repeat:no-repeat}.galleria-theme-classic.galleria-container.videoplay .galleria-counter,.galleria-theme-classic.galleria-container.videoplay .galleria-info{display:none!important}
\ No newline at end of file
diff --git a/script/galleria/themes/classic/galleria.classic.min.js b/script/galleria/themes/classic/galleria.classic.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..4f9987c2ea1e01aea02f31259f807d56f7b47fe4
--- /dev/null
+++ b/script/galleria/themes/classic/galleria.classic.min.js
@@ -0,0 +1 @@
+(function($){Galleria.addTheme({name:"classic",version:1.5,author:"Galleria",css:"galleria.classic.css",defaults:{transition:"slide",thumbCrop:"height",_toggleInfo:true},init:function(options){Galleria.requires(1.4,"This version of Classic theme requires Galleria 1.4 or later");this.addElement("info-link","info-close");this.append({info:["info-link","info-close"]});var info=this.$("info-link,info-close,info-text"),touch=Galleria.TOUCH;this.$("loader,counter").show().css("opacity",.4);if(!touch){this.addIdleState(this.get("image-nav-left"),{left:-50});this.addIdleState(this.get("image-nav-right"),{right:-50});this.addIdleState(this.get("counter"),{opacity:0})}if(options._toggleInfo===true){info.bind("click:fast",function(){info.toggle()})}else{info.show();this.$("info-link, info-close").hide()}this.bind("thumbnail",function(e){if(!touch){$(e.thumbTarget).css("opacity",.6).parent().hover(function(){$(this).not(".active").children().stop().fadeTo(100,1)},function(){$(this).not(".active").children().stop().fadeTo(400,.6)});if(e.index===this.getIndex()){$(e.thumbTarget).css("opacity",1)}}else{$(e.thumbTarget).css("opacity",this.getIndex()?1:.6).bind("click:fast",function(){$(this).css("opacity",1).parent().siblings().children().css("opacity",.6)})}});var activate=function(e){$(e.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)};this.bind("loadstart",function(e){if(!e.cached){this.$("loader").show().fadeTo(200,.4)}window.setTimeout(function(){activate(e)},touch?300:0);this.$("info").toggle(this.hasInfo())});this.bind("loadfinish",function(e){this.$("loader").fadeOut(200)})}})})(jQuery);
\ No newline at end of file
diff --git a/script/galleria/themes/fullscreen/b.png b/script/galleria/themes/fullscreen/b.png
new file mode 100644
index 0000000000000000000000000000000000000000..42ee9a0e6b8bb73a0742f74866ca31664dd59704
Binary files /dev/null and b/script/galleria/themes/fullscreen/b.png differ
diff --git a/script/galleria/themes/fullscreen/down-neg.gif b/script/galleria/themes/fullscreen/down-neg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..629f78fbee79ec1d491faa7b5916155aebcd4d58
Binary files /dev/null and b/script/galleria/themes/fullscreen/down-neg.gif differ
diff --git a/script/galleria/themes/fullscreen/down.gif b/script/galleria/themes/fullscreen/down.gif
new file mode 100644
index 0000000000000000000000000000000000000000..006dcc254439119209fd9df8b05d61a86ff0956d
Binary files /dev/null and b/script/galleria/themes/fullscreen/down.gif differ
diff --git a/script/galleria/themes/fullscreen/fix.gif b/script/galleria/themes/fullscreen/fix.gif
new file mode 100644
index 0000000000000000000000000000000000000000..35d42e808f0a8017b8d52a06be2f8fec0b466a66
Binary files /dev/null and b/script/galleria/themes/fullscreen/fix.gif differ
diff --git a/script/galleria/themes/fullscreen/fullscreen-demo-cdn.html b/script/galleria/themes/fullscreen/fullscreen-demo-cdn.html
new file mode 100644
index 0000000000000000000000000000000000000000..094df19e6c1b017cf3d5f99e269cc259160ce351
--- /dev/null
+++ b/script/galleria/themes/fullscreen/fullscreen-demo-cdn.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html lang="sv">
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no">
+        <title>Galleria Fullscreen Theme Demo</title>
+
+        <style>
+        body{background:#000;}
+        </style>
+
+    </head>
+<body>
+    <div class="galleria">
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                data-title="Biandintz eta zaldiak"
+                data-description="Horses on Bianditz mountain, in Navarre, Spain."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                data-title="Athabasca Rail"
+                data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                data-title="Back-scattering crepuscular rays"
+                data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                data-title="Interior convento"
+                data-description="Interior view of Yuriria Convent, founded in 1550."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                data-title="Oxbow Bend outlook"
+                data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                data-title="Hazy blue hour"
+                data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                data-title="Haute Severaisse valley"
+                data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                data-title="Bohinj lake"
+                data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                data-title="Bowling Balls"
+                data-description="Mendocino county, California, USA."
+            >
+        </a>
+    </div>
+
+    <!-- load jQuery -->
+    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+    <!-- load Galleria -->
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.4/galleria.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/galleria/1.5.4/themes/fullscreen/galleria.fullscreen.min.js"></script>
+    <script>
+        $(function() {
+            Galleria.run('.galleria');
+        });
+    </script>
+    </body>
+</html>
diff --git a/script/galleria/themes/fullscreen/fullscreen-demo.html b/script/galleria/themes/fullscreen/fullscreen-demo.html
new file mode 100644
index 0000000000000000000000000000000000000000..3c0bfef17686254f3bf2fe5b06ae9678e3bbd996
--- /dev/null
+++ b/script/galleria/themes/fullscreen/fullscreen-demo.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="sv">
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no">
+        <title>Galleria Fullscreen Theme Demo</title>
+
+        <!-- load jQuery -->
+        <!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js"></script> -->
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
+
+        <!-- load Galleria -->
+        <script src="../../galleria-1.5.7.min.js"></script>
+
+        <style>
+        body{background:#000;}
+        </style>
+
+    </head>
+<body>
+    <div class="galleria">
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg"
+                data-title="Biandintz eta zaldiak"
+                data-description="Horses on Bianditz mountain, in Navarre, Spain."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg"
+                data-title="Athabasca Rail"
+                data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg"
+                data-title="Back-scattering crepuscular rays"
+                data-description="Picture of the day on Wikimedia Commons 26 September 2010."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg"
+                data-title="Interior convento"
+                data-description="Interior view of Yuriria Convent, founded in 1550."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"
+                data-title="Oxbow Bend outlook"
+                data-description="View over the Snake River to the Mount Moran with the Skillet Glacier."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG"
+                data-title="Hazy blue hour"
+                data-description="Hazy blue hour in Grand Canyon. View from the South Rim."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg"
+                data-title="Haute Severaisse valley"
+                data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg"
+                data-title="Bohinj lake"
+                data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning."
+            >
+        </a>
+        <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg">
+            <img 
+                src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg",
+                data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg"
+                data-title="Bowling Balls"
+                data-description="Mendocino county, California, USA."
+            >
+        </a>
+    </div>
+    <script>
+    $(function() {
+        // Load the Fullscreen theme
+        Galleria.loadTheme('galleria.fullscreen.min.js');
+
+        // Initialize Galleria
+        Galleria.run('.galleria');
+    });
+    </script>
+    </body>
+</html>
diff --git a/script/galleria/themes/fullscreen/galleria.fullscreen.css b/script/galleria/themes/fullscreen/galleria.fullscreen.css
new file mode 100644
index 0000000000000000000000000000000000000000..205be2292ecaea68bd1145ec9472edaaa22e8bff
--- /dev/null
+++ b/script/galleria/themes/fullscreen/galleria.fullscreen.css
@@ -0,0 +1,217 @@
+/**
+ * Galleria Classic Theme 2017-02-27
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed 2017-02-27 under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+#galleria-loader{height:1px!important}
+
+html,
+body { background: #000 }
+.galleria-theme-fullscreen {
+    height: 100%;
+    overflow: hidden;
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    background: #000;
+    -webkit-font-smoothing: antialiased;
+}
+.galleria-theme-fullscreen img {
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -o-user-select: none;
+}
+.galleria-theme-fullscreen .galleria-stage {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+}
+.galleria-theme-fullscreen .galleria-thumbnails-container {
+    position: absolute;
+    bottom: 0;
+    z-index: 2;
+    padding-top: 16px;
+    width: 100%;
+}
+.galleria-theme-fullscreen.videoplay .galleria-thumbnails-container { display:none!important; }
+.galleria-theme-fullscreen.videoplay .galleria-image-nav { top:80px; bottom:80px; height:auto; }
+
+.galleria-theme-fullscreen .galleria-thumbnails-tab {
+    opacity: .7;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
+    filter: alpha(opacity=70);
+    position: absolute;
+    left: 50%;
+    margin-left: -50px;
+    top: 0;
+    height: 16px;
+    width: 100px;
+    background: #000 url(up.gif) no-repeat 50% 5px;
+    cursor: pointer;
+    -moz-border-radius-topleft: 4px;
+    -moz-border-radius-topright: 4px;
+    -webkit-border-top-right-radius: 4px;
+    -webkit-border-top-left-radius: 4px;
+}
+.galleria-theme-fullscreen.light .galleria-thumbnails-tab {
+    background:#fff url(up-neg.gif) no-repeat 50% 50%;
+    opacity: 1;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+    filter: alpha(opacity=100);
+}
+.galleria-theme-fullscreen .galleria-thumbnails-tab:hover {
+    opacity: 1;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+    filter: alpha(opacity=100);
+}
+.galleria-theme-fullscreen .galleria-thumbnails-tab.open,
+.galleria-theme-fullscreen .galleria-thumbnails-tab.open:hover {
+    background-image: url(down.gif);
+    opacity: 1;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+    filter: alpha(opacity=100);
+}
+.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open,
+.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open:hover {
+    background-image: url(down-neg.gif);
+}
+.galleria-theme-fullscreen .galleria-thumbnails {
+    background: #000;
+    overflow: hidden;
+}
+.galleria-theme-fullscreen .galleria-thumbnails-list {
+    background: #000;
+    padding-top: 5px;
+    padding-bottom: 5px;
+    overflow: hidden;
+}
+.galleria-theme-fullscreen.light .galleria-thumbnails,
+.galleria-theme-fullscreen.light .galleria-thumbnails-list {
+    background:#fff;
+}
+.galleria-theme-fullscreen .galleria-thumbnails .galleria-image {
+    width: 80px;
+    height: 50px;
+    float: left;
+    cursor: pointer;
+    margin-right: 5px;
+}
+.galleria-theme-fullscreen .galleria-thumbnails .galleria-image img { background: #000 }
+.galleria-theme-fullscreen .galleria-thumbnails .active { cursor: default }
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumbnails-list {
+    border-left: 30px solid #000;
+    border-right: 30px solid #000;
+}
+.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumbnails-list {
+    border-color: #fff;
+}
+.galleria-theme-fullscreen .galleria-image-nav {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+.galleria-theme-fullscreen .galleria-image-nav-right,
+.galleria-theme-fullscreen .galleria-image-nav-left {
+    width: 100px;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    background: url(r.gif) no-repeat 50% 50%;
+    position: absolute;
+    cursor: pointer;
+    z-index: 2;
+    display: none;
+}
+.galleria-theme-fullscreen.smallarrows .galleria-image-nav-right {
+    background-image: url(r-neg.png);
+}
+.galleria-theme-fullscreen .galleria-image-nav-left {
+    left: 0;
+    right: auto;
+    background-image: url(l.gif);
+}
+.galleria-theme-fullscreen.smallarrows .galleria-image-nav-left {
+    background-image: url(l-neg.png);
+}
+.galleria-theme-fullscreen .galleria-loader {
+    width: 30px;
+    height: 30px;
+    background: #fff url(loader.gif) no-repeat 50% 50%;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-top: -15px;
+    margin-left: -15px;
+    z-index: 3;
+}
+.galleria-theme-fullscreen .galleria-info {
+    z-index: 4;
+    font: 13px/1.4 helvetica,arial,sans-serif;
+    color: #fff;
+    position: absolute;
+    top: 0;
+    width: 100%;
+    border-top: 2px solid #000;
+    display: none;
+    text-align: center;
+    padding: 10px 0;
+    background: rgba(0,0,0,.5);
+    border-bottom:1px solid rgba(0,0,0,.1);
+}
+.galleria-theme-fullscreen.light .galleria-info{background:rgba(255,255,255,.5);color:#000;}
+.galleria-theme-fullscreen .galleria-info-text {
+    width: 50%;
+    margin: 0 auto;
+}
+.galleria-theme-fullscreen .galleria-info-title { font-weight: bold; display: inline-block; margin-right:10px; }
+.galleria-theme-fullscreen .galleria-info-description { display:inline-block; }
+.galleria-theme-fullscreen .galleria-thumb-nav-left,
+.galleria-theme-fullscreen .galleria-thumb-nav-right {
+    cursor: pointer;
+    display: none;
+    background: url(p.gif) no-repeat 50% 50%;
+    position: absolute;
+    left: 5px;
+    top: 21px;
+    bottom: 5px;
+    width: 20px;
+    z-index: 3;
+    opacity: .8;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
+    filter: alpha(opacity=80);
+}
+.galleria-theme-fullscreen.light .galleria-thumb-nav-left{
+    background-image: url(p-neg.png);
+}
+.galleria-theme-fullscreen .galleria-thumb-nav-right {
+    background-image: url(n.gif);
+    left: auto;
+    right: 5px;
+}
+.galleria-theme-fullscreen.light .galleria-thumb-nav-right{
+    background-image: url(n-neg.png);
+}
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left,
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right { display: block }
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left:hover,
+.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right:hover { background-color: #222 }
+.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled,
+.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled,
+.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled:hover,
+.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled:hover {
+    opacity: .2;
+    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
+    filter: alpha(opacity=20);
+    cursor: default;
+}
+.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-left:hover,
+.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-right:hover { background-color: #ddd }
+
diff --git a/script/galleria/themes/fullscreen/galleria.fullscreen.js b/script/galleria/themes/fullscreen/galleria.fullscreen.js
new file mode 100644
index 0000000000000000000000000000000000000000..4bb6608f4ae31cebe34a328920aefc4a7310a626
--- /dev/null
+++ b/script/galleria/themes/fullscreen/galleria.fullscreen.js
@@ -0,0 +1,182 @@
+/**
+ * Galleria Classic Theme 2017-02-27
+ * http://galleria.io
+ *
+ * Copyright (c) 2010 - 2017 worse is better UG
+ * Licensed 2017-02-27 under the MIT license
+ * https://raw.github.com/worseisbetter/galleria/master/LICENSE
+ *
+ */
+
+(function($) {
+
+/*global jQuery, Galleria, window */
+
+Galleria.addTheme({
+    name: 'fullscreen',
+    version: '1.5.4',
+    author: 'Galleria',
+    css: 'galleria.fullscreen.css',
+    // begin site script
+    defaults: {
+        transition: 'none',
+        imageCrop: true,
+        thumbCrop: 'height',
+        easing: 'galleriaOut',
+        trueFullscreen: false,
+
+        // set this to false if you want to keep the thumbnails:
+        _hideDock: Galleria.TOUCH ? false : true,
+
+        // set this to true if you want to shrink the carousel when clicking a thumbnail:
+        _closeOnClick: false
+    },
+    init: function(options) {
+
+        Galleria.requires( 1.5, 'This version of Fullscreen theme requires Galleria version 1.5 or later');
+
+        this.addElement('thumbnails-tab');
+        this.appendChild('thumbnails-container', 'thumbnails-tab');
+
+        var tab      = this.$('thumbnails-tab'),
+            loader   = this.$('loader'),
+            thumbs   = this.$('thumbnails-container'),
+            list     = this.$('thumbnails-list'),
+            infotext = this.$('info-text'),
+            info     = this.$('info'),
+            OPEN     = !options._hideDock,
+            POS      = 0;
+            
+        if (Galleria.IE) {
+            this.addElement('iefix');
+            this.appendChild('container', 'iefix');
+            this.$('iefix').css({
+                zIndex: 3,
+                position: 'absolute',
+                backgroundColor: this.hasVariation('light') ? '#fff' : '#000',
+                opacity: 0.4,
+                top: 0
+            });
+        }
+
+        if ( options.thumbnails === false ) {
+            thumbs.hide();
+        }
+
+        var fixCaption = this.proxy(function(img) {
+
+            var w = img.width || $(img).width();
+
+            if (!(img || w)) {
+                return;
+            }
+            w = Math.min(w, $(window).width());
+            infotext.width(w - 40);
+            if (Galleria.IE && this.getOptions('showInfo')) {
+                this.$('iefix').width(info.outerWidth()).height(info.outerHeight());
+            }
+        });
+
+        this.bind('rescale', function() {
+            POS = this.getStageHeight() - tab.height() - 2;
+            thumbs.css('top', OPEN ? POS - list.outerHeight() + 2 : POS);
+            var img = this.getActiveImage();
+            if (img) {
+                fixCaption(img);
+            }
+        });
+
+        this.bind('loadstart', function(e) {
+            if (!e.cached) {
+                loader.show().fadeTo(100, 1);
+            }
+            $(e.thumbTarget).css('opacity', 1).parent().siblings().children().css('opacity', 0.6);
+        });
+
+        this.bind('loadfinish', function(e) {
+            loader.fadeOut(300);
+            this.$('info, iefix').toggle(this.hasInfo());
+        });
+
+        this.bind('image', function(e) {
+            e.imageTarget && fixCaption(e.imageTarget);
+        });
+
+        this.bind('thumbnail', function(e) {
+            $(e.thumbTarget).parent(':not(.active)').children().css('opacity', 0.6);
+            $(e.thumbTarget).on('click:fast', function() {
+                if (OPEN && options._closeOnClick) {
+                    tab.trigger('click:fast');
+                }
+            });
+        });
+
+        this.trigger('rescale');
+
+        if ( !Galleria.TOUCH ) {
+
+            this.addIdleState(thumbs, { opacity: 0 });
+            this.addIdleState(this.get('info'), { opacity: 0 });
+
+            this.$('image-nav-left, image-nav-right').css('opacity', 0.01).hover(function() {
+                $(this).animate({opacity: 1}, 100);
+            }, function() {
+                $(this).animate({opacity: 0});
+            }).show();
+
+        }
+
+        if (Galleria.IE) {
+            this.addIdleState(this.get('iefix'), { opacity: 0 });
+        }
+
+        if (options._hideDock) {
+            tab.on('click:fast', this.proxy(function() {
+                tab.toggleClass('open', !OPEN);
+                if (!OPEN) {
+                    thumbs.animate({
+                        top: POS - list.outerHeight() + 2
+                    }, 400, options.easing);
+                } else {
+                    thumbs.animate({
+                        top: POS
+                    }, 400, options.easing);
+                }
+                OPEN = !OPEN;
+            }));
+        } else {
+            this.bind('thumbnail', function() {
+                thumbs.css('top', POS - list.outerHeight() + 2);
+            });
+            tab.css('visibility', 'hidden');
+        }
+
+        this.$('thumbnails').children().hover(function() {
+            $(this).not('.active').children().stop().fadeTo(100, 1);
+        }, function() {
+            $(this).not('.active').children().stop().fadeTo(400, 0.6);
+        });
+
+        this.enterFullscreen();
+        this.attachKeyboard({
+            escape: function(e) {
+                return false;
+            },
+            up: function(e) {
+                if (!OPEN) {
+                    tab.trigger('click:fast');
+                }
+                e.preventDefault();
+            },
+            down: function(e) {
+                if (OPEN) {
+                    tab.trigger('click:fast');
+                }
+                e.preventDefault();
+            }
+        });
+    }
+    // end site script
+});
+
+}(jQuery));
diff --git a/script/galleria/themes/fullscreen/galleria.fullscreen.min.css b/script/galleria/themes/fullscreen/galleria.fullscreen.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..6e5e1606f2fcd4dd5ae73855222157436f715451
--- /dev/null
+++ b/script/galleria/themes/fullscreen/galleria.fullscreen.min.css
@@ -0,0 +1 @@
+#galleria-loader{height:1px!important}body,html{background:#000}.galleria-theme-fullscreen{height:100%;overflow:hidden;position:fixed;top:0;left:0;width:100%;background:#000;-webkit-font-smoothing:antialiased}.galleria-theme-fullscreen img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none}.galleria-theme-fullscreen .galleria-stage{width:100%;height:100%;position:absolute}.galleria-theme-fullscreen .galleria-thumbnails-container{position:absolute;bottom:0;z-index:2;padding-top:16px;width:100%}.galleria-theme-fullscreen.videoplay .galleria-thumbnails-container{display:none!important}.galleria-theme-fullscreen.videoplay .galleria-image-nav{top:80px;bottom:80px;height:auto}.galleria-theme-fullscreen .galleria-thumbnails-tab{opacity:.7;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";filter:alpha(opacity=70);position:absolute;left:50%;margin-left:-50px;top:0;height:16px;width:100px;background:url(up.gif) 50% 5px no-repeat #000;cursor:pointer;-moz-border-radius-topleft:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-webkit-border-top-left-radius:4px}.galleria-theme-fullscreen.light .galleria-thumbnails-tab{background:url(up-neg.gif) 50% 50% no-repeat #fff;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen .galleria-thumbnails-tab:hover{opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen .galleria-thumbnails-tab.open,.galleria-theme-fullscreen .galleria-thumbnails-tab.open:hover{background-image:url(down.gif);opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open,.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open:hover{background-image:url(down-neg.gif)}.galleria-theme-fullscreen .galleria-thumbnails{background:#000;overflow:hidden}.galleria-theme-fullscreen .galleria-thumbnails-list{background:#000;padding-top:5px;padding-bottom:5px;overflow:hidden}.galleria-theme-fullscreen.light .galleria-thumbnails,.galleria-theme-fullscreen.light .galleria-thumbnails-list{background:#fff}.galleria-theme-fullscreen .galleria-thumbnails .galleria-image{width:80px;height:50px;float:left;cursor:pointer;margin-right:5px}.galleria-theme-fullscreen .galleria-thumbnails .galleria-image img{background:#000}.galleria-theme-fullscreen .galleria-thumbnails .active{cursor:default}.galleria-theme-fullscreen .galleria-carousel .galleria-thumbnails-list{border-left:30px solid #000;border-right:30px solid #000}.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumbnails-list{border-color:#fff}.galleria-theme-fullscreen .galleria-image-nav{width:100%;height:100%;position:absolute;top:0;left:0}.galleria-theme-fullscreen .galleria-image-nav-left,.galleria-theme-fullscreen .galleria-image-nav-right{width:100px;right:0;top:0;bottom:0;background:url(r.gif) 50% 50% no-repeat;position:absolute;cursor:pointer;z-index:2;display:none}.galleria-theme-fullscreen.smallarrows .galleria-image-nav-right{background-image:url(r-neg.png)}.galleria-theme-fullscreen .galleria-image-nav-left{left:0;right:auto;background-image:url(l.gif)}.galleria-theme-fullscreen.smallarrows .galleria-image-nav-left{background-image:url(l-neg.png)}.galleria-theme-fullscreen .galleria-loader{width:30px;height:30px;background:url(loader.gif) 50% 50% no-repeat #fff;position:absolute;top:50%;left:50%;margin-top:-15px;margin-left:-15px;z-index:3}.galleria-theme-fullscreen .galleria-info{z-index:4;font:13px/1.4 helvetica,arial,sans-serif;color:#fff;position:absolute;top:0;width:100%;border-top:2px solid #000;display:none;text-align:center;padding:10px 0;background:rgba(0,0,0,.5);border-bottom:1px solid rgba(0,0,0,.1)}.galleria-theme-fullscreen.light .galleria-info{background:rgba(255,255,255,.5);color:#000}.galleria-theme-fullscreen .galleria-info-text{width:50%;margin:0 auto}.galleria-theme-fullscreen .galleria-info-title{font-weight:700;display:inline-block;margin-right:10px}.galleria-theme-fullscreen .galleria-info-description{display:inline-block}.galleria-theme-fullscreen .galleria-thumb-nav-left,.galleria-theme-fullscreen .galleria-thumb-nav-right{cursor:pointer;display:none;background:url(p.gif) 50% 50% no-repeat;position:absolute;left:5px;top:21px;bottom:5px;width:20px;z-index:3;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.galleria-theme-fullscreen.light .galleria-thumb-nav-left{background-image:url(p-neg.png)}.galleria-theme-fullscreen .galleria-thumb-nav-right{background-image:url(n.gif);left:auto;right:5px}.galleria-theme-fullscreen.light .galleria-thumb-nav-right{background-image:url(n-neg.png)}.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left,.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right{display:block}.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left:hover,.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right:hover{background-color:#222}.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled,.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled:hover,.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled,.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled:hover{opacity:.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20);cursor:default}.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-left:hover,.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-right:hover{background-color:#ddd}
\ No newline at end of file
diff --git a/script/galleria/themes/fullscreen/galleria.fullscreen.min.js b/script/galleria/themes/fullscreen/galleria.fullscreen.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c8118cd0969d47c23d6f2db5bd8d2461782b4ee
--- /dev/null
+++ b/script/galleria/themes/fullscreen/galleria.fullscreen.min.js
@@ -0,0 +1 @@
+(function($){Galleria.addTheme({name:"fullscreen",version:"1.5.4",author:"Galleria",css:"galleria.fullscreen.css",defaults:{transition:"none",imageCrop:true,thumbCrop:"height",easing:"galleriaOut",trueFullscreen:false,_hideDock:Galleria.TOUCH?false:true,_closeOnClick:false},init:function(options){Galleria.requires(1.5,"This version of Fullscreen theme requires Galleria version 1.5 or later");this.addElement("thumbnails-tab");this.appendChild("thumbnails-container","thumbnails-tab");var tab=this.$("thumbnails-tab"),loader=this.$("loader"),thumbs=this.$("thumbnails-container"),list=this.$("thumbnails-list"),infotext=this.$("info-text"),info=this.$("info"),OPEN=!options._hideDock,POS=0;if(Galleria.IE){this.addElement("iefix");this.appendChild("container","iefix");this.$("iefix").css({zIndex:3,position:"absolute",backgroundColor:this.hasVariation("light")?"#fff":"#000",opacity:.4,top:0})}if(options.thumbnails===false){thumbs.hide()}var fixCaption=this.proxy(function(img){var w=img.width||$(img).width();if(!(img||w)){return}w=Math.min(w,$(window).width());infotext.width(w-40);if(Galleria.IE&&this.getOptions("showInfo")){this.$("iefix").width(info.outerWidth()).height(info.outerHeight())}});this.bind("rescale",function(){POS=this.getStageHeight()-tab.height()-2;thumbs.css("top",OPEN?POS-list.outerHeight()+2:POS);var img=this.getActiveImage();if(img){fixCaption(img)}});this.bind("loadstart",function(e){if(!e.cached){loader.show().fadeTo(100,1)}$(e.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)});this.bind("loadfinish",function(e){loader.fadeOut(300);this.$("info, iefix").toggle(this.hasInfo())});this.bind("image",function(e){e.imageTarget&&fixCaption(e.imageTarget)});this.bind("thumbnail",function(e){$(e.thumbTarget).parent(":not(.active)").children().css("opacity",.6);$(e.thumbTarget).on("click:fast",function(){if(OPEN&&options._closeOnClick){tab.trigger("click:fast")}})});this.trigger("rescale");if(!Galleria.TOUCH){this.addIdleState(thumbs,{opacity:0});this.addIdleState(this.get("info"),{opacity:0});this.$("image-nav-left, image-nav-right").css("opacity",.01).hover(function(){$(this).animate({opacity:1},100)},function(){$(this).animate({opacity:0})}).show()}if(Galleria.IE){this.addIdleState(this.get("iefix"),{opacity:0})}if(options._hideDock){tab.on("click:fast",this.proxy(function(){tab.toggleClass("open",!OPEN);if(!OPEN){thumbs.animate({top:POS-list.outerHeight()+2},400,options.easing)}else{thumbs.animate({top:POS},400,options.easing)}OPEN=!OPEN}))}else{this.bind("thumbnail",function(){thumbs.css("top",POS-list.outerHeight()+2)});tab.css("visibility","hidden")}this.$("thumbnails").children().hover(function(){$(this).not(".active").children().stop().fadeTo(100,1)},function(){$(this).not(".active").children().stop().fadeTo(400,.6)});this.enterFullscreen();this.attachKeyboard({escape:function(e){return false},up:function(e){if(!OPEN){tab.trigger("click:fast")}e.preventDefault()},down:function(e){if(OPEN){tab.trigger("click:fast")}e.preventDefault()}})}})})(jQuery);
\ No newline at end of file
diff --git a/script/galleria/themes/fullscreen/i.png b/script/galleria/themes/fullscreen/i.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e61d85cf5c3d76932e0ddb3bf988d9a56faec7a
Binary files /dev/null and b/script/galleria/themes/fullscreen/i.png differ
diff --git a/script/galleria/themes/fullscreen/index.html b/script/galleria/themes/fullscreen/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/script/galleria/themes/fullscreen/l-neg.png b/script/galleria/themes/fullscreen/l-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c47490397a25816e3e193da19b094b8a0afb24d
Binary files /dev/null and b/script/galleria/themes/fullscreen/l-neg.png differ
diff --git a/script/galleria/themes/fullscreen/l.gif b/script/galleria/themes/fullscreen/l.gif
new file mode 100644
index 0000000000000000000000000000000000000000..36b43faf7eb2c02e76ed30359dc95375324977db
Binary files /dev/null and b/script/galleria/themes/fullscreen/l.gif differ
diff --git a/script/galleria/themes/fullscreen/loader.gif b/script/galleria/themes/fullscreen/loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e0057080d42b2b892e0c5c4ebd59cde3fc420afd
Binary files /dev/null and b/script/galleria/themes/fullscreen/loader.gif differ
diff --git a/script/galleria/themes/fullscreen/n-neg.png b/script/galleria/themes/fullscreen/n-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..61c9b3f94052bc80411a0873e03f751f333ac1ba
Binary files /dev/null and b/script/galleria/themes/fullscreen/n-neg.png differ
diff --git a/script/galleria/themes/fullscreen/n.gif b/script/galleria/themes/fullscreen/n.gif
new file mode 100644
index 0000000000000000000000000000000000000000..df1d4ed9e08d32abb0517b55471e3e56a2078aac
Binary files /dev/null and b/script/galleria/themes/fullscreen/n.gif differ
diff --git a/script/galleria/themes/fullscreen/p-neg.png b/script/galleria/themes/fullscreen/p-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..aeee4121d16b2950aabba0d8f6a0ed85f2de6327
Binary files /dev/null and b/script/galleria/themes/fullscreen/p-neg.png differ
diff --git a/script/galleria/themes/fullscreen/p.gif b/script/galleria/themes/fullscreen/p.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9626e4ecdda1b24eb8092850a3d59213ccf52c70
Binary files /dev/null and b/script/galleria/themes/fullscreen/p.gif differ
diff --git a/script/galleria/themes/fullscreen/r-neg.png b/script/galleria/themes/fullscreen/r-neg.png
new file mode 100644
index 0000000000000000000000000000000000000000..dc909aa59507e3f164d8558191a3fa51e76aa850
Binary files /dev/null and b/script/galleria/themes/fullscreen/r-neg.png differ
diff --git a/script/galleria/themes/fullscreen/r.gif b/script/galleria/themes/fullscreen/r.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2d6a6ead72fd83cf98b13f92af559ac4fe0bf517
Binary files /dev/null and b/script/galleria/themes/fullscreen/r.gif differ
diff --git a/script/galleria/themes/fullscreen/up-neg.gif b/script/galleria/themes/fullscreen/up-neg.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d9556e7fc6a844cec4dd0b415223af7d33934977
Binary files /dev/null and b/script/galleria/themes/fullscreen/up-neg.gif differ
diff --git a/script/galleria/themes/fullscreen/up.gif b/script/galleria/themes/fullscreen/up.gif
new file mode 100644
index 0000000000000000000000000000000000000000..fc00d14fffcec4330eaf8b5afe7360a7c9fd786e
Binary files /dev/null and b/script/galleria/themes/fullscreen/up.gif differ
diff --git a/vorstandsgesch.md b/vorstandsgesch.md
new file mode 100644
index 0000000000000000000000000000000000000000..1092bea1ee6672abe8691d937b105f83d6e28f7f
--- /dev/null
+++ b/vorstandsgesch.md
@@ -0,0 +1,11 @@
+---
+layout: verein
+title: Verein
+permalink: /verein/geschaeftsordnung
+aside: true
+feature_image: "https://chaotikum.org/_media/hackerspace:nbsp:nbspvonoben.jpg"
+---
+
+### Geschäftsordnung des Vorstands
+
+...