├── .gitignore
├── .github
├── FUNDING.yml
└── workflows
│ └── test.yml
├── img
├── close.png
├── error.png
├── next.png
├── prev.png
├── loading.gif
├── play-pause.png
├── video-play.png
├── next.svg
├── prev.svg
├── close.svg
├── video-play.svg
├── error.svg
├── play-pause.svg
└── loading.svg
├── bin
└── sync-vendor-libs.sh
├── LICENSE.txt
├── css
├── demo
│ └── demo.css
├── blueimp-gallery-video.css
├── blueimp-gallery-indicator.css
├── blueimp-gallery.min.css.map
├── blueimp-gallery.css
└── blueimp-gallery.min.css
├── js
├── jquery.blueimp-gallery.js
├── blueimp-gallery-fullscreen.js
├── demo
│ └── demo.js
├── blueimp-gallery-indicator.js
├── blueimp-helper.js
├── blueimp-gallery-vimeo.js
├── blueimp-gallery-youtube.js
├── blueimp-gallery-video.js
├── jquery.blueimp-gallery.min.js
├── blueimp-gallery.min.js
├── jquery.blueimp-gallery.min.js.map
└── blueimp-gallery.min.js.map
├── package.json
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [blueimp]
2 |
--------------------------------------------------------------------------------
/img/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueimp/Gallery/HEAD/img/close.png
--------------------------------------------------------------------------------
/img/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueimp/Gallery/HEAD/img/error.png
--------------------------------------------------------------------------------
/img/next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueimp/Gallery/HEAD/img/next.png
--------------------------------------------------------------------------------
/img/prev.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueimp/Gallery/HEAD/img/prev.png
--------------------------------------------------------------------------------
/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueimp/Gallery/HEAD/img/loading.gif
--------------------------------------------------------------------------------
/img/play-pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueimp/Gallery/HEAD/img/play-pause.png
--------------------------------------------------------------------------------
/img/video-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueimp/Gallery/HEAD/img/video-play.png
--------------------------------------------------------------------------------
/bin/sync-vendor-libs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | cd "$(dirname "$0")/.."
3 | cp node_modules/jquery/dist/jquery.js js/vendor/
4 |
--------------------------------------------------------------------------------
/img/next.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/img/prev.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/img/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/img/video-play.svg:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/img/error.svg:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/img/play-pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | lint:
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | node-version: [14, 16]
11 | steps:
12 | - uses: actions/checkout@v2
13 | - uses: actions/setup-node@v2
14 | with:
15 | node-version: ${{ matrix.node-version }}
16 | - run: npm install
17 | - run: npm run build --if-present
18 | - run: npm test
19 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright © 2013 Sebastian Tschan, https://blueimp.net
4 |
5 | Swipe implementation based on: https://github.com/thebird/Swipe
6 | Copyright © 2013 Brad Birdsall, https://github.com/thebird
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | this software and associated documentation files (the "Software"), to deal in
10 | the Software without restriction, including without limitation the rights to
11 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 | the Software, and to permit persons to whom the Software is furnished to do so,
13 | subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in all
16 | copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/css/demo/demo.css:
--------------------------------------------------------------------------------
1 | /*
2 | * blueimp Gallery Demo CSS
3 | * https://github.com/blueimp/Gallery
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | body {
13 | max-width: 990px;
14 | margin: 0 auto;
15 | padding: 1em;
16 | font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue',
17 | Arial, sans-serif;
18 | -webkit-text-size-adjust: 100%;
19 | line-height: 1.4;
20 | background: #212121;
21 | color: #dedede;
22 | }
23 | a {
24 | color: #61afef;
25 | text-decoration: none;
26 | }
27 | a:visited {
28 | color: #56b6c2;
29 | }
30 | a:hover {
31 | color: #98c379;
32 | }
33 | img {
34 | max-width: 100%;
35 | border: 0;
36 | vertical-align: middle;
37 | }
38 | h1,
39 | h2,
40 | h3,
41 | h4,
42 | h5,
43 | h6 {
44 | margin-top: 1.5em;
45 | margin-bottom: 0.5em;
46 | }
47 | h1 {
48 | margin-top: 0.5em;
49 | }
50 |
51 | @media (prefers-color-scheme: light) {
52 | body {
53 | background: #ececec;
54 | color: #212121;
55 | }
56 | a {
57 | color: #225c8d;
58 | }
59 | a:visited {
60 | color: #378f9a;
61 | }
62 | a:hover {
63 | color: #6fa349;
64 | }
65 | }
66 |
67 | @media (min-width: 540px) {
68 | #navigation {
69 | list-style: none;
70 | padding: 0;
71 | }
72 | #navigation li {
73 | display: inline-block;
74 | }
75 | #navigation li:not(:first-child)::before {
76 | content: ' | ';
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/css/blueimp-gallery-video.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * blueimp Gallery Video Factory CSS
4 | * https://github.com/blueimp/Gallery
5 | *
6 | * Copyright 2013, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | .blueimp-gallery > .slides > .slide > .video-content > video,
14 | .blueimp-gallery > .slides > .slide > .video-content > iframe,
15 | .blueimp-gallery > .slides > .slide > .video-content > .video-cover {
16 | position: absolute;
17 | top: 0;
18 | left: 0;
19 | width: 100%;
20 | height: 100%;
21 | border: none;
22 | }
23 | .blueimp-gallery > .slides > .slide > .video-content > .video-cover {
24 | background: center no-repeat;
25 | background-size: contain;
26 | }
27 | .blueimp-gallery > .slides > .slide > .video-iframe > .video-cover {
28 | background-color: #000;
29 | background-color: rgba(0, 0, 0, 0.7);
30 | }
31 | .blueimp-gallery > .slides > .slide > .video-content > .video-play {
32 | position: absolute;
33 | top: 50%;
34 | right: 0;
35 | left: 0;
36 | margin: -64px auto 0;
37 | width: 128px;
38 | height: 128px;
39 | background: url(../img/video-play.png) center no-repeat;
40 | opacity: 0.8;
41 | cursor: pointer;
42 | }
43 | .blueimp-gallery-svgasimg > .slides > .slide > .video-content > .video-play {
44 | background-image: url(../img/video-play.svg);
45 | }
46 | .blueimp-gallery > .slides > .slide > .video-playing > .video-play,
47 | .blueimp-gallery > .slides > .slide > .video-playing > .video-cover {
48 | display: none;
49 | }
50 | .blueimp-gallery > .slides > .slide > .video-loading > .video-play {
51 | background: url(../img/loading.gif) center no-repeat;
52 | background-size: 64px 64px;
53 | }
54 | .blueimp-gallery-smil > .slides > .slide > .video-loading > .video-play {
55 | background-image: url(../img/loading.svg);
56 | }
57 |
58 | /* IE7 fixes */
59 | * + html .blueimp-gallery > .slides > .slide > .video-content {
60 | height: 100%;
61 | }
62 | * + html .blueimp-gallery > .slides > .slide > .video-content > .video-play {
63 | left: 50%;
64 | margin-left: -64px;
65 | }
66 |
67 | .blueimp-gallery > .slides > .slide > .video-content > .video-play:hover {
68 | opacity: 1;
69 | }
70 |
--------------------------------------------------------------------------------
/js/jquery.blueimp-gallery.js:
--------------------------------------------------------------------------------
1 | /*
2 | * blueimp Gallery jQuery plugin
3 | * https://github.com/blueimp/Gallery
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global define */
13 |
14 | ;(function (factory) {
15 | 'use strict'
16 | if (typeof define === 'function' && define.amd) {
17 | define(['jquery', './blueimp-gallery'], factory)
18 | } else {
19 | factory(window.jQuery, window.blueimp.Gallery)
20 | }
21 | })(function ($, Gallery) {
22 | 'use strict'
23 |
24 | // Global click handler to open links with data-gallery attribute
25 | // in the Gallery lightbox:
26 | $(document).on('click', '[data-gallery]', function (event) {
27 | // Get the container id from the data-gallery attribute:
28 | var id = $(this).data('gallery')
29 | var widget = $(id)
30 | var container =
31 | (widget.length && widget) || $(Gallery.prototype.options.container)
32 | var callbacks = {
33 | onopen: function () {
34 | container.data('gallery', this).trigger('open')
35 | },
36 | onopened: function () {
37 | container.trigger('opened')
38 | },
39 | onslide: function () {
40 | container.trigger('slide', arguments)
41 | },
42 | onslideend: function () {
43 | container.trigger('slideend', arguments)
44 | },
45 | onslidecomplete: function () {
46 | container.trigger('slidecomplete', arguments)
47 | },
48 | onclose: function () {
49 | container.trigger('close')
50 | },
51 | onclosed: function () {
52 | container.trigger('closed').removeData('gallery')
53 | }
54 | }
55 | var options = $.extend(
56 | // Retrieve custom options from data-attributes
57 | // on the Gallery widget:
58 | container.data(),
59 | {
60 | container: container[0],
61 | index: this,
62 | event: event
63 | },
64 | callbacks
65 | )
66 | // Select all links with the same data-gallery attribute:
67 | var links = $(this)
68 | .closest('[data-gallery-group], body')
69 | .find('[data-gallery="' + id + '"]')
70 | if (options.filter) {
71 | links = links.filter(options.filter)
72 | }
73 | return new Gallery(links, options)
74 | })
75 | })
76 |
--------------------------------------------------------------------------------
/css/blueimp-gallery-indicator.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * blueimp Gallery Indicator CSS
4 | * https://github.com/blueimp/Gallery
5 | *
6 | * Copyright 2013, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | .blueimp-gallery > .indicator {
14 | position: absolute;
15 | top: auto;
16 | right: 15px;
17 | bottom: 15px;
18 | left: 15px;
19 | margin: 0 40px;
20 | padding: 0;
21 | list-style: none;
22 | text-align: center;
23 | line-height: 10px;
24 | display: none;
25 | -webkit-user-select: none;
26 | -khtml-user-select: none;
27 | -moz-user-select: none;
28 | -ms-user-select: none;
29 | user-select: none;
30 | }
31 | .blueimp-gallery > .indicator > li {
32 | display: inline-block;
33 | position: relative;
34 | width: 9px;
35 | height: 9px;
36 | margin: 6px 3px 0 3px;
37 | -webkit-box-sizing: content-box;
38 | -moz-box-sizing: content-box;
39 | box-sizing: content-box;
40 | border: 1px solid transparent;
41 | background: #ccc;
42 | background: rgba(255, 255, 255, 0.25) center no-repeat;
43 | border-radius: 5px;
44 | box-shadow: 0 0 2px #000;
45 | opacity: 0.5;
46 | cursor: pointer;
47 | }
48 |
49 | /* IE7 fixes */
50 | * + html .blueimp-gallery > .indicator > li {
51 | display: inline;
52 | }
53 |
54 | .blueimp-gallery > .indicator > li:hover,
55 | .blueimp-gallery > .indicator > .active {
56 | background-color: #fff;
57 | border-color: #fff;
58 | opacity: 1;
59 | }
60 |
61 | .blueimp-gallery > .indicator > li:after {
62 | opacity: 0;
63 | display: block;
64 | position: absolute;
65 | content: '';
66 | top: -5em;
67 | left: 4px;
68 | width: 75px;
69 | height: 75px;
70 | transition: transform 600ms ease-out, opacity 400ms ease-out;
71 | transform: translateX(-50%) translateY(0) translateZ(0px);
72 | pointer-events: none;
73 | }
74 |
75 | .blueimp-gallery > .indicator > li:hover:after {
76 | opacity: 1;
77 | border-radius: 50%;
78 | background: inherit;
79 | transform: translateX(-50%) translateY(-5px) translateZ(0px);
80 | }
81 |
82 | .blueimp-gallery > .indicator > .active:after {
83 | display: none;
84 | }
85 |
86 | .blueimp-gallery-controls > .indicator {
87 | display: block;
88 | /* Fix z-index issues (controls behind slide element) on Android: */
89 | -webkit-transform: translateZ(0);
90 | -moz-transform: translateZ(0);
91 | -ms-transform: translateZ(0);
92 | -o-transform: translateZ(0);
93 | transform: translateZ(0);
94 | }
95 | .blueimp-gallery-single > .indicator {
96 | display: none;
97 | }
98 |
--------------------------------------------------------------------------------
/js/blueimp-gallery-fullscreen.js:
--------------------------------------------------------------------------------
1 | /*
2 | * blueimp Gallery Fullscreen JS
3 | * https://github.com/blueimp/Gallery
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global define */
13 |
14 | ;(function (factory) {
15 | 'use strict'
16 | if (typeof define === 'function' && define.amd) {
17 | // Register as an anonymous AMD module:
18 | define(['./blueimp-helper', './blueimp-gallery'], factory)
19 | } else {
20 | // Browser globals:
21 | factory(window.blueimp.helper || window.jQuery, window.blueimp.Gallery)
22 | }
23 | })(function ($, Gallery) {
24 | 'use strict'
25 |
26 | var galleryPrototype = Gallery.prototype
27 |
28 | $.extend(galleryPrototype.options, {
29 | // Defines if the gallery should open in fullscreen mode:
30 | fullscreen: false
31 | })
32 |
33 | var initialize = galleryPrototype.initialize
34 | var close = galleryPrototype.close
35 |
36 | $.extend(galleryPrototype, {
37 | getFullScreenElement: function () {
38 | return (
39 | document.fullscreenElement ||
40 | document.webkitFullscreenElement ||
41 | document.mozFullScreenElement ||
42 | document.msFullscreenElement
43 | )
44 | },
45 |
46 | requestFullScreen: function (element) {
47 | if (element.requestFullscreen) {
48 | element.requestFullscreen()
49 | } else if (element.webkitRequestFullscreen) {
50 | element.webkitRequestFullscreen()
51 | } else if (element.mozRequestFullScreen) {
52 | element.mozRequestFullScreen()
53 | } else if (element.msRequestFullscreen) {
54 | element.msRequestFullscreen()
55 | }
56 | },
57 |
58 | exitFullScreen: function () {
59 | if (document.exitFullscreen) {
60 | document.exitFullscreen()
61 | } else if (document.webkitCancelFullScreen) {
62 | document.webkitCancelFullScreen()
63 | } else if (document.mozCancelFullScreen) {
64 | document.mozCancelFullScreen()
65 | } else if (document.msExitFullscreen) {
66 | document.msExitFullscreen()
67 | }
68 | },
69 |
70 | initialize: function () {
71 | initialize.call(this)
72 | if (this.options.fullscreen && !this.getFullScreenElement()) {
73 | this.requestFullScreen(this.container[0])
74 | }
75 | },
76 |
77 | close: function () {
78 | if (this.getFullScreenElement() === this.container[0]) {
79 | this.exitFullScreen()
80 | }
81 | close.call(this)
82 | }
83 | })
84 |
85 | return Gallery
86 | })
87 |
--------------------------------------------------------------------------------
/css/blueimp-gallery.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["blueimp-gallery.css","blueimp-gallery-indicator.css","blueimp-gallery-video.css"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/img/loading.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blueimp-gallery",
3 | "version": "3.4.0",
4 | "title": "blueimp Gallery",
5 | "description": "blueimp Gallery is a touch-enabled, responsive and customizable image and video gallery, carousel and lightbox, optimized for both mobile and desktop web browsers. It features swipe, mouse and keyboard navigation, transition effects, slideshow functionality, fullscreen support and on-demand content loading and can be extended to display additional content types.",
6 | "keywords": [
7 | "image",
8 | "video",
9 | "gallery",
10 | "carousel",
11 | "lightbox",
12 | "mobile",
13 | "desktop",
14 | "touch",
15 | "responsive",
16 | "swipe",
17 | "mouse",
18 | "keyboard",
19 | "navigation",
20 | "transition",
21 | "effects",
22 | "slideshow",
23 | "fullscreen"
24 | ],
25 | "homepage": "https://github.com/blueimp/Gallery",
26 | "author": {
27 | "name": "Sebastian Tschan",
28 | "url": "https://blueimp.net"
29 | },
30 | "repository": {
31 | "type": "git",
32 | "url": "git://github.com/blueimp/Gallery.git"
33 | },
34 | "license": "MIT",
35 | "devDependencies": {
36 | "clean-css-cli": "5",
37 | "eslint": "7",
38 | "eslint-config-blueimp": "2",
39 | "eslint-config-prettier": "8",
40 | "eslint-plugin-jsdoc": "36",
41 | "eslint-plugin-prettier": "4",
42 | "jquery": "1",
43 | "prettier": "2",
44 | "stylelint": "13",
45 | "stylelint-config-prettier": "8",
46 | "stylelint-config-recommended": "5",
47 | "uglify-js": "3"
48 | },
49 | "stylelint": {
50 | "extends": [
51 | "stylelint-config-recommended",
52 | "stylelint-config-prettier"
53 | ],
54 | "ignoreFiles": [
55 | "css/*.min.css"
56 | ]
57 | },
58 | "eslintConfig": {
59 | "extends": [
60 | "blueimp",
61 | "plugin:jsdoc/recommended",
62 | "plugin:prettier/recommended"
63 | ],
64 | "env": {
65 | "browser": true
66 | }
67 | },
68 | "eslintIgnore": [
69 | "js/*.min.js",
70 | "js/vendor"
71 | ],
72 | "prettier": {
73 | "arrowParens": "avoid",
74 | "proseWrap": "always",
75 | "semi": false,
76 | "singleQuote": true,
77 | "trailingComma": "none"
78 | },
79 | "scripts": {
80 | "test": "stylelint '**/*.css' && eslint .",
81 | "prebuild": "bin/sync-vendor-libs.sh",
82 | "build:js": "cd js && uglifyjs blueimp-helper.js blueimp-gallery.js blueimp-gallery-fullscreen.js blueimp-gallery-indicator.js blueimp-gallery-video.js blueimp-gallery-vimeo.js blueimp-gallery-youtube.js --ie8 -c -m -o blueimp-gallery.min.js --source-map url=blueimp-gallery.min.js.map",
83 | "build:jquery": "cd js && uglifyjs blueimp-gallery.js blueimp-gallery-fullscreen.js blueimp-gallery-indicator.js blueimp-gallery-video.js blueimp-gallery-vimeo.js blueimp-gallery-youtube.js jquery.blueimp-gallery.js --ie8 -c -m -o jquery.blueimp-gallery.min.js --source-map url=jquery.blueimp-gallery.min.js.map",
84 | "build:css": "cd css && cleancss -c ie7 --source-map -o blueimp-gallery.min.css blueimp-gallery.css blueimp-gallery-indicator.css blueimp-gallery-video.css",
85 | "build": "npm run build:js && npm run build:jquery && npm run build:css",
86 | "preversion": "npm test",
87 | "version": "npm run build && git add -A js css",
88 | "postversion": "git push --tags origin master master:gh-pages && npm publish"
89 | },
90 | "files": [
91 | "css/*.css",
92 | "css/*.css.map",
93 | "img/*.gif",
94 | "img/*.png",
95 | "img/*.svg",
96 | "js/*.js",
97 | "js/*.js.map"
98 | ],
99 | "main": "js/blueimp-gallery.js"
100 | }
101 |
--------------------------------------------------------------------------------
/js/demo/demo.js:
--------------------------------------------------------------------------------
1 | /*
2 | * blueimp Gallery Demo JS
3 | * https://github.com/blueimp/Gallery
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global blueimp, $ */
13 |
14 | $(function () {
15 | 'use strict'
16 |
17 | // Flickr image types:
18 | var imageTypes = [
19 | // https://www.flickr.com/services/api/misc.urls.html
20 | 'sq', // 75x75
21 | 'q', // 150x150
22 | 't', // 100 on longest side
23 | 's', // 240 on longest side
24 | 'n', // 320 on longest side
25 | 'm', // 500 on longest side
26 | 'z', // 640 on longest side
27 | 'c', // 800 on longest side
28 | 'l', // 1024 on longest side
29 | 'h', // 1600 on longest side
30 | 'k', // 2048 on longest side
31 | 'o' // original dimensions
32 | ]
33 |
34 | // Load demo images from Flickr:
35 | $.ajax({
36 | url: 'https://api.flickr.com/services/rest/',
37 | data: {
38 | // https://www.flickr.com/services/api/flickr.interestingness.getList.html
39 | method: 'flickr.interestingness.getList',
40 | format: 'json',
41 | extras: 'url_' + imageTypes.join(',url_'),
42 | // eslint-disable-next-line camelcase
43 | api_key: '7617adae70159d09ba78cfec73c13be3'
44 | },
45 | dataType: 'jsonp',
46 | jsonp: 'jsoncallback'
47 | }).done(function (result) {
48 | var maxWidth = $(document.body).css('max-width')
49 | var sizes = '(min-width: ' + maxWidth + ') ' + maxWidth + ', 100vw'
50 | var carouselLinks = []
51 | var linksContainer = $('#links')
52 | // Add the demo images as links with thumbnails to the page:
53 | $.each(result.photos.photo, function (_, photo) {
54 | var thumbnail = $('')
55 | .prop('loading', 'lazy')
56 | .prop('width', photo.width_sq)
57 | .prop('height', photo.height_sq)
58 | .prop('src', photo.url_sq)
59 | .prop('alt', photo.title)
60 | var srcset = []
61 | $.each(imageTypes, function (_, type) {
62 | var url = photo['url_' + type]
63 | var width = photo['width_' + type]
64 | if (url) {
65 | srcset.push(url + ' ' + width + 'w')
66 | }
67 | })
68 | srcset = srcset.join(',')
69 | $('')
70 | .append(thumbnail)
71 | .prop('title', photo.title)
72 | .prop('href', photo.url_l)
73 | .attr('data-srcset', srcset)
74 | .attr('data-gallery', '')
75 | .appendTo(linksContainer)
76 | carouselLinks.push({
77 | title: photo.title,
78 | href: photo.url_l,
79 | sizes: sizes,
80 | srcset: srcset
81 | })
82 | })
83 | // Initialize the Gallery as image carousel:
84 | // eslint-disable-next-line new-cap
85 | blueimp.Gallery(carouselLinks, {
86 | container: '#blueimp-image-carousel',
87 | carousel: true
88 | })
89 | })
90 |
91 | // Initialize the Gallery as video carousel:
92 | // eslint-disable-next-line new-cap
93 | blueimp.Gallery(
94 | [
95 | {
96 | title: 'Sintel',
97 | type: 'video',
98 | sources: [
99 | {
100 | type: 'video/webm',
101 | src:
102 | 'https://upload.wikimedia.org/wikipedia/commons/f/f1/' +
103 | 'Sintel_movie_4K.webm'
104 | },
105 | {
106 | type: 'video/mp4',
107 | src: 'https://archive.org/download/Sintel/sintel-2048-surround.mp4'
108 | },
109 | {
110 | type: 'video/ogg',
111 | src: 'https://archive.org/download/Sintel/sintel-2048-stereo.ogv'
112 | }
113 | ],
114 | poster:
115 | 'https://upload.wikimedia.org/wikipedia/commons/d/dc/' +
116 | 'Sintel_1920x1080.png'
117 | },
118 | {
119 | title: 'LES TWINS - An Industry Ahead',
120 | type: 'text/html',
121 | youtube: 'zi4CIXpx7Bg'
122 | },
123 | {
124 | title: 'KN1GHT - Last Moon',
125 | type: 'text/html',
126 | vimeo: '73686146',
127 | poster: 'https://secure-a.vimeocdn.com/ts/448/835/448835699_960.jpg'
128 | }
129 | ],
130 | {
131 | container: '#blueimp-video-carousel',
132 | carousel: true,
133 | startSlideshow: false
134 | }
135 | )
136 |
137 | $('#fullscreen').change(function () {
138 | $('#blueimp-gallery').data('fullscreen', this.checked)
139 | })
140 | })
141 |
--------------------------------------------------------------------------------
/js/blueimp-gallery-indicator.js:
--------------------------------------------------------------------------------
1 | /*
2 | * blueimp Gallery Indicator JS
3 | * https://github.com/blueimp/Gallery
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global define */
13 |
14 | ;(function (factory) {
15 | 'use strict'
16 | if (typeof define === 'function' && define.amd) {
17 | // Register as an anonymous AMD module:
18 | define(['./blueimp-helper', './blueimp-gallery'], factory)
19 | } else {
20 | // Browser globals:
21 | factory(window.blueimp.helper || window.jQuery, window.blueimp.Gallery)
22 | }
23 | })(function ($, Gallery) {
24 | 'use strict'
25 |
26 | var galleryPrototype = Gallery.prototype
27 |
28 | $.extend(galleryPrototype.options, {
29 | // The tag name, Id, element or querySelector of the indicator container:
30 | indicatorContainer: 'ol',
31 | // The class for the active indicator:
32 | activeIndicatorClass: 'active',
33 | // The list object property (or data attribute) with the thumbnail URL,
34 | // used as alternative to a thumbnail child element:
35 | thumbnailProperty: 'thumbnail',
36 | // Defines if the gallery indicators should display a thumbnail:
37 | thumbnailIndicators: true
38 | })
39 |
40 | var initSlides = galleryPrototype.initSlides
41 | var addSlide = galleryPrototype.addSlide
42 | var resetSlides = galleryPrototype.resetSlides
43 | var handleClick = galleryPrototype.handleClick
44 | var handleSlide = galleryPrototype.handleSlide
45 | var handleClose = galleryPrototype.handleClose
46 |
47 | $.extend(galleryPrototype, {
48 | createIndicator: function (obj) {
49 | var indicator = this.indicatorPrototype.cloneNode(false)
50 | var title = this.getItemProperty(obj, this.options.titleProperty)
51 | var thumbnailProperty = this.options.thumbnailProperty
52 | var thumbnailUrl
53 | var thumbnail
54 | if (this.options.thumbnailIndicators) {
55 | if (thumbnailProperty) {
56 | thumbnailUrl = this.getItemProperty(obj, thumbnailProperty)
57 | }
58 | if (thumbnailUrl === undefined) {
59 | thumbnail = obj.getElementsByTagName && $(obj).find('img')[0]
60 | if (thumbnail) {
61 | thumbnailUrl = thumbnail.src
62 | }
63 | }
64 | if (thumbnailUrl) {
65 | indicator.style.backgroundImage = 'url("' + thumbnailUrl + '")'
66 | }
67 | }
68 | if (title) {
69 | indicator.title = title
70 | }
71 | indicator.setAttribute('role', 'link')
72 | return indicator
73 | },
74 |
75 | addIndicator: function (index) {
76 | if (this.indicatorContainer.length) {
77 | var indicator = this.createIndicator(this.list[index])
78 | indicator.setAttribute('data-index', index)
79 | this.indicatorContainer[0].appendChild(indicator)
80 | this.indicators.push(indicator)
81 | }
82 | },
83 |
84 | setActiveIndicator: function (index) {
85 | if (this.indicators) {
86 | if (this.activeIndicator) {
87 | this.activeIndicator.removeClass(this.options.activeIndicatorClass)
88 | }
89 | this.activeIndicator = $(this.indicators[index])
90 | this.activeIndicator.addClass(this.options.activeIndicatorClass)
91 | }
92 | },
93 |
94 | initSlides: function (reload) {
95 | if (!reload) {
96 | this.indicatorContainer = this.container.find(
97 | this.options.indicatorContainer
98 | )
99 | if (this.indicatorContainer.length) {
100 | this.indicatorPrototype = document.createElement('li')
101 | this.indicators = this.indicatorContainer[0].children
102 | }
103 | }
104 | initSlides.call(this, reload)
105 | },
106 |
107 | addSlide: function (index) {
108 | addSlide.call(this, index)
109 | this.addIndicator(index)
110 | },
111 |
112 | resetSlides: function () {
113 | resetSlides.call(this)
114 | this.indicatorContainer.empty()
115 | this.indicators = []
116 | },
117 |
118 | handleClick: function (event) {
119 | var target = event.target || event.srcElement
120 | var parent = target.parentNode
121 | if (parent === this.indicatorContainer[0]) {
122 | // Click on indicator element
123 | this.preventDefault(event)
124 | this.slide(this.getNodeIndex(target))
125 | } else if (parent.parentNode === this.indicatorContainer[0]) {
126 | // Click on indicator child element
127 | this.preventDefault(event)
128 | this.slide(this.getNodeIndex(parent))
129 | } else {
130 | return handleClick.call(this, event)
131 | }
132 | },
133 |
134 | handleSlide: function (oldIndex, newIndex) {
135 | handleSlide.call(this, oldIndex, newIndex)
136 | this.setActiveIndicator(newIndex)
137 | },
138 |
139 | handleClose: function () {
140 | if (this.activeIndicator) {
141 | this.activeIndicator.removeClass(this.options.activeIndicatorClass)
142 | }
143 | handleClose.call(this)
144 | }
145 | })
146 |
147 | return Gallery
148 | })
149 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
34 | blueimp Gallery is a 35 | touch-enabled, responsive and customizable image & video gallery, 36 | carousel and lightbox, optimized for both mobile and desktop web browsers. 37 |
38 |39 | It features swipe, mouse and keyboard navigation, transition effects, 40 | slideshow functionality, fullscreen support and on-demand content loading 41 | and can be extended to display additional content types. 42 |
43 | 55 |104 | 105 | 106 |
107 | 108 | 109 | 110 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /js/blueimp-helper.js: -------------------------------------------------------------------------------- 1 | /* 2 | * blueimp helper JS 3 | * https://github.com/blueimp/Gallery 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define */ 13 | 14 | /* eslint-disable no-param-reassign */ 15 | 16 | ;(function () { 17 | 'use strict' 18 | 19 | /** 20 | * Object.assign polyfill 21 | * 22 | * @param {object} obj1 First object 23 | * @param {object} obj2 Second object 24 | * @returns {object} Merged object 25 | */ 26 | function extend(obj1, obj2) { 27 | var prop 28 | for (prop in obj2) { 29 | if (Object.prototype.hasOwnProperty.call(obj2, prop)) { 30 | obj1[prop] = obj2[prop] 31 | } 32 | } 33 | return obj1 34 | } 35 | /** 36 | * Helper constructor 37 | * 38 | * @class 39 | * @param {*} query jQuery type query argument 40 | */ 41 | function Helper(query) { 42 | if (!this || this.find !== Helper.prototype.find) { 43 | // Called as function instead of as constructor, 44 | // so we simply return a new instance: 45 | return new Helper(query) 46 | } 47 | this.length = 0 48 | if (query) { 49 | if (typeof query === 'string') { 50 | query = this.find(query) 51 | } 52 | if (query.nodeType || query === query.window) { 53 | // Single HTML element 54 | this.length = 1 55 | this[0] = query 56 | } else { 57 | // HTML element collection 58 | var i = query.length 59 | this.length = i 60 | while (i) { 61 | i -= 1 62 | this[i] = query[i] 63 | } 64 | } 65 | } 66 | } 67 | 68 | Helper.extend = extend 69 | 70 | Helper.contains = function (container, element) { 71 | do { 72 | element = element.parentNode 73 | if (element === container) { 74 | return true 75 | } 76 | } while (element) 77 | return false 78 | } 79 | 80 | Helper.parseJSON = function (string) { 81 | return JSON.parse(string) 82 | } 83 | 84 | extend(Helper.prototype, { 85 | find: function (query) { 86 | var container = this[0] || document 87 | if (typeof query === 'string') { 88 | if (container.querySelectorAll) { 89 | query = container.querySelectorAll(query) 90 | } else if (query.charAt(0) === '#') { 91 | query = container.getElementById(query.slice(1)) 92 | } else { 93 | query = container.getElementsByTagName(query) 94 | } 95 | } 96 | return new Helper(query) 97 | }, 98 | 99 | hasClass: function (className) { 100 | if (!this[0]) return false 101 | return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test( 102 | this[0].className 103 | ) 104 | }, 105 | 106 | addClass: function (className) { 107 | var i = this.length 108 | var classNames 109 | var element 110 | var j 111 | while (i) { 112 | i -= 1 113 | element = this[i] 114 | if (!element.className) { 115 | element.className = className 116 | continue 117 | } 118 | if (!classNames) classNames = className.split(/\s+/) 119 | for (j = 0; j < classNames.length; j += 1) { 120 | if (this.hasClass(classNames[j])) { 121 | continue 122 | } 123 | element.className += ' ' + classNames[j] 124 | } 125 | } 126 | return this 127 | }, 128 | 129 | removeClass: function (className) { 130 | // Match any of the given class names 131 | var regexp = new RegExp('^(?:' + className.split(/\s+/).join('|') + ')$') 132 | // Match any class names and their trailing whitespace 133 | var matcher = /(\S+)(?:\s+|$)/g 134 | var replacer = function (match, className) { 135 | // Replace class names that match the given ones 136 | return regexp.test(className) ? '' : match 137 | } 138 | var trimEnd = /\s+$/ 139 | var i = this.length 140 | var element 141 | while (i) { 142 | i -= 1 143 | element = this[i] 144 | element.className = element.className 145 | .replace(matcher, replacer) 146 | .replace(trimEnd, '') 147 | } 148 | return this 149 | }, 150 | 151 | on: function (eventName, handler) { 152 | var eventNames = eventName.split(/\s+/) 153 | var i 154 | var element 155 | while (eventNames.length) { 156 | eventName = eventNames.shift() 157 | i = this.length 158 | while (i) { 159 | i -= 1 160 | element = this[i] 161 | if (element.addEventListener) { 162 | element.addEventListener(eventName, handler, false) 163 | } else if (element.attachEvent) { 164 | element.attachEvent('on' + eventName, handler) 165 | } 166 | } 167 | } 168 | return this 169 | }, 170 | 171 | off: function (eventName, handler) { 172 | var eventNames = eventName.split(/\s+/) 173 | var i 174 | var element 175 | while (eventNames.length) { 176 | eventName = eventNames.shift() 177 | i = this.length 178 | while (i) { 179 | i -= 1 180 | element = this[i] 181 | if (element.removeEventListener) { 182 | element.removeEventListener(eventName, handler, false) 183 | } else if (element.detachEvent) { 184 | element.detachEvent('on' + eventName, handler) 185 | } 186 | } 187 | } 188 | return this 189 | }, 190 | 191 | empty: function () { 192 | var i = this.length 193 | var element 194 | while (i) { 195 | i -= 1 196 | element = this[i] 197 | while (element.hasChildNodes()) { 198 | element.removeChild(element.lastChild) 199 | } 200 | } 201 | return this 202 | }, 203 | 204 | first: function () { 205 | return new Helper(this[0]) 206 | } 207 | }) 208 | 209 | if (typeof define === 'function' && define.amd) { 210 | define(function () { 211 | return Helper 212 | }) 213 | } else { 214 | window.blueimp = window.blueimp || {} 215 | window.blueimp.helper = Helper 216 | } 217 | })() 218 | -------------------------------------------------------------------------------- /js/blueimp-gallery-vimeo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * blueimp Gallery Vimeo Video Factory JS 3 | * https://github.com/blueimp/Gallery 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define, $f */ 13 | 14 | ;(function (factory) { 15 | 'use strict' 16 | if (typeof define === 'function' && define.amd) { 17 | // Register as an anonymous AMD module: 18 | define(['./blueimp-helper', './blueimp-gallery-video'], factory) 19 | } else { 20 | // Browser globals: 21 | factory(window.blueimp.helper || window.jQuery, window.blueimp.Gallery) 22 | } 23 | })(function ($, Gallery) { 24 | 'use strict' 25 | 26 | if (!window.postMessage) { 27 | return Gallery 28 | } 29 | 30 | var galleryPrototype = Gallery.prototype 31 | 32 | $.extend(galleryPrototype.options, { 33 | // The list object property (or data attribute) with the Vimeo video id: 34 | vimeoVideoIdProperty: 'vimeo', 35 | // The URL for the Vimeo video player, can be extended with custom parameters: 36 | // https://developer.vimeo.com/player/embedding 37 | vimeoPlayerUrl: 38 | 'https://player.vimeo.com/video/VIDEO_ID?api=1&player_id=PLAYER_ID', 39 | // The prefix for the Vimeo video player ID: 40 | vimeoPlayerIdPrefix: 'vimeo-player-', 41 | // Require a click on the native Vimeo player for the initial playback: 42 | vimeoClickToPlay: false 43 | }) 44 | 45 | var textFactory = 46 | galleryPrototype.textFactory || galleryPrototype.imageFactory 47 | var VimeoPlayer = function (url, videoId, playerId, clickToPlay) { 48 | this.url = url 49 | this.videoId = videoId 50 | this.playerId = playerId 51 | this.clickToPlay = clickToPlay 52 | this.element = document.createElement('div') 53 | this.listeners = {} 54 | } 55 | var counter = 0 56 | 57 | $.extend(VimeoPlayer.prototype, { 58 | on: function (type, func) { 59 | this.listeners[type] = func 60 | return this 61 | }, 62 | 63 | loadAPI: function () { 64 | var that = this 65 | var apiUrl = 'https://f.vimeocdn.com/js/froogaloop2.min.js' 66 | var scriptTags = document.getElementsByTagName('script') 67 | var i = scriptTags.length 68 | var scriptTag 69 | var called 70 | /** 71 | * Callback function 72 | */ 73 | function callback() { 74 | if (!called && that.playOnReady) { 75 | that.play() 76 | } 77 | called = true 78 | } 79 | while (i) { 80 | i -= 1 81 | if (scriptTags[i].src === apiUrl) { 82 | scriptTag = scriptTags[i] 83 | break 84 | } 85 | } 86 | if (!scriptTag) { 87 | scriptTag = document.createElement('script') 88 | scriptTag.src = apiUrl 89 | } 90 | $(scriptTag).on('load', callback) 91 | scriptTags[0].parentNode.insertBefore(scriptTag, scriptTags[0]) 92 | // Fix for cached scripts on IE 8: 93 | if (/loaded|complete/.test(scriptTag.readyState)) { 94 | callback() 95 | } 96 | }, 97 | 98 | onReady: function () { 99 | var that = this 100 | this.ready = true 101 | this.player.addEvent('play', function () { 102 | that.hasPlayed = true 103 | that.onPlaying() 104 | }) 105 | this.player.addEvent('pause', function () { 106 | that.onPause() 107 | }) 108 | this.player.addEvent('finish', function () { 109 | that.onPause() 110 | }) 111 | if (this.playOnReady) { 112 | this.play() 113 | } 114 | }, 115 | 116 | onPlaying: function () { 117 | if (this.playStatus < 2) { 118 | this.listeners.playing() 119 | this.playStatus = 2 120 | } 121 | }, 122 | 123 | onPause: function () { 124 | this.listeners.pause() 125 | delete this.playStatus 126 | }, 127 | 128 | insertIframe: function () { 129 | var iframe = document.createElement('iframe') 130 | iframe.src = this.url 131 | .replace('VIDEO_ID', this.videoId) 132 | .replace('PLAYER_ID', this.playerId) 133 | iframe.id = this.playerId 134 | iframe.allow = 'autoplay' 135 | this.element.parentNode.replaceChild(iframe, this.element) 136 | this.element = iframe 137 | }, 138 | 139 | play: function () { 140 | var that = this 141 | if (!this.playStatus) { 142 | this.listeners.play() 143 | this.playStatus = 1 144 | } 145 | if (this.ready) { 146 | if ( 147 | !this.hasPlayed && 148 | (this.clickToPlay || 149 | (window.navigator && 150 | /iP(hone|od|ad)/.test(window.navigator.platform))) 151 | ) { 152 | // Manually trigger the playing callback if clickToPlay 153 | // is enabled and to workaround a limitation in iOS, 154 | // which requires synchronous user interaction to start 155 | // the video playback: 156 | this.onPlaying() 157 | } else { 158 | this.player.api('play') 159 | } 160 | } else { 161 | this.playOnReady = true 162 | if (!window.$f) { 163 | this.loadAPI() 164 | } else if (!this.player) { 165 | this.insertIframe() 166 | this.player = $f(this.element) 167 | this.player.addEvent('ready', function () { 168 | that.onReady() 169 | }) 170 | } 171 | } 172 | }, 173 | 174 | pause: function () { 175 | if (this.ready) { 176 | this.player.api('pause') 177 | } else if (this.playStatus) { 178 | delete this.playOnReady 179 | this.listeners.pause() 180 | delete this.playStatus 181 | } 182 | } 183 | }) 184 | 185 | $.extend(galleryPrototype, { 186 | VimeoPlayer: VimeoPlayer, 187 | 188 | textFactory: function (obj, callback) { 189 | var options = this.options 190 | var videoId = this.getItemProperty(obj, options.vimeoVideoIdProperty) 191 | if (videoId) { 192 | if (this.getItemProperty(obj, options.urlProperty) === undefined) { 193 | obj[options.urlProperty] = 'https://vimeo.com/' + videoId 194 | } 195 | counter += 1 196 | return this.videoFactory( 197 | obj, 198 | callback, 199 | new VimeoPlayer( 200 | options.vimeoPlayerUrl, 201 | videoId, 202 | options.vimeoPlayerIdPrefix + counter, 203 | options.vimeoClickToPlay 204 | ) 205 | ) 206 | } 207 | return textFactory.call(this, obj, callback) 208 | } 209 | }) 210 | 211 | return Gallery 212 | }) 213 | -------------------------------------------------------------------------------- /js/blueimp-gallery-youtube.js: -------------------------------------------------------------------------------- 1 | /* 2 | * blueimp Gallery YouTube Video Factory JS 3 | * https://github.com/blueimp/Gallery 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define, YT */ 13 | 14 | ;(function (factory) { 15 | 'use strict' 16 | if (typeof define === 'function' && define.amd) { 17 | // Register as an anonymous AMD module: 18 | define(['./blueimp-helper', './blueimp-gallery-video'], factory) 19 | } else { 20 | // Browser globals: 21 | factory(window.blueimp.helper || window.jQuery, window.blueimp.Gallery) 22 | } 23 | })(function ($, Gallery) { 24 | 'use strict' 25 | 26 | if (!window.postMessage) { 27 | return Gallery 28 | } 29 | 30 | var galleryPrototype = Gallery.prototype 31 | 32 | $.extend(galleryPrototype.options, { 33 | // The list object property (or data attribute) with the YouTube video id: 34 | youTubeVideoIdProperty: 'youtube', 35 | // Optional object with parameters passed to the YouTube video player: 36 | // https://developers.google.com/youtube/player_parameters 37 | youTubePlayerVars: { 38 | wmode: 'transparent' 39 | }, 40 | // Require a click on the native YouTube player for the initial playback: 41 | youTubeClickToPlay: false 42 | }) 43 | 44 | var textFactory = 45 | galleryPrototype.textFactory || galleryPrototype.imageFactory 46 | var YouTubePlayer = function (videoId, playerVars, clickToPlay) { 47 | this.videoId = videoId 48 | this.playerVars = playerVars 49 | this.clickToPlay = clickToPlay 50 | this.element = document.createElement('div') 51 | this.listeners = {} 52 | } 53 | 54 | $.extend(YouTubePlayer.prototype, { 55 | on: function (type, func) { 56 | this.listeners[type] = func 57 | return this 58 | }, 59 | 60 | loadAPI: function () { 61 | var that = this 62 | var onYouTubeIframeAPIReady = window.onYouTubeIframeAPIReady 63 | var apiUrl = 'https://www.youtube.com/iframe_api' 64 | var scriptTags = document.getElementsByTagName('script') 65 | var i = scriptTags.length 66 | var scriptTag 67 | window.onYouTubeIframeAPIReady = function () { 68 | if (onYouTubeIframeAPIReady) { 69 | onYouTubeIframeAPIReady.apply(this) 70 | } 71 | if (that.playOnReady) { 72 | that.play() 73 | } 74 | } 75 | while (i) { 76 | i -= 1 77 | if (scriptTags[i].src === apiUrl) { 78 | return 79 | } 80 | } 81 | scriptTag = document.createElement('script') 82 | scriptTag.src = apiUrl 83 | scriptTags[0].parentNode.insertBefore(scriptTag, scriptTags[0]) 84 | }, 85 | 86 | onReady: function () { 87 | this.ready = true 88 | if (this.playOnReady) { 89 | this.play() 90 | } 91 | }, 92 | 93 | onPlaying: function () { 94 | if (this.playStatus < 2) { 95 | this.listeners.playing() 96 | this.playStatus = 2 97 | } 98 | }, 99 | 100 | onPause: function () { 101 | this.listeners.pause() 102 | delete this.playStatus 103 | }, 104 | 105 | onStateChange: function (event) { 106 | window.clearTimeout(this.pauseTimeout) 107 | switch (event.data) { 108 | case YT.PlayerState.PLAYING: 109 | this.hasPlayed = true 110 | this.onPlaying() 111 | break 112 | case YT.PlayerState.UNSTARTED: 113 | case YT.PlayerState.PAUSED: 114 | // YouTube sends an unstarted event if pause is triggered before the 115 | // video has started. 116 | // YouTube sends a pause event when seeking. 117 | // In both cases, we initiate a pause in a timeout that gets cleared 118 | // if followed by another event within the timeout window. 119 | this.pauseTimeout = galleryPrototype.setTimeout.call( 120 | this, 121 | this.onPause, 122 | null, 123 | 500 124 | ) 125 | break 126 | case YT.PlayerState.ENDED: 127 | this.onPause() 128 | break 129 | } 130 | }, 131 | 132 | onError: function (event) { 133 | this.listeners.error(event) 134 | }, 135 | 136 | play: function () { 137 | var that = this 138 | if (!this.playStatus) { 139 | this.listeners.play() 140 | this.playStatus = 1 141 | } 142 | if (this.ready) { 143 | if ( 144 | !this.hasPlayed && 145 | (this.clickToPlay || 146 | (window.navigator && 147 | /iP(hone|od|ad)/.test(window.navigator.platform))) 148 | ) { 149 | // Manually trigger the playing callback if clickToPlay 150 | // is enabled and to workaround a limitation in iOS, 151 | // which requires synchronous user interaction to start 152 | // the video playback: 153 | this.onPlaying() 154 | } else { 155 | this.player.playVideo() 156 | } 157 | } else { 158 | this.playOnReady = true 159 | if (!(window.YT && YT.Player)) { 160 | this.loadAPI() 161 | } else if (!this.player) { 162 | this.player = new YT.Player(this.element, { 163 | videoId: this.videoId, 164 | playerVars: this.playerVars, 165 | events: { 166 | onReady: function () { 167 | that.onReady() 168 | }, 169 | onStateChange: function (event) { 170 | that.onStateChange(event) 171 | }, 172 | onError: function (event) { 173 | that.onError(event) 174 | } 175 | } 176 | }) 177 | } 178 | } 179 | }, 180 | 181 | pause: function () { 182 | if (this.ready) { 183 | this.player.pauseVideo() 184 | } else if (this.playStatus) { 185 | delete this.playOnReady 186 | this.listeners.pause() 187 | delete this.playStatus 188 | } 189 | } 190 | }) 191 | 192 | $.extend(galleryPrototype, { 193 | YouTubePlayer: YouTubePlayer, 194 | 195 | textFactory: function (obj, callback) { 196 | var options = this.options 197 | var videoId = this.getItemProperty(obj, options.youTubeVideoIdProperty) 198 | if (videoId) { 199 | if (this.getItemProperty(obj, options.urlProperty) === undefined) { 200 | obj[options.urlProperty] = 201 | 'https://www.youtube.com/watch?v=' + videoId 202 | } 203 | if ( 204 | this.getItemProperty(obj, options.videoPosterProperty) === undefined 205 | ) { 206 | obj[options.videoPosterProperty] = 207 | 'https://img.youtube.com/vi/' + videoId + '/maxresdefault.jpg' 208 | } 209 | return this.videoFactory( 210 | obj, 211 | callback, 212 | new YouTubePlayer( 213 | videoId, 214 | options.youTubePlayerVars, 215 | options.youTubeClickToPlay 216 | ) 217 | ) 218 | } 219 | return textFactory.call(this, obj, callback) 220 | } 221 | }) 222 | 223 | return Gallery 224 | }) 225 | -------------------------------------------------------------------------------- /js/blueimp-gallery-video.js: -------------------------------------------------------------------------------- 1 | /* 2 | * blueimp Gallery Video Factory JS 3 | * https://github.com/blueimp/Gallery 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define */ 13 | 14 | ;(function (factory) { 15 | 'use strict' 16 | if (typeof define === 'function' && define.amd) { 17 | // Register as an anonymous AMD module: 18 | define(['./blueimp-helper', './blueimp-gallery'], factory) 19 | } else { 20 | // Browser globals: 21 | factory(window.blueimp.helper || window.jQuery, window.blueimp.Gallery) 22 | } 23 | })(function ($, Gallery) { 24 | 'use strict' 25 | 26 | var galleryPrototype = Gallery.prototype 27 | 28 | $.extend(galleryPrototype.options, { 29 | // The class for video content elements: 30 | videoContentClass: 'video-content', 31 | // The class for video when it is loading: 32 | videoLoadingClass: 'video-loading', 33 | // The class for video when it is playing: 34 | videoPlayingClass: 'video-playing', 35 | // The class for video content displayed in an iframe: 36 | videoIframeClass: 'video-iframe', 37 | // The class for the video cover element: 38 | videoCoverClass: 'video-cover', 39 | // The class for the video play control: 40 | videoPlayClass: 'video-play', 41 | // Play videos inline by default: 42 | videoPlaysInline: true, 43 | // The list object property (or data attribute) for video preload: 44 | videoPreloadProperty: 'preload', 45 | // The list object property (or data attribute) for the video poster URL: 46 | videoPosterProperty: 'poster' 47 | }) 48 | 49 | var handleSlide = galleryPrototype.handleSlide 50 | 51 | $.extend(galleryPrototype, { 52 | handleSlide: function (oldIndex, newIndex) { 53 | handleSlide.call(this, oldIndex, newIndex) 54 | this.setTimeout(function () { 55 | if (this.activeVideo) { 56 | this.activeVideo.pause() 57 | } 58 | }) 59 | }, 60 | 61 | videoFactory: function (obj, callback, videoInterface) { 62 | var that = this 63 | var options = this.options 64 | var videoContainerNode = this.elementPrototype.cloneNode(false) 65 | var videoContainer = $(videoContainerNode) 66 | var errorArgs = [ 67 | { 68 | type: 'error', 69 | target: videoContainerNode 70 | } 71 | ] 72 | var video = videoInterface || document.createElement('video') 73 | var coverElement = this.elementPrototype.cloneNode(false) 74 | var playElement = document.createElement('a') 75 | var url = this.getItemProperty(obj, options.urlProperty) 76 | var sources = this.getItemProperty(obj, options.sourcesProperty) 77 | var title = this.getItemProperty(obj, options.titleProperty) 78 | var posterUrl = this.getItemProperty(obj, options.videoPosterProperty) 79 | var playControls = [playElement] 80 | var hasGalleryControls 81 | var isLoading 82 | var i 83 | videoContainer.addClass(options.videoContentClass) 84 | $(playElement).addClass(options.videoPlayClass) 85 | if ( 86 | !$(coverElement) 87 | .addClass(options.videoCoverClass) 88 | .hasClass(options.toggleClass) 89 | ) { 90 | playControls.push(coverElement) 91 | } 92 | coverElement.draggable = false 93 | if (title) { 94 | videoContainerNode.title = title 95 | playElement.setAttribute('aria-label', title) 96 | } 97 | if (posterUrl) { 98 | // Set as background image instead of as poster video element property: 99 | // - Is accessible for browsers that do not support the video element 100 | // - Is accessible for both video element and iframe video players 101 | // - Avoids visual artifacts in IE with the poster property set 102 | coverElement.style.backgroundImage = 'url("' + posterUrl + '")' 103 | } 104 | if (video.setAttribute) { 105 | if (options.videoPlaysInline) video.setAttribute('playsinline', '') 106 | } else { 107 | videoContainer.addClass(options.videoIframeClass) 108 | } 109 | video.preload = 110 | this.getItemProperty(obj, options.videoPreloadProperty) || 'none' 111 | if (this.support.source && sources) { 112 | for (i = 0; i < sources.length; i += 1) { 113 | video.appendChild( 114 | $.extend(this.sourcePrototype.cloneNode(false), sources[i]) 115 | ) 116 | } 117 | } 118 | if (url) video.src = url 119 | playElement.href = url || (sources && sources.length && sources[0].src) 120 | if (video.play && video.pause) { 121 | ;(videoInterface || $(video)) 122 | .on('error', function () { 123 | that.setTimeout(callback, errorArgs) 124 | }) 125 | .on('pause', function () { 126 | if (video.seeking) return 127 | isLoading = false 128 | videoContainer 129 | .removeClass(that.options.videoLoadingClass) 130 | .removeClass(that.options.videoPlayingClass) 131 | if (hasGalleryControls) { 132 | that.container.addClass(that.options.controlsClass) 133 | } 134 | video.controls = false 135 | if (video === that.activeVideo) delete that.activeVideo 136 | if (that.interval) { 137 | // Continue slideshow interval 138 | that.play() 139 | } 140 | }) 141 | .on('playing', function () { 142 | isLoading = false 143 | coverElement.removeAttribute('style') 144 | videoContainer 145 | .removeClass(that.options.videoLoadingClass) 146 | .addClass(that.options.videoPlayingClass) 147 | }) 148 | .on('play', function () { 149 | // Clear slideshow timeout: 150 | window.clearTimeout(that.timeout) 151 | isLoading = true 152 | videoContainer.addClass(that.options.videoLoadingClass) 153 | if (that.container.hasClass(that.options.controlsClass)) { 154 | hasGalleryControls = true 155 | that.container.removeClass(that.options.controlsClass) 156 | } else { 157 | hasGalleryControls = false 158 | } 159 | video.controls = true 160 | that.activeVideo = video 161 | }) 162 | $(playControls).on('click', function (event) { 163 | that.preventDefault(event) 164 | that.activeVideo = video 165 | if (isLoading) { 166 | video.pause() 167 | } else { 168 | video.play() 169 | } 170 | }) 171 | videoContainerNode.appendChild( 172 | (videoInterface && videoInterface.element) || video 173 | ) 174 | } 175 | videoContainerNode.appendChild(coverElement) 176 | videoContainerNode.appendChild(playElement) 177 | this.setTimeout(callback, [ 178 | { 179 | type: 'load', 180 | target: videoContainerNode 181 | } 182 | ]) 183 | return videoContainerNode 184 | } 185 | }) 186 | 187 | return Gallery 188 | }) 189 | -------------------------------------------------------------------------------- /css/blueimp-gallery.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 3 | * blueimp Gallery CSS 4 | * https://github.com/blueimp/Gallery 5 | * 6 | * Copyright 2013, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * https://opensource.org/licenses/MIT 11 | */ 12 | 13 | .blueimp-gallery, 14 | .blueimp-gallery > .slides > .slide > .slide-content, 15 | .blueimp-gallery > .slides > .slide > .slide-content > img { 16 | position: absolute; 17 | top: 0; 18 | right: 0; 19 | bottom: 0; 20 | left: 0; 21 | -webkit-transition: opacity 0.2s linear; 22 | -moz-transition: opacity 0.2s linear; 23 | -ms-transition: opacity 0.2s linear; 24 | -o-transition: opacity 0.2s linear; 25 | transition: opacity 0.2s linear; 26 | /* Prevent artifacts in Mozilla Firefox: */ 27 | backface-visibility: hidden; 28 | -moz-backface-visibility: hidden; 29 | } 30 | .blueimp-gallery > .slides > .slide > .slide-content, 31 | .blueimp-gallery > .slides > .slide > .slide-content > img { 32 | margin: auto; 33 | width: auto; 34 | height: auto; 35 | max-width: 100%; 36 | max-height: 100%; 37 | opacity: 1; 38 | } 39 | .blueimp-gallery { 40 | position: fixed; 41 | z-index: 999999; 42 | overflow: hidden; 43 | background: #000; 44 | opacity: 0; 45 | display: none; 46 | direction: ltr; 47 | -ms-touch-action: pinch-zoom; 48 | touch-action: pinch-zoom; 49 | } 50 | .blueimp-gallery-carousel { 51 | position: relative; 52 | z-index: auto; 53 | margin: 1em auto; 54 | /* Set the carousel width/height ratio to 16/9: */ 55 | padding-bottom: 56.25%; 56 | box-shadow: 0 0 4px rgba(0, 0, 0, 0.1); 57 | -ms-touch-action: pan-y pinch-zoom; 58 | touch-action: pan-y pinch-zoom; 59 | display: block; 60 | } 61 | .blueimp-gallery-display { 62 | display: block; 63 | opacity: 1; 64 | } 65 | .blueimp-gallery > .slides { 66 | position: relative; 67 | height: 100%; 68 | overflow: hidden; 69 | } 70 | .blueimp-gallery-carousel > .slides { 71 | position: absolute; 72 | } 73 | .blueimp-gallery > .slides > .slide { 74 | visibility: hidden; 75 | position: relative; 76 | float: left; 77 | height: 100%; 78 | text-align: center; 79 | -webkit-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1); 80 | -moz-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1); 81 | -ms-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1); 82 | -o-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1); 83 | transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1); 84 | } 85 | .blueimp-gallery > .slides > .slide-prev, 86 | .blueimp-gallery > .slides > .slide-active, 87 | .blueimp-gallery > .slides > .slide-next { 88 | visibility: visible; 89 | } 90 | .blueimp-gallery > .slides > .slide-loading { 91 | background: url(../img/loading.gif) center no-repeat; 92 | background-size: 64px 64px; 93 | } 94 | .blueimp-gallery-smil > .slides > .slide-loading { 95 | background-image: url(../img/loading.svg); 96 | } 97 | .blueimp-gallery > .slides > .slide-loading > .slide-content { 98 | opacity: 0; 99 | } 100 | .blueimp-gallery > .slides > .slide-error { 101 | background: url(../img/error.png) center no-repeat; 102 | } 103 | .blueimp-gallery-svgasimg > .slides > .slide-error { 104 | background-image: url(../img/error.svg); 105 | } 106 | .blueimp-gallery > .slides > .slide-error > .slide-content { 107 | display: none; 108 | } 109 | .blueimp-gallery-display > .prev, 110 | .blueimp-gallery-display > .next { 111 | position: absolute; 112 | top: 50%; 113 | left: 15px; 114 | width: 8px; 115 | height: 20px; 116 | padding: 10px 14px 10px 18px; 117 | margin-top: -23px; 118 | -webkit-box-sizing: content-box; 119 | -moz-box-sizing: content-box; 120 | box-sizing: content-box; 121 | background: #222 url(../img/prev.png) center no-repeat; 122 | background-color: rgba(0, 0, 0, 0.5); 123 | border: 3px solid #fff; 124 | -webkit-border-radius: 30px; 125 | -moz-border-radius: 30px; 126 | border-radius: 30px; 127 | opacity: 0.5; 128 | cursor: pointer; 129 | display: none; 130 | } 131 | .blueimp-gallery-display > .next { 132 | right: 15px; 133 | left: auto; 134 | background-image: url(../img/next.png); 135 | } 136 | .blueimp-gallery-svgasimg > .prev { 137 | background-image: url(../img/prev.svg); 138 | } 139 | .blueimp-gallery-svgasimg > .next { 140 | background-image: url(../img/next.svg); 141 | } 142 | .blueimp-gallery-display > .close { 143 | position: absolute; 144 | top: 15px; 145 | right: 15px; 146 | width: 30px; 147 | height: 30px; 148 | background: url(../img/close.png) center no-repeat; 149 | opacity: 0.8; 150 | cursor: pointer; 151 | display: none; 152 | } 153 | .blueimp-gallery-svgasimg > .close { 154 | background-image: url(../img/close.svg); 155 | } 156 | .blueimp-gallery > .title { 157 | position: absolute; 158 | top: 15px; 159 | left: 15px; 160 | margin: 0 60px 0 0; 161 | font-size: 20px; 162 | line-height: 30px; 163 | color: #fff; 164 | text-shadow: 0 0 2px #000; 165 | opacity: 0.8; 166 | display: none; 167 | } 168 | .blueimp-gallery-display > .play-pause { 169 | position: absolute; 170 | right: 15px; 171 | bottom: 15px; 172 | width: 30px; 173 | height: 30px; 174 | background: url(../img/play-pause.png) 0 0 no-repeat; 175 | cursor: pointer; 176 | opacity: 0.5; 177 | display: none; 178 | } 179 | .blueimp-gallery-svgasimg > .play-pause { 180 | background-image: url(../img/play-pause.svg); 181 | } 182 | .blueimp-gallery-playing > .play-pause { 183 | background-position: -30px 0; 184 | } 185 | .blueimp-gallery-controls > .prev, 186 | .blueimp-gallery-controls > .next, 187 | .blueimp-gallery-controls > .close, 188 | .blueimp-gallery-controls > .title, 189 | .blueimp-gallery-controls > .play-pause { 190 | display: block; 191 | /* Fix z-index issues (controls behind slide element) on Android: */ 192 | -webkit-transform: translateZ(0); 193 | -moz-transform: translateZ(0); 194 | -ms-transform: translateZ(0); 195 | -o-transform: translateZ(0); 196 | transform: translateZ(0); 197 | } 198 | .blueimp-gallery-single > .prev, 199 | .blueimp-gallery-left > .prev, 200 | .blueimp-gallery-single > .next, 201 | .blueimp-gallery-right > .next, 202 | .blueimp-gallery-single > .play-pause { 203 | display: none; 204 | } 205 | .blueimp-gallery > .slides > .slide > .slide-content, 206 | .blueimp-gallery > .prev, 207 | .blueimp-gallery > .next, 208 | .blueimp-gallery > .close, 209 | .blueimp-gallery > .play-pause { 210 | -webkit-user-select: none; 211 | -khtml-user-select: none; 212 | -moz-user-select: none; 213 | -ms-user-select: none; 214 | user-select: none; 215 | } 216 | .blueimp-gallery > .prev:hover, 217 | .blueimp-gallery > .next:hover, 218 | .blueimp-gallery > .close:hover, 219 | .blueimp-gallery > .title:hover, 220 | .blueimp-gallery > .play-pause:hover { 221 | color: #fff; 222 | opacity: 1; 223 | } 224 | 225 | /* IE7 fixes */ 226 | * + html .blueimp-gallery > .slides > .slide { 227 | min-height: 300px; 228 | } 229 | * + html .blueimp-gallery > .slides > .slide > .slide-content { 230 | position: relative; 231 | } 232 | * + html .blueimp-gallery > .slides > .slide > .slide-content > img { 233 | position: relative; 234 | } 235 | 236 | @supports (object-fit: contain) { 237 | .blueimp-gallery-contain > .slides > .slide > .slide-content, 238 | .blueimp-gallery-contain > .slides > .slide > .slide-content > img { 239 | width: 100%; 240 | height: 100%; 241 | object-fit: contain; 242 | } 243 | } 244 | 245 | @media (prefers-color-scheme: light) { 246 | .blueimp-gallery-carousel { 247 | background: #fff; 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /css/blueimp-gallery.min.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.slides>.slide>.slide-content>img{position:absolute;top:0;right:0;bottom:0;left:0;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-ms-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear;backface-visibility:hidden;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.slides>.slide>.slide-content>img{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;opacity:0;display:none;direction:ltr;-ms-touch-action:pinch-zoom;touch-action:pinch-zoom}.blueimp-gallery-carousel{position:relative;z-index:auto;margin:1em auto;padding-bottom:56.25%;box-shadow:0 0 4px rgba(0,0,0,.1);-ms-touch-action:pan-y pinch-zoom;touch-action:pan-y pinch-zoom;display:block}.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{visibility:hidden;position:relative;float:left;height:100%;text-align:center;-webkit-transition-timing-function:cubic-bezier(0.645,0.045,0.355,1);-moz-transition-timing-function:cubic-bezier(0.645,0.045,0.355,1);-ms-transition-timing-function:cubic-bezier(0.645,0.045,0.355,1);-o-transition-timing-function:cubic-bezier(0.645,0.045,0.355,1);transition-timing-function:cubic-bezier(0.645,0.045,0.355,1)}.blueimp-gallery>.slides>.slide-active,.blueimp-gallery>.slides>.slide-next,.blueimp-gallery>.slides>.slide-prev{visibility:visible}.blueimp-gallery>.slides>.slide-loading{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery-smil>.slides>.slide-loading{background-image:url(../img/loading.svg)}.blueimp-gallery>.slides>.slide-loading>.slide-content{opacity:0}.blueimp-gallery>.slides>.slide-error{background:url(../img/error.png) center no-repeat}.blueimp-gallery-svgasimg>.slides>.slide-error{background-image:url(../img/error.svg)}.blueimp-gallery>.slides>.slide-error>.slide-content{display:none}.blueimp-gallery-display>.next,.blueimp-gallery-display>.prev{position:absolute;top:50%;left:15px;width:8px;height:20px;padding:10px 14px 10px 18px;margin-top:-23px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;background:#222 url(../img/prev.png) center no-repeat;background-color:rgba(0,0,0,.5);border:3px solid #fff;-webkit-border-radius:30px;-moz-border-radius:30px;border-radius:30px;opacity:.5;cursor:pointer;display:none}.blueimp-gallery-display>.next{right:15px;left:auto;background-image:url(../img/next.png)}.blueimp-gallery-svgasimg>.prev{background-image:url(../img/prev.svg)}.blueimp-gallery-svgasimg>.next{background-image:url(../img/next.svg)}.blueimp-gallery-display>.close{position:absolute;top:15px;right:15px;width:30px;height:30px;background:url(../img/close.png) center no-repeat;opacity:.8;cursor:pointer;display:none}.blueimp-gallery-svgasimg>.close{background-image:url(../img/close.svg)}.blueimp-gallery>.title{position:absolute;top:15px;left:15px;margin:0 60px 0 0;font-size:20px;line-height:30px;color:#fff;text-shadow:0 0 2px #000;opacity:.8;display:none}.blueimp-gallery-display>.play-pause{position:absolute;right:15px;bottom:15px;width:30px;height:30px;background:url(../img/play-pause.png) 0 0 no-repeat;cursor:pointer;opacity:.5;display:none}.blueimp-gallery-svgasimg>.play-pause{background-image:url(../img/play-pause.svg)}.blueimp-gallery-playing>.play-pause{background-position:-30px 0}.blueimp-gallery-controls>.close,.blueimp-gallery-controls>.next,.blueimp-gallery-controls>.play-pause,.blueimp-gallery-controls>.prev,.blueimp-gallery-controls>.title{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-left>.prev,.blueimp-gallery-right>.next,.blueimp-gallery-single>.next,.blueimp-gallery-single>.play-pause,.blueimp-gallery-single>.prev{display:none}.blueimp-gallery>.close,.blueimp-gallery>.next,.blueimp-gallery>.play-pause,.blueimp-gallery>.prev,.blueimp-gallery>.slides>.slide>.slide-content{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.blueimp-gallery>.close:hover,.blueimp-gallery>.next:hover,.blueimp-gallery>.play-pause:hover,.blueimp-gallery>.prev:hover,.blueimp-gallery>.title:hover{color:#fff;opacity:1}*+html .blueimp-gallery>.slides>.slide{min-height:300px}*+html .blueimp-gallery>.slides>.slide>.slide-content{position:relative}*+html .blueimp-gallery>.slides>.slide>.slide-content>img{position:relative}@supports (object-fit:contain){.blueimp-gallery-contain>.slides>.slide>.slide-content,.blueimp-gallery-contain>.slides>.slide>.slide-content>img{width:100%;height:100%;object-fit:contain}}@media (prefers-color-scheme:light){.blueimp-gallery-carousel{background:#fff}}.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;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.blueimp-gallery>.indicator>li{display:inline-block;position:relative;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,.25) center no-repeat;border-radius:5px;box-shadow:0 0 2px #000;opacity:.5;cursor:pointer}*+html .blueimp-gallery>.indicator>li{display:inline}.blueimp-gallery>.indicator>.active,.blueimp-gallery>.indicator>li:hover{background-color:#fff;border-color:#fff;opacity:1}.blueimp-gallery>.indicator>li:after{opacity:0;display:block;position:absolute;content:'';top:-5em;left:4px;width:75px;height:75px;transition:transform .6s ease-out,opacity .4s ease-out;transform:translateX(-50%) translateY(0) translateZ(0);pointer-events:none}.blueimp-gallery>.indicator>li:hover:after{opacity:1;border-radius:50%;background:inherit;transform:translateX(-50%) translateY(-5px) translateZ(0)}.blueimp-gallery>.indicator>.active:after{display:none}.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>.slides>.slide>.video-content>.video-cover,.blueimp-gallery>.slides>.slide>.video-content>iframe,.blueimp-gallery>.slides>.slide>.video-content>video{position:absolute;top:0;left:0;width:100%;height:100%;border:none}.blueimp-gallery>.slides>.slide>.video-content>.video-cover{background:center no-repeat;background-size:contain}.blueimp-gallery>.slides>.slide>.video-iframe>.video-cover{background-color:#000;background-color:rgba(0,0,0,.7)}.blueimp-gallery>.slides>.slide>.video-content>.video-play{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-svgasimg>.slides>.slide>.video-content>.video-play{background-image:url(../img/video-play.svg)}.blueimp-gallery>.slides>.slide>.video-playing>.video-cover,.blueimp-gallery>.slides>.slide>.video-playing>.video-play{display:none}.blueimp-gallery>.slides>.slide>.video-loading>.video-play{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery-smil>.slides>.slide>.video-loading>.video-play{background-image:url(../img/loading.svg)}*+html .blueimp-gallery>.slides>.slide>.video-content{height:100%}*+html .blueimp-gallery>.slides>.slide>.video-content>.video-play{left:50%;margin-left:-64px}.blueimp-gallery>.slides>.slide>.video-content>.video-play:hover{opacity:1} 2 | /*# sourceMappingURL=blueimp-gallery.min.css.map */ -------------------------------------------------------------------------------- /js/jquery.blueimp-gallery.min.js: -------------------------------------------------------------------------------- 1 | !function(t){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper"],t):(window.blueimp=window.blueimp||{},window.blueimp.Gallery=t(window.blueimp.helper||window.jQuery))}(function(y){"use strict";function i(t,e){return document.body.style.maxHeight===undefined?null:this&&this.options===i.prototype.options?void(t&&t.length?(this.list=t,this.num=t.length,this.initOptions(e),this.initialize()):this.console.log("blueimp Gallery: No or empty list provided as first argument.",t)):new i(t,e)}return y.extend(i.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",svgasimgClass:"blueimp-gallery-svgasimg",smilClass:"blueimp-gallery-smil",slideClass:"slide",slideActiveClass:"slide-active",slidePrevClass:"slide-prev",slideNextClass:"slide-next",slideLoadingClass:"slide-loading",slideErrorClass:"slide-error",slideContentClass:"slide-content",toggleClass:"toggle",prevClass:"prev",nextClass:"next",closeClass:"close",playPauseClass:"play-pause",typeProperty:"type",titleProperty:"title",altTextProperty:"alt",urlProperty:"href",srcsetProperty:"srcset",sizesProperty:"sizes",sourcesProperty:"sources",displayTransition:!0,clearSlides:!0,toggleControlsOnEnter:!0,toggleControlsOnSlideClick:!0,toggleSlideshowOnSpace:!0,enableKeyboardNavigation:!0,closeOnEscape:!0,closeOnSlideClick:!0,closeOnSwipeUpOrDown:!0,closeOnHashChange:!0,emulateTouchEvents:!0,stopTouchEventsPropagation:!1,hidePageScrollbars:!0,disableScroll:!0,carousel:!1,continuous:!0,unloadElements:!0,startSlideshow:!1,slideshowInterval:5e3,slideshowDirection:"ltr",index:0,preloadRange:2,transitionDuration:300,slideshowTransitionDuration:500,event:undefined,onopen:undefined,onopened:undefined,onslide:undefined,onslideend:undefined,onslidecomplete:undefined,onclose:undefined,onclosed:undefined},carouselOptions:{hidePageScrollbars:!1,toggleControlsOnEnter:!1,toggleSlideshowOnSpace:!1,enableKeyboardNavigation:!1,closeOnEscape:!1,closeOnSlideClick:!1,closeOnSwipeUpOrDown:!1,closeOnHashChange:!1,disableScroll:!1,startSlideshow:!0},console:window.console&&"function"==typeof window.console.log?window.console:{log:function(){}},support:function(s){var t,n={source:!!window.HTMLSourceElement,picture:!!window.HTMLPictureElement,svgasimg:document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1"),smil:!!document.createElementNS&&/SVGAnimate/.test(document.createElementNS("http://www.w3.org/2000/svg","animate").toString()),touch:window.ontouchstart!==undefined||window.DocumentTouch&&document instanceof DocumentTouch},e={webkitTransition:{end:"webkitTransitionEnd",prefix:"-webkit-"},MozTransition:{end:"transitionend",prefix:"-moz-"},OTransition:{end:"otransitionend",prefix:"-o-"},transition:{end:"transitionend",prefix:""}};for(t in e)if(Object.prototype.hasOwnProperty.call(e,t)&&s.style[t]!==undefined){n.transition=e[t],n.transition.name=t;break}function i(){var t,e,i=n.transition;document.body.appendChild(s),i&&(t=i.name.slice(0,-9)+"ransform",s.style[t]!==undefined&&(s.style[t]="translateZ(0)",e=window.getComputedStyle(s).getPropertyValue(i.prefix+"transform"),n.transform={prefix:i.prefix,name:t,translate:!0,translateZ:!!e&&"none"!==e})),document.body.removeChild(s)}return document.body?i():y(document).on("DOMContentLoaded",i),n}(document.createElement("div")),requestAnimationFrame:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame,cancelAnimationFrame:window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame,initialize:function(){if(this.initStartIndex(),!1===this.initWidget())return!1;this.initEventListeners(),this.onslide(this.index),this.ontransitionend(),this.options.startSlideshow&&this.play()},slide:function(t,e){window.clearTimeout(this.timeout);var i,s,n,o=this.index;if(o!==t&&1!==this.num){if(e=e||this.options.transitionDuration,this.support.transform){for(this.options.continuous||(t=this.circle(t)),i=Math.abs(o-t)/(o-t),this.options.continuous&&(s=i,(i=-this.positions[this.circle(t)]/this.slideWidth)!==s&&(t=-i*this.num+t)),n=Math.abs(o-t)-1;n;)this.move(this.circle((o