diff --git a/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery-indicator.css b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery-indicator.css
new file mode 100644
index 000000000..e47171a3c
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery-indicator.css
@@ -0,0 +1,71 @@
+@charset "UTF-8";
+/*
+ * blueimp Gallery Indicator CSS 1.1.0
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+.blueimp-gallery > .indicator {
+ position: absolute;
+ top: auto;
+ right: 15px;
+ bottom: 15px;
+ left: 15px;
+ margin: 0 40px;
+ padding: 0;
+ list-style: none;
+ text-align: center;
+ line-height: 10px;
+ display: none;
+}
+.blueimp-gallery > .indicator > li {
+ display: inline-block;
+ width: 9px;
+ height: 9px;
+ margin: 6px 3px 0 3px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ border: 1px solid transparent;
+ background: #ccc;
+ background: rgba(255, 255, 255, 0.25) center no-repeat;
+ border-radius: 5px;
+ box-shadow: 0 0 2px #000;
+ opacity: 0.5;
+ cursor: pointer;
+}
+.blueimp-gallery > .indicator > li:hover,
+.blueimp-gallery > .indicator > .active {
+ background-color: #fff;
+ border-color: #fff;
+ opacity: 1;
+}
+.blueimp-gallery-controls > .indicator {
+ display: block;
+ /* Fix z-index issues (controls behind slide element) on Android: */
+ -webkit-transform: translateZ(0);
+ -moz-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ -o-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.blueimp-gallery-single > .indicator {
+ display: none;
+}
+.blueimp-gallery > .indicator {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+/* IE7 fixes */
+*+html .blueimp-gallery > .indicator > li {
+ display: inline;
+}
diff --git a/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery-video.css b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery-video.css
new file mode 100644
index 000000000..59695647a
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery-video.css
@@ -0,0 +1,87 @@
+@charset "UTF-8";
+/*
+ * blueimp Gallery Video Factory CSS 1.3.0
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+.blueimp-gallery > .slides > .slide > .video-content > img {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin: auto;
+ width: auto;
+ height: auto;
+ max-width: 100%;
+ max-height: 100%;
+ /* Prevent artifacts in Mozilla Firefox: */
+ -moz-backface-visibility: hidden;
+}
+.blueimp-gallery > .slides > .slide > .video-content > video {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+.blueimp-gallery > .slides > .slide > .video-content > iframe {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: none;
+}
+.blueimp-gallery > .slides > .slide > .video-playing > iframe {
+ top: 0;
+}
+.blueimp-gallery > .slides > .slide > .video-content > a {
+ position: absolute;
+ top: 50%;
+ right: 0;
+ left: 0;
+ margin: -64px auto 0;
+ width: 128px;
+ height: 128px;
+ background: url(../img/video-play.png) center no-repeat;
+ opacity: 0.8;
+ cursor: pointer;
+}
+.blueimp-gallery > .slides > .slide > .video-content > a:hover {
+ opacity: 1;
+}
+.blueimp-gallery > .slides > .slide > .video-playing > a,
+.blueimp-gallery > .slides > .slide > .video-playing > img {
+ display: none;
+}
+.blueimp-gallery > .slides > .slide > .video-content > video {
+ display: none;
+}
+.blueimp-gallery > .slides > .slide > .video-playing > video {
+ display: block;
+}
+.blueimp-gallery > .slides > .slide > .video-loading > a {
+ background: url(../img/loading.gif) center no-repeat;
+ background-size: 64px 64px;
+}
+
+/* Replace PNGs with SVGs for capable browsers (excluding IE<9) */
+body:last-child .blueimp-gallery > .slides > .slide > .video-content:not(.video-loading) > a {
+ background-image: url(../img/video-play.svg);
+}
+
+/* IE7 fixes */
+*+html .blueimp-gallery > .slides > .slide > .video-content {
+ height: 100%;
+}
+*+html .blueimp-gallery > .slides > .slide > .video-content > a {
+ left: 50%;
+ margin-left: -64px;
+}
diff --git a/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery.css b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery.css
new file mode 100644
index 000000000..b860d7864
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery.css
@@ -0,0 +1,226 @@
+@charset "UTF-8";
+/*
+ * blueimp Gallery CSS 2.11.1
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+.blueimp-gallery,
+.blueimp-gallery > .slides > .slide > .slide-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ /* Prevent artifacts in Mozilla Firefox: */
+ -moz-backface-visibility: hidden;
+}
+.blueimp-gallery > .slides > .slide > .slide-content {
+ margin: auto;
+ width: auto;
+ height: auto;
+ max-width: 100%;
+ max-height: 100%;
+ opacity: 1;
+}
+.blueimp-gallery {
+ position: fixed;
+ z-index: 999999;
+ overflow: hidden;
+ background: #000;
+ background: rgba(0, 0, 0, 0.9);
+ opacity: 0;
+ display: none;
+ direction: ltr;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.blueimp-gallery-carousel {
+ position: relative;
+ z-index: auto;
+ margin: 1em auto;
+ /* Set the carousel width/height ratio to 16/9: */
+ padding-bottom: 56.25%;
+ box-shadow: 0 0 10px #000;
+ -ms-touch-action: pan-y;
+ touch-action: pan-y;
+}
+.blueimp-gallery-display {
+ display: block;
+ opacity: 1;
+}
+.blueimp-gallery > .slides {
+ position: relative;
+ height: 100%;
+ overflow: hidden;
+}
+.blueimp-gallery-carousel > .slides {
+ position: absolute;
+}
+.blueimp-gallery > .slides > .slide {
+ position: relative;
+ float: left;
+ height: 100%;
+ text-align: center;
+ -webkit-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
+ -moz-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
+ -ms-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
+ -o-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
+ transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
+}
+.blueimp-gallery,
+.blueimp-gallery > .slides > .slide > .slide-content {
+ -webkit-transition: opacity 0.5s linear;
+ -moz-transition: opacity 0.5s linear;
+ -ms-transition: opacity 0.5s linear;
+ -o-transition: opacity 0.5s linear;
+ transition: opacity 0.5s linear;
+}
+.blueimp-gallery > .slides > .slide-loading {
+ background: url(../img/loading.gif) center no-repeat;
+ background-size: 64px 64px;
+}
+.blueimp-gallery > .slides > .slide-loading > .slide-content {
+ opacity: 0;
+}
+.blueimp-gallery > .slides > .slide-error {
+ background: url(../img/error.png) center no-repeat;
+}
+.blueimp-gallery > .slides > .slide-error > .slide-content {
+ display: none;
+}
+.blueimp-gallery > .prev,
+.blueimp-gallery > .next {
+ position: absolute;
+ top: 50%;
+ left: 15px;
+ width: 40px;
+ height: 40px;
+ margin-top: -23px;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 60px;
+ font-weight: 100;
+ line-height: 30px;
+ color: #fff;
+ text-decoration: none;
+ text-shadow: 0 0 2px #000;
+ text-align: center;
+ background: #222;
+ background: rgba(0, 0, 0, 0.5);
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ border: 3px solid #fff;
+ -webkit-border-radius: 23px;
+ -moz-border-radius: 23px;
+ border-radius: 23px;
+ opacity: 0.5;
+ cursor: pointer;
+ display: none;
+}
+.blueimp-gallery > .next {
+ left: auto;
+ right: 15px;
+}
+.blueimp-gallery > .close,
+.blueimp-gallery > .title {
+ position: absolute;
+ top: 15px;
+ left: 15px;
+ margin: 0 40px 0 0;
+ font-size: 20px;
+ line-height: 30px;
+ color: #fff;
+ text-shadow: 0 0 2px #000;
+ opacity: 0.8;
+ display: none;
+}
+.blueimp-gallery > .close {
+ padding: 15px;
+ right: 15px;
+ left: auto;
+ margin: -15px;
+ font-size: 30px;
+ text-decoration: none;
+ cursor: pointer;
+}
+.blueimp-gallery > .play-pause {
+ position: absolute;
+ right: 15px;
+ bottom: 15px;
+ width: 15px;
+ height: 15px;
+ background: url(../img/play-pause.png) 0 0 no-repeat;
+ cursor: pointer;
+ opacity: 0.5;
+ display: none;
+}
+.blueimp-gallery-playing > .play-pause {
+ background-position: -15px 0;
+}
+.blueimp-gallery > .prev:hover,
+.blueimp-gallery > .next:hover,
+.blueimp-gallery > .close:hover,
+.blueimp-gallery > .title:hover,
+.blueimp-gallery > .play-pause:hover {
+ color: #fff;
+ opacity: 1;
+}
+.blueimp-gallery-controls > .prev,
+.blueimp-gallery-controls > .next,
+.blueimp-gallery-controls > .close,
+.blueimp-gallery-controls > .title,
+.blueimp-gallery-controls > .play-pause {
+ display: block;
+ /* Fix z-index issues (controls behind slide element) on Android: */
+ -webkit-transform: translateZ(0);
+ -moz-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ -o-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.blueimp-gallery-single > .prev,
+.blueimp-gallery-left > .prev,
+.blueimp-gallery-single > .next,
+.blueimp-gallery-right > .next,
+.blueimp-gallery-single > .play-pause {
+ display: none;
+}
+.blueimp-gallery > .slides > .slide > .slide-content,
+.blueimp-gallery > .prev,
+.blueimp-gallery > .next,
+.blueimp-gallery > .close,
+.blueimp-gallery > .play-pause {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+/* Replace PNGs with SVGs for capable browsers (excluding IE<9) */
+body:last-child .blueimp-gallery > .slides > .slide-error {
+ background-image: url(../img/error.svg);
+}
+body:last-child .blueimp-gallery > .play-pause {
+ width: 20px;
+ height: 20px;
+ background-size: 40px 20px;
+ background-image: url(../img/play-pause.svg);
+}
+body:last-child .blueimp-gallery-playing > .play-pause {
+ background-position: -20px 0;
+}
+
+/* IE7 fixes */
+*+html .blueimp-gallery > .slides > .slide {
+ min-height: 300px;
+}
+*+html .blueimp-gallery > .slides > .slide > .slide-content {
+ position: relative;
+}
diff --git a/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery.min.css b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery.min.css
new file mode 100644
index 000000000..c65eaa051
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/css/blueimp-gallery.min.css
@@ -0,0 +1 @@
+@charset "UTF-8";.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{position:absolute;top:0;right:0;bottom:0;left:0;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.slide-content{margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;opacity:1}.blueimp-gallery{position:fixed;z-index:999999;overflow:hidden;background:#000;background:rgba(0,0,0,.9);opacity:0;display:none;direction:ltr;-ms-touch-action:none;touch-action:none}.blueimp-gallery-carousel{position:relative;z-index:auto;margin:1em auto;padding-bottom:56.25%;box-shadow:0 0 10px #000;-ms-touch-action:pan-y;touch-action:pan-y}.blueimp-gallery-display{display:block;opacity:1}.blueimp-gallery>.slides{position:relative;height:100%;overflow:hidden}.blueimp-gallery-carousel>.slides{position:absolute}.blueimp-gallery>.slides>.slide{position:relative;float:left;height:100%;text-align:center;-webkit-transition-timing-function:cubic-bezier(0.645,.045,.355,1);-moz-transition-timing-function:cubic-bezier(0.645,.045,.355,1);-ms-transition-timing-function:cubic-bezier(0.645,.045,.355,1);-o-transition-timing-function:cubic-bezier(0.645,.045,.355,1);transition-timing-function:cubic-bezier(0.645,.045,.355,1)}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{-webkit-transition:opacity .5s linear;-moz-transition:opacity .5s linear;-ms-transition:opacity .5s linear;-o-transition:opacity .5s linear;transition:opacity .5s linear}.blueimp-gallery>.slides>.slide-loading{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery>.slides>.slide-loading>.slide-content{opacity:0}.blueimp-gallery>.slides>.slide-error{background:url(../img/error.png) center no-repeat}.blueimp-gallery>.slides>.slide-error>.slide-content{display:none}.blueimp-gallery>.prev,.blueimp-gallery>.next{position:absolute;top:50%;left:15px;width:40px;height:40px;margin-top:-23px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-decoration:none;text-shadow:0 0 2px #000;text-align:center;background:#222;background:rgba(0,0,0,.5);-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;cursor:pointer;display:none}.blueimp-gallery>.next{left:auto;right:15px}.blueimp-gallery>.close,.blueimp-gallery>.title{position:absolute;top:15px;left:15px;margin:0 40px 0 0;font-size:20px;line-height:30px;color:#fff;text-shadow:0 0 2px #000;opacity:.8;display:none}.blueimp-gallery>.close{padding:15px;right:15px;left:auto;margin:-15px;font-size:30px;text-decoration:none;cursor:pointer}.blueimp-gallery>.play-pause{position:absolute;right:15px;bottom:15px;width:15px;height:15px;background:url(../img/play-pause.png) 0 0 no-repeat;cursor:pointer;opacity:.5;display:none}.blueimp-gallery-playing>.play-pause{background-position:-15px 0}.blueimp-gallery>.prev:hover,.blueimp-gallery>.next:hover,.blueimp-gallery>.close:hover,.blueimp-gallery>.title:hover,.blueimp-gallery>.play-pause:hover{color:#fff;opacity:1}.blueimp-gallery-controls>.prev,.blueimp-gallery-controls>.next,.blueimp-gallery-controls>.close,.blueimp-gallery-controls>.title,.blueimp-gallery-controls>.play-pause{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.prev,.blueimp-gallery-left>.prev,.blueimp-gallery-single>.next,.blueimp-gallery-right>.next,.blueimp-gallery-single>.play-pause{display:none}.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.prev,.blueimp-gallery>.next,.blueimp-gallery>.close,.blueimp-gallery>.play-pause{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:last-child .blueimp-gallery>.slides>.slide-error{background-image:url(../img/error.svg)}body:last-child .blueimp-gallery>.play-pause{width:20px;height:20px;background-size:40px 20px;background-image:url(../img/play-pause.svg)}body:last-child .blueimp-gallery-playing>.play-pause{background-position:-20px 0}*+html .blueimp-gallery>.slides>.slide{min-height:300px}*+html .blueimp-gallery>.slides>.slide>.slide-content{position:relative}@charset "UTF-8";.blueimp-gallery>.indicator{position:absolute;top:auto;right:15px;bottom:15px;left:15px;margin:0 40px;padding:0;list-style:none;text-align:center;line-height:10px;display:none}.blueimp-gallery>.indicator>li{display:inline-block;width:9px;height:9px;margin:6px 3px 0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;border:1px solid transparent;background:#ccc;background:rgba(255,255,255,.25)center no-repeat;border-radius:5px;box-shadow:0 0 2px #000;opacity:.5;cursor:pointer}.blueimp-gallery>.indicator>li:hover,.blueimp-gallery>.indicator>.active{background-color:#fff;border-color:#fff;opacity:1}.blueimp-gallery-controls>.indicator{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.indicator{display:none}.blueimp-gallery>.indicator{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}*+html .blueimp-gallery>.indicator>li{display:inline}@charset "UTF-8";.blueimp-gallery>.slides>.slide>.video-content>img{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.video-content>video{position:absolute;top:0;left:0;width:100%;height:100%}.blueimp-gallery>.slides>.slide>.video-content>iframe{position:absolute;top:100%;left:0;width:100%;height:100%;border:none}.blueimp-gallery>.slides>.slide>.video-playing>iframe{top:0}.blueimp-gallery>.slides>.slide>.video-content>a{position:absolute;top:50%;right:0;left:0;margin:-64px auto 0;width:128px;height:128px;background:url(../img/video-play.png) center no-repeat;opacity:.8;cursor:pointer}.blueimp-gallery>.slides>.slide>.video-content>a:hover{opacity:1}.blueimp-gallery>.slides>.slide>.video-playing>a,.blueimp-gallery>.slides>.slide>.video-playing>img{display:none}.blueimp-gallery>.slides>.slide>.video-content>video{display:none}.blueimp-gallery>.slides>.slide>.video-playing>video{display:block}.blueimp-gallery>.slides>.slide>.video-loading>a{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}body:last-child .blueimp-gallery>.slides>.slide>.video-content:not(.video-loading)>a{background-image:url(../img/video-play.svg)}*+html .blueimp-gallery>.slides>.slide>.video-content{height:100%}*+html .blueimp-gallery>.slides>.slide>.video-content>a{left:50%;margin-left:-64px}
\ No newline at end of file
diff --git a/ajax/libs/blueimp-gallery/2.15.1/img/error.png b/ajax/libs/blueimp-gallery/2.15.1/img/error.png
new file mode 100644
index 000000000..a5577c33a
Binary files /dev/null and b/ajax/libs/blueimp-gallery/2.15.1/img/error.png differ
diff --git a/ajax/libs/blueimp-gallery/2.15.1/img/error.svg b/ajax/libs/blueimp-gallery/2.15.1/img/error.svg
new file mode 100644
index 000000000..184206a14
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/img/error.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/ajax/libs/blueimp-gallery/2.15.1/img/loading.gif b/ajax/libs/blueimp-gallery/2.15.1/img/loading.gif
new file mode 100644
index 000000000..90f28cbdb
Binary files /dev/null and b/ajax/libs/blueimp-gallery/2.15.1/img/loading.gif differ
diff --git a/ajax/libs/blueimp-gallery/2.15.1/img/play-pause.png b/ajax/libs/blueimp-gallery/2.15.1/img/play-pause.png
new file mode 100644
index 000000000..ece6cfb9b
Binary files /dev/null and b/ajax/libs/blueimp-gallery/2.15.1/img/play-pause.png differ
diff --git a/ajax/libs/blueimp-gallery/2.15.1/img/play-pause.svg b/ajax/libs/blueimp-gallery/2.15.1/img/play-pause.svg
new file mode 100644
index 000000000..a7f1f50cd
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/img/play-pause.svg
@@ -0,0 +1,6 @@
+
+
diff --git a/ajax/libs/blueimp-gallery/2.15.1/img/video-play.png b/ajax/libs/blueimp-gallery/2.15.1/img/video-play.png
new file mode 100644
index 000000000..353e3a592
Binary files /dev/null and b/ajax/libs/blueimp-gallery/2.15.1/img/video-play.png differ
diff --git a/ajax/libs/blueimp-gallery/2.15.1/img/video-play.svg b/ajax/libs/blueimp-gallery/2.15.1/img/video-play.svg
new file mode 100644
index 000000000..b5ea206dd
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/img/video-play.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-fullscreen.js b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-fullscreen.js
new file mode 100644
index 000000000..eb0de1136
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-fullscreen.js
@@ -0,0 +1,90 @@
+/*
+ * blueimp Gallery Fullscreen JS 1.2.0
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/* global define, window, document */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ './blueimp-helper',
+ './blueimp-gallery'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.blueimp.helper || window.jQuery,
+ window.blueimp.Gallery
+ );
+ }
+}(function ($, Gallery) {
+ 'use strict';
+
+ $.extend(Gallery.prototype.options, {
+ // Defines if the gallery should open in fullscreen mode:
+ fullScreen: false
+ });
+
+ var initialize = Gallery.prototype.initialize,
+ close = Gallery.prototype.close;
+
+ $.extend(Gallery.prototype, {
+
+ getFullScreenElement: function () {
+ return document.fullscreenElement ||
+ document.webkitFullscreenElement ||
+ document.mozFullScreenElement ||
+ document.msFullscreenElement;
+ },
+
+ requestFullScreen: function (element) {
+ if (element.requestFullscreen) {
+ element.requestFullscreen();
+ } else if (element.webkitRequestFullscreen) {
+ element.webkitRequestFullscreen();
+ } else if (element.mozRequestFullScreen) {
+ element.mozRequestFullScreen();
+ } else if (element.msRequestFullscreen) {
+ element.msRequestFullscreen();
+ }
+ },
+
+ exitFullScreen: function () {
+ if (document.exitFullscreen) {
+ document.exitFullscreen();
+ } else if (document.webkitCancelFullScreen) {
+ document.webkitCancelFullScreen();
+ } else if (document.mozCancelFullScreen) {
+ document.mozCancelFullScreen();
+ } else if (document.msExitFullscreen) {
+ document.msExitFullscreen();
+ }
+ },
+
+ initialize: function () {
+ initialize.call(this);
+ if (this.options.fullScreen && !this.getFullScreenElement()) {
+ this.requestFullScreen(this.container[0]);
+ }
+ },
+
+ close: function () {
+ if (this.getFullScreenElement() === this.container[0]) {
+ this.exitFullScreen();
+ }
+ close.call(this);
+ }
+
+ });
+
+ return Gallery;
+}));
diff --git a/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-indicator.js b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-indicator.js
new file mode 100644
index 000000000..cd0cf7d5e
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-indicator.js
@@ -0,0 +1,153 @@
+/*
+ * blueimp Gallery Indicator JS 1.1.0
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/* global define, window, document */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ './blueimp-helper',
+ './blueimp-gallery'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.blueimp.helper || window.jQuery,
+ window.blueimp.Gallery
+ );
+ }
+}(function ($, Gallery) {
+ 'use strict';
+
+ $.extend(Gallery.prototype.options, {
+ // The tag name, Id, element or querySelector of the indicator container:
+ indicatorContainer: 'ol',
+ // The class for the active indicator:
+ activeIndicatorClass: 'active',
+ // The list object property (or data attribute) with the thumbnail URL,
+ // used as alternative to a thumbnail child element:
+ thumbnailProperty: 'thumbnail',
+ // Defines if the gallery indicators should display a thumbnail:
+ thumbnailIndicators: true
+ });
+
+ var initSlides = Gallery.prototype.initSlides,
+ addSlide = Gallery.prototype.addSlide,
+ resetSlides = Gallery.prototype.resetSlides,
+ handleClick = Gallery.prototype.handleClick,
+ handleSlide = Gallery.prototype.handleSlide,
+ handleClose = Gallery.prototype.handleClose;
+
+ $.extend(Gallery.prototype, {
+
+ createIndicator: function (obj) {
+ var indicator = this.indicatorPrototype.cloneNode(false),
+ title = this.getItemProperty(obj, this.options.titleProperty),
+ thumbnailProperty = this.options.thumbnailProperty,
+ thumbnailUrl,
+ thumbnail;
+ if (this.options.thumbnailIndicators) {
+ thumbnail = obj.getElementsByTagName && $(obj).find('img')[0];
+ if (thumbnail) {
+ thumbnailUrl = thumbnail.src;
+ } else if (thumbnailProperty) {
+ thumbnailUrl = this.getItemProperty(obj, thumbnailProperty);
+ }
+ if (thumbnailUrl) {
+ indicator.style.backgroundImage = 'url("' + thumbnailUrl + '")';
+ }
+ }
+ if (title) {
+ indicator.title = title;
+ }
+ return indicator;
+ },
+
+ addIndicator: function (index) {
+ if (this.indicatorContainer.length) {
+ var indicator = this.createIndicator(this.list[index]);
+ indicator.setAttribute('data-index', index);
+ this.indicatorContainer[0].appendChild(indicator);
+ this.indicators.push(indicator);
+ }
+ },
+
+ setActiveIndicator: function (index) {
+ if (this.indicators) {
+ if (this.activeIndicator) {
+ this.activeIndicator
+ .removeClass(this.options.activeIndicatorClass);
+ }
+ this.activeIndicator = $(this.indicators[index]);
+ this.activeIndicator
+ .addClass(this.options.activeIndicatorClass);
+ }
+ },
+
+ initSlides: function (reload) {
+ if (!reload) {
+ this.indicatorContainer = this.container.find(
+ this.options.indicatorContainer
+ );
+ if (this.indicatorContainer.length) {
+ this.indicatorPrototype = document.createElement('li');
+ this.indicators = this.indicatorContainer[0].children;
+ }
+ }
+ initSlides.call(this, reload);
+ },
+
+ addSlide: function (index) {
+ addSlide.call(this, index);
+ this.addIndicator(index);
+ },
+
+ resetSlides: function () {
+ resetSlides.call(this);
+ this.indicatorContainer.empty();
+ this.indicators = [];
+ },
+
+ handleClick: function (event) {
+ var target = event.target || event.srcElement,
+ parent = target.parentNode;
+ if (parent === this.indicatorContainer[0]) {
+ // Click on indicator element
+ this.preventDefault(event);
+ this.slide(this.getNodeIndex(target));
+ } else if (parent.parentNode === this.indicatorContainer[0]) {
+ // Click on indicator child element
+ this.preventDefault(event);
+ this.slide(this.getNodeIndex(parent));
+ } else {
+ return handleClick.call(this, event);
+ }
+ },
+
+ handleSlide: function (index) {
+ handleSlide.call(this, index);
+ this.setActiveIndicator(index);
+ },
+
+ handleClose: function () {
+ if (this.activeIndicator) {
+ this.activeIndicator
+ .removeClass(this.options.activeIndicatorClass);
+ }
+ handleClose.call(this);
+ }
+
+ });
+
+ return Gallery;
+}));
diff --git a/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-video.js b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-video.js
new file mode 100644
index 000000000..ee0343554
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-video.js
@@ -0,0 +1,171 @@
+/*
+ * blueimp Gallery Video Factory JS 1.1.1
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/* global define, window, document */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ './blueimp-helper',
+ './blueimp-gallery'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.blueimp.helper || window.jQuery,
+ window.blueimp.Gallery
+ );
+ }
+}(function ($, Gallery) {
+ 'use strict';
+
+ $.extend(Gallery.prototype.options, {
+ // The class for video content elements:
+ videoContentClass: 'video-content',
+ // The class for video when it is loading:
+ videoLoadingClass: 'video-loading',
+ // The class for video when it is playing:
+ videoPlayingClass: 'video-playing',
+ // The list object property (or data attribute) for the video poster URL:
+ videoPosterProperty: 'poster',
+ // The list object property (or data attribute) for the video sources array:
+ videoSourcesProperty: 'sources'
+ });
+
+ var handleSlide = Gallery.prototype.handleSlide;
+
+ $.extend(Gallery.prototype, {
+
+ handleSlide: function (index) {
+ handleSlide.call(this, index);
+ if (this.playingVideo) {
+ this.playingVideo.pause();
+ }
+ },
+
+ videoFactory: function (obj, callback, videoInterface) {
+ var that = this,
+ options = this.options,
+ videoContainerNode = this.elementPrototype.cloneNode(false),
+ videoContainer = $(videoContainerNode),
+ errorArgs = [{
+ type: 'error',
+ target: videoContainerNode
+ }],
+ video = videoInterface || document.createElement('video'),
+ url = this.getItemProperty(obj, options.urlProperty),
+ type = this.getItemProperty(obj, options.typeProperty),
+ title = this.getItemProperty(obj, options.titleProperty),
+ posterUrl = this.getItemProperty(obj, options.videoPosterProperty),
+ posterImage,
+ sources = this.getItemProperty(
+ obj,
+ options.videoSourcesProperty
+ ),
+ source,
+ playMediaControl,
+ isLoading,
+ hasControls;
+ videoContainer.addClass(options.videoContentClass);
+ if (title) {
+ videoContainerNode.title = title;
+ }
+ if (video.canPlayType) {
+ if (url && type && video.canPlayType(type)) {
+ video.src = url;
+ } else {
+ while (sources && sources.length) {
+ source = sources.shift();
+ url = this.getItemProperty(source, options.urlProperty);
+ type = this.getItemProperty(source, options.typeProperty);
+ if (url && type && video.canPlayType(type)) {
+ video.src = url;
+ break;
+ }
+ }
+ }
+ }
+ if (posterUrl) {
+ video.poster = posterUrl;
+ posterImage = this.imagePrototype.cloneNode(false);
+ $(posterImage).addClass(options.toggleClass);
+ posterImage.src = posterUrl;
+ posterImage.draggable = false;
+ videoContainerNode.appendChild(posterImage);
+ }
+ playMediaControl = document.createElement('a');
+ playMediaControl.setAttribute('target', '_blank');
+ if (!videoInterface) {
+ playMediaControl.setAttribute('download', title);
+ }
+ playMediaControl.href = url;
+ if (video.src) {
+ video.controls = true;
+ (videoInterface || $(video))
+ .on('error', function () {
+ that.setTimeout(callback, errorArgs);
+ })
+ .on('pause', function () {
+ isLoading = false;
+ videoContainer
+ .removeClass(that.options.videoLoadingClass)
+ .removeClass(that.options.videoPlayingClass);
+ if (hasControls) {
+ that.container.addClass(that.options.controlsClass);
+ }
+ delete that.playingVideo;
+ if (that.interval) {
+ that.play();
+ }
+ })
+ .on('playing', function () {
+ isLoading = false;
+ videoContainer
+ .removeClass(that.options.videoLoadingClass)
+ .addClass(that.options.videoPlayingClass);
+ if (that.container.hasClass(that.options.controlsClass)) {
+ hasControls = true;
+ that.container.removeClass(that.options.controlsClass);
+ } else {
+ hasControls = false;
+ }
+ })
+ .on('play', function () {
+ window.clearTimeout(that.timeout);
+ isLoading = true;
+ videoContainer.addClass(that.options.videoLoadingClass);
+ that.playingVideo = video;
+ });
+ $(playMediaControl).on('click', function (event) {
+ that.preventDefault(event);
+ if (isLoading) {
+ video.pause();
+ } else {
+ video.play();
+ }
+ });
+ videoContainerNode.appendChild(
+ (videoInterface && videoInterface.element) || video
+ );
+ }
+ videoContainerNode.appendChild(playMediaControl);
+ this.setTimeout(callback, [{
+ type: 'load',
+ target: videoContainerNode
+ }]);
+ return videoContainerNode;
+ }
+ });
+
+ return Gallery;
+}));
diff --git a/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-vimeo.js b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-vimeo.js
new file mode 100644
index 000000000..6ffff646b
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-vimeo.js
@@ -0,0 +1,215 @@
+/*
+ * blueimp Gallery Vimeo Video Factory JS 1.2.0
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/* global define, window, document, location, $f */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ './blueimp-helper',
+ './blueimp-gallery-video'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.blueimp.helper || window.jQuery,
+ window.blueimp.Gallery
+ );
+ }
+}(function ($, Gallery) {
+ 'use strict';
+
+ if (!window.postMessage) {
+ return Gallery;
+ }
+
+ $.extend(Gallery.prototype.options, {
+ // The list object property (or data attribute) with the Vimeo video id:
+ vimeoVideoIdProperty: 'vimeo',
+ // The URL for the Vimeo video player, can be extended with custom parameters:
+ // https://developer.vimeo.com/player/embedding
+ vimeoPlayerUrl: '//player.vimeo.com/video/VIDEO_ID?api=1&player_id=PLAYER_ID',
+ // The prefix for the Vimeo video player ID:
+ vimeoPlayerIdPrefix: 'vimeo-player-',
+ // Require a click on the native Vimeo player for the initial playback:
+ vimeoClickToPlay: true
+ });
+
+ var textFactory = Gallery.prototype.textFactory || Gallery.prototype.imageFactory,
+ VimeoPlayer = function (url, videoId, playerId, clickToPlay) {
+ this.url = url;
+ this.videoId = videoId;
+ this.playerId = playerId;
+ this.clickToPlay = clickToPlay;
+ this.element = document.createElement('div');
+ this.listeners = {};
+ },
+ counter = 0;
+
+ $.extend(VimeoPlayer.prototype, {
+
+ canPlayType: function () {
+ return true;
+ },
+
+ on: function (type, func) {
+ this.listeners[type] = func;
+ return this;
+ },
+
+ loadAPI: function () {
+ var that = this,
+ apiUrl = '//' + (location.protocol === 'https' ? 'secure-' : '') +
+ 'a.vimeocdn.com/js/froogaloop2.min.js',
+ scriptTags = document.getElementsByTagName('script'),
+ i = scriptTags.length,
+ scriptTag,
+ called,
+ callback = function () {
+ if (!called && that.playOnReady) {
+ that.play();
+ }
+ called = true;
+ };
+ while (i) {
+ i -= 1;
+ if (scriptTags[i].src === apiUrl) {
+ scriptTag = scriptTags[i];
+ break;
+ }
+ }
+ if (!scriptTag) {
+ scriptTag = document.createElement('script');
+ scriptTag.src = apiUrl;
+ }
+ $(scriptTag).on('load', callback);
+ scriptTags[0].parentNode.insertBefore(scriptTag, scriptTags[0]);
+ // Fix for cached scripts on IE 8:
+ if (/loaded|complete/.test(scriptTag.readyState)) {
+ callback();
+ }
+ },
+
+ onReady: function () {
+ var that = this;
+ this.ready = true;
+ this.player.addEvent('play', function () {
+ that.hasPlayed = true;
+ that.onPlaying();
+ });
+ this.player.addEvent('pause', function () {
+ that.onPause();
+ });
+ this.player.addEvent('finish', function () {
+ that.onPause();
+ });
+ if (this.playOnReady) {
+ this.play();
+ }
+ },
+
+ onPlaying: function () {
+ if (this.playStatus < 2) {
+ this.listeners.playing();
+ this.playStatus = 2;
+ }
+ },
+
+ onPause: function () {
+ this.listeners.pause();
+ delete this.playStatus;
+ },
+
+ insertIframe: function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = this.url
+ .replace('VIDEO_ID', this.videoId)
+ .replace('PLAYER_ID', this.playerId);
+ iframe.id = this.playerId;
+ this.element.parentNode.replaceChild(iframe, this.element);
+ this.element = iframe;
+ },
+
+ play: function () {
+ var that = this;
+ if (!this.playStatus) {
+ this.listeners.play();
+ this.playStatus = 1;
+ }
+ if (this.ready) {
+ if (!this.hasPlayed && (this.clickToPlay || (window.navigator &&
+ /iP(hone|od|ad)/.test(window.navigator.platform)))) {
+ // Manually trigger the playing callback if clickToPlay
+ // is enabled and to workaround a limitation in iOS,
+ // which requires synchronous user interaction to start
+ // the video playback:
+ this.onPlaying();
+ } else {
+ this.player.api('play');
+ }
+ } else {
+ this.playOnReady = true;
+ if (!window.$f) {
+ this.loadAPI();
+ } else if (!this.player) {
+ this.insertIframe();
+ this.player = $f(this.element);
+ this.player.addEvent('ready', function () {
+ that.onReady();
+ });
+ }
+ }
+ },
+
+ pause: function () {
+ if (this.ready) {
+ this.player.api('pause');
+ } else if (this.playStatus) {
+ delete this.playOnReady;
+ this.listeners.pause();
+ delete this.playStatus;
+ }
+ }
+
+ });
+
+ $.extend(Gallery.prototype, {
+
+ VimeoPlayer: VimeoPlayer,
+
+ textFactory: function (obj, callback) {
+ var options = this.options,
+ videoId = this.getItemProperty(obj, options.vimeoVideoIdProperty);
+ if (videoId) {
+ if (this.getItemProperty(obj, options.urlProperty) === undefined) {
+ obj[options.urlProperty] = '//vimeo.com/' + videoId;
+ }
+ counter += 1;
+ return this.videoFactory(
+ obj,
+ callback,
+ new VimeoPlayer(
+ options.vimeoPlayerUrl,
+ videoId,
+ options.vimeoPlayerIdPrefix + counter,
+ options.vimeoClickToPlay
+ )
+ );
+ }
+ return textFactory.call(this, obj, callback);
+ }
+
+ });
+
+ return Gallery;
+}));
diff --git a/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-youtube.js b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-youtube.js
new file mode 100644
index 000000000..da8831daa
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery-youtube.js
@@ -0,0 +1,229 @@
+/*
+ * blueimp Gallery YouTube Video Factory JS 1.2.0
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/* global define, window, document, YT */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ './blueimp-helper',
+ './blueimp-gallery-video'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.blueimp.helper || window.jQuery,
+ window.blueimp.Gallery
+ );
+ }
+}(function ($, Gallery) {
+ 'use strict';
+
+ if (!window.postMessage) {
+ return Gallery;
+ }
+
+ $.extend(Gallery.prototype.options, {
+ // The list object property (or data attribute) with the YouTube video id:
+ youTubeVideoIdProperty: 'youtube',
+ // Optional object with parameters passed to the YouTube video player:
+ // https://developers.google.com/youtube/player_parameters
+ youTubePlayerVars: {
+ wmode: 'transparent'
+ },
+ // Require a click on the native YouTube player for the initial playback:
+ youTubeClickToPlay: true
+ });
+
+ var textFactory = Gallery.prototype.textFactory || Gallery.prototype.imageFactory,
+ YouTubePlayer = function (videoId, playerVars, clickToPlay) {
+ this.videoId = videoId;
+ this.playerVars = playerVars;
+ this.clickToPlay = clickToPlay;
+ this.element = document.createElement('div');
+ this.listeners = {};
+ };
+
+ $.extend(YouTubePlayer.prototype, {
+
+ canPlayType: function () {
+ return true;
+ },
+
+ on: function (type, func) {
+ this.listeners[type] = func;
+ return this;
+ },
+
+ loadAPI: function () {
+ var that = this,
+ onYouTubeIframeAPIReady = window.onYouTubeIframeAPIReady,
+ apiUrl = '//www.youtube.com/iframe_api',
+ scriptTags = document.getElementsByTagName('script'),
+ i = scriptTags.length,
+ scriptTag;
+ window.onYouTubeIframeAPIReady = function () {
+ if (onYouTubeIframeAPIReady) {
+ onYouTubeIframeAPIReady.apply(this);
+ }
+ if (that.playOnReady) {
+ that.play();
+ }
+ };
+ while (i) {
+ i -= 1;
+ if (scriptTags[i].src === apiUrl) {
+ return;
+ }
+ }
+ scriptTag = document.createElement('script');
+ scriptTag.src = apiUrl;
+ scriptTags[0].parentNode.insertBefore(scriptTag, scriptTags[0]);
+ },
+
+ onReady: function () {
+ this.ready = true;
+ if (this.playOnReady) {
+ this.play();
+ }
+ },
+
+ onPlaying: function () {
+ if (this.playStatus < 2) {
+ this.listeners.playing();
+ this.playStatus = 2;
+ }
+ },
+
+ onPause: function () {
+ Gallery.prototype.setTimeout.call(
+ this,
+ this.checkSeek,
+ null,
+ 2000
+ );
+ },
+
+ checkSeek: function () {
+ if (this.stateChange === YT.PlayerState.PAUSED ||
+ this.stateChange === YT.PlayerState.ENDED) {
+ // check if current state change is actually paused
+ this.listeners.pause();
+ delete this.playStatus;
+ }
+ },
+
+ onStateChange: function (event) {
+ switch (event.data) {
+ case YT.PlayerState.PLAYING:
+ this.hasPlayed = true;
+ this.onPlaying();
+ break;
+ case YT.PlayerState.PAUSED:
+ case YT.PlayerState.ENDED:
+ this.onPause();
+ break;
+ }
+ // Save most recent state change to this.stateChange
+ this.stateChange = event.data;
+ },
+
+ onError: function (event) {
+ this.listeners.error(event);
+ },
+
+ play: function () {
+ var that = this;
+ if (!this.playStatus) {
+ this.listeners.play();
+ this.playStatus = 1;
+ }
+ if (this.ready) {
+ if (!this.hasPlayed && (this.clickToPlay || (window.navigator &&
+ /iP(hone|od|ad)/.test(window.navigator.platform)))) {
+ // Manually trigger the playing callback if clickToPlay
+ // is enabled and to workaround a limitation in iOS,
+ // which requires synchronous user interaction to start
+ // the video playback:
+ this.onPlaying();
+ } else {
+ this.player.playVideo();
+ }
+ } else {
+ this.playOnReady = true;
+ if (!(window.YT && YT.Player)) {
+ this.loadAPI();
+ } else if (!this.player) {
+ this.player = new YT.Player(this.element, {
+ videoId: this.videoId,
+ playerVars: this.playerVars,
+ events: {
+ onReady: function () {
+ that.onReady();
+ },
+ onStateChange: function (event) {
+ that.onStateChange(event);
+ },
+ onError: function (event) {
+ that.onError(event);
+ }
+ }
+ });
+ }
+ }
+ },
+
+ pause: function () {
+ if (this.ready) {
+ this.player.pauseVideo();
+ } else if (this.playStatus) {
+ delete this.playOnReady;
+ this.listeners.pause();
+ delete this.playStatus;
+ }
+ }
+
+ });
+
+ $.extend(Gallery.prototype, {
+
+ YouTubePlayer: YouTubePlayer,
+
+ textFactory: function (obj, callback) {
+ var options = this.options,
+ videoId = this.getItemProperty(obj, options.youTubeVideoIdProperty);
+ if (videoId) {
+ if (this.getItemProperty(obj, options.urlProperty) === undefined) {
+ obj[options.urlProperty] = '//www.youtube.com/watch?v=' + videoId;
+ }
+ if (this.getItemProperty(obj, options.videoPosterProperty) === undefined) {
+ obj[options.videoPosterProperty] = '//img.youtube.com/vi/' + videoId +
+ '/maxresdefault.jpg';
+ }
+ return this.videoFactory(
+ obj,
+ callback,
+ new YouTubePlayer(
+ videoId,
+ options.youTubePlayerVars,
+ options.youTubeClickToPlay
+ )
+ );
+ }
+ return textFactory.call(this, obj, callback);
+ }
+
+ });
+
+ return Gallery;
+}));
diff --git a/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery.js b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery.js
new file mode 100644
index 000000000..c4c9337a6
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery.js
@@ -0,0 +1,1341 @@
+/*
+ * blueimp Gallery JS 2.14.0
+ * https://github.com/blueimp/Gallery
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Swipe implementation based on
+ * https://github.com/bradbirdsall/Swipe
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/* global define, window, document, DocumentTouch */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define(['./blueimp-helper'], factory);
+ } else {
+ // Browser globals:
+ window.blueimp = window.blueimp || {};
+ window.blueimp.Gallery = factory(
+ window.blueimp.helper || window.jQuery
+ );
+ }
+}(function ($) {
+ 'use strict';
+
+ function Gallery(list, options) {
+ if (document.body.style.maxHeight === undefined) {
+ // document.body.style.maxHeight is undefined on IE6 and lower
+ return null;
+ }
+ if (!this || this.options !== Gallery.prototype.options) {
+ // Called as function instead of as constructor,
+ // so we simply return a new instance:
+ return new Gallery(list, options);
+ }
+ if (!list || !list.length) {
+ this.console.log(
+ 'blueimp Gallery: No or empty list provided as first argument.',
+ list
+ );
+ return;
+ }
+ this.list = list;
+ this.num = list.length;
+ this.initOptions(options);
+ this.initialize();
+ }
+
+ $.extend(Gallery.prototype, {
+
+ options: {
+ // The Id, element or querySelector of the gallery widget:
+ container: '#blueimp-gallery',
+ // The tag name, Id, element or querySelector of the slides container:
+ slidesContainer: 'div',
+ // The tag name, Id, element or querySelector of the title element:
+ titleElement: 'h3',
+ // The class to add when the gallery is visible:
+ displayClass: 'blueimp-gallery-display',
+ // The class to add when the gallery controls are visible:
+ controlsClass: 'blueimp-gallery-controls',
+ // The class to add when the gallery only displays one element:
+ singleClass: 'blueimp-gallery-single',
+ // The class to add when the left edge has been reached:
+ leftEdgeClass: 'blueimp-gallery-left',
+ // The class to add when the right edge has been reached:
+ rightEdgeClass: 'blueimp-gallery-right',
+ // The class to add when the automatic slideshow is active:
+ playingClass: 'blueimp-gallery-playing',
+ // The class for all slides:
+ slideClass: 'slide',
+ // The slide class for loading elements:
+ slideLoadingClass: 'slide-loading',
+ // The slide class for elements that failed to load:
+ slideErrorClass: 'slide-error',
+ // The class for the content element loaded into each slide:
+ slideContentClass: 'slide-content',
+ // The class for the "toggle" control:
+ toggleClass: 'toggle',
+ // The class for the "prev" control:
+ prevClass: 'prev',
+ // The class for the "next" control:
+ nextClass: 'next',
+ // The class for the "close" control:
+ closeClass: 'close',
+ // The class for the "play-pause" toggle control:
+ playPauseClass: 'play-pause',
+ // The list object property (or data attribute) with the object type:
+ typeProperty: 'type',
+ // The list object property (or data attribute) with the object title:
+ titleProperty: 'title',
+ // The list object property (or data attribute) with the object URL:
+ urlProperty: 'href',
+ // The gallery listens for transitionend events before triggering the
+ // opened and closed events, unless the following option is set to false:
+ displayTransition: true,
+ // Defines if the gallery slides are cleared from the gallery modal,
+ // or reused for the next gallery initialization:
+ clearSlides: true,
+ // Defines if images should be stretched to fill the available space,
+ // while maintaining their aspect ratio (will only be enabled for browsers
+ // supporting background-size="contain", which excludes IE < 9).
+ // Set to "cover", to make images cover all available space (requires
+ // support for background-size="cover", which excludes IE < 9):
+ stretchImages: false,
+ // Toggle the controls on pressing the Return key:
+ toggleControlsOnReturn: true,
+ // Toggle the automatic slideshow interval on pressing the Space key:
+ toggleSlideshowOnSpace: true,
+ // Navigate the gallery by pressing left and right on the keyboard:
+ enableKeyboardNavigation: true,
+ // Close the gallery on pressing the Esc key:
+ closeOnEscape: true,
+ // Close the gallery when clicking on an empty slide area:
+ closeOnSlideClick: true,
+ // Close the gallery by swiping up or down:
+ closeOnSwipeUpOrDown: true,
+ // Emulate touch events on mouse-pointer devices such as desktop browsers:
+ emulateTouchEvents: true,
+ // Stop touch events from bubbling up to ancestor elements of the Gallery:
+ stopTouchEventsPropagation: false,
+ // Hide the page scrollbars:
+ hidePageScrollbars: true,
+ // Stops any touches on the container from scrolling the page:
+ disableScroll: true,
+ // Carousel mode (shortcut for carousel specific options):
+ carousel: false,
+ // Allow continuous navigation, moving from last to first
+ // and from first to last slide:
+ continuous: true,
+ // Remove elements outside of the preload range from the DOM:
+ unloadElements: true,
+ // Start with the automatic slideshow:
+ startSlideshow: false,
+ // Delay in milliseconds between slides for the automatic slideshow:
+ slideshowInterval: 5000,
+ // The starting index as integer.
+ // Can also be an object of the given list,
+ // or an equal object with the same url property:
+ index: 0,
+ // The number of elements to load around the current index:
+ preloadRange: 2,
+ // The transition speed between slide changes in milliseconds:
+ transitionSpeed: 400,
+ // The transition speed for automatic slide changes, set to an integer
+ // greater 0 to override the default transition speed:
+ slideshowTransitionSpeed: undefined,
+ // The event object for which the default action will be canceled
+ // on Gallery initialization (e.g. the click event to open the Gallery):
+ event: undefined,
+ // Callback function executed when the Gallery is initialized.
+ // Is called with the gallery instance as "this" object:
+ onopen: undefined,
+ // Callback function executed when the Gallery has been initialized
+ // and the initialization transition has been completed.
+ // Is called with the gallery instance as "this" object:
+ onopened: undefined,
+ // Callback function executed on slide change.
+ // Is called with the gallery instance as "this" object and the
+ // current index and slide as arguments:
+ onslide: undefined,
+ // Callback function executed after the slide change transition.
+ // Is called with the gallery instance as "this" object and the
+ // current index and slide as arguments:
+ onslideend: undefined,
+ // Callback function executed on slide content load.
+ // Is called with the gallery instance as "this" object and the
+ // slide index and slide element as arguments:
+ onslidecomplete: undefined,
+ // Callback function executed when the Gallery is about to be closed.
+ // Is called with the gallery instance as "this" object:
+ onclose: undefined,
+ // Callback function executed when the Gallery has been closed
+ // and the closing transition has been completed.
+ // Is called with the gallery instance as "this" object:
+ onclosed: undefined
+ },
+
+ carouselOptions: {
+ hidePageScrollbars: false,
+ toggleControlsOnReturn: false,
+ toggleSlideshowOnSpace: false,
+ enableKeyboardNavigation: false,
+ closeOnEscape: false,
+ closeOnSlideClick: false,
+ closeOnSwipeUpOrDown: false,
+ disableScroll: false,
+ startSlideshow: true
+ },
+
+ console: window.console && typeof window.console.log === 'function' ?
+ window.console :
+ {log: function () {}},
+
+ // Detect touch, transition, transform and background-size support:
+ support: (function (element) {
+ var support = {
+ touch: window.ontouchstart !== undefined ||
+ (window.DocumentTouch && document instanceof DocumentTouch)
+ },
+ transitions = {
+ webkitTransition: {
+ end: 'webkitTransitionEnd',
+ prefix: '-webkit-'
+ },
+ MozTransition: {
+ end: 'transitionend',
+ prefix: '-moz-'
+ },
+ OTransition: {
+ end: 'otransitionend',
+ prefix: '-o-'
+ },
+ transition: {
+ end: 'transitionend',
+ prefix: ''
+ }
+ },
+ elementTests = function () {
+ var transition = support.transition,
+ prop,
+ translateZ;
+ document.body.appendChild(element);
+ if (transition) {
+ prop = transition.name.slice(0, -9) + 'ransform';
+ if (element.style[prop] !== undefined) {
+ element.style[prop] = 'translateZ(0)';
+ translateZ = window.getComputedStyle(element)
+ .getPropertyValue(transition.prefix + 'transform');
+ support.transform = {
+ prefix: transition.prefix,
+ name: prop,
+ translate: true,
+ translateZ: !!translateZ && translateZ !== 'none'
+ };
+ }
+ }
+ if (element.style.backgroundSize !== undefined) {
+ support.backgroundSize = {};
+ element.style.backgroundSize = 'contain';
+ support.backgroundSize.contain = window
+ .getComputedStyle(element)
+ .getPropertyValue('background-size') === 'contain';
+ element.style.backgroundSize = 'cover';
+ support.backgroundSize.cover = window
+ .getComputedStyle(element)
+ .getPropertyValue('background-size') === 'cover';
+ }
+ document.body.removeChild(element);
+ };
+ (function (support, transitions) {
+ var prop;
+ for (prop in transitions) {
+ if (transitions.hasOwnProperty(prop) &&
+ element.style[prop] !== undefined) {
+ support.transition = transitions[prop];
+ support.transition.name = prop;
+ break;
+ }
+ }
+ }(support, transitions));
+ if (document.body) {
+ elementTests();
+ } else {
+ $(document).on('DOMContentLoaded', elementTests);
+ }
+ return support;
+ // Test element, has to be standard HTML and must not be hidden
+ // for the CSS3 tests using window.getComputedStyle to be applicable:
+ }(document.createElement('div'))),
+
+ requestAnimationFrame: window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame,
+
+ initialize: function () {
+ this.initStartIndex();
+ if (this.initWidget() === false) {
+ return false;
+ }
+ this.initEventListeners();
+ // Load the slide at the given index:
+ this.onslide(this.index);
+ // Manually trigger the slideend event for the initial slide:
+ this.ontransitionend();
+ // Start the automatic slideshow if applicable:
+ if (this.options.startSlideshow) {
+ this.play();
+ }
+ },
+
+ slide: function (to, speed) {
+ window.clearTimeout(this.timeout);
+ var index = this.index,
+ direction,
+ naturalDirection,
+ diff;
+ if (index === to || this.num === 1) {
+ return;
+ }
+ if (!speed) {
+ speed = this.options.transitionSpeed;
+ }
+ if (this.support.transition) {
+ if (!this.options.continuous) {
+ to = this.circle(to);
+ }
+ // 1: backward, -1: forward:
+ direction = Math.abs(index - to) / (index - to);
+ // Get the actual position of the slide:
+ if (this.options.continuous) {
+ naturalDirection = direction;
+ direction = -this.positions[this.circle(to)] / this.slideWidth;
+ // If going forward but to < index, use to = slides.length + to
+ // If going backward but to > index, use to = -slides.length + to
+ if (direction !== naturalDirection) {
+ to = -direction * this.num + to;
+ }
+ }
+ diff = Math.abs(index - to) - 1;
+ // Move all the slides between index and to in the right direction:
+ while (diff) {
+ diff -= 1;
+ this.move(
+ this.circle((to > index ? to : index) - diff - 1),
+ this.slideWidth * direction,
+ 0
+ );
+ }
+ to = this.circle(to);
+ this.move(index, this.slideWidth * direction, speed);
+ this.move(to, 0, speed);
+ if (this.options.continuous) {
+ this.move(
+ this.circle(to - direction),
+ -(this.slideWidth * direction),
+ 0
+ );
+ }
+ } else {
+ to = this.circle(to);
+ this.animate(index * -this.slideWidth, to * -this.slideWidth, speed);
+ }
+ this.onslide(to);
+ },
+
+ getIndex: function () {
+ return this.index;
+ },
+
+ getNumber: function () {
+ return this.num;
+ },
+
+ prev: function () {
+ if (this.options.continuous || this.index) {
+ this.slide(this.index - 1);
+ }
+ },
+
+ next: function () {
+ if (this.options.continuous || this.index < this.num - 1) {
+ this.slide(this.index + 1);
+ }
+ },
+
+ play: function (time) {
+ var that = this;
+ window.clearTimeout(this.timeout);
+ this.interval = time || this.options.slideshowInterval;
+ if (this.elements[this.index] > 1) {
+ this.timeout = this.setTimeout(
+ (!this.requestAnimationFrame && this.slide) || function (to, speed) {
+ that.animationFrameId = that.requestAnimationFrame.call(
+ window,
+ function () {
+ that.slide(to, speed);
+ }
+ );
+ },
+ [this.index + 1, this.options.slideshowTransitionSpeed],
+ this.interval
+ );
+ }
+ this.container.addClass(this.options.playingClass);
+ },
+
+ pause: function () {
+ window.clearTimeout(this.timeout);
+ this.interval = null;
+ this.container.removeClass(this.options.playingClass);
+ },
+
+ add: function (list) {
+ var i;
+ if (!list.concat) {
+ // Make a real array out of the list to add:
+ list = Array.prototype.slice.call(list);
+ }
+ if (!this.list.concat) {
+ // Make a real array out of the Gallery list:
+ this.list = Array.prototype.slice.call(this.list);
+ }
+ this.list = this.list.concat(list);
+ this.num = this.list.length;
+ if (this.num > 2 && this.options.continuous === null) {
+ this.options.continuous = true;
+ this.container.removeClass(this.options.leftEdgeClass);
+ }
+ this.container
+ .removeClass(this.options.rightEdgeClass)
+ .removeClass(this.options.singleClass);
+ for (i = this.num - list.length; i < this.num; i += 1) {
+ this.addSlide(i);
+ this.positionSlide(i);
+ }
+ this.positions.length = this.num;
+ this.initSlides(true);
+ },
+
+ resetSlides: function () {
+ this.slidesContainer.empty();
+ this.slides = [];
+ },
+
+ handleClose: function () {
+ var options = this.options;
+ this.destroyEventListeners();
+ // Cancel the slideshow:
+ this.pause();
+ this.container[0].style.display = 'none';
+ this.container
+ .removeClass(options.displayClass)
+ .removeClass(options.singleClass)
+ .removeClass(options.leftEdgeClass)
+ .removeClass(options.rightEdgeClass);
+ if (options.hidePageScrollbars) {
+ document.body.style.overflow = this.bodyOverflowStyle;
+ }
+ if (this.options.clearSlides) {
+ this.resetSlides();
+ }
+ if (this.options.onclosed) {
+ this.options.onclosed.call(this);
+ }
+ },
+
+ close: function () {
+ var that = this,
+ closeHandler = function (event) {
+ if (event.target === that.container[0]) {
+ that.container.off(
+ that.support.transition.end,
+ closeHandler
+ );
+ that.handleClose();
+ }
+ };
+ if (this.options.onclose) {
+ this.options.onclose.call(this);
+ }
+ if (this.support.transition && this.options.displayTransition) {
+ this.container.on(
+ this.support.transition.end,
+ closeHandler
+ );
+ this.container.removeClass(this.options.displayClass);
+ } else {
+ this.handleClose();
+ }
+ },
+
+ circle: function (index) {
+ // Always return a number inside of the slides index range:
+ return (this.num + (index % this.num)) % this.num;
+ },
+
+ move: function (index, dist, speed) {
+ this.translateX(index, dist, speed);
+ this.positions[index] = dist;
+ },
+
+ translate: function (index, x, y, speed) {
+ var style = this.slides[index].style,
+ transition = this.support.transition,
+ transform = this.support.transform;
+ style[transition.name + 'Duration'] = speed + 'ms';
+ style[transform.name] = 'translate(' + x + 'px, ' + y + 'px)' +
+ (transform.translateZ ? ' translateZ(0)' : '');
+ },
+
+ translateX: function (index, x, speed) {
+ this.translate(index, x, 0, speed);
+ },
+
+ translateY: function (index, y, speed) {
+ this.translate(index, 0, y, speed);
+ },
+
+ animate: function (from, to, speed) {
+ if (!speed) {
+ this.slidesContainer[0].style.left = to + 'px';
+ return;
+ }
+ var that = this,
+ start = new Date().getTime(),
+ timer = window.setInterval(function () {
+ var timeElap = new Date().getTime() - start;
+ if (timeElap > speed) {
+ that.slidesContainer[0].style.left = to + 'px';
+ that.ontransitionend();
+ window.clearInterval(timer);
+ return;
+ }
+ that.slidesContainer[0].style.left = (((to - from) *
+ (Math.floor((timeElap / speed) * 100) / 100)) +
+ from) + 'px';
+ }, 4);
+ },
+
+ preventDefault: function (event) {
+ if (event.preventDefault) {
+ event.preventDefault();
+ } else {
+ event.returnValue = false;
+ }
+ },
+
+ stopPropagation: function (event) {
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ } else {
+ event.cancelBubble = true;
+ }
+ },
+
+ onresize: function () {
+ this.initSlides(true);
+ },
+
+ onmousedown: function (event) {
+ // Trigger on clicks of the left mouse button only
+ // and exclude video elements:
+ if (event.which && event.which === 1 &&
+ event.target.nodeName !== 'VIDEO') {
+ // Preventing the default mousedown action is required
+ // to make touch emulation work with Firefox:
+ event.preventDefault();
+ (event.originalEvent || event).touches = [{
+ pageX: event.pageX,
+ pageY: event.pageY
+ }];
+ this.ontouchstart(event);
+ }
+ },
+
+ onmousemove: function (event) {
+ if (this.touchStart) {
+ (event.originalEvent || event).touches = [{
+ pageX: event.pageX,
+ pageY: event.pageY
+ }];
+ this.ontouchmove(event);
+ }
+ },
+
+ onmouseup: function (event) {
+ if (this.touchStart) {
+ this.ontouchend(event);
+ delete this.touchStart;
+ }
+ },
+
+ onmouseout: function (event) {
+ if (this.touchStart) {
+ var target = event.target,
+ related = event.relatedTarget;
+ if (!related || (related !== target &&
+ !$.contains(target, related))) {
+ this.onmouseup(event);
+ }
+ }
+ },
+
+ ontouchstart: function (event) {
+ if (this.options.stopTouchEventsPropagation) {
+ this.stopPropagation(event);
+ }
+ // jQuery doesn't copy touch event properties by default,
+ // so we have to access the originalEvent object:
+ var touches = (event.originalEvent || event).touches[0];
+ this.touchStart = {
+ // Remember the initial touch coordinates:
+ x: touches.pageX,
+ y: touches.pageY,
+ // Store the time to determine touch duration:
+ time: Date.now()
+ };
+ // Helper variable to detect scroll movement:
+ this.isScrolling = undefined;
+ // Reset delta values:
+ this.touchDelta = {};
+ },
+
+ ontouchmove: function (event) {
+ if (this.options.stopTouchEventsPropagation) {
+ this.stopPropagation(event);
+ }
+ // jQuery doesn't copy touch event properties by default,
+ // so we have to access the originalEvent object:
+ var touches = (event.originalEvent || event).touches[0],
+ scale = (event.originalEvent || event).scale,
+ index = this.index,
+ touchDeltaX,
+ indices;
+ // Ensure this is a one touch swipe and not, e.g. a pinch:
+ if (touches.length > 1 || (scale && scale !== 1)) {
+ return;
+ }
+ if (this.options.disableScroll) {
+ event.preventDefault();
+ }
+ // Measure change in x and y coordinates:
+ this.touchDelta = {
+ x: touches.pageX - this.touchStart.x,
+ y: touches.pageY - this.touchStart.y
+ };
+ touchDeltaX = this.touchDelta.x;
+ // Detect if this is a vertical scroll movement (run only once per touch):
+ if (this.isScrolling === undefined) {
+ this.isScrolling = this.isScrolling ||
+ Math.abs(touchDeltaX) < Math.abs(this.touchDelta.y);
+ }
+ if (!this.isScrolling) {
+ // Always prevent horizontal scroll:
+ event.preventDefault();
+ // Stop the slideshow:
+ window.clearTimeout(this.timeout);
+ if (this.options.continuous) {
+ indices = [
+ this.circle(index + 1),
+ index,
+ this.circle(index - 1)
+ ];
+ } else {
+ // Increase resistance if first slide and sliding left
+ // or last slide and sliding right:
+ this.touchDelta.x = touchDeltaX =
+ touchDeltaX /
+ (((!index && touchDeltaX > 0) ||
+ (index === this.num - 1 && touchDeltaX < 0)) ?
+ (Math.abs(touchDeltaX) / this.slideWidth + 1) : 1);
+ indices = [index];
+ if (index) {
+ indices.push(index - 1);
+ }
+ if (index < this.num - 1) {
+ indices.unshift(index + 1);
+ }
+ }
+ while (indices.length) {
+ index = indices.pop();
+ this.translateX(index, touchDeltaX + this.positions[index], 0);
+ }
+ } else if (this.options.closeOnSwipeUpOrDown) {
+ this.translateY(index, this.touchDelta.y + this.positions[index], 0);
+ }
+ },
+
+ ontouchend: function (event) {
+ if (this.options.stopTouchEventsPropagation) {
+ this.stopPropagation(event);
+ }
+ var index = this.index,
+ speed = this.options.transitionSpeed,
+ slideWidth = this.slideWidth,
+ isShortDuration = Number(Date.now() - this.touchStart.time) < 250,
+ // Determine if slide attempt triggers next/prev slide:
+ isValidSlide = (isShortDuration && Math.abs(this.touchDelta.x) > 20) ||
+ Math.abs(this.touchDelta.x) > slideWidth / 2,
+ // Determine if slide attempt is past start or end:
+ isPastBounds = (!index && this.touchDelta.x > 0) ||
+ (index === this.num - 1 && this.touchDelta.x < 0),
+ isValidClose = !isValidSlide && this.options.closeOnSwipeUpOrDown &&
+ ((isShortDuration && Math.abs(this.touchDelta.y) > 20) ||
+ Math.abs(this.touchDelta.y) > this.slideHeight / 2),
+ direction,
+ indexForward,
+ indexBackward,
+ distanceForward,
+ distanceBackward;
+ if (this.options.continuous) {
+ isPastBounds = false;
+ }
+ // Determine direction of swipe (true: right, false: left):
+ direction = this.touchDelta.x < 0 ? -1 : 1;
+ if (!this.isScrolling) {
+ if (isValidSlide && !isPastBounds) {
+ indexForward = index + direction;
+ indexBackward = index - direction;
+ distanceForward = slideWidth * direction;
+ distanceBackward = -slideWidth * direction;
+ if (this.options.continuous) {
+ this.move(this.circle(indexForward), distanceForward, 0);
+ this.move(this.circle(index - 2 * direction), distanceBackward, 0);
+ } else if (indexForward >= 0 &&
+ indexForward < this.num) {
+ this.move(indexForward, distanceForward, 0);
+ }
+ this.move(index, this.positions[index] + distanceForward, speed);
+ this.move(
+ this.circle(indexBackward),
+ this.positions[this.circle(indexBackward)] + distanceForward,
+ speed
+ );
+ index = this.circle(indexBackward);
+ this.onslide(index);
+ } else {
+ // Move back into position
+ if (this.options.continuous) {
+ this.move(this.circle(index - 1), -slideWidth, speed);
+ this.move(index, 0, speed);
+ this.move(this.circle(index + 1), slideWidth, speed);
+ } else {
+ if (index) {
+ this.move(index - 1, -slideWidth, speed);
+ }
+ this.move(index, 0, speed);
+ if (index < this.num - 1) {
+ this.move(index + 1, slideWidth, speed);
+ }
+ }
+ }
+ } else {
+ if (isValidClose) {
+ this.close();
+ } else {
+ // Move back into position
+ this.translateY(index, 0, speed);
+ }
+ }
+ },
+
+ ontouchcancel: function (event) {
+ if (this.touchStart) {
+ this.ontouchend(event);
+ delete this.touchStart;
+ }
+ },
+
+ ontransitionend: function (event) {
+ var slide = this.slides[this.index];
+ if (!event || slide === event.target) {
+ if (this.interval) {
+ this.play();
+ }
+ this.setTimeout(
+ this.options.onslideend,
+ [this.index, slide]
+ );
+ }
+ },
+
+ oncomplete: function (event) {
+ var target = event.target || event.srcElement,
+ parent = target && target.parentNode,
+ index;
+ if (!target || !parent) {
+ return;
+ }
+ index = this.getNodeIndex(parent);
+ $(parent).removeClass(this.options.slideLoadingClass);
+ if (event.type === 'error') {
+ $(parent).addClass(this.options.slideErrorClass);
+ this.elements[index] = 3; // Fail
+ } else {
+ this.elements[index] = 2; // Done
+ }
+ // Fix for IE7's lack of support for percentage max-height:
+ if (target.clientHeight > this.container[0].clientHeight) {
+ target.style.maxHeight = this.container[0].clientHeight;
+ }
+ if (this.interval && this.slides[this.index] === parent) {
+ this.play();
+ }
+ this.setTimeout(
+ this.options.onslidecomplete,
+ [index, parent]
+ );
+ },
+
+ onload: function (event) {
+ this.oncomplete(event);
+ },
+
+ onerror: function (event) {
+ this.oncomplete(event);
+ },
+
+ onkeydown: function (event) {
+ switch (event.which || event.keyCode) {
+ case 13: // Return
+ if (this.options.toggleControlsOnReturn) {
+ this.preventDefault(event);
+ this.toggleControls();
+ }
+ break;
+ case 27: // Esc
+ if (this.options.closeOnEscape) {
+ this.close();
+ }
+ break;
+ case 32: // Space
+ if (this.options.toggleSlideshowOnSpace) {
+ this.preventDefault(event);
+ this.toggleSlideshow();
+ }
+ break;
+ case 37: // Left
+ if (this.options.enableKeyboardNavigation) {
+ this.preventDefault(event);
+ this.prev();
+ }
+ break;
+ case 39: // Right
+ if (this.options.enableKeyboardNavigation) {
+ this.preventDefault(event);
+ this.next();
+ }
+ break;
+ }
+ },
+
+ handleClick: function (event) {
+ var options = this.options,
+ target = event.target || event.srcElement,
+ parent = target.parentNode,
+ isTarget = function (className) {
+ return $(target).hasClass(className) ||
+ $(parent).hasClass(className);
+ };
+ if (isTarget(options.toggleClass)) {
+ // Click on "toggle" control
+ this.preventDefault(event);
+ this.toggleControls();
+ } else if (isTarget(options.prevClass)) {
+ // Click on "prev" control
+ this.preventDefault(event);
+ this.prev();
+ } else if (isTarget(options.nextClass)) {
+ // Click on "next" control
+ this.preventDefault(event);
+ this.next();
+ } else if (isTarget(options.closeClass)) {
+ // Click on "close" control
+ this.preventDefault(event);
+ this.close();
+ } else if (isTarget(options.playPauseClass)) {
+ // Click on "play-pause" control
+ this.preventDefault(event);
+ this.toggleSlideshow();
+ } else if (parent === this.slidesContainer[0]) {
+ // Click on slide background
+ this.preventDefault(event);
+ if (options.closeOnSlideClick) {
+ this.close();
+ } else {
+ this.toggleControls();
+ }
+ } else if (parent.parentNode &&
+ parent.parentNode === this.slidesContainer[0]) {
+ // Click on displayed element
+ this.preventDefault(event);
+ this.toggleControls();
+ }
+ },
+
+ onclick: function (event) {
+ if (this.options.emulateTouchEvents &&
+ this.touchDelta && (Math.abs(this.touchDelta.x) > 20 ||
+ Math.abs(this.touchDelta.y) > 20)) {
+ delete this.touchDelta;
+ return;
+ }
+ return this.handleClick(event);
+ },
+
+ updateEdgeClasses: function (index) {
+ if (!index) {
+ this.container.addClass(this.options.leftEdgeClass);
+ } else {
+ this.container.removeClass(this.options.leftEdgeClass);
+ }
+ if (index === this.num - 1) {
+ this.container.addClass(this.options.rightEdgeClass);
+ } else {
+ this.container.removeClass(this.options.rightEdgeClass);
+ }
+ },
+
+ handleSlide: function (index) {
+ if (!this.options.continuous) {
+ this.updateEdgeClasses(index);
+ }
+ this.loadElements(index);
+ if (this.options.unloadElements) {
+ this.unloadElements(index);
+ }
+ this.setTitle(index);
+ },
+
+ onslide: function (index) {
+ this.index = index;
+ this.handleSlide(index);
+ this.setTimeout(this.options.onslide, [index, this.slides[index]]);
+ },
+
+ setTitle: function (index) {
+ var text = this.slides[index].firstChild.title,
+ titleElement = this.titleElement;
+ if (titleElement.length) {
+ this.titleElement.empty();
+ if (text) {
+ titleElement[0].appendChild(document.createTextNode(text));
+ }
+ }
+ },
+
+ setTimeout: function (func, args, wait) {
+ var that = this;
+ return func && window.setTimeout(function () {
+ func.apply(that, args || []);
+ }, wait || 0);
+ },
+
+ imageFactory: function (obj, callback) {
+ var that = this,
+ img = this.imagePrototype.cloneNode(false),
+ url = obj,
+ backgroundSize = this.options.stretchImages,
+ called,
+ element,
+ callbackWrapper = function (event) {
+ if (!called) {
+ event = {
+ type: event.type,
+ target: element
+ };
+ if (!element.parentNode) {
+ // Fix for IE7 firing the load event for
+ // cached images before the element could
+ // be added to the DOM:
+ return that.setTimeout(callbackWrapper, [event]);
+ }
+ called = true;
+ $(img).off('load error', callbackWrapper);
+ if (backgroundSize) {
+ if (event.type === 'load') {
+ element.style.background = 'url("' + url +
+ '") center no-repeat';
+ element.style.backgroundSize = backgroundSize;
+ }
+ }
+ callback(event);
+ }
+ },
+ title;
+ if (typeof url !== 'string') {
+ url = this.getItemProperty(obj, this.options.urlProperty);
+ title = this.getItemProperty(obj, this.options.titleProperty);
+ }
+ if (backgroundSize === true) {
+ backgroundSize = 'contain';
+ }
+ backgroundSize = this.support.backgroundSize &&
+ this.support.backgroundSize[backgroundSize] && backgroundSize;
+ if (backgroundSize) {
+ element = this.elementPrototype.cloneNode(false);
+ } else {
+ element = img;
+ img.draggable = false;
+ }
+ if (title) {
+ element.title = title;
+ }
+ $(img).on('load error', callbackWrapper);
+ img.src = url;
+ return element;
+ },
+
+ createElement: function (obj, callback) {
+ var type = obj && this.getItemProperty(obj, this.options.typeProperty),
+ factory = (type && this[type.split('/')[0] + 'Factory']) ||
+ this.imageFactory,
+ element = obj && factory.call(this, obj, callback);
+ if (!element) {
+ element = this.elementPrototype.cloneNode(false);
+ this.setTimeout(callback, [{
+ type: 'error',
+ target: element
+ }]);
+ }
+ $(element).addClass(this.options.slideContentClass);
+ return element;
+ },
+
+ loadElement: function (index) {
+ if (!this.elements[index]) {
+ if (this.slides[index].firstChild) {
+ this.elements[index] = $(this.slides[index])
+ .hasClass(this.options.slideErrorClass) ? 3 : 2;
+ } else {
+ this.elements[index] = 1; // Loading
+ $(this.slides[index]).addClass(this.options.slideLoadingClass);
+ this.slides[index].appendChild(this.createElement(
+ this.list[index],
+ this.proxyListener
+ ));
+ }
+ }
+ },
+
+ loadElements: function (index) {
+ var limit = Math.min(this.num, this.options.preloadRange * 2 + 1),
+ j = index,
+ i;
+ for (i = 0; i < limit; i += 1) {
+ // First load the current slide element (0),
+ // then the next one (+1),
+ // then the previous one (-2),
+ // then the next after next (+2), etc.:
+ j += i * (i % 2 === 0 ? -1 : 1);
+ // Connect the ends of the list to load slide elements for
+ // continuous navigation:
+ j = this.circle(j);
+ this.loadElement(j);
+ }
+ },
+
+ unloadElements: function (index) {
+ var i,
+ slide,
+ diff;
+ for (i in this.elements) {
+ if (this.elements.hasOwnProperty(i)) {
+ diff = Math.abs(index - i);
+ if (diff > this.options.preloadRange &&
+ diff + this.options.preloadRange < this.num) {
+ slide = this.slides[i];
+ slide.removeChild(slide.firstChild);
+ delete this.elements[i];
+ }
+ }
+ }
+ },
+
+ addSlide: function (index) {
+ var slide = this.slidePrototype.cloneNode(false);
+ slide.setAttribute('data-index', index);
+ this.slidesContainer[0].appendChild(slide);
+ this.slides.push(slide);
+ },
+
+ positionSlide: function (index) {
+ var slide = this.slides[index];
+ slide.style.width = this.slideWidth + 'px';
+ if (this.support.transition) {
+ slide.style.left = (index * -this.slideWidth) + 'px';
+ this.move(index, this.index > index ? -this.slideWidth :
+ (this.index < index ? this.slideWidth : 0), 0);
+ }
+ },
+
+ initSlides: function (reload) {
+ var clearSlides,
+ i;
+ if (!reload) {
+ this.positions = [];
+ this.positions.length = this.num;
+ this.elements = {};
+ this.imagePrototype = document.createElement('img');
+ this.elementPrototype = document.createElement('div');
+ this.slidePrototype = document.createElement('div');
+ $(this.slidePrototype).addClass(this.options.slideClass);
+ this.slides = this.slidesContainer[0].children;
+ clearSlides = this.options.clearSlides ||
+ this.slides.length !== this.num;
+ }
+ this.slideWidth = this.container[0].offsetWidth;
+ this.slideHeight = this.container[0].offsetHeight;
+ this.slidesContainer[0].style.width =
+ (this.num * this.slideWidth) + 'px';
+ if (clearSlides) {
+ this.resetSlides();
+ }
+ for (i = 0; i < this.num; i += 1) {
+ if (clearSlides) {
+ this.addSlide(i);
+ }
+ this.positionSlide(i);
+ }
+ // Reposition the slides before and after the given index:
+ if (this.options.continuous && this.support.transition) {
+ this.move(this.circle(this.index - 1), -this.slideWidth, 0);
+ this.move(this.circle(this.index + 1), this.slideWidth, 0);
+ }
+ if (!this.support.transition) {
+ this.slidesContainer[0].style.left =
+ (this.index * -this.slideWidth) + 'px';
+ }
+ },
+
+ toggleControls: function () {
+ var controlsClass = this.options.controlsClass;
+ if (this.container.hasClass(controlsClass)) {
+ this.container.removeClass(controlsClass);
+ } else {
+ this.container.addClass(controlsClass);
+ }
+ },
+
+ toggleSlideshow: function () {
+ if (!this.interval) {
+ this.play();
+ } else {
+ this.pause();
+ }
+ },
+
+ getNodeIndex: function (element) {
+ return parseInt(element.getAttribute('data-index'), 10);
+ },
+
+ getNestedProperty: function (obj, property) {
+ property.replace(
+ // Matches native JavaScript notation in a String,
+ // e.g. '["doubleQuoteProp"].dotProp[2]'
+ /\[(?:'([^']+)'|"([^"]+)"|(\d+))\]|(?:(?:^|\.)([^\.\[]+))/g,
+ function (str, singleQuoteProp, doubleQuoteProp, arrayIndex, dotProp) {
+ var prop = dotProp || singleQuoteProp || doubleQuoteProp ||
+ (arrayIndex && parseInt(arrayIndex, 10));
+ if (str && obj) {
+ obj = obj[prop];
+ }
+ }
+ );
+ return obj;
+ },
+
+ getDataProperty: function (obj, property) {
+ if (obj.getAttribute) {
+ var prop = obj.getAttribute('data-' +
+ property.replace(/([A-Z])/g, '-$1').toLowerCase());
+ if (typeof prop === 'string') {
+ if (/^(true|false|null|-?\d+(\.\d+)?|\{[\s\S]*\}|\[[\s\S]*\])$/
+ .test(prop)) {
+ try {
+ return $.parseJSON(prop);
+ } catch (ignore) {}
+ }
+ return prop;
+ }
+ }
+ },
+
+ getItemProperty: function (obj, property) {
+ var prop = obj[property];
+ if (prop === undefined) {
+ prop = this.getDataProperty(obj, property);
+ if (prop === undefined) {
+ prop = this.getNestedProperty(obj, property);
+ }
+ }
+ return prop;
+ },
+
+ initStartIndex: function () {
+ var index = this.options.index,
+ urlProperty = this.options.urlProperty,
+ i;
+ // Check if the index is given as a list object:
+ if (index && typeof index !== 'number') {
+ for (i = 0; i < this.num; i += 1) {
+ if (this.list[i] === index ||
+ this.getItemProperty(this.list[i], urlProperty) ===
+ this.getItemProperty(index, urlProperty)) {
+ index = i;
+ break;
+ }
+ }
+ }
+ // Make sure the index is in the list range:
+ this.index = this.circle(parseInt(index, 10) || 0);
+ },
+
+ initEventListeners: function () {
+ var that = this,
+ slidesContainer = this.slidesContainer,
+ proxyListener = function (event) {
+ var type = that.support.transition &&
+ that.support.transition.end === event.type ?
+ 'transitionend' : event.type;
+ that['on' + type](event);
+ };
+ $(window).on('resize', proxyListener);
+ $(document.body).on('keydown', proxyListener);
+ this.container.on('click', proxyListener);
+ if (this.support.touch) {
+ slidesContainer
+ .on('touchstart touchmove touchend touchcancel', proxyListener);
+ } else if (this.options.emulateTouchEvents &&
+ this.support.transition) {
+ slidesContainer
+ .on('mousedown mousemove mouseup mouseout', proxyListener);
+ }
+ if (this.support.transition) {
+ slidesContainer.on(
+ this.support.transition.end,
+ proxyListener
+ );
+ }
+ this.proxyListener = proxyListener;
+ },
+
+ destroyEventListeners: function () {
+ var slidesContainer = this.slidesContainer,
+ proxyListener = this.proxyListener;
+ $(window).off('resize', proxyListener);
+ $(document.body).off('keydown', proxyListener);
+ this.container.off('click', proxyListener);
+ if (this.support.touch) {
+ slidesContainer
+ .off('touchstart touchmove touchend touchcancel', proxyListener);
+ } else if (this.options.emulateTouchEvents &&
+ this.support.transition) {
+ slidesContainer
+ .off('mousedown mousemove mouseup mouseout', proxyListener);
+ }
+ if (this.support.transition) {
+ slidesContainer.off(
+ this.support.transition.end,
+ proxyListener
+ );
+ }
+ },
+
+ handleOpen: function () {
+ if (this.options.onopened) {
+ this.options.onopened.call(this);
+ }
+ },
+
+ initWidget: function () {
+ var that = this,
+ openHandler = function (event) {
+ if (event.target === that.container[0]) {
+ that.container.off(
+ that.support.transition.end,
+ openHandler
+ );
+ that.handleOpen();
+ }
+ };
+ this.container = $(this.options.container);
+ if (!this.container.length) {
+ this.console.log(
+ 'blueimp Gallery: Widget container not found.',
+ this.options.container
+ );
+ return false;
+ }
+ this.slidesContainer = this.container.find(
+ this.options.slidesContainer
+ ).first();
+ if (!this.slidesContainer.length) {
+ this.console.log(
+ 'blueimp Gallery: Slides container not found.',
+ this.options.slidesContainer
+ );
+ return false;
+ }
+ this.titleElement = this.container.find(
+ this.options.titleElement
+ ).first();
+ if (this.num === 1) {
+ this.container.addClass(this.options.singleClass);
+ }
+ if (this.options.onopen) {
+ this.options.onopen.call(this);
+ }
+ if (this.support.transition && this.options.displayTransition) {
+ this.container.on(
+ this.support.transition.end,
+ openHandler
+ );
+ } else {
+ this.handleOpen();
+ }
+ if (this.options.hidePageScrollbars) {
+ // Hide the page scrollbars:
+ this.bodyOverflowStyle = document.body.style.overflow;
+ document.body.style.overflow = 'hidden';
+ }
+ this.container[0].style.display = 'block';
+ this.initSlides();
+ this.container.addClass(this.options.displayClass);
+ },
+
+ initOptions: function (options) {
+ // Create a copy of the prototype options:
+ this.options = $.extend({}, this.options);
+ // Check if carousel mode is enabled:
+ if ((options && options.carousel) ||
+ (this.options.carousel && (!options || options.carousel !== false))) {
+ $.extend(this.options, this.carouselOptions);
+ }
+ // Override any given options:
+ $.extend(this.options, options);
+ if (this.num < 3) {
+ // 1 or 2 slides cannot be displayed continuous,
+ // remember the original option by setting to null instead of false:
+ this.options.continuous = this.options.continuous ? null : false;
+ }
+ if (!this.support.transition) {
+ this.options.emulateTouchEvents = false;
+ }
+ if (this.options.event) {
+ this.preventDefault(this.options.event);
+ }
+ }
+
+ });
+
+ return Gallery;
+}));
diff --git a/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery.min.js b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery.min.js
new file mode 100644
index 000000000..8203e6067
--- /dev/null
+++ b/ajax/libs/blueimp-gallery/2.15.1/js/blueimp-gallery.min.js
@@ -0,0 +1,2 @@
+!function(){"use strict";function a(a,b){var c;for(c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function b(a){if(!this||this.find!==b.prototype.find)return new b(a);if(this.length=0,a)if("string"==typeof a&&(a=this.find(a)),a.nodeType||a===a.window)this.length=1,this[0]=a;else{var c=a.length;for(this.length=c;c;)c-=1,this[c]=a[c]}}b.extend=a,b.contains=function(a,b){do if(b=b.parentNode,b===a)return!0;while(b);return!1},b.parseJSON=function(a){return window.JSON&&JSON.parse(a)},a(b.prototype,{find:function(a){var c=this[0]||document;return"string"==typeof a&&(a=c.querySelectorAll?c.querySelectorAll(a):"#"===a.charAt(0)?c.getElementById(a.slice(1)):c.getElementsByTagName(a)),new b(a)},hasClass:function(a){return this[0]?new RegExp("(^|\\s+)"+a+"(\\s+|$)").test(this[0].className):!1},addClass:function(a){for(var b,c=this.length;c;){if(c-=1,b=this[c],!b.className)return b.className=a,this;if(this.hasClass(a))return this;b.className+=" "+a}return this},removeClass:function(a){for(var b,c=new RegExp("(^|\\s+)"+a+"(\\s+|$)"),d=this.length;d;)d-=1,b=this[d],b.className=b.className.replace(c," ");return this},on:function(a,b){for(var c,d,e=a.split(/\s+/);e.length;)for(a=e.shift(),c=this.length;c;)c-=1,d=this[c],d.addEventListener?d.addEventListener(a,b,!1):d.attachEvent&&d.attachEvent("on"+a,b);return this},off:function(a,b){for(var c,d,e=a.split(/\s+/);e.length;)for(a=e.shift(),c=this.length;c;)c-=1,d=this[c],d.removeEventListener?d.removeEventListener(a,b,!1):d.detachEvent&&d.detachEvent("on"+a,b);return this},empty:function(){for(var a,b=this.length;b;)for(b-=1,a=this[b];a.hasChildNodes();)a.removeChild(a.lastChild);return this},first:function(){return new b(this[0])}}),"function"==typeof define&&define.amd?define(function(){return b}):(window.blueimp=window.blueimp||{},window.blueimp.helper=b)}(),function(a){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper"],a):(window.blueimp=window.blueimp||{},window.blueimp.Gallery=a(window.blueimp.helper||window.jQuery))}(function(a){"use strict";function b(a,c){return void 0===document.body.style.maxHeight?null:this&&this.options===b.prototype.options?a&&a.length?(this.list=a,this.num=a.length,this.initOptions(c),void this.initialize()):void this.console.log("blueimp Gallery: No or empty list provided as first argument.",a):new b(a,c)}return a.extend(b.prototype,{options:{container:"#blueimp-gallery",slidesContainer:"div",titleElement:"h3",displayClass:"blueimp-gallery-display",controlsClass:"blueimp-gallery-controls",singleClass:"blueimp-gallery-single",leftEdgeClass:"blueimp-gallery-left",rightEdgeClass:"blueimp-gallery-right",playingClass:"blueimp-gallery-playing",slideClass:"slide",slideLoadingClass:"slide-loading",slideErrorClass:"slide-error",slideContentClass:"slide-content",toggleClass:"toggle",prevClass:"prev",nextClass:"next",closeClass:"close",playPauseClass:"play-pause",typeProperty:"type",titleProperty:"title",urlProperty:"href",displayTransition:!0,clearSlides:!0,stretchImages:!1,toggleControlsOnReturn:!0,toggleSlideshowOnSpace:!0,enableKeyboardNavigation:!0,closeOnEscape:!0,closeOnSlideClick:!0,closeOnSwipeUpOrDown:!0,emulateTouchEvents:!0,stopTouchEventsPropagation:!1,hidePageScrollbars:!0,disableScroll:!0,carousel:!1,continuous:!0,unloadElements:!0,startSlideshow:!1,slideshowInterval:5e3,index:0,preloadRange:2,transitionSpeed:400,slideshowTransitionSpeed:void 0,event:void 0,onopen:void 0,onopened:void 0,onslide:void 0,onslideend:void 0,onslidecomplete:void 0,onclose:void 0,onclosed:void 0},carouselOptions:{hidePageScrollbars:!1,toggleControlsOnReturn:!1,toggleSlideshowOnSpace:!1,enableKeyboardNavigation:!1,closeOnEscape:!1,closeOnSlideClick:!1,closeOnSwipeUpOrDown:!1,disableScroll:!1,startSlideshow:!0},console:window.console&&"function"==typeof window.console.log?window.console:{log:function(){}},support:function(b){var c={touch:void 0!==window.ontouchstart||window.DocumentTouch&&document instanceof DocumentTouch},d={webkitTransition:{end:"webkitTransitionEnd",prefix:"-webkit-"},MozTransition:{end:"transitionend",prefix:"-moz-"},OTransition:{end:"otransitionend",prefix:"-o-"},transition:{end:"transitionend",prefix:""}},e=function(){var a,d,e=c.transition;document.body.appendChild(b),e&&(a=e.name.slice(0,-9)+"ransform",void 0!==b.style[a]&&(b.style[a]="translateZ(0)",d=window.getComputedStyle(b).getPropertyValue(e.prefix+"transform"),c.transform={prefix:e.prefix,name:a,translate:!0,translateZ:!!d&&"none"!==d})),void 0!==b.style.backgroundSize&&(c.backgroundSize={},b.style.backgroundSize="contain",c.backgroundSize.contain="contain"===window.getComputedStyle(b).getPropertyValue("background-size"),b.style.backgroundSize="cover",c.backgroundSize.cover="cover"===window.getComputedStyle(b).getPropertyValue("background-size")),document.body.removeChild(b)};return function(a,c){var d;for(d in c)if(c.hasOwnProperty(d)&&void 0!==b.style[d]){a.transition=c[d],a.transition.name=d;break}}(c,d),document.body?e():a(document).on("DOMContentLoaded",e),c}(document.createElement("div")),requestAnimationFrame:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame,initialize:function(){return this.initStartIndex(),this.initWidget()===!1?!1:(this.initEventListeners(),this.onslide(this.index),this.ontransitionend(),void(this.options.startSlideshow&&this.play()))},slide:function(a,b){window.clearTimeout(this.timeout);var c,d,e,f=this.index;if(f!==a&&1!==this.num){if(b||(b=this.options.transitionSpeed),this.support.transition){for(this.options.continuous||(a=this.circle(a)),c=Math.abs(f-a)/(f-a),this.options.continuous&&(d=c,c=-this.positions[this.circle(a)]/this.slideWidth,c!==d&&(a=-c*this.num+a)),e=Math.abs(f-a)-1;e;)e-=1,this.move(this.circle((a>f?a:f)-e-1),this.slideWidth*c,0);a=this.circle(a),this.move(f,this.slideWidth*c,b),this.move(a,0,b),this.options.continuous&&this.move(this.circle(a-c),-(this.slideWidth*c),0)}else a=this.circle(a),this.animate(f*-this.slideWidth,a*-this.slideWidth,b);this.onslide(a)}},getIndex:function(){return this.index},getNumber:function(){return this.num},prev:function(){(this.options.continuous||this.index)&&this.slide(this.index-1)},next:function(){(this.options.continuous||this.index1&&(this.timeout=this.setTimeout(!this.requestAnimationFrame&&this.slide||function(a,c){b.animationFrameId=b.requestAnimationFrame.call(window,function(){b.slide(a,c)})},[this.index+1,this.options.slideshowTransitionSpeed],this.interval)),this.container.addClass(this.options.playingClass)},pause:function(){window.clearTimeout(this.timeout),this.interval=null,this.container.removeClass(this.options.playingClass)},add:function(a){var b;for(a.concat||(a=Array.prototype.slice.call(a)),this.list.concat||(this.list=Array.prototype.slice.call(this.list)),this.list=this.list.concat(a),this.num=this.list.length,this.num>2&&null===this.options.continuous&&(this.options.continuous=!0,this.container.removeClass(this.options.leftEdgeClass)),this.container.removeClass(this.options.rightEdgeClass).removeClass(this.options.singleClass),b=this.num-a.length;bc?(d.slidesContainer[0].style.left=b+"px",d.ontransitionend(),void window.clearInterval(f)):void(d.slidesContainer[0].style.left=(b-a)*(Math.floor(g/c*100)/100)+a+"px")},4)},preventDefault:function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},onresize:function(){this.initSlides(!0)},onmousedown:function(a){a.which&&1===a.which&&"VIDEO"!==a.target.nodeName&&(a.preventDefault(),(a.originalEvent||a).touches=[{pageX:a.pageX,pageY:a.pageY}],this.ontouchstart(a))},onmousemove:function(a){this.touchStart&&((a.originalEvent||a).touches=[{pageX:a.pageX,pageY:a.pageY}],this.ontouchmove(a))},onmouseup:function(a){this.touchStart&&(this.ontouchend(a),delete this.touchStart)},onmouseout:function(b){if(this.touchStart){var c=b.target,d=b.relatedTarget;(!d||d!==c&&!a.contains(c,d))&&this.onmouseup(b)}},ontouchstart:function(a){this.options.stopTouchEventsPropagation&&this.stopPropagation(a);var b=(a.originalEvent||a).touches[0];this.touchStart={x:b.pageX,y:b.pageY,time:Date.now()},this.isScrolling=void 0,this.touchDelta={}},ontouchmove:function(a){this.options.stopTouchEventsPropagation&&this.stopPropagation(a);var b,c,d=(a.originalEvent||a).touches[0],e=(a.originalEvent||a).scale,f=this.index;if(!(d.length>1||e&&1!==e))if(this.options.disableScroll&&a.preventDefault(),this.touchDelta={x:d.pageX-this.touchStart.x,y:d.pageY-this.touchStart.y},b=this.touchDelta.x,void 0===this.isScrolling&&(this.isScrolling=this.isScrolling||Math.abs(b)0||f===this.num-1&&0>b?Math.abs(b)/this.slideWidth+1:1,c=[f],f&&c.push(f-1),f20||Math.abs(this.touchDelta.x)>i/2,l=!g&&this.touchDelta.x>0||g===this.num-1&&this.touchDelta.x<0,m=!k&&this.options.closeOnSwipeUpOrDown&&(j&&Math.abs(this.touchDelta.y)>20||Math.abs(this.touchDelta.y)>this.slideHeight/2);this.options.continuous&&(l=!1),b=this.touchDelta.x<0?-1:1,this.isScrolling?m?this.close():this.translateY(g,0,h):k&&!l?(c=g+b,d=g-b,e=i*b,f=-i*b,this.options.continuous?(this.move(this.circle(c),e,0),this.move(this.circle(g-2*b),f,0)):c>=0&&cthis.container[0].clientHeight&&(d.style.maxHeight=this.container[0].clientHeight),this.interval&&this.slides[this.index]===e&&this.play(),this.setTimeout(this.options.onslidecomplete,[c,e]))},onload:function(a){this.oncomplete(a)},onerror:function(a){this.oncomplete(a)},onkeydown:function(a){switch(a.which||a.keyCode){case 13:this.options.toggleControlsOnReturn&&(this.preventDefault(a),this.toggleControls());break;case 27:this.options.closeOnEscape&&this.close();break;case 32:this.options.toggleSlideshowOnSpace&&(this.preventDefault(a),this.toggleSlideshow());break;case 37:this.options.enableKeyboardNavigation&&(this.preventDefault(a),this.prev());break;case 39:this.options.enableKeyboardNavigation&&(this.preventDefault(a),this.next())}},handleClick:function(b){var c=this.options,d=b.target||b.srcElement,e=d.parentNode,f=function(b){return a(d).hasClass(b)||a(e).hasClass(b)};f(c.toggleClass)?(this.preventDefault(b),this.toggleControls()):f(c.prevClass)?(this.preventDefault(b),this.prev()):f(c.nextClass)?(this.preventDefault(b),this.next()):f(c.closeClass)?(this.preventDefault(b),this.close()):f(c.playPauseClass)?(this.preventDefault(b),this.toggleSlideshow()):e===this.slidesContainer[0]?(this.preventDefault(b),c.closeOnSlideClick?this.close():this.toggleControls()):e.parentNode&&e.parentNode===this.slidesContainer[0]&&(this.preventDefault(b),this.toggleControls())},onclick:function(a){return this.options.emulateTouchEvents&&this.touchDelta&&(Math.abs(this.touchDelta.x)>20||Math.abs(this.touchDelta.y)>20)?void delete this.touchDelta:this.handleClick(a)},updateEdgeClasses:function(a){a?this.container.removeClass(this.options.leftEdgeClass):this.container.addClass(this.options.leftEdgeClass),a===this.num-1?this.container.addClass(this.options.rightEdgeClass):this.container.removeClass(this.options.rightEdgeClass)},handleSlide:function(a){this.options.continuous||this.updateEdgeClasses(a),this.loadElements(a),this.options.unloadElements&&this.unloadElements(a),this.setTitle(a)},onslide:function(a){this.index=a,this.handleSlide(a),this.setTimeout(this.options.onslide,[a,this.slides[a]])},setTitle:function(a){var b=this.slides[a].firstChild.title,c=this.titleElement;c.length&&(this.titleElement.empty(),b&&c[0].appendChild(document.createTextNode(b)))},setTimeout:function(a,b,c){var d=this;return a&&window.setTimeout(function(){a.apply(d,b||[])},c||0)},imageFactory:function(b,c){var d,e,f,g=this,h=this.imagePrototype.cloneNode(!1),i=b,j=this.options.stretchImages,k=function(b){if(!d){if(b={type:b.type,target:e},!e.parentNode)return g.setTimeout(k,[b]);d=!0,a(h).off("load error",k),j&&"load"===b.type&&(e.style.background='url("'+i+'") center no-repeat',e.style.backgroundSize=j),c(b)}};return"string"!=typeof i&&(i=this.getItemProperty(b,this.options.urlProperty),f=this.getItemProperty(b,this.options.titleProperty)),j===!0&&(j="contain"),j=this.support.backgroundSize&&this.support.backgroundSize[j]&&j,j?e=this.elementPrototype.cloneNode(!1):(e=h,h.draggable=!1),f&&(e.title=f),a(h).on("load error",k),h.src=i,e},createElement:function(b,c){var d=b&&this.getItemProperty(b,this.options.typeProperty),e=d&&this[d.split("/")[0]+"Factory"]||this.imageFactory,f=b&&e.call(this,b,c);return f||(f=this.elementPrototype.cloneNode(!1),this.setTimeout(c,[{type:"error",target:f}])),a(f).addClass(this.options.slideContentClass),f},loadElement:function(b){this.elements[b]||(this.slides[b].firstChild?this.elements[b]=a(this.slides[b]).hasClass(this.options.slideErrorClass)?3:2:(this.elements[b]=1,a(this.slides[b]).addClass(this.options.slideLoadingClass),this.slides[b].appendChild(this.createElement(this.list[b],this.proxyListener))))},loadElements:function(a){var b,c=Math.min(this.num,2*this.options.preloadRange+1),d=a;for(b=0;c>b;b+=1)d+=b*(b%2===0?-1:1),d=this.circle(d),this.loadElement(d)},unloadElements:function(a){var b,c,d;for(b in this.elements)this.elements.hasOwnProperty(b)&&(d=Math.abs(a-b),d>this.options.preloadRange&&d+this.options.preloadRangea?-this.slideWidth:this.indexf?a:f)-e-1),this.slideWidth*c,0);a=this.circle(a),this.move(f,this.slideWidth*c,b),this.move(a,0,b),this.options.continuous&&this.move(this.circle(a-c),-(this.slideWidth*c),0)}else a=this.circle(a),this.animate(f*-this.slideWidth,a*-this.slideWidth,b);this.onslide(a)}},getIndex:function(){return this.index},getNumber:function(){return this.num},prev:function(){(this.options.continuous||this.index)&&this.slide(this.index-1)},next:function(){(this.options.continuous||this.index1&&(this.timeout=this.setTimeout(!this.requestAnimationFrame&&this.slide||function(a,c){b.animationFrameId=b.requestAnimationFrame.call(window,function(){b.slide(a,c)})},[this.index+1,this.options.slideshowTransitionSpeed],this.interval)),this.container.addClass(this.options.playingClass)},pause:function(){window.clearTimeout(this.timeout),this.interval=null,this.container.removeClass(this.options.playingClass)},add:function(a){var b;for(a.concat||(a=Array.prototype.slice.call(a)),this.list.concat||(this.list=Array.prototype.slice.call(this.list)),this.list=this.list.concat(a),this.num=this.list.length,this.num>2&&null===this.options.continuous&&(this.options.continuous=!0,this.container.removeClass(this.options.leftEdgeClass)),this.container.removeClass(this.options.rightEdgeClass).removeClass(this.options.singleClass),b=this.num-a.length;bc?(d.slidesContainer[0].style.left=b+"px",d.ontransitionend(),void window.clearInterval(f)):void(d.slidesContainer[0].style.left=(b-a)*(Math.floor(g/c*100)/100)+a+"px")},4)},preventDefault:function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},onresize:function(){this.initSlides(!0)},onmousedown:function(a){a.which&&1===a.which&&"VIDEO"!==a.target.nodeName&&(a.preventDefault(),(a.originalEvent||a).touches=[{pageX:a.pageX,pageY:a.pageY}],this.ontouchstart(a))},onmousemove:function(a){this.touchStart&&((a.originalEvent||a).touches=[{pageX:a.pageX,pageY:a.pageY}],this.ontouchmove(a))},onmouseup:function(a){this.touchStart&&(this.ontouchend(a),delete this.touchStart)},onmouseout:function(b){if(this.touchStart){var c=b.target,d=b.relatedTarget;(!d||d!==c&&!a.contains(c,d))&&this.onmouseup(b)}},ontouchstart:function(a){this.options.stopTouchEventsPropagation&&this.stopPropagation(a);var b=(a.originalEvent||a).touches[0];this.touchStart={x:b.pageX,y:b.pageY,time:Date.now()},this.isScrolling=void 0,this.touchDelta={}},ontouchmove:function(a){this.options.stopTouchEventsPropagation&&this.stopPropagation(a);var b,c,d=(a.originalEvent||a).touches[0],e=(a.originalEvent||a).scale,f=this.index;if(!(d.length>1||e&&1!==e))if(this.options.disableScroll&&a.preventDefault(),this.touchDelta={x:d.pageX-this.touchStart.x,y:d.pageY-this.touchStart.y},b=this.touchDelta.x,void 0===this.isScrolling&&(this.isScrolling=this.isScrolling||Math.abs(b)0||f===this.num-1&&0>b?Math.abs(b)/this.slideWidth+1:1,c=[f],f&&c.push(f-1),f20||Math.abs(this.touchDelta.x)>i/2,l=!g&&this.touchDelta.x>0||g===this.num-1&&this.touchDelta.x<0,m=!k&&this.options.closeOnSwipeUpOrDown&&(j&&Math.abs(this.touchDelta.y)>20||Math.abs(this.touchDelta.y)>this.slideHeight/2);this.options.continuous&&(l=!1),b=this.touchDelta.x<0?-1:1,this.isScrolling?m?this.close():this.translateY(g,0,h):k&&!l?(c=g+b,d=g-b,e=i*b,f=-i*b,this.options.continuous?(this.move(this.circle(c),e,0),this.move(this.circle(g-2*b),f,0)):c>=0&&cthis.container[0].clientHeight&&(d.style.maxHeight=this.container[0].clientHeight),this.interval&&this.slides[this.index]===e&&this.play(),this.setTimeout(this.options.onslidecomplete,[c,e]))},onload:function(a){this.oncomplete(a)},onerror:function(a){this.oncomplete(a)},onkeydown:function(a){switch(a.which||a.keyCode){case 13:this.options.toggleControlsOnReturn&&(this.preventDefault(a),this.toggleControls());break;case 27:this.options.closeOnEscape&&this.close();break;case 32:this.options.toggleSlideshowOnSpace&&(this.preventDefault(a),this.toggleSlideshow());break;case 37:this.options.enableKeyboardNavigation&&(this.preventDefault(a),this.prev());break;case 39:this.options.enableKeyboardNavigation&&(this.preventDefault(a),this.next())}},handleClick:function(b){var c=this.options,d=b.target||b.srcElement,e=d.parentNode,f=function(b){return a(d).hasClass(b)||a(e).hasClass(b)};f(c.toggleClass)?(this.preventDefault(b),this.toggleControls()):f(c.prevClass)?(this.preventDefault(b),this.prev()):f(c.nextClass)?(this.preventDefault(b),this.next()):f(c.closeClass)?(this.preventDefault(b),this.close()):f(c.playPauseClass)?(this.preventDefault(b),this.toggleSlideshow()):e===this.slidesContainer[0]?(this.preventDefault(b),c.closeOnSlideClick?this.close():this.toggleControls()):e.parentNode&&e.parentNode===this.slidesContainer[0]&&(this.preventDefault(b),this.toggleControls())},onclick:function(a){return this.options.emulateTouchEvents&&this.touchDelta&&(Math.abs(this.touchDelta.x)>20||Math.abs(this.touchDelta.y)>20)?void delete this.touchDelta:this.handleClick(a)},updateEdgeClasses:function(a){a?this.container.removeClass(this.options.leftEdgeClass):this.container.addClass(this.options.leftEdgeClass),a===this.num-1?this.container.addClass(this.options.rightEdgeClass):this.container.removeClass(this.options.rightEdgeClass)},handleSlide:function(a){this.options.continuous||this.updateEdgeClasses(a),this.loadElements(a),this.options.unloadElements&&this.unloadElements(a),this.setTitle(a)},onslide:function(a){this.index=a,this.handleSlide(a),this.setTimeout(this.options.onslide,[a,this.slides[a]])},setTitle:function(a){var b=this.slides[a].firstChild.title,c=this.titleElement;c.length&&(this.titleElement.empty(),b&&c[0].appendChild(document.createTextNode(b)))},setTimeout:function(a,b,c){var d=this;return a&&window.setTimeout(function(){a.apply(d,b||[])},c||0)},imageFactory:function(b,c){var d,e,f,g=this,h=this.imagePrototype.cloneNode(!1),i=b,j=this.options.stretchImages,k=function(b){if(!d){if(b={type:b.type,target:e},!e.parentNode)return g.setTimeout(k,[b]);d=!0,a(h).off("load error",k),j&&"load"===b.type&&(e.style.background='url("'+i+'") center no-repeat',e.style.backgroundSize=j),c(b)}};return"string"!=typeof i&&(i=this.getItemProperty(b,this.options.urlProperty),f=this.getItemProperty(b,this.options.titleProperty)),j===!0&&(j="contain"),j=this.support.backgroundSize&&this.support.backgroundSize[j]&&j,j?e=this.elementPrototype.cloneNode(!1):(e=h,h.draggable=!1),f&&(e.title=f),a(h).on("load error",k),h.src=i,e},createElement:function(b,c){var d=b&&this.getItemProperty(b,this.options.typeProperty),e=d&&this[d.split("/")[0]+"Factory"]||this.imageFactory,f=b&&e.call(this,b,c);return f||(f=this.elementPrototype.cloneNode(!1),this.setTimeout(c,[{type:"error",target:f}])),a(f).addClass(this.options.slideContentClass),f},loadElement:function(b){this.elements[b]||(this.slides[b].firstChild?this.elements[b]=a(this.slides[b]).hasClass(this.options.slideErrorClass)?3:2:(this.elements[b]=1,a(this.slides[b]).addClass(this.options.slideLoadingClass),this.slides[b].appendChild(this.createElement(this.list[b],this.proxyListener))))},loadElements:function(a){var b,c=Math.min(this.num,2*this.options.preloadRange+1),d=a;for(b=0;c>b;b+=1)d+=b*(b%2===0?-1:1),d=this.circle(d),this.loadElement(d)},unloadElements:function(a){var b,c,d;for(b in this.elements)this.elements.hasOwnProperty(b)&&(d=Math.abs(a-b),d>this.options.preloadRange&&d+this.options.preloadRangea?-this.slideWidth:this.index